diff options
author | Patrick Boettcher <pboettcher@kernellabs.com> | 2013-04-22 11:45:52 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-04-22 15:58:16 -0400 |
commit | 173a64cb3fcff1993b2aa8113e53fd379f6a968f (patch) | |
tree | c1836b2c5208456f61cb7acfcf1771ac5bf444ad /drivers/media/dvb-frontends | |
parent | 1552fb344d5ddd5178e8774a31fdb08765c668e1 (diff) |
[media] dib8000: enhancement
The intend of this patch is to improve the support of the dib8000.
Signed-off-by: Olivier Grenie <olivier.grenie@parrot.com>
Signed-off-by: Patrick Boettcher <patrick.boettcher@parrot.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb-frontends')
-rw-r--r-- | drivers/media/dvb-frontends/dib8000.c | 2235 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dib8000.h | 6 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dibx000_common.h | 3 |
3 files changed, 1320 insertions, 924 deletions
diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index 1f3bcb5a1de8..1d719cce8995 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c | |||
@@ -23,8 +23,8 @@ | |||
23 | #define LAYER_B 2 | 23 | #define LAYER_B 2 |
24 | #define LAYER_C 3 | 24 | #define LAYER_C 3 |
25 | 25 | ||
26 | #define FE_CALLBACK_TIME_NEVER 0xffffffff | ||
27 | #define MAX_NUMBER_OF_FRONTENDS 6 | 26 | #define MAX_NUMBER_OF_FRONTENDS 6 |
27 | /* #define DIB8000_AGC_FREEZE */ | ||
28 | 28 | ||
29 | static int debug; | 29 | static int debug; |
30 | module_param(debug, int, 0644); | 30 | module_param(debug, int, 0644); |
@@ -32,8 +32,6 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | |||
32 | 32 | ||
33 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0) | 33 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0) |
34 | 34 | ||
35 | #define FE_STATUS_TUNE_FAILED 0 | ||
36 | |||
37 | struct i2c_device { | 35 | struct i2c_device { |
38 | struct i2c_adapter *adap; | 36 | struct i2c_adapter *adap; |
39 | u8 addr; | 37 | u8 addr; |
@@ -42,6 +40,23 @@ struct i2c_device { | |||
42 | struct mutex *i2c_buffer_lock; | 40 | struct mutex *i2c_buffer_lock; |
43 | }; | 41 | }; |
44 | 42 | ||
43 | enum param_loop_step { | ||
44 | LOOP_TUNE_1, | ||
45 | LOOP_TUNE_2 | ||
46 | }; | ||
47 | |||
48 | enum dib8000_autosearch_step { | ||
49 | AS_START = 0, | ||
50 | AS_SEARCHING_FFT, | ||
51 | AS_SEARCHING_GUARD, | ||
52 | AS_DONE = 100, | ||
53 | }; | ||
54 | |||
55 | enum timeout_mode { | ||
56 | SYMBOL_DEPENDENT_OFF = 0, | ||
57 | SYMBOL_DEPENDENT_ON, | ||
58 | }; | ||
59 | |||
45 | struct dib8000_state { | 60 | struct dib8000_state { |
46 | struct dib8000_config cfg; | 61 | struct dib8000_config cfg; |
47 | 62 | ||
@@ -72,7 +87,7 @@ struct dib8000_state { | |||
72 | u16 revision; | 87 | u16 revision; |
73 | u8 isdbt_cfg_loaded; | 88 | u8 isdbt_cfg_loaded; |
74 | enum frontend_tune_state tune_state; | 89 | enum frontend_tune_state tune_state; |
75 | u32 status; | 90 | s32 status; |
76 | 91 | ||
77 | struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS]; | 92 | struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS]; |
78 | 93 | ||
@@ -85,6 +100,30 @@ struct dib8000_state { | |||
85 | 100 | ||
86 | u16 tuner_enable; | 101 | u16 tuner_enable; |
87 | struct i2c_adapter dib8096p_tuner_adap; | 102 | struct i2c_adapter dib8096p_tuner_adap; |
103 | u16 current_demod_bw; | ||
104 | |||
105 | u16 seg_mask; | ||
106 | u16 seg_diff_mask; | ||
107 | u16 mode; | ||
108 | u8 layer_b_nb_seg; | ||
109 | u8 layer_c_nb_seg; | ||
110 | |||
111 | u8 channel_parameters_set; | ||
112 | u16 autosearch_state; | ||
113 | u16 found_nfft; | ||
114 | u16 found_guard; | ||
115 | u8 subchannel; | ||
116 | u8 symbol_duration; | ||
117 | u32 timeout; | ||
118 | u8 longest_intlv_layer; | ||
119 | u16 output_mode; | ||
120 | |||
121 | #ifdef DIB8000_AGC_FREEZE | ||
122 | u16 agc1_max; | ||
123 | u16 agc1_min; | ||
124 | u16 agc2_max; | ||
125 | u16 agc2_min; | ||
126 | #endif | ||
88 | }; | 127 | }; |
89 | 128 | ||
90 | enum dib8000_power_mode { | 129 | enum dib8000_power_mode { |
@@ -338,9 +377,9 @@ static void dib8000_set_acquisition_mode(struct dib8000_state *state) | |||
338 | static int dib8000_set_output_mode(struct dvb_frontend *fe, int mode) | 377 | static int dib8000_set_output_mode(struct dvb_frontend *fe, int mode) |
339 | { | 378 | { |
340 | struct dib8000_state *state = fe->demodulator_priv; | 379 | struct dib8000_state *state = fe->demodulator_priv; |
341 | |||
342 | u16 outreg, fifo_threshold, smo_mode, sram = 0x0205; /* by default SDRAM deintlv is enabled */ | 380 | u16 outreg, fifo_threshold, smo_mode, sram = 0x0205; /* by default SDRAM deintlv is enabled */ |
343 | 381 | ||
382 | state->output_mode = mode; | ||
344 | outreg = 0; | 383 | outreg = 0; |
345 | fifo_threshold = 1792; | 384 | fifo_threshold = 1792; |
346 | smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1); | 385 | smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1); |
@@ -399,8 +438,9 @@ static int dib8000_set_output_mode(struct dvb_frontend *fe, int mode) | |||
399 | static int dib8000_set_diversity_in(struct dvb_frontend *fe, int onoff) | 438 | static int dib8000_set_diversity_in(struct dvb_frontend *fe, int onoff) |
400 | { | 439 | { |
401 | struct dib8000_state *state = fe->demodulator_priv; | 440 | struct dib8000_state *state = fe->demodulator_priv; |
402 | u16 sync_wait = dib8000_read_word(state, 273) & 0xfff0; | 441 | u16 tmp, sync_wait = dib8000_read_word(state, 273) & 0xfff0; |
403 | 442 | ||
443 | dprintk("set diversity input to %i", onoff); | ||
404 | if (!state->differential_constellation) { | 444 | if (!state->differential_constellation) { |
405 | dib8000_write_word(state, 272, 1 << 9); //dvsy_off_lmod4 = 1 | 445 | dib8000_write_word(state, 272, 1 << 9); //dvsy_off_lmod4 = 1 |
406 | dib8000_write_word(state, 273, sync_wait | (1 << 2) | 2); // sync_enable = 1; comb_mode = 2 | 446 | dib8000_write_word(state, 273, sync_wait | (1 << 2) | 2); // sync_enable = 1; comb_mode = 2 |
@@ -424,6 +464,13 @@ static int dib8000_set_diversity_in(struct dvb_frontend *fe, int onoff) | |||
424 | dib8000_write_word(state, 271, 1); | 464 | dib8000_write_word(state, 271, 1); |
425 | break; | 465 | break; |
426 | } | 466 | } |
467 | |||
468 | if (state->revision == 0x8002) { | ||
469 | tmp = dib8000_read_word(state, 903); | ||
470 | dib8000_write_word(state, 903, tmp & ~(1 << 3)); | ||
471 | msleep(30); | ||
472 | dib8000_write_word(state, 903, tmp | (1 << 3)); | ||
473 | } | ||
427 | return 0; | 474 | return 0; |
428 | } | 475 | } |
429 | 476 | ||
@@ -468,27 +515,6 @@ static void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_pow | |||
468 | dib8000_write_word(state, 1280, reg_1280); | 515 | dib8000_write_word(state, 1280, reg_1280); |
469 | } | 516 | } |
470 | 517 | ||
471 | static int dib8000_init_sdram(struct dib8000_state *state) | ||
472 | { | ||
473 | u16 reg = 0; | ||
474 | dprintk("Init sdram"); | ||
475 | |||
476 | reg = dib8000_read_word(state, 274)&0xfff0; | ||
477 | /* P_dintlv_delay_ram = 7 because of MobileSdram */ | ||
478 | dib8000_write_word(state, 274, reg | 0x7); | ||
479 | |||
480 | dib8000_write_word(state, 1803, (7<<2)); | ||
481 | |||
482 | reg = dib8000_read_word(state, 1280); | ||
483 | /* force restart P_restart_sdram */ | ||
484 | dib8000_write_word(state, 1280, reg | (1<<2)); | ||
485 | |||
486 | /* release restart P_restart_sdram */ | ||
487 | dib8000_write_word(state, 1280, reg); | ||
488 | |||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | static int dib8000_set_adc_state(struct dib8000_state *state, enum dibx000_adc_states no) | 518 | static int dib8000_set_adc_state(struct dib8000_state *state, enum dibx000_adc_states no) |
493 | { | 519 | { |
494 | int ret = 0; | 520 | int ret = 0; |
@@ -584,18 +610,23 @@ static int dib8000_set_bandwidth(struct dvb_frontend *fe, u32 bw) | |||
584 | 610 | ||
585 | static int dib8000_sad_calib(struct dib8000_state *state) | 611 | static int dib8000_sad_calib(struct dib8000_state *state) |
586 | { | 612 | { |
613 | u8 sad_sel = 3; | ||
614 | |||
587 | if (state->revision == 0x8090) { | 615 | if (state->revision == 0x8090) { |
588 | dprintk("%s: the sad calibration is not needed for the dib8096P", | 616 | dib8000_write_word(state, 922, (sad_sel << 2)); |
589 | __func__); | 617 | dib8000_write_word(state, 923, 2048); |
590 | return 0; | ||
591 | } | ||
592 | /* internal */ | ||
593 | dib8000_write_word(state, 923, (0 << 1) | (0 << 0)); | ||
594 | dib8000_write_word(state, 924, 776); // 0.625*3.3 / 4096 | ||
595 | 618 | ||
596 | /* do the calibration */ | 619 | dib8000_write_word(state, 922, (sad_sel << 2) | 0x1); |
597 | dib8000_write_word(state, 923, (1 << 0)); | 620 | dib8000_write_word(state, 922, (sad_sel << 2)); |
598 | dib8000_write_word(state, 923, (0 << 0)); | 621 | } else { |
622 | /* internal */ | ||
623 | dib8000_write_word(state, 923, (0 << 1) | (0 << 0)); | ||
624 | dib8000_write_word(state, 924, 776); | ||
625 | |||
626 | /* do the calibration */ | ||
627 | dib8000_write_word(state, 923, (1 << 0)); | ||
628 | dib8000_write_word(state, 923, (0 << 0)); | ||
629 | } | ||
599 | 630 | ||
600 | msleep(1); | 631 | msleep(1); |
601 | return 0; | 632 | return 0; |
@@ -609,8 +640,8 @@ int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value) | |||
609 | state->wbd_ref = value; | 640 | state->wbd_ref = value; |
610 | return dib8000_write_word(state, 106, value); | 641 | return dib8000_write_word(state, 106, value); |
611 | } | 642 | } |
612 | |||
613 | EXPORT_SYMBOL(dib8000_set_wbd_ref); | 643 | EXPORT_SYMBOL(dib8000_set_wbd_ref); |
644 | |||
614 | static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw) | 645 | static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw) |
615 | { | 646 | { |
616 | dprintk("ifreq: %d %x, inversion: %d", bw->ifreq, bw->ifreq, bw->ifreq >> 25); | 647 | dprintk("ifreq: %d %x, inversion: %d", bw->ifreq, bw->ifreq, bw->ifreq >> 25); |
@@ -685,20 +716,23 @@ static void dib8000_reset_pll(struct dib8000_state *state) | |||
685 | } | 716 | } |
686 | 717 | ||
687 | int dib8000_update_pll(struct dvb_frontend *fe, | 718 | int dib8000_update_pll(struct dvb_frontend *fe, |
688 | struct dibx000_bandwidth_config *pll) | 719 | struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio) |
689 | { | 720 | { |
690 | struct dib8000_state *state = fe->demodulator_priv; | 721 | struct dib8000_state *state = fe->demodulator_priv; |
691 | u16 reg_1857, reg_1856 = dib8000_read_word(state, 1856); | 722 | u16 reg_1857, reg_1856 = dib8000_read_word(state, 1856); |
692 | u8 loopdiv, prediv; | 723 | u8 loopdiv, prediv, oldprediv = state->cfg.pll->pll_prediv ; |
693 | u32 internal, xtal; | 724 | u32 internal, xtal; |
694 | 725 | ||
695 | /* get back old values */ | 726 | /* get back old values */ |
696 | prediv = reg_1856 & 0x3f; | 727 | prediv = reg_1856 & 0x3f; |
697 | loopdiv = (reg_1856 >> 6) & 0x3f; | 728 | loopdiv = (reg_1856 >> 6) & 0x3f; |
698 | 729 | ||
699 | if ((pll != NULL) && (pll->pll_prediv != prediv || | 730 | if ((pll == NULL) || (pll->pll_prediv == prediv && |
700 | pll->pll_ratio != loopdiv)) { | 731 | pll->pll_ratio == loopdiv)) |
701 | dprintk("Updating pll (prediv: old = %d new = %d ; loopdiv : old = %d new = %d)", prediv, pll->pll_prediv, loopdiv, pll->pll_ratio); | 732 | return -EINVAL; |
733 | |||
734 | dprintk("Updating pll (prediv: old = %d new = %d ; loopdiv : old = %d new = %d)", prediv, pll->pll_prediv, loopdiv, pll->pll_ratio); | ||
735 | if (state->revision == 0x8090) { | ||
702 | reg_1856 &= 0xf000; | 736 | reg_1856 &= 0xf000; |
703 | reg_1857 = dib8000_read_word(state, 1857); | 737 | reg_1857 = dib8000_read_word(state, 1857); |
704 | /* disable PLL */ | 738 | /* disable PLL */ |
@@ -729,10 +763,33 @@ int dib8000_update_pll(struct dvb_frontend *fe, | |||
729 | reg_1856 = dib8000_read_word(state, 1856); | 763 | reg_1856 = dib8000_read_word(state, 1856); |
730 | dprintk("PLL Updated with prediv = %d and loopdiv = %d", | 764 | dprintk("PLL Updated with prediv = %d and loopdiv = %d", |
731 | reg_1856&0x3f, (reg_1856>>6)&0x3f); | 765 | reg_1856&0x3f, (reg_1856>>6)&0x3f); |
766 | } else { | ||
767 | if (bw != state->current_demod_bw) { | ||
768 | /** Bandwidth change => force PLL update **/ | ||
769 | dprintk("PLL: Bandwidth Change %d MHz -> %d MHz (prediv: %d->%d)", state->current_demod_bw / 1000, bw / 1000, oldprediv, state->cfg.pll->pll_prediv); | ||
770 | |||
771 | if (state->cfg.pll->pll_prediv != oldprediv) { | ||
772 | /** Full PLL change only if prediv is changed **/ | ||
773 | |||
774 | /** full update => bypass and reconfigure **/ | ||
775 | dprintk("PLL: New Setting for %d MHz Bandwidth (prediv: %d, ratio: %d)", bw/1000, state->cfg.pll->pll_prediv, state->cfg.pll->pll_ratio); | ||
776 | dib8000_write_word(state, 902, dib8000_read_word(state, 902) | (1<<3)); /* bypass PLL */ | ||
777 | dib8000_reset_pll(state); | ||
778 | dib8000_write_word(state, 898, 0x0004); /* sad */ | ||
779 | } else | ||
780 | ratio = state->cfg.pll->pll_ratio; | ||
732 | 781 | ||
733 | return 0; | 782 | state->current_demod_bw = bw; |
734 | } | 783 | } |
735 | return -EINVAL; | 784 | |
785 | if (ratio != 0) { | ||
786 | /** ratio update => only change ratio **/ | ||
787 | dprintk("PLL: Update ratio (prediv: %d, ratio: %d)", state->cfg.pll->pll_prediv, ratio); | ||
788 | dib8000_write_word(state, 901, (state->cfg.pll->pll_prediv << 8) | (ratio << 0)); /* only the PLL ratio is updated. */ | ||
789 | } | ||
790 | } | ||
791 | |||
792 | return 0; | ||
736 | } | 793 | } |
737 | EXPORT_SYMBOL(dib8000_update_pll); | 794 | EXPORT_SYMBOL(dib8000_update_pll); |
738 | 795 | ||
@@ -928,7 +985,7 @@ static int dib8000_reset(struct dvb_frontend *fe) | |||
928 | dib8000_set_power_mode(state, DIB8000_POWER_ALL); | 985 | dib8000_set_power_mode(state, DIB8000_POWER_ALL); |
929 | 986 | ||
930 | /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */ | 987 | /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */ |
931 | dib8000_set_adc_state(state, DIBX000_VBG_ENABLE); | 988 | dib8000_set_adc_state(state, DIBX000_ADC_OFF); |
932 | 989 | ||
933 | /* restart all parts */ | 990 | /* restart all parts */ |
934 | dib8000_write_word(state, 770, 0xffff); | 991 | dib8000_write_word(state, 770, 0xffff); |
@@ -992,12 +1049,11 @@ static int dib8000_reset(struct dvb_frontend *fe) | |||
992 | l = *n++; | 1049 | l = *n++; |
993 | } | 1050 | } |
994 | } | 1051 | } |
995 | if (state->revision != 0x8090) | 1052 | |
996 | dib8000_write_word(state, 903, (0 << 4) | 2); | ||
997 | state->isdbt_cfg_loaded = 0; | 1053 | state->isdbt_cfg_loaded = 0; |
998 | 1054 | ||
999 | //div_cfg override for special configs | 1055 | //div_cfg override for special configs |
1000 | if (state->cfg.div_cfg != 0) | 1056 | if ((state->revision != 8090) && (state->cfg.div_cfg != 0)) |
1001 | dib8000_write_word(state, 903, state->cfg.div_cfg); | 1057 | dib8000_write_word(state, 903, state->cfg.div_cfg); |
1002 | 1058 | ||
1003 | /* unforce divstr regardless whether i2c enumeration was done or not */ | 1059 | /* unforce divstr regardless whether i2c enumeration was done or not */ |
@@ -1006,10 +1062,12 @@ static int dib8000_reset(struct dvb_frontend *fe) | |||
1006 | dib8000_set_bandwidth(fe, 6000); | 1062 | dib8000_set_bandwidth(fe, 6000); |
1007 | 1063 | ||
1008 | dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON); | 1064 | dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON); |
1009 | if (state->revision != 0x8090) { | 1065 | dib8000_sad_calib(state); |
1010 | dib8000_sad_calib(state); | 1066 | if (state->revision != 0x8090) |
1011 | dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF); | 1067 | dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF); |
1012 | } | 1068 | |
1069 | /* ber_rs_len = 3 */ | ||
1070 | dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5)); | ||
1013 | 1071 | ||
1014 | dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY); | 1072 | dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY); |
1015 | 1073 | ||
@@ -1441,6 +1499,7 @@ static int dib8096p_set_output_mode(struct dvb_frontend *fe, int mode) | |||
1441 | u8 prefer_mpeg_mux_use = 1; | 1499 | u8 prefer_mpeg_mux_use = 1; |
1442 | int ret = 0; | 1500 | int ret = 0; |
1443 | 1501 | ||
1502 | state->output_mode = mode; | ||
1444 | dib8096p_host_bus_drive(state, 1); | 1503 | dib8096p_host_bus_drive(state, 1); |
1445 | 1504 | ||
1446 | fifo_threshold = 1792; | 1505 | fifo_threshold = 1792; |
@@ -1879,782 +1938,637 @@ static const u16 adc_target_16dB[11] = { | |||
1879 | }; | 1938 | }; |
1880 | static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 }; | 1939 | static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 }; |
1881 | 1940 | ||
1882 | static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosearching) | 1941 | static u16 dib8000_set_layer(struct dib8000_state *state, u8 layer_index, u16 max_constellation) |
1883 | { | 1942 | { |
1884 | u16 mode, max_constellation, seg_diff_mask = 0, nbseg_diff = 0; | 1943 | u8 cr, constellation, time_intlv; |
1885 | u8 guard, crate, constellation, timeI; | ||
1886 | u16 i, coeff[4], P_cfr_left_edge = 0, P_cfr_right_edge = 0, seg_mask13 = 0x1fff; // All 13 segments enabled | ||
1887 | const s16 *ncoeff = NULL, *ana_fe; | ||
1888 | u16 tmcc_pow = 0; | ||
1889 | u16 coff_pow = 0x2800; | ||
1890 | u16 init_prbs = 0xfff; | ||
1891 | u16 ana_gain = 0; | ||
1892 | |||
1893 | if (state->revision == 0x8090) | ||
1894 | dib8000_init_sdram(state); | ||
1895 | |||
1896 | if (state->ber_monitored_layer != LAYER_ALL) | ||
1897 | dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & 0x60) | state->ber_monitored_layer); | ||
1898 | else | ||
1899 | dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60); | ||
1900 | |||
1901 | i = dib8000_read_word(state, 26) & 1; // P_dds_invspec | ||
1902 | dib8000_write_word(state, 26, state->fe[0]->dtv_property_cache.inversion^i); | ||
1903 | |||
1904 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) { | ||
1905 | //compute new dds_freq for the seg and adjust prbs | ||
1906 | int seg_offset = | ||
1907 | state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx - | ||
1908 | (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) - | ||
1909 | (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2); | ||
1910 | int clk = state->cfg.pll->internal; | ||
1911 | u32 segtodds = ((u32) (430 << 23) / clk) << 3; // segtodds = SegBW / Fclk * pow(2,26) | ||
1912 | int dds_offset = seg_offset * segtodds; | ||
1913 | int new_dds, sub_channel; | ||
1914 | if ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) | ||
1915 | dds_offset -= (int)(segtodds / 2); | ||
1916 | |||
1917 | if (state->cfg.pll->ifreq == 0) { | ||
1918 | if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0) { | ||
1919 | dib8000_write_word(state, 26, dib8000_read_word(state, 26) | 1); | ||
1920 | new_dds = dds_offset; | ||
1921 | } else | ||
1922 | new_dds = dds_offset; | ||
1923 | |||
1924 | // We shift tuning frequency if the wanted segment is : | ||
1925 | // - the segment of center frequency with an odd total number of segments | ||
1926 | // - the segment to the left of center frequency with an even total number of segments | ||
1927 | // - the segment to the right of center frequency with an even total number of segments | ||
1928 | if ((state->fe[0]->dtv_property_cache.delivery_system == SYS_ISDBT) | ||
1929 | && (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) | ||
1930 | && (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) | ||
1931 | && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx == | ||
1932 | ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))) | ||
1933 | || (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) | ||
1934 | && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx == (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2))) | ||
1935 | || (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) | ||
1936 | && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx == | ||
1937 | ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))) | ||
1938 | )) { | ||
1939 | new_dds -= ((u32) (850 << 22) / clk) << 4; // new_dds = 850 (freq shift in KHz) / Fclk * pow(2,26) | ||
1940 | } | ||
1941 | } else { | ||
1942 | if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0) | ||
1943 | new_dds = state->cfg.pll->ifreq - dds_offset; | ||
1944 | else | ||
1945 | new_dds = state->cfg.pll->ifreq + dds_offset; | ||
1946 | } | ||
1947 | dib8000_write_word(state, 27, (u16) ((new_dds >> 16) & 0x01ff)); | ||
1948 | dib8000_write_word(state, 28, (u16) (new_dds & 0xffff)); | ||
1949 | if (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) | ||
1950 | sub_channel = ((state->fe[0]->dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset) + 1) % 41) / 3; | ||
1951 | else | ||
1952 | sub_channel = ((state->fe[0]->dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset)) % 41) / 3; | ||
1953 | sub_channel -= 6; | ||
1954 | |||
1955 | if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K | ||
1956 | || state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_4K) { | ||
1957 | dib8000_write_word(state, 219, dib8000_read_word(state, 219) | 0x1); //adp_pass =1 | ||
1958 | dib8000_write_word(state, 190, dib8000_read_word(state, 190) | (0x1 << 14)); //pha3_force_pha_shift = 1 | ||
1959 | } else { | ||
1960 | dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); //adp_pass =0 | ||
1961 | dib8000_write_word(state, 190, dib8000_read_word(state, 190) & 0xbfff); //pha3_force_pha_shift = 0 | ||
1962 | } | ||
1963 | |||
1964 | switch (state->fe[0]->dtv_property_cache.transmission_mode) { | ||
1965 | case TRANSMISSION_MODE_2K: | ||
1966 | switch (sub_channel) { | ||
1967 | case -6: | ||
1968 | init_prbs = 0x0; | ||
1969 | break; // 41, 0, 1 | ||
1970 | case -5: | ||
1971 | init_prbs = 0x423; | ||
1972 | break; // 02~04 | ||
1973 | case -4: | ||
1974 | init_prbs = 0x9; | ||
1975 | break; // 05~07 | ||
1976 | case -3: | ||
1977 | init_prbs = 0x5C7; | ||
1978 | break; // 08~10 | ||
1979 | case -2: | ||
1980 | init_prbs = 0x7A6; | ||
1981 | break; // 11~13 | ||
1982 | case -1: | ||
1983 | init_prbs = 0x3D8; | ||
1984 | break; // 14~16 | ||
1985 | case 0: | ||
1986 | init_prbs = 0x527; | ||
1987 | break; // 17~19 | ||
1988 | case 1: | ||
1989 | init_prbs = 0x7FF; | ||
1990 | break; // 20~22 | ||
1991 | case 2: | ||
1992 | init_prbs = 0x79B; | ||
1993 | break; // 23~25 | ||
1994 | case 3: | ||
1995 | init_prbs = 0x3D6; | ||
1996 | break; // 26~28 | ||
1997 | case 4: | ||
1998 | init_prbs = 0x3A2; | ||
1999 | break; // 29~31 | ||
2000 | case 5: | ||
2001 | init_prbs = 0x53B; | ||
2002 | break; // 32~34 | ||
2003 | case 6: | ||
2004 | init_prbs = 0x2F4; | ||
2005 | break; // 35~37 | ||
2006 | default: | ||
2007 | case 7: | ||
2008 | init_prbs = 0x213; | ||
2009 | break; // 38~40 | ||
2010 | } | ||
2011 | break; | ||
2012 | 1944 | ||
2013 | case TRANSMISSION_MODE_4K: | 1945 | switch (state->fe[0]->dtv_property_cache.layer[layer_index].modulation) { |
2014 | switch (sub_channel) { | 1946 | case DQPSK: |
2015 | case -6: | ||
2016 | init_prbs = 0x0; | ||
2017 | break; // 41, 0, 1 | ||
2018 | case -5: | ||
2019 | init_prbs = 0x208; | ||
2020 | break; // 02~04 | ||
2021 | case -4: | ||
2022 | init_prbs = 0xC3; | ||
2023 | break; // 05~07 | ||
2024 | case -3: | ||
2025 | init_prbs = 0x7B9; | ||
2026 | break; // 08~10 | ||
2027 | case -2: | ||
2028 | init_prbs = 0x423; | ||
2029 | break; // 11~13 | ||
2030 | case -1: | ||
2031 | init_prbs = 0x5C7; | ||
2032 | break; // 14~16 | ||
2033 | case 0: | ||
2034 | init_prbs = 0x3D8; | ||
2035 | break; // 17~19 | ||
2036 | case 1: | ||
2037 | init_prbs = 0x7FF; | ||
2038 | break; // 20~22 | ||
2039 | case 2: | ||
2040 | init_prbs = 0x3D6; | ||
2041 | break; // 23~25 | ||
2042 | case 3: | ||
2043 | init_prbs = 0x53B; | ||
2044 | break; // 26~28 | ||
2045 | case 4: | ||
2046 | init_prbs = 0x213; | ||
2047 | break; // 29~31 | ||
2048 | case 5: | ||
2049 | init_prbs = 0x29; | ||
2050 | break; // 32~34 | ||
2051 | case 6: | ||
2052 | init_prbs = 0xD0; | ||
2053 | break; // 35~37 | ||
2054 | default: | ||
2055 | case 7: | ||
2056 | init_prbs = 0x48E; | ||
2057 | break; // 38~40 | ||
2058 | } | ||
2059 | break; | ||
2060 | |||
2061 | default: | ||
2062 | case TRANSMISSION_MODE_8K: | ||
2063 | switch (sub_channel) { | ||
2064 | case -6: | ||
2065 | init_prbs = 0x0; | ||
2066 | break; // 41, 0, 1 | ||
2067 | case -5: | ||
2068 | init_prbs = 0x740; | ||
2069 | break; // 02~04 | ||
2070 | case -4: | ||
2071 | init_prbs = 0x069; | ||
2072 | break; // 05~07 | ||
2073 | case -3: | ||
2074 | init_prbs = 0x7DD; | ||
2075 | break; // 08~10 | ||
2076 | case -2: | ||
2077 | init_prbs = 0x208; | ||
2078 | break; // 11~13 | ||
2079 | case -1: | ||
2080 | init_prbs = 0x7B9; | ||
2081 | break; // 14~16 | ||
2082 | case 0: | ||
2083 | init_prbs = 0x5C7; | ||
2084 | break; // 17~19 | ||
2085 | case 1: | ||
2086 | init_prbs = 0x7FF; | ||
2087 | break; // 20~22 | ||
2088 | case 2: | ||
2089 | init_prbs = 0x53B; | ||
2090 | break; // 23~25 | ||
2091 | case 3: | ||
2092 | init_prbs = 0x29; | ||
2093 | break; // 26~28 | ||
2094 | case 4: | ||
2095 | init_prbs = 0x48E; | ||
2096 | break; // 29~31 | ||
2097 | case 5: | ||
2098 | init_prbs = 0x4C4; | ||
2099 | break; // 32~34 | ||
2100 | case 6: | ||
2101 | init_prbs = 0x367; | ||
2102 | break; // 33~37 | ||
2103 | default: | ||
2104 | case 7: | ||
2105 | init_prbs = 0x684; | ||
2106 | break; // 38~40 | ||
2107 | } | ||
2108 | break; | ||
2109 | } | ||
2110 | } else { | ||
2111 | dib8000_write_word(state, 27, (u16) ((state->cfg.pll->ifreq >> 16) & 0x01ff)); | ||
2112 | dib8000_write_word(state, 28, (u16) (state->cfg.pll->ifreq & 0xffff)); | ||
2113 | dib8000_write_word(state, 26, (u16) ((state->cfg.pll->ifreq >> 25) & 0x0003)); | ||
2114 | } | ||
2115 | /*P_mode == ?? */ | ||
2116 | dib8000_write_word(state, 10, (seq << 4)); | ||
2117 | // dib8000_write_word(state, 287, (dib8000_read_word(state, 287) & 0xe000) | 0x1000); | ||
2118 | |||
2119 | switch (state->fe[0]->dtv_property_cache.guard_interval) { | ||
2120 | case GUARD_INTERVAL_1_32: | ||
2121 | guard = 0; | ||
2122 | break; | ||
2123 | case GUARD_INTERVAL_1_16: | ||
2124 | guard = 1; | ||
2125 | break; | ||
2126 | case GUARD_INTERVAL_1_8: | ||
2127 | guard = 2; | ||
2128 | break; | ||
2129 | case GUARD_INTERVAL_1_4: | ||
2130 | default: | ||
2131 | guard = 3; | ||
2132 | break; | ||
2133 | } | ||
2134 | |||
2135 | dib8000_write_word(state, 1, (init_prbs << 2) | (guard & 0x3)); // ADDR 1 | ||
2136 | |||
2137 | max_constellation = DQPSK; | ||
2138 | for (i = 0; i < 3; i++) { | ||
2139 | switch (state->fe[0]->dtv_property_cache.layer[i].modulation) { | ||
2140 | case DQPSK: | ||
2141 | constellation = 0; | 1947 | constellation = 0; |
2142 | break; | 1948 | break; |
2143 | case QPSK: | 1949 | case QPSK: |
2144 | constellation = 1; | 1950 | constellation = 1; |
2145 | break; | 1951 | break; |
2146 | case QAM_16: | 1952 | case QAM_16: |
2147 | constellation = 2; | 1953 | constellation = 2; |
2148 | break; | 1954 | break; |
2149 | case QAM_64: | 1955 | case QAM_64: |
2150 | default: | 1956 | default: |
2151 | constellation = 3; | 1957 | constellation = 3; |
2152 | break; | 1958 | break; |
2153 | } | 1959 | } |
2154 | 1960 | ||
2155 | switch (state->fe[0]->dtv_property_cache.layer[i].fec) { | 1961 | switch (state->fe[0]->dtv_property_cache.layer[layer_index].fec) { |
2156 | case FEC_1_2: | 1962 | case FEC_1_2: |
2157 | crate = 1; | 1963 | cr = 1; |
2158 | break; | 1964 | break; |
2159 | case FEC_2_3: | 1965 | case FEC_2_3: |
2160 | crate = 2; | 1966 | cr = 2; |
2161 | break; | 1967 | break; |
2162 | case FEC_3_4: | 1968 | case FEC_3_4: |
2163 | crate = 3; | 1969 | cr = 3; |
2164 | break; | 1970 | break; |
2165 | case FEC_5_6: | 1971 | case FEC_5_6: |
2166 | crate = 5; | 1972 | cr = 5; |
2167 | break; | 1973 | break; |
2168 | case FEC_7_8: | 1974 | case FEC_7_8: |
2169 | default: | 1975 | default: |
2170 | crate = 7; | 1976 | cr = 7; |
2171 | break; | 1977 | break; |
2172 | } | 1978 | } |
2173 | 1979 | ||
2174 | if ((state->fe[0]->dtv_property_cache.layer[i].interleaving > 0) && | 1980 | if ((state->fe[0]->dtv_property_cache.layer[layer_index].interleaving > 0) && ((state->fe[0]->dtv_property_cache.layer[layer_index].interleaving <= 3) || (state->fe[0]->dtv_property_cache.layer[layer_index].interleaving == 4 && state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1))) |
2175 | ((state->fe[0]->dtv_property_cache.layer[i].interleaving <= 3) || | 1981 | time_intlv = state->fe[0]->dtv_property_cache.layer[layer_index].interleaving; |
2176 | (state->fe[0]->dtv_property_cache.layer[i].interleaving == 4 && state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1)) | 1982 | else |
2177 | ) | 1983 | time_intlv = 0; |
2178 | timeI = state->fe[0]->dtv_property_cache.layer[i].interleaving; | 1984 | |
2179 | else | 1985 | dib8000_write_word(state, 2 + layer_index, (constellation << 10) | ((state->fe[0]->dtv_property_cache.layer[layer_index].segment_count & 0xf) << 6) | (cr << 3) | time_intlv); |
2180 | timeI = 0; | 1986 | if (state->fe[0]->dtv_property_cache.layer[layer_index].segment_count > 0) { |
2181 | dib8000_write_word(state, 2 + i, (constellation << 10) | ((state->fe[0]->dtv_property_cache.layer[i].segment_count & 0xf) << 6) | | 1987 | switch (max_constellation) { |
2182 | (crate << 3) | timeI); | 1988 | case DQPSK: |
2183 | if (state->fe[0]->dtv_property_cache.layer[i].segment_count > 0) { | 1989 | case QPSK: |
2184 | switch (max_constellation) { | 1990 | if (state->fe[0]->dtv_property_cache.layer[layer_index].modulation == QAM_16 || state->fe[0]->dtv_property_cache.layer[layer_index].modulation == QAM_64) |
2185 | case DQPSK: | 1991 | max_constellation = state->fe[0]->dtv_property_cache.layer[layer_index].modulation; |
2186 | case QPSK: | ||
2187 | if (state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_16 || | ||
2188 | state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_64) | ||
2189 | max_constellation = state->fe[0]->dtv_property_cache.layer[i].modulation; | ||
2190 | break; | 1992 | break; |
2191 | case QAM_16: | 1993 | case QAM_16: |
2192 | if (state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_64) | 1994 | if (state->fe[0]->dtv_property_cache.layer[layer_index].modulation == QAM_64) |
2193 | max_constellation = state->fe[0]->dtv_property_cache.layer[i].modulation; | 1995 | max_constellation = state->fe[0]->dtv_property_cache.layer[layer_index].modulation; |
2194 | break; | 1996 | break; |
2195 | } | ||
2196 | } | 1997 | } |
2197 | } | 1998 | } |
2198 | 1999 | ||
2199 | mode = fft_to_mode(state); | 2000 | return max_constellation; |
2001 | } | ||
2200 | 2002 | ||
2201 | //dib8000_write_word(state, 5, 13); /*p_last_seg = 13*/ | 2003 | static const u16 adp_Q64[4] = {0x0148, 0xfff0, 0x00a4, 0xfff8}; /* P_adp_regul_cnt 0.04, P_adp_noise_cnt -0.002, P_adp_regul_ext 0.02, P_adp_noise_ext -0.001 */ |
2004 | static const u16 adp_Q16[4] = {0x023d, 0xffdf, 0x00a4, 0xfff0}; /* P_adp_regul_cnt 0.07, P_adp_noise_cnt -0.004, P_adp_regul_ext 0.02, P_adp_noise_ext -0.002 */ | ||
2005 | static const u16 adp_Qdefault[4] = {0x099a, 0xffae, 0x0333, 0xfff8}; /* P_adp_regul_cnt 0.3, P_adp_noise_cnt -0.01, P_adp_regul_ext 0.1, P_adp_noise_ext -0.002 */ | ||
2006 | static u16 dib8000_adp_fine_tune(struct dib8000_state *state, u16 max_constellation) | ||
2007 | { | ||
2008 | u16 i, ana_gain = 0; | ||
2009 | const u16 *adp; | ||
2202 | 2010 | ||
2203 | dib8000_write_word(state, 274, (dib8000_read_word(state, 274) & 0xffcf) | | 2011 | /* channel estimation fine configuration */ |
2204 | ((state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 5) | ((state->fe[0]->dtv_property_cache. | 2012 | switch (max_constellation) { |
2205 | isdbt_sb_mode & 1) << 4)); | 2013 | case QAM_64: |
2014 | ana_gain = 0x7; | ||
2015 | adp = &adp_Q64[0]; | ||
2016 | break; | ||
2017 | case QAM_16: | ||
2018 | ana_gain = 0x7; | ||
2019 | adp = &adp_Q16[0]; | ||
2020 | break; | ||
2021 | default: | ||
2022 | ana_gain = 0; | ||
2023 | adp = &adp_Qdefault[0]; | ||
2024 | break; | ||
2025 | } | ||
2206 | 2026 | ||
2207 | dprintk("mode = %d ; guard = %d", mode, state->fe[0]->dtv_property_cache.guard_interval); | 2027 | for (i = 0; i < 4; i++) |
2028 | dib8000_write_word(state, 215 + i, adp[i]); | ||
2208 | 2029 | ||
2209 | /* signal optimization parameter */ | 2030 | return ana_gain; |
2031 | } | ||
2210 | 2032 | ||
2211 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception) { | 2033 | static void dib8000_update_ana_gain(struct dib8000_state *state, u16 ana_gain) |
2212 | seg_diff_mask = (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) << permu_seg[0]; | 2034 | { |
2213 | for (i = 1; i < 3; i++) | 2035 | u16 i; |
2214 | nbseg_diff += | 2036 | |
2215 | (state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count; | 2037 | dib8000_write_word(state, 116, ana_gain); |
2216 | for (i = 0; i < nbseg_diff; i++) | 2038 | |
2217 | seg_diff_mask |= 1 << permu_seg[i + 1]; | 2039 | /* update ADC target depending on ana_gain */ |
2218 | } else { | 2040 | if (ana_gain) { /* set -16dB ADC target for ana_gain=-1 */ |
2219 | for (i = 0; i < 3; i++) | 2041 | for (i = 0; i < 10; i++) |
2220 | nbseg_diff += | 2042 | dib8000_write_word(state, 80 + i, adc_target_16dB[i]); |
2221 | (state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count; | 2043 | } else { /* set -22dB ADC target for ana_gain=0 */ |
2222 | for (i = 0; i < nbseg_diff; i++) | 2044 | for (i = 0; i < 10; i++) |
2223 | seg_diff_mask |= 1 << permu_seg[i]; | 2045 | dib8000_write_word(state, 80 + i, adc_target_16dB[i] - 355); |
2224 | } | 2046 | } |
2225 | dprintk("nbseg_diff = %X (%d)", seg_diff_mask, seg_diff_mask); | 2047 | } |
2226 | 2048 | ||
2227 | state->differential_constellation = (seg_diff_mask != 0); | 2049 | static void dib8000_load_ana_fe_coefs(struct dib8000_state *state, const s16 *ana_fe) |
2228 | if (state->revision != 0x8090) | 2050 | { |
2229 | dib8000_set_diversity_in(state->fe[0], state->diversity_onoff); | 2051 | u16 mode = 0; |
2230 | else | ||
2231 | dib8096p_set_diversity_in(state->fe[0], state->diversity_onoff); | ||
2232 | 2052 | ||
2233 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | 2053 | if (state->isdbt_cfg_loaded == 0) |
2234 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1) | 2054 | for (mode = 0; mode < 24; mode++) |
2235 | seg_mask13 = 0x00E0; | 2055 | dib8000_write_word(state, 117 + mode, ana_fe[mode]); |
2236 | else // 1-segment | 2056 | } |
2237 | seg_mask13 = 0x0040; | 2057 | |
2238 | } else | 2058 | static const u16 lut_prbs_2k[14] = { |
2239 | seg_mask13 = 0x1fff; | 2059 | 0, 0x423, 0x009, 0x5C7, 0x7A6, 0x3D8, 0x527, 0x7FF, 0x79B, 0x3D6, 0x3A2, 0x53B, 0x2F4, 0x213 |
2060 | }; | ||
2061 | static const u16 lut_prbs_4k[14] = { | ||
2062 | 0, 0x208, 0x0C3, 0x7B9, 0x423, 0x5C7, 0x3D8, 0x7FF, 0x3D6, 0x53B, 0x213, 0x029, 0x0D0, 0x48E | ||
2063 | }; | ||
2064 | static const u16 lut_prbs_8k[14] = { | ||
2065 | 0, 0x740, 0x069, 0x7DD, 0x208, 0x7B9, 0x5C7, 0x7FF, 0x53B, 0x029, 0x48E, 0x4C4, 0x367, 0x684 | ||
2066 | }; | ||
2240 | 2067 | ||
2241 | // WRITE: Mode & Diff mask | 2068 | static u16 dib8000_get_init_prbs(struct dib8000_state *state, u16 subchannel) |
2242 | dib8000_write_word(state, 0, (mode << 13) | seg_diff_mask); | 2069 | { |
2070 | int sub_channel_prbs_group = 0; | ||
2243 | 2071 | ||
2244 | if ((seg_diff_mask) || (state->fe[0]->dtv_property_cache.isdbt_sb_mode)) | 2072 | sub_channel_prbs_group = (subchannel / 3) + 1; |
2245 | dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200); | 2073 | dprintk("sub_channel_prbs_group = %d , subchannel =%d prbs = 0x%04x", sub_channel_prbs_group, subchannel, lut_prbs_8k[sub_channel_prbs_group]); |
2246 | else | 2074 | |
2247 | dib8000_write_word(state, 268, (2 << 9) | 39); //init value | 2075 | switch (state->fe[0]->dtv_property_cache.transmission_mode) { |
2076 | case TRANSMISSION_MODE_2K: | ||
2077 | return lut_prbs_2k[sub_channel_prbs_group]; | ||
2078 | case TRANSMISSION_MODE_4K: | ||
2079 | return lut_prbs_4k[sub_channel_prbs_group]; | ||
2080 | default: | ||
2081 | case TRANSMISSION_MODE_8K: | ||
2082 | return lut_prbs_8k[sub_channel_prbs_group]; | ||
2083 | } | ||
2084 | } | ||
2248 | 2085 | ||
2249 | // ---- SMALL ---- | 2086 | static void dib8000_set_13seg_channel(struct dib8000_state *state) |
2250 | // P_small_seg_diff | 2087 | { |
2251 | dib8000_write_word(state, 352, seg_diff_mask); // ADDR 352 | 2088 | u16 i; |
2089 | u16 coff_pow = 0x2800; | ||
2252 | 2090 | ||
2253 | dib8000_write_word(state, 353, seg_mask13); // ADDR 353 | 2091 | state->seg_mask = 0x1fff; /* All 13 segments enabled */ |
2254 | 2092 | ||
2255 | /* // P_small_narrow_band=0, P_small_last_seg=13, P_small_offset_num_car=5 */ | 2093 | /* ---- COFF ---- Carloff, the most robust --- */ |
2094 | if (state->isdbt_cfg_loaded == 0) { /* if not Sound Broadcasting mode : put default values for 13 segments */ | ||
2095 | dib8000_write_word(state, 180, (16 << 6) | 9); | ||
2096 | dib8000_write_word(state, 187, (4 << 12) | (8 << 5) | 0x2); | ||
2097 | coff_pow = 0x2800; | ||
2098 | for (i = 0; i < 6; i++) | ||
2099 | dib8000_write_word(state, 181+i, coff_pow); | ||
2100 | |||
2101 | /* P_ctrl_corm_thres4pre_freq_inh=1, P_ctrl_pre_freq_mode_sat=1 */ | ||
2102 | /* P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 3, P_pre_freq_win_len=1 */ | ||
2103 | dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (3 << 5) | 1); | ||
2104 | |||
2105 | /* P_ctrl_pre_freq_win_len=8, P_ctrl_pre_freq_thres_lockin=6 */ | ||
2106 | dib8000_write_word(state, 340, (8 << 6) | (6 << 0)); | ||
2107 | /* P_ctrl_pre_freq_thres_lockout=4, P_small_use_tmcc/ac/cp=1 */ | ||
2108 | dib8000_write_word(state, 341, (4 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); | ||
2109 | |||
2110 | dib8000_write_word(state, 228, 0); /* default value */ | ||
2111 | dib8000_write_word(state, 265, 31); /* default value */ | ||
2112 | dib8000_write_word(state, 205, 0x200f); /* init value */ | ||
2113 | } | ||
2114 | |||
2115 | /* | ||
2116 | * make the cpil_coff_lock more robust but slower p_coff_winlen | ||
2117 | * 6bits; p_coff_thres_lock 6bits (for coff lock if needed) | ||
2118 | */ | ||
2119 | |||
2120 | if (state->cfg.pll->ifreq == 0) | ||
2121 | dib8000_write_word(state, 266, ~state->seg_mask | state->seg_diff_mask | 0x40); /* P_equal_noise_seg_inh */ | ||
2122 | |||
2123 | dib8000_load_ana_fe_coefs(state, ana_fe_coeff_13seg); | ||
2124 | } | ||
2125 | |||
2126 | static void dib8000_set_subchannel_prbs(struct dib8000_state *state, u16 init_prbs) | ||
2127 | { | ||
2128 | u16 reg_1; | ||
2256 | 2129 | ||
2257 | // ---- SMALL ---- | 2130 | reg_1 = dib8000_read_word(state, 1); |
2258 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | 2131 | dib8000_write_word(state, 1, (init_prbs << 2) | (reg_1 & 0x3)); /* ADDR 1 */ |
2132 | } | ||
2133 | |||
2134 | static void dib8000_small_fine_tune(struct dib8000_state *state) | ||
2135 | { | ||
2136 | u16 i; | ||
2137 | const s16 *ncoeff; | ||
2138 | |||
2139 | dib8000_write_word(state, 352, state->seg_diff_mask); | ||
2140 | dib8000_write_word(state, 353, state->seg_mask); | ||
2141 | |||
2142 | /* P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5 */ | ||
2143 | dib8000_write_word(state, 351, (state->fe[0]->dtv_property_cache.isdbt_sb_mode << 9) | (state->fe[0]->dtv_property_cache.isdbt_sb_mode << 8) | (13 << 4) | 5); | ||
2144 | |||
2145 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) { | ||
2146 | /* ---- SMALL ---- */ | ||
2259 | switch (state->fe[0]->dtv_property_cache.transmission_mode) { | 2147 | switch (state->fe[0]->dtv_property_cache.transmission_mode) { |
2260 | case TRANSMISSION_MODE_2K: | 2148 | case TRANSMISSION_MODE_2K: |
2261 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { | 2149 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { /* 1-seg */ |
2262 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) | 2150 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) /* DQPSK */ |
2263 | ncoeff = coeff_2k_sb_1seg_dqpsk; | 2151 | ncoeff = coeff_2k_sb_1seg_dqpsk; |
2264 | else // QPSK or QAM | 2152 | else /* QPSK or QAM */ |
2265 | ncoeff = coeff_2k_sb_1seg; | 2153 | ncoeff = coeff_2k_sb_1seg; |
2266 | } else { // 3-segments | 2154 | } else { /* 3-segments */ |
2267 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { | 2155 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { /* DQPSK on central segment */ |
2268 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) | 2156 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) /* DQPSK on external segments */ |
2269 | ncoeff = coeff_2k_sb_3seg_0dqpsk_1dqpsk; | 2157 | ncoeff = coeff_2k_sb_3seg_0dqpsk_1dqpsk; |
2270 | else // QPSK or QAM on external segments | 2158 | else /* QPSK or QAM on external segments */ |
2271 | ncoeff = coeff_2k_sb_3seg_0dqpsk; | 2159 | ncoeff = coeff_2k_sb_3seg_0dqpsk; |
2272 | } else { // QPSK or QAM on central segment | 2160 | } else { /* QPSK or QAM on central segment */ |
2273 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) | 2161 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) /* DQPSK on external segments */ |
2274 | ncoeff = coeff_2k_sb_3seg_1dqpsk; | 2162 | ncoeff = coeff_2k_sb_3seg_1dqpsk; |
2275 | else // QPSK or QAM on external segments | 2163 | else /* QPSK or QAM on external segments */ |
2276 | ncoeff = coeff_2k_sb_3seg; | 2164 | ncoeff = coeff_2k_sb_3seg; |
2165 | } | ||
2277 | } | 2166 | } |
2278 | } | 2167 | break; |
2279 | break; | ||
2280 | |||
2281 | case TRANSMISSION_MODE_4K: | 2168 | case TRANSMISSION_MODE_4K: |
2282 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { | 2169 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { /* 1-seg */ |
2283 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) | 2170 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) /* DQPSK */ |
2284 | ncoeff = coeff_4k_sb_1seg_dqpsk; | 2171 | ncoeff = coeff_4k_sb_1seg_dqpsk; |
2285 | else // QPSK or QAM | 2172 | else /* QPSK or QAM */ |
2286 | ncoeff = coeff_4k_sb_1seg; | 2173 | ncoeff = coeff_4k_sb_1seg; |
2287 | } else { // 3-segments | 2174 | } else { /* 3-segments */ |
2288 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { | 2175 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { /* DQPSK on central segment */ |
2289 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) { | 2176 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) /* DQPSK on external segments */ |
2290 | ncoeff = coeff_4k_sb_3seg_0dqpsk_1dqpsk; | 2177 | ncoeff = coeff_4k_sb_3seg_0dqpsk_1dqpsk; |
2291 | } else { // QPSK or QAM on external segments | 2178 | else /* QPSK or QAM on external segments */ |
2292 | ncoeff = coeff_4k_sb_3seg_0dqpsk; | 2179 | ncoeff = coeff_4k_sb_3seg_0dqpsk; |
2180 | } else { /* QPSK or QAM on central segment */ | ||
2181 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) /* DQPSK on external segments */ | ||
2182 | ncoeff = coeff_4k_sb_3seg_1dqpsk; | ||
2183 | else /* QPSK or QAM on external segments */ | ||
2184 | ncoeff = coeff_4k_sb_3seg; | ||
2293 | } | 2185 | } |
2294 | } else { // QPSK or QAM on central segment | ||
2295 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) { | ||
2296 | ncoeff = coeff_4k_sb_3seg_1dqpsk; | ||
2297 | } else // QPSK or QAM on external segments | ||
2298 | ncoeff = coeff_4k_sb_3seg; | ||
2299 | } | 2186 | } |
2300 | } | 2187 | break; |
2301 | break; | ||
2302 | |||
2303 | case TRANSMISSION_MODE_AUTO: | 2188 | case TRANSMISSION_MODE_AUTO: |
2304 | case TRANSMISSION_MODE_8K: | 2189 | case TRANSMISSION_MODE_8K: |
2305 | default: | 2190 | default: |
2306 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { | 2191 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { /* 1-seg */ |
2307 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) | 2192 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) /* DQPSK */ |
2308 | ncoeff = coeff_8k_sb_1seg_dqpsk; | 2193 | ncoeff = coeff_8k_sb_1seg_dqpsk; |
2309 | else // QPSK or QAM | 2194 | else /* QPSK or QAM */ |
2310 | ncoeff = coeff_8k_sb_1seg; | 2195 | ncoeff = coeff_8k_sb_1seg; |
2311 | } else { // 3-segments | 2196 | } else { /* 3-segments */ |
2312 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { | 2197 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { /* DQPSK on central segment */ |
2313 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) { | 2198 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) /* DQPSK on external segments */ |
2314 | ncoeff = coeff_8k_sb_3seg_0dqpsk_1dqpsk; | 2199 | ncoeff = coeff_8k_sb_3seg_0dqpsk_1dqpsk; |
2315 | } else { // QPSK or QAM on external segments | 2200 | else /* QPSK or QAM on external segments */ |
2316 | ncoeff = coeff_8k_sb_3seg_0dqpsk; | 2201 | ncoeff = coeff_8k_sb_3seg_0dqpsk; |
2202 | } else { /* QPSK or QAM on central segment */ | ||
2203 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) /* DQPSK on external segments */ | ||
2204 | ncoeff = coeff_8k_sb_3seg_1dqpsk; | ||
2205 | else /* QPSK or QAM on external segments */ | ||
2206 | ncoeff = coeff_8k_sb_3seg; | ||
2317 | } | 2207 | } |
2318 | } else { // QPSK or QAM on central segment | ||
2319 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) { | ||
2320 | ncoeff = coeff_8k_sb_3seg_1dqpsk; | ||
2321 | } else // QPSK or QAM on external segments | ||
2322 | ncoeff = coeff_8k_sb_3seg; | ||
2323 | } | 2208 | } |
2324 | } | 2209 | break; |
2325 | break; | ||
2326 | } | 2210 | } |
2211 | |||
2327 | for (i = 0; i < 8; i++) | 2212 | for (i = 0; i < 8; i++) |
2328 | dib8000_write_word(state, 343 + i, ncoeff[i]); | 2213 | dib8000_write_word(state, 343 + i, ncoeff[i]); |
2329 | } | 2214 | } |
2215 | } | ||
2330 | 2216 | ||
2331 | // P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5 | 2217 | static const u16 coff_thres_1seg[3] = {300, 150, 80}; |
2332 | dib8000_write_word(state, 351, | 2218 | static const u16 coff_thres_3seg[3] = {350, 300, 250}; |
2333 | (state->fe[0]->dtv_property_cache.isdbt_sb_mode << 9) | (state->fe[0]->dtv_property_cache.isdbt_sb_mode << 8) | (13 << 4) | 5); | 2219 | static void dib8000_set_sb_channel(struct dib8000_state *state) |
2220 | { | ||
2221 | const u16 *coff; | ||
2222 | u16 i; | ||
2334 | 2223 | ||
2335 | // ---- COFF ---- | 2224 | if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K || state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_4K) { |
2336 | // Carloff, the most robust | 2225 | dib8000_write_word(state, 219, dib8000_read_word(state, 219) | 0x1); /* adp_pass =1 */ |
2337 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | 2226 | dib8000_write_word(state, 190, dib8000_read_word(state, 190) | (0x1 << 14)); /* pha3_force_pha_shift = 1 */ |
2227 | } else { | ||
2228 | dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); /* adp_pass =0 */ | ||
2229 | dib8000_write_word(state, 190, dib8000_read_word(state, 190) & 0xbfff); /* pha3_force_pha_shift = 0 */ | ||
2230 | } | ||
2338 | 2231 | ||
2339 | // P_coff_cpil_alpha=4, P_coff_inh=0, P_coff_cpil_winlen=64 | 2232 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1) /* 3-segments */ |
2340 | // P_coff_narrow_band=1, P_coff_square_val=1, P_coff_one_seg=~partial_rcpt, P_coff_use_tmcc=1, P_coff_use_ac=1 | 2233 | state->seg_mask = 0x00E0; |
2341 | dib8000_write_word(state, 187, | 2234 | else /* 1-segment */ |
2342 | (4 << 12) | (0 << 11) | (63 << 5) | (0x3 << 3) | ((~state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 2) | 2235 | state->seg_mask = 0x0040; |
2343 | | 0x3); | ||
2344 | 2236 | ||
2345 | /* // P_small_coef_ext_enable = 1 */ | 2237 | dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200); |
2346 | /* dib8000_write_word(state, 351, dib8000_read_word(state, 351) | 0x200); */ | ||
2347 | 2238 | ||
2348 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { | 2239 | /* ---- COFF ---- Carloff, the most robust --- */ |
2240 | /* P_coff_cpil_alpha=4, P_coff_inh=0, P_coff_cpil_winlen=64, P_coff_narrow_band=1, P_coff_square_val=1, P_coff_one_seg=~partial_rcpt, P_coff_use_tmcc=1, P_coff_use_ac=1 */ | ||
2241 | dib8000_write_word(state, 187, (4 << 12) | (0 << 11) | (63 << 5) | (0x3 << 3) | ((~state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 2) | 0x3); | ||
2349 | 2242 | ||
2350 | // P_coff_winlen=63, P_coff_thres_lock=15, P_coff_one_seg_width= (P_mode == 3) , P_coff_one_seg_sym= (P_mode-1) | 2243 | dib8000_write_word(state, 340, (16 << 6) | (8 << 0)); /* P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8 */ |
2351 | if (mode == 3) | 2244 | dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0));/* P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1 */ |
2352 | dib8000_write_word(state, 180, 0x1fcf | ((mode - 1) << 14)); | ||
2353 | else | ||
2354 | dib8000_write_word(state, 180, 0x0fcf | ((mode - 1) << 14)); | ||
2355 | // P_ctrl_corm_thres4pre_freq_inh=1,P_ctrl_pre_freq_mode_sat=1, | ||
2356 | // P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 5, P_pre_freq_win_len=4 | ||
2357 | dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (5 << 5) | 4); | ||
2358 | // P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8 | ||
2359 | dib8000_write_word(state, 340, (16 << 6) | (8 << 0)); | ||
2360 | // P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1 | ||
2361 | dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); | ||
2362 | |||
2363 | // P_coff_corthres_8k, 4k, 2k and P_coff_cpilthres_8k, 4k, 2k | ||
2364 | dib8000_write_word(state, 181, 300); | ||
2365 | dib8000_write_word(state, 182, 150); | ||
2366 | dib8000_write_word(state, 183, 80); | ||
2367 | dib8000_write_word(state, 184, 300); | ||
2368 | dib8000_write_word(state, 185, 150); | ||
2369 | dib8000_write_word(state, 186, 80); | ||
2370 | } else { // Sound Broadcasting mode 3 seg | ||
2371 | // P_coff_one_seg_sym= 1, P_coff_one_seg_width= 1, P_coff_winlen=63, P_coff_thres_lock=15 | ||
2372 | /* if (mode == 3) */ | ||
2373 | /* dib8000_write_word(state, 180, 0x2fca | ((0) << 14)); */ | ||
2374 | /* else */ | ||
2375 | /* dib8000_write_word(state, 180, 0x2fca | ((1) << 14)); */ | ||
2376 | dib8000_write_word(state, 180, 0x1fcf | (1 << 14)); | ||
2377 | |||
2378 | // P_ctrl_corm_thres4pre_freq_inh = 1, P_ctrl_pre_freq_mode_sat=1, | ||
2379 | // P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 4, P_pre_freq_win_len=4 | ||
2380 | dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (4 << 5) | 4); | ||
2381 | // P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8 | ||
2382 | dib8000_write_word(state, 340, (16 << 6) | (8 << 0)); | ||
2383 | //P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1 | ||
2384 | dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); | ||
2385 | |||
2386 | // P_coff_corthres_8k, 4k, 2k and P_coff_cpilthres_8k, 4k, 2k | ||
2387 | dib8000_write_word(state, 181, 350); | ||
2388 | dib8000_write_word(state, 182, 300); | ||
2389 | dib8000_write_word(state, 183, 250); | ||
2390 | dib8000_write_word(state, 184, 350); | ||
2391 | dib8000_write_word(state, 185, 300); | ||
2392 | dib8000_write_word(state, 186, 250); | ||
2393 | } | ||
2394 | 2245 | ||
2395 | } else if (state->isdbt_cfg_loaded == 0) { // if not Sound Broadcasting mode : put default values for 13 segments | 2246 | /* Sound Broadcasting mode 1 seg */ |
2396 | dib8000_write_word(state, 180, (16 << 6) | 9); | 2247 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { |
2397 | dib8000_write_word(state, 187, (4 << 12) | (8 << 5) | 0x2); | 2248 | /* P_coff_winlen=63, P_coff_thres_lock=15, P_coff_one_seg_width = (P_mode == 3) , P_coff_one_seg_sym = (P_mode-1) */ |
2398 | coff_pow = 0x2800; | 2249 | if (state->mode == 3) |
2399 | for (i = 0; i < 6; i++) | 2250 | dib8000_write_word(state, 180, 0x1fcf | ((state->mode - 1) << 14)); |
2400 | dib8000_write_word(state, 181 + i, coff_pow); | 2251 | else |
2252 | dib8000_write_word(state, 180, 0x0fcf | ((state->mode - 1) << 14)); | ||
2401 | 2253 | ||
2402 | // P_ctrl_corm_thres4pre_freq_inh=1, P_ctrl_pre_freq_mode_sat=1, | 2254 | /* P_ctrl_corm_thres4pre_freq_inh=1,P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 5, P_pre_freq_win_len=4 */ |
2403 | // P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 3, P_pre_freq_win_len=1 | 2255 | dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (5 << 5) | 4); |
2404 | dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (3 << 5) | 1); | 2256 | coff = &coff_thres_1seg[0]; |
2257 | } else { /* Sound Broadcasting mode 3 seg */ | ||
2258 | dib8000_write_word(state, 180, 0x1fcf | (1 << 14)); | ||
2259 | /* P_ctrl_corm_thres4pre_freq_inh = 1, P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 4, P_pre_freq_win_len=4 */ | ||
2260 | dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (4 << 5) | 4); | ||
2261 | coff = &coff_thres_3seg[0]; | ||
2262 | } | ||
2405 | 2263 | ||
2406 | // P_ctrl_pre_freq_win_len=8, P_ctrl_pre_freq_thres_lockin=6 | 2264 | dib8000_write_word(state, 228, 1); /* P_2d_mode_byp=1 */ |
2407 | dib8000_write_word(state, 340, (8 << 6) | (6 << 0)); | 2265 | dib8000_write_word(state, 205, dib8000_read_word(state, 205) & 0xfff0); /* P_cspu_win_cut = 0 */ |
2408 | // P_ctrl_pre_freq_thres_lockout=4, P_small_use_tmcc/ac/cp=1 | 2266 | |
2409 | dib8000_write_word(state, 341, (4 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); | 2267 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0 && state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K) |
2268 | dib8000_write_word(state, 265, 15); /* P_equal_noise_sel = 15 */ | ||
2269 | |||
2270 | /* Write COFF thres */ | ||
2271 | for (i = 0 ; i < 3; i++) { | ||
2272 | dib8000_write_word(state, 181+i, coff[i]); | ||
2273 | dib8000_write_word(state, 184+i, coff[i]); | ||
2410 | } | 2274 | } |
2411 | // ---- FFT ---- | ||
2412 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1 && state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) | ||
2413 | dib8000_write_word(state, 178, 64); // P_fft_powrange=64 | ||
2414 | else | ||
2415 | dib8000_write_word(state, 178, 32); // P_fft_powrange=32 | ||
2416 | 2275 | ||
2417 | /* make the cpil_coff_lock more robust but slower p_coff_winlen | 2276 | /* |
2277 | * make the cpil_coff_lock more robust but slower p_coff_winlen | ||
2418 | * 6bits; p_coff_thres_lock 6bits (for coff lock if needed) | 2278 | * 6bits; p_coff_thres_lock 6bits (for coff lock if needed) |
2419 | */ | 2279 | */ |
2420 | /* if ( ( nbseg_diff>0)&&(nbseg_diff<13)) | 2280 | |
2421 | dib8000_write_word(state, 187, (dib8000_read_word(state, 187) & 0xfffb) | (1 << 3)); */ | 2281 | dib8000_write_word(state, 266, ~state->seg_mask | state->seg_diff_mask); /* P_equal_noise_seg_inh */ |
2422 | 2282 | ||
2423 | dib8000_write_word(state, 189, ~seg_mask13 | seg_diff_mask); /* P_lmod4_seg_inh */ | 2283 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) |
2424 | dib8000_write_word(state, 192, ~seg_mask13 | seg_diff_mask); /* P_pha3_seg_inh */ | 2284 | dib8000_write_word(state, 178, 64); /* P_fft_powrange = 64 */ |
2425 | dib8000_write_word(state, 225, ~seg_mask13 | seg_diff_mask); /* P_tac_seg_inh */ | ||
2426 | if ((!state->fe[0]->dtv_property_cache.isdbt_sb_mode) && (state->cfg.pll->ifreq == 0)) | ||
2427 | dib8000_write_word(state, 266, ~seg_mask13 | seg_diff_mask | 0x40); /* P_equal_noise_seg_inh */ | ||
2428 | else | ||
2429 | dib8000_write_word(state, 266, ~seg_mask13 | seg_diff_mask); /* P_equal_noise_seg_inh */ | ||
2430 | dib8000_write_word(state, 287, ~seg_mask13 | 0x1000); /* P_tmcc_seg_inh */ | ||
2431 | //dib8000_write_word(state, 288, ~seg_mask13 | seg_diff_mask); /* P_tmcc_seg_eq_inh */ | ||
2432 | if (!autosearching) | ||
2433 | dib8000_write_word(state, 288, (~seg_mask13 | seg_diff_mask) & 0x1fff); /* P_tmcc_seg_eq_inh */ | ||
2434 | else | 2285 | else |
2435 | dib8000_write_word(state, 288, 0x1fff); //disable equalisation of the tmcc when autosearch to be able to find the DQPSK channels. | 2286 | dib8000_write_word(state, 178, 32); /* P_fft_powrange = 32 */ |
2436 | dprintk("287 = %X (%d)", ~seg_mask13 | 0x1000, ~seg_mask13 | 0x1000); | 2287 | } |
2437 | |||
2438 | dib8000_write_word(state, 211, seg_mask13 & (~seg_diff_mask)); /* P_des_seg_enabled */ | ||
2439 | |||
2440 | /* offset loop parameters */ | ||
2441 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | ||
2442 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) | ||
2443 | /* P_timf_alpha = (11-P_mode), P_corm_alpha=6, P_corm_thres=0x80 */ | ||
2444 | dib8000_write_word(state, 32, ((11 - mode) << 12) | (6 << 8) | 0x40); | ||
2445 | |||
2446 | else // Sound Broadcasting mode 3 seg | ||
2447 | /* P_timf_alpha = (10-P_mode), P_corm_alpha=6, P_corm_thres=0x80 */ | ||
2448 | dib8000_write_word(state, 32, ((10 - mode) << 12) | (6 << 8) | 0x60); | ||
2449 | } else | ||
2450 | // TODO in 13 seg, timf_alpha can always be the same or not ? | ||
2451 | /* P_timf_alpha = (9-P_mode, P_corm_alpha=6, P_corm_thres=0x80 */ | ||
2452 | dib8000_write_word(state, 32, ((9 - mode) << 12) | (6 << 8) | 0x80); | ||
2453 | |||
2454 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | ||
2455 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) | ||
2456 | /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (11-P_mode) */ | ||
2457 | dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (10 - mode)); | ||
2458 | |||
2459 | else // Sound Broadcasting mode 3 seg | ||
2460 | /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (10-P_mode) */ | ||
2461 | dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (9 - mode)); | ||
2462 | } else | ||
2463 | /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = 9 */ | ||
2464 | dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (8 - mode)); | ||
2465 | 2288 | ||
2466 | /* P_dvsy_sync_wait - reuse mode */ | 2289 | static void dib8000_set_isdbt_common_channel(struct dib8000_state *state, u8 seq, u8 autosearching) |
2467 | switch (state->fe[0]->dtv_property_cache.transmission_mode) { | 2290 | { |
2468 | case TRANSMISSION_MODE_8K: | 2291 | u16 p_cfr_left_edge = 0, p_cfr_right_edge = 0; |
2469 | mode = 256; | 2292 | u16 tmcc_pow = 0, ana_gain = 0, tmp = 0, i = 0, nbseg_diff = 0 ; |
2470 | break; | 2293 | u16 max_constellation = DQPSK; |
2471 | case TRANSMISSION_MODE_4K: | 2294 | int init_prbs; |
2472 | mode = 128; | 2295 | |
2473 | break; | 2296 | /* P_mode */ |
2474 | default: | 2297 | dib8000_write_word(state, 10, (seq << 4)); |
2475 | case TRANSMISSION_MODE_2K: | 2298 | |
2476 | mode = 64; | 2299 | /* init mode */ |
2477 | break; | 2300 | state->mode = fft_to_mode(state); |
2301 | |||
2302 | /* set guard */ | ||
2303 | tmp = dib8000_read_word(state, 1); | ||
2304 | dib8000_write_word(state, 1, (tmp&0xfffc) | (state->fe[0]->dtv_property_cache.guard_interval & 0x3)); | ||
2305 | |||
2306 | dib8000_write_word(state, 274, (dib8000_read_word(state, 274) & 0xffcf) | ((state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 5) | ((state->fe[0]->dtv_property_cache.isdbt_sb_mode & 1) << 4)); | ||
2307 | |||
2308 | /* signal optimization parameter */ | ||
2309 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception) { | ||
2310 | state->seg_diff_mask = (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) << permu_seg[0]; | ||
2311 | for (i = 1; i < 3; i++) | ||
2312 | nbseg_diff += (state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count; | ||
2313 | for (i = 0; i < nbseg_diff; i++) | ||
2314 | state->seg_diff_mask |= 1 << permu_seg[i+1]; | ||
2315 | } else { | ||
2316 | for (i = 0; i < 3; i++) | ||
2317 | nbseg_diff += (state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count; | ||
2318 | for (i = 0; i < nbseg_diff; i++) | ||
2319 | state->seg_diff_mask |= 1 << permu_seg[i]; | ||
2478 | } | 2320 | } |
2479 | if (state->cfg.diversity_delay == 0) | 2321 | |
2480 | mode = (mode * (1 << (guard)) * 3) / 2 + 48; // add 50% SFN margin + compensate for one DVSY-fifo | 2322 | if (state->seg_diff_mask) |
2323 | dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200); | ||
2481 | else | 2324 | else |
2482 | mode = (mode * (1 << (guard)) * 3) / 2 + state->cfg.diversity_delay; // add 50% SFN margin + compensate for DVSY-fifo | 2325 | dib8000_write_word(state, 268, (2 << 9) | 39); /*init value */ |
2483 | mode <<= 4; | ||
2484 | dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | mode); | ||
2485 | 2326 | ||
2486 | /* channel estimation fine configuration */ | 2327 | for (i = 0; i < 3; i++) |
2487 | switch (max_constellation) { | 2328 | max_constellation = dib8000_set_layer(state, i, max_constellation); |
2488 | case QAM_64: | 2329 | if (autosearching == 0) { |
2489 | ana_gain = 0x7; // -1 : avoid def_est saturation when ADC target is -16dB | 2330 | state->layer_b_nb_seg = state->fe[0]->dtv_property_cache.layer[1].segment_count; |
2490 | coeff[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ | 2331 | state->layer_c_nb_seg = state->fe[0]->dtv_property_cache.layer[2].segment_count; |
2491 | coeff[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ | ||
2492 | coeff[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | ||
2493 | coeff[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ | ||
2494 | //if (!state->cfg.hostbus_diversity) //if diversity, we should prehaps use the configuration of the max_constallation -1 | ||
2495 | break; | ||
2496 | case QAM_16: | ||
2497 | ana_gain = 0x7; // -1 : avoid def_est saturation when ADC target is -16dB | ||
2498 | coeff[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ | ||
2499 | coeff[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ | ||
2500 | coeff[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | ||
2501 | coeff[3] = 0xfff0; /* P_adp_noise_ext -0.002 */ | ||
2502 | //if (!((state->cfg.hostbus_diversity) && (max_constellation == QAM_16))) | ||
2503 | break; | ||
2504 | default: | ||
2505 | ana_gain = 0; // 0 : goes along with ADC target at -22dB to keep good mobile performance and lock at sensitivity level | ||
2506 | coeff[0] = 0x099a; /* P_adp_regul_cnt 0.3 */ | ||
2507 | coeff[1] = 0xffae; /* P_adp_noise_cnt -0.01 */ | ||
2508 | coeff[2] = 0x0333; /* P_adp_regul_ext 0.1 */ | ||
2509 | coeff[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ | ||
2510 | break; | ||
2511 | } | 2332 | } |
2512 | for (mode = 0; mode < 4; mode++) | ||
2513 | dib8000_write_word(state, 215 + mode, coeff[mode]); | ||
2514 | 2333 | ||
2515 | // update ana_gain depending on max constellation | 2334 | /* WRITE: Mode & Diff mask */ |
2516 | dib8000_write_word(state, 116, ana_gain); | 2335 | dib8000_write_word(state, 0, (state->mode << 13) | state->seg_diff_mask); |
2517 | // update ADC target depending on ana_gain | ||
2518 | if (ana_gain) { // set -16dB ADC target for ana_gain=-1 | ||
2519 | for (i = 0; i < 10; i++) | ||
2520 | dib8000_write_word(state, 80 + i, adc_target_16dB[i]); | ||
2521 | } else { // set -22dB ADC target for ana_gain=0 | ||
2522 | for (i = 0; i < 10; i++) | ||
2523 | dib8000_write_word(state, 80 + i, adc_target_16dB[i] - 355); | ||
2524 | } | ||
2525 | 2336 | ||
2526 | // ---- ANA_FE ---- | 2337 | state->differential_constellation = (state->seg_diff_mask != 0); |
2338 | |||
2339 | /* channel estimation fine configuration */ | ||
2340 | ana_gain = dib8000_adp_fine_tune(state, max_constellation); | ||
2341 | |||
2342 | /* update ana_gain depending on max constellation */ | ||
2343 | dib8000_update_ana_gain(state, ana_gain); | ||
2344 | |||
2345 | /* ---- ANA_FE ---- */ | ||
2346 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception) /* 3-segments */ | ||
2347 | dib8000_load_ana_fe_coefs(state, ana_fe_coeff_3seg); | ||
2348 | else | ||
2349 | dib8000_load_ana_fe_coefs(state, ana_fe_coeff_1seg); /* 1-segment */ | ||
2350 | |||
2351 | /* TSB or ISDBT ? apply it now */ | ||
2527 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) { | 2352 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) { |
2528 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1) | 2353 | dib8000_set_sb_channel(state); |
2529 | ana_fe = ana_fe_coeff_3seg; | 2354 | if (state->fe[0]->dtv_property_cache.isdbt_sb_subchannel != -1) |
2530 | else // 1-segment | 2355 | init_prbs = dib8000_get_init_prbs(state, state->fe[0]->dtv_property_cache.isdbt_sb_subchannel); |
2531 | ana_fe = ana_fe_coeff_1seg; | 2356 | else |
2532 | } else | 2357 | init_prbs = 0; |
2533 | ana_fe = ana_fe_coeff_13seg; | 2358 | } else { |
2534 | 2359 | dib8000_set_13seg_channel(state); | |
2535 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1 || state->isdbt_cfg_loaded == 0) | 2360 | init_prbs = 0xfff; |
2536 | for (mode = 0; mode < 24; mode++) | 2361 | } |
2537 | dib8000_write_word(state, 117 + mode, ana_fe[mode]); | ||
2538 | 2362 | ||
2539 | // ---- CHAN_BLK ---- | 2363 | /* SMALL */ |
2364 | dib8000_small_fine_tune(state); | ||
2365 | |||
2366 | dib8000_set_subchannel_prbs(state, init_prbs); | ||
2367 | |||
2368 | /* ---- CHAN_BLK ---- */ | ||
2540 | for (i = 0; i < 13; i++) { | 2369 | for (i = 0; i < 13; i++) { |
2541 | if ((((~seg_diff_mask) >> i) & 1) == 1) { | 2370 | if ((((~state->seg_diff_mask) >> i) & 1) == 1) { |
2542 | P_cfr_left_edge += (1 << i) * ((i == 0) || ((((seg_mask13 & (~seg_diff_mask)) >> (i - 1)) & 1) == 0)); | 2371 | p_cfr_left_edge += (1 << i) * ((i == 0) || ((((state->seg_mask & (~state->seg_diff_mask)) >> (i - 1)) & 1) == 0)); |
2543 | P_cfr_right_edge += (1 << i) * ((i == 12) || ((((seg_mask13 & (~seg_diff_mask)) >> (i + 1)) & 1) == 0)); | 2372 | p_cfr_right_edge += (1 << i) * ((i == 12) || ((((state->seg_mask & (~state->seg_diff_mask)) >> (i + 1)) & 1) == 0)); |
2544 | } | 2373 | } |
2545 | } | 2374 | } |
2546 | dib8000_write_word(state, 222, P_cfr_left_edge); // P_cfr_left_edge | 2375 | dib8000_write_word(state, 222, p_cfr_left_edge); /* p_cfr_left_edge */ |
2547 | dib8000_write_word(state, 223, P_cfr_right_edge); // P_cfr_right_edge | 2376 | dib8000_write_word(state, 223, p_cfr_right_edge); /* p_cfr_right_edge */ |
2548 | // "P_cspu_left_edge" not used => do not care | 2377 | /* "P_cspu_left_edge" & "P_cspu_right_edge" not used => do not care */ |
2549 | // "P_cspu_right_edge" not used => do not care | 2378 | |
2550 | 2379 | dib8000_write_word(state, 189, ~state->seg_mask | state->seg_diff_mask); /* P_lmod4_seg_inh */ | |
2551 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | 2380 | dib8000_write_word(state, 192, ~state->seg_mask | state->seg_diff_mask); /* P_pha3_seg_inh */ |
2552 | dib8000_write_word(state, 228, 1); // P_2d_mode_byp=1 | 2381 | dib8000_write_word(state, 225, ~state->seg_mask | state->seg_diff_mask); /* P_tac_seg_inh */ |
2553 | dib8000_write_word(state, 205, dib8000_read_word(state, 205) & 0xfff0); // P_cspu_win_cut = 0 | 2382 | |
2554 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0 | 2383 | if (!autosearching) |
2555 | && state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K) { | 2384 | dib8000_write_word(state, 288, (~state->seg_mask | state->seg_diff_mask) & 0x1fff); /* P_tmcc_seg_eq_inh */ |
2556 | //dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); // P_adp_pass = 0 | 2385 | else |
2557 | dib8000_write_word(state, 265, 15); // P_equal_noise_sel = 15 | 2386 | dib8000_write_word(state, 288, 0x1fff); /*disable equalisation of the tmcc when autosearch to be able to find the DQPSK channels. */ |
2558 | } | 2387 | |
2559 | } else if (state->isdbt_cfg_loaded == 0) { | 2388 | dib8000_write_word(state, 211, state->seg_mask & (~state->seg_diff_mask)); /* P_des_seg_enabled */ |
2560 | dib8000_write_word(state, 228, 0); // default value | 2389 | dib8000_write_word(state, 287, ~state->seg_mask | 0x1000); /* P_tmcc_seg_inh */ |
2561 | dib8000_write_word(state, 265, 31); // default value | 2390 | |
2562 | dib8000_write_word(state, 205, 0x200f); // init value | 2391 | dib8000_write_word(state, 178, 32); /* P_fft_powrange = 32 */ |
2563 | } | 2392 | |
2564 | // ---- TMCC ---- | 2393 | /* ---- TMCC ---- */ |
2565 | for (i = 0; i < 3; i++) | 2394 | for (i = 0; i < 3; i++) |
2566 | tmcc_pow += | 2395 | tmcc_pow += (((state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * 4 + 1) * state->fe[0]->dtv_property_cache.layer[i].segment_count) ; |
2567 | (((state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * 4 + 1) * state->fe[0]->dtv_property_cache.layer[i].segment_count); | 2396 | |
2568 | // Quantif of "P_tmcc_dec_thres_?k" is (0, 5+mode, 9); | 2397 | /* Quantif of "P_tmcc_dec_thres_?k" is (0, 5+mode, 9); */ |
2569 | // Threshold is set at 1/4 of max power. | 2398 | /* Threshold is set at 1/4 of max power. */ |
2570 | tmcc_pow *= (1 << (9 - 2)); | 2399 | tmcc_pow *= (1 << (9-2)); |
2571 | 2400 | dib8000_write_word(state, 290, tmcc_pow); /* P_tmcc_dec_thres_2k */ | |
2572 | dib8000_write_word(state, 290, tmcc_pow); // P_tmcc_dec_thres_2k | 2401 | dib8000_write_word(state, 291, tmcc_pow); /* P_tmcc_dec_thres_4k */ |
2573 | dib8000_write_word(state, 291, tmcc_pow); // P_tmcc_dec_thres_4k | 2402 | dib8000_write_word(state, 292, tmcc_pow); /* P_tmcc_dec_thres_8k */ |
2574 | dib8000_write_word(state, 292, tmcc_pow); // P_tmcc_dec_thres_8k | 2403 | /*dib8000_write_word(state, 287, (1 << 13) | 0x1000 ); */ |
2575 | //dib8000_write_word(state, 287, (1 << 13) | 0x1000 ); | ||
2576 | // ---- PHA3 ---- | ||
2577 | 2404 | ||
2405 | /* ---- PHA3 ---- */ | ||
2578 | if (state->isdbt_cfg_loaded == 0) | 2406 | if (state->isdbt_cfg_loaded == 0) |
2579 | dib8000_write_word(state, 250, 3285); /*p_2d_hspeed_thr0 */ | 2407 | dib8000_write_word(state, 250, 3285); /* p_2d_hspeed_thr0 */ |
2580 | 2408 | ||
2581 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) | 2409 | state->isdbt_cfg_loaded = 0; |
2582 | state->isdbt_cfg_loaded = 0; | 2410 | } |
2583 | else | ||
2584 | state->isdbt_cfg_loaded = 1; | ||
2585 | 2411 | ||
2412 | u32 dib8000_wait_lock(struct dib8000_state *state, u32 internal, u32 wait0_ms, u32 wait1_ms, u32 wait2_ms) | ||
2413 | { | ||
2414 | u32 value; | ||
2415 | u16 reg = 11; /* P_search_end0 start addr */ | ||
2416 | |||
2417 | for (reg = 11; reg < 16; reg += 2) { | ||
2418 | if (reg == 11) { | ||
2419 | if (state->revision == 0x8090) | ||
2420 | value = internal * wait1_ms; /* P_search_end0 wait time */ | ||
2421 | else | ||
2422 | value = internal * wait0_ms; /* P_search_end0 wait time */ | ||
2423 | } else if (reg == 13) | ||
2424 | value = internal * wait1_ms; /* P_search_end0 wait time */ | ||
2425 | else if (reg == 15) | ||
2426 | value = internal * wait2_ms; /* P_search_end0 wait time */ | ||
2427 | dib8000_write_word(state, reg, (u16)((value >> 16) & 0xffff)); | ||
2428 | dib8000_write_word(state, (reg + 1), (u16)(value & 0xffff)); | ||
2429 | } | ||
2430 | return value; | ||
2586 | } | 2431 | } |
2587 | 2432 | ||
2588 | static int dib8000_autosearch_start(struct dvb_frontend *fe) | 2433 | static int dib8000_autosearch_start(struct dvb_frontend *fe) |
2589 | { | 2434 | { |
2590 | u8 factor; | ||
2591 | u32 value; | ||
2592 | struct dib8000_state *state = fe->demodulator_priv; | 2435 | struct dib8000_state *state = fe->demodulator_priv; |
2436 | u8 slist = 0; | ||
2437 | u32 value, internal = state->cfg.pll->internal; | ||
2438 | |||
2439 | if (state->revision == 0x8090) | ||
2440 | internal = dib8000_read32(state, 23) / 1000; | ||
2593 | 2441 | ||
2594 | int slist = 0; | 2442 | if (state->autosearch_state == AS_SEARCHING_FFT) { |
2443 | dib8000_write_word(state, 37, 0x0065); /* P_ctrl_pha_off_max default values */ | ||
2444 | dib8000_write_word(state, 116, 0x0000); /* P_ana_gain to 0 */ | ||
2595 | 2445 | ||
2596 | state->fe[0]->dtv_property_cache.inversion = 0; | 2446 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x1fff) | (0 << 13) | (1 << 15)); /* P_mode = 0, P_restart_search=1 */ |
2597 | if (!state->fe[0]->dtv_property_cache.isdbt_sb_mode) | 2447 | dib8000_write_word(state, 1, (dib8000_read_word(state, 1) & 0xfffc) | 0); /* P_guard = 0 */ |
2598 | state->fe[0]->dtv_property_cache.layer[0].segment_count = 13; | 2448 | dib8000_write_word(state, 6, 0); /* P_lock0_mask = 0 */ |
2599 | state->fe[0]->dtv_property_cache.layer[0].modulation = QAM_64; | 2449 | dib8000_write_word(state, 7, 0); /* P_lock1_mask = 0 */ |
2600 | state->fe[0]->dtv_property_cache.layer[0].fec = FEC_2_3; | 2450 | dib8000_write_word(state, 8, 0); /* P_lock2_mask = 0 */ |
2601 | state->fe[0]->dtv_property_cache.layer[0].interleaving = 0; | 2451 | dib8000_write_word(state, 10, (dib8000_read_word(state, 10) & 0x200) | (16 << 4) | (0 << 0)); /* P_search_list=16, P_search_maxtrial=0 */ |
2602 | 2452 | ||
2603 | //choose the right list, in sb, always do everything | 2453 | if (state->revision == 0x8090) |
2604 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) { | 2454 | value = dib8000_wait_lock(state, internal, 10, 10, 10); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ |
2455 | else | ||
2456 | value = dib8000_wait_lock(state, internal, 20, 20, 20); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ | ||
2457 | |||
2458 | dib8000_write_word(state, 17, 0); | ||
2459 | dib8000_write_word(state, 18, 200); /* P_search_rstst = 200 */ | ||
2460 | dib8000_write_word(state, 19, 0); | ||
2461 | dib8000_write_word(state, 20, 400); /* P_search_rstend = 400 */ | ||
2462 | dib8000_write_word(state, 21, (value >> 16) & 0xffff); /* P_search_checkst */ | ||
2463 | dib8000_write_word(state, 22, value & 0xffff); | ||
2464 | |||
2465 | if (state->revision == 0x8090) | ||
2466 | dib8000_write_word(state, 32, (dib8000_read_word(state, 32) & 0xf0ff) | (0 << 8)); /* P_corm_alpha = 0 */ | ||
2467 | else | ||
2468 | dib8000_write_word(state, 32, (dib8000_read_word(state, 32) & 0xf0ff) | (9 << 8)); /* P_corm_alpha = 3 */ | ||
2469 | dib8000_write_word(state, 355, 2); /* P_search_param_max = 2 */ | ||
2470 | |||
2471 | /* P_search_param_select = (1 | 1<<4 | 1 << 8) */ | ||
2472 | dib8000_write_word(state, 356, 0); | ||
2473 | dib8000_write_word(state, 357, 0x111); | ||
2474 | |||
2475 | dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (1 << 13)); /* P_restart_ccg = 1 */ | ||
2476 | dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (0 << 13)); /* P_restart_ccg = 0 */ | ||
2477 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x7ff) | (0 << 15) | (1 << 13)); /* P_restart_search = 0; */ | ||
2478 | } else if (state->autosearch_state == AS_SEARCHING_GUARD) { | ||
2605 | state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; | 2479 | state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; |
2606 | state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; | 2480 | state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; |
2607 | slist = 7; | 2481 | state->fe[0]->dtv_property_cache.inversion = 0; |
2608 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); | 2482 | state->fe[0]->dtv_property_cache.layer[0].modulation = QAM_64; |
2483 | state->fe[0]->dtv_property_cache.layer[0].fec = FEC_2_3; | ||
2484 | state->fe[0]->dtv_property_cache.layer[0].interleaving = 0; | ||
2485 | state->fe[0]->dtv_property_cache.layer[0].segment_count = 13; | ||
2486 | |||
2487 | slist = 16; | ||
2488 | state->fe[0]->dtv_property_cache.transmission_mode = state->found_nfft; | ||
2489 | |||
2490 | dib8000_set_isdbt_common_channel(state, slist, 1); | ||
2491 | |||
2492 | /* set lock_mask values */ | ||
2493 | dib8000_write_word(state, 6, 0x4); | ||
2494 | if (state->revision == 0x8090) | ||
2495 | dib8000_write_word(state, 7, ((1 << 12) | (1 << 11) | (1 << 10)));/* tmcc_dec_lock, tmcc_sync_lock, tmcc_data_lock, tmcc_bch_uncor */ | ||
2496 | else | ||
2497 | dib8000_write_word(state, 7, 0x8); | ||
2498 | dib8000_write_word(state, 8, 0x1000); | ||
2499 | |||
2500 | /* set lock_mask wait time values */ | ||
2501 | if (state->revision == 0x8090) | ||
2502 | dib8000_wait_lock(state, internal, 50, 100, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ | ||
2503 | else | ||
2504 | dib8000_wait_lock(state, internal, 50, 200, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ | ||
2505 | |||
2506 | dib8000_write_word(state, 355, 3); /* P_search_param_max = 3 */ | ||
2507 | |||
2508 | /* P_search_param_select = 0xf; look for the 4 different guard intervals */ | ||
2509 | dib8000_write_word(state, 356, 0); | ||
2510 | dib8000_write_word(state, 357, 0xf); | ||
2511 | |||
2512 | value = dib8000_read_word(state, 0); | ||
2513 | dib8000_write_word(state, 0, (u16)((1 << 15) | value)); | ||
2514 | dib8000_read_word(state, 1284); /* reset the INT. n_irq_pending */ | ||
2515 | dib8000_write_word(state, 0, (u16)value); | ||
2609 | } else { | 2516 | } else { |
2610 | if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) { | 2517 | state->fe[0]->dtv_property_cache.inversion = 0; |
2611 | if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) { | 2518 | state->fe[0]->dtv_property_cache.layer[0].modulation = QAM_64; |
2612 | slist = 7; | 2519 | state->fe[0]->dtv_property_cache.layer[0].fec = FEC_2_3; |
2613 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); // P_mode = 1 to have autosearch start ok with mode2 | 2520 | state->fe[0]->dtv_property_cache.layer[0].interleaving = 0; |
2614 | } else | 2521 | state->fe[0]->dtv_property_cache.layer[0].segment_count = 13; |
2615 | slist = 3; | 2522 | if (!state->fe[0]->dtv_property_cache.isdbt_sb_mode) |
2523 | state->fe[0]->dtv_property_cache.layer[0].segment_count = 13; | ||
2524 | |||
2525 | /* choose the right list, in sb, always do everything */ | ||
2526 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) { | ||
2527 | slist = 7; | ||
2528 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); | ||
2616 | } else { | 2529 | } else { |
2617 | if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) { | 2530 | if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) { |
2618 | slist = 2; | 2531 | if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) { |
2619 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); // P_mode = 1 | 2532 | state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; |
2620 | } else | 2533 | state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; |
2621 | slist = 0; | 2534 | slist = 7; |
2535 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); /* P_mode = 1 to have autosearch start ok with mode2 */ | ||
2536 | } else { | ||
2537 | state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; | ||
2538 | slist = 3; | ||
2539 | } | ||
2540 | } else { | ||
2541 | if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) { | ||
2542 | state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; | ||
2543 | slist = 2; | ||
2544 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); /* P_mode = 1 */ | ||
2545 | } else | ||
2546 | slist = 0; | ||
2547 | } | ||
2622 | } | 2548 | } |
2549 | dprintk("Using list for autosearch : %d", slist); | ||
2623 | 2550 | ||
2624 | if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) | 2551 | dib8000_set_isdbt_common_channel(state, slist, 1); |
2625 | state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; | ||
2626 | if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) | ||
2627 | state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; | ||
2628 | |||
2629 | dprintk("using list for autosearch : %d", slist); | ||
2630 | dib8000_set_channel(state, (unsigned char)slist, 1); | ||
2631 | //dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); // P_mode = 1 | ||
2632 | |||
2633 | factor = 1; | ||
2634 | 2552 | ||
2635 | //set lock_mask values | 2553 | /* set lock_mask values */ |
2636 | dib8000_write_word(state, 6, 0x4); | 2554 | dib8000_write_word(state, 6, 0x4); |
2637 | dib8000_write_word(state, 7, 0x8); | 2555 | if (state->revision == 0x8090) |
2556 | dib8000_write_word(state, 7, (1 << 12) | (1 << 11) | (1 << 10)); | ||
2557 | else | ||
2558 | dib8000_write_word(state, 7, 0x8); | ||
2638 | dib8000_write_word(state, 8, 0x1000); | 2559 | dib8000_write_word(state, 8, 0x1000); |
2639 | 2560 | ||
2640 | //set lock_mask wait time values | 2561 | /* set lock_mask wait time values */ |
2641 | value = 50 * state->cfg.pll->internal * factor; | 2562 | if (state->revision == 0x8090) |
2642 | dib8000_write_word(state, 11, (u16) ((value >> 16) & 0xffff)); // lock0 wait time | 2563 | dib8000_wait_lock(state, internal, 50, 200, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ |
2643 | dib8000_write_word(state, 12, (u16) (value & 0xffff)); // lock0 wait time | 2564 | else |
2644 | value = 100 * state->cfg.pll->internal * factor; | 2565 | dib8000_wait_lock(state, internal, 50, 100, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ |
2645 | dib8000_write_word(state, 13, (u16) ((value >> 16) & 0xffff)); // lock1 wait time | ||
2646 | dib8000_write_word(state, 14, (u16) (value & 0xffff)); // lock1 wait time | ||
2647 | value = 1000 * state->cfg.pll->internal * factor; | ||
2648 | dib8000_write_word(state, 15, (u16) ((value >> 16) & 0xffff)); // lock2 wait time | ||
2649 | dib8000_write_word(state, 16, (u16) (value & 0xffff)); // lock2 wait time | ||
2650 | 2566 | ||
2651 | value = dib8000_read_word(state, 0); | 2567 | value = dib8000_read_word(state, 0); |
2652 | dib8000_write_word(state, 0, (u16) ((1 << 15) | value)); | 2568 | dib8000_write_word(state, 0, (u16)((1 << 15) | value)); |
2653 | dib8000_read_word(state, 1284); // reset the INT. n_irq_pending | 2569 | dib8000_read_word(state, 1284); /* reset the INT. n_irq_pending */ |
2654 | dib8000_write_word(state, 0, (u16) value); | 2570 | dib8000_write_word(state, 0, (u16)value); |
2655 | |||
2656 | } | 2571 | } |
2657 | |||
2658 | return 0; | 2572 | return 0; |
2659 | } | 2573 | } |
2660 | 2574 | ||
@@ -2663,96 +2577,623 @@ static int dib8000_autosearch_irq(struct dvb_frontend *fe) | |||
2663 | struct dib8000_state *state = fe->demodulator_priv; | 2577 | struct dib8000_state *state = fe->demodulator_priv; |
2664 | u16 irq_pending = dib8000_read_word(state, 1284); | 2578 | u16 irq_pending = dib8000_read_word(state, 1284); |
2665 | 2579 | ||
2666 | if (irq_pending & 0x1) { // failed | 2580 | if (state->autosearch_state == AS_SEARCHING_FFT) { |
2667 | dprintk("dib8000_autosearch_irq failed"); | 2581 | if (irq_pending & 0x1) { |
2668 | return 1; | 2582 | dprintk("dib8000_autosearch_irq: max correlation result available"); |
2669 | } | 2583 | return 3; |
2584 | } | ||
2585 | } else { | ||
2586 | if (irq_pending & 0x1) { /* failed */ | ||
2587 | dprintk("dib8000_autosearch_irq failed"); | ||
2588 | return 1; | ||
2589 | } | ||
2670 | 2590 | ||
2671 | if (irq_pending & 0x2) { // succeeded | 2591 | if (irq_pending & 0x2) { /* succeeded */ |
2672 | dprintk("dib8000_autosearch_irq succeeded"); | 2592 | dprintk("dib8000_autosearch_irq succeeded"); |
2673 | return 2; | 2593 | return 2; |
2594 | } | ||
2674 | } | 2595 | } |
2675 | 2596 | ||
2676 | return 0; // still pending | 2597 | return 0; // still pending |
2677 | } | 2598 | } |
2678 | 2599 | ||
2679 | static int dib8000_tune(struct dvb_frontend *fe) | 2600 | static void dib8000_viterbi_state(struct dib8000_state *state, u8 onoff) |
2680 | { | 2601 | { |
2681 | struct dib8000_state *state = fe->demodulator_priv; | 2602 | u16 tmp; |
2682 | int ret = 0; | ||
2683 | u16 lock, value, mode; | ||
2684 | 2603 | ||
2685 | // we are already tuned - just resuming from suspend | 2604 | tmp = dib8000_read_word(state, 771); |
2686 | if (state == NULL) | 2605 | if (onoff) /* start P_restart_chd : channel_decoder */ |
2687 | return -EINVAL; | 2606 | dib8000_write_word(state, 771, tmp & 0xfffd); |
2607 | else /* stop P_restart_chd : channel_decoder */ | ||
2608 | dib8000_write_word(state, 771, tmp | (1<<1)); | ||
2609 | } | ||
2688 | 2610 | ||
2689 | mode = fft_to_mode(state); | 2611 | static void dib8000_set_dds(struct dib8000_state *state, s32 offset_khz) |
2612 | { | ||
2613 | s16 unit_khz_dds_val; | ||
2614 | u32 abs_offset_khz = ABS(offset_khz); | ||
2615 | u32 dds = state->cfg.pll->ifreq & 0x1ffffff; | ||
2616 | u8 invert = !!(state->cfg.pll->ifreq & (1 << 25)); | ||
2617 | u8 ratio; | ||
2690 | 2618 | ||
2691 | dib8000_set_bandwidth(fe, state->fe[0]->dtv_property_cache.bandwidth_hz / 1000); | 2619 | if (state->revision == 0x8090) { |
2692 | dib8000_set_channel(state, 0, 0); | 2620 | ratio = 4; |
2621 | unit_khz_dds_val = (1<<26) / (dib8000_read32(state, 23) / 1000); | ||
2622 | if (offset_khz < 0) | ||
2623 | dds = (1 << 26) - (abs_offset_khz * unit_khz_dds_val); | ||
2624 | else | ||
2625 | dds = (abs_offset_khz * unit_khz_dds_val); | ||
2693 | 2626 | ||
2694 | // restart demod | 2627 | if (invert) |
2695 | ret |= dib8000_write_word(state, 770, 0x4000); | 2628 | dds = (1<<26) - dds; |
2696 | ret |= dib8000_write_word(state, 770, 0x0000); | 2629 | } else { |
2697 | msleep(45); | 2630 | ratio = 2; |
2631 | unit_khz_dds_val = (u16) (67108864 / state->cfg.pll->internal); | ||
2698 | 2632 | ||
2699 | /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3 */ | 2633 | if (offset_khz < 0) |
2700 | /* ret |= dib8000_write_word(state, 29, (0 << 9) | (4 << 5) | (0 << 4) | (3 << 0) ); workaround inh_isi stays at 1 */ | 2634 | unit_khz_dds_val *= -1; |
2701 | 2635 | ||
2702 | // never achieved a lock before - wait for timfreq to update | 2636 | /* IF tuner */ |
2703 | if (state->timf == 0) { | 2637 | if (invert) |
2704 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | 2638 | dds -= abs_offset_khz * unit_khz_dds_val; |
2705 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) | 2639 | else |
2706 | msleep(300); | 2640 | dds += abs_offset_khz * unit_khz_dds_val; |
2707 | else // Sound Broadcasting mode 3 seg | 2641 | } |
2708 | msleep(500); | 2642 | |
2709 | } else // 13 seg | 2643 | dprintk("setting a DDS frequency offset of %c%dkHz", invert ? '-' : ' ', dds / unit_khz_dds_val); |
2710 | msleep(200); | 2644 | |
2645 | if (abs_offset_khz <= (state->cfg.pll->internal / ratio)) { | ||
2646 | /* Max dds offset is the half of the demod freq */ | ||
2647 | dib8000_write_word(state, 26, invert); | ||
2648 | dib8000_write_word(state, 27, (u16)(dds >> 16) & 0x1ff); | ||
2649 | dib8000_write_word(state, 28, (u16)(dds & 0xffff)); | ||
2711 | } | 2650 | } |
2712 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | 2651 | } |
2713 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { | ||
2714 | 2652 | ||
2715 | /* P_timf_alpha = (13-P_mode) , P_corm_alpha=6, P_corm_thres=0x40 alpha to check on board */ | 2653 | static void dib8000_set_frequency_offset(struct dib8000_state *state) |
2716 | dib8000_write_word(state, 32, ((13 - mode) << 12) | (6 << 8) | 0x40); | 2654 | { |
2717 | //dib8000_write_word(state, 32, (8 << 12) | (6 << 8) | 0x80); | 2655 | int i; |
2656 | u32 current_rf; | ||
2657 | int total_dds_offset_khz; | ||
2718 | 2658 | ||
2719 | /* P_ctrl_sfreq_step= (12-P_mode) P_ctrl_sfreq_inh =0 P_ctrl_pha_off_max */ | 2659 | if (state->fe[0]->ops.tuner_ops.get_frequency) |
2720 | ret |= dib8000_write_word(state, 37, (12 - mode) | ((5 + mode) << 5)); | 2660 | state->fe[0]->ops.tuner_ops.get_frequency(state->fe[0], ¤t_rf); |
2661 | else | ||
2662 | current_rf = state->fe[0]->dtv_property_cache.frequency; | ||
2663 | current_rf /= 1000; | ||
2664 | total_dds_offset_khz = (int)current_rf - (int)state->fe[0]->dtv_property_cache.frequency / 1000; | ||
2721 | 2665 | ||
2722 | } else { // Sound Broadcasting mode 3 seg | 2666 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) { |
2667 | state->subchannel = state->fe[0]->dtv_property_cache.isdbt_sb_subchannel; | ||
2723 | 2668 | ||
2724 | /* P_timf_alpha = (12-P_mode) , P_corm_alpha=6, P_corm_thres=0x60 alpha to check on board */ | 2669 | i = dib8000_read_word(state, 26) & 1; /* P_dds_invspec */ |
2725 | dib8000_write_word(state, 32, ((12 - mode) << 12) | (6 << 8) | 0x60); | 2670 | dib8000_write_word(state, 26, state->fe[0]->dtv_property_cache.inversion ^ i); |
2726 | 2671 | ||
2727 | ret |= dib8000_write_word(state, 37, (11 - mode) | ((5 + mode) << 5)); | 2672 | if (state->cfg.pll->ifreq == 0) { /* low if tuner */ |
2673 | if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0) | ||
2674 | dib8000_write_word(state, 26, dib8000_read_word(state, 26) | 1); | ||
2675 | } else { | ||
2676 | if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0) | ||
2677 | total_dds_offset_khz *= -1; | ||
2728 | } | 2678 | } |
2679 | } | ||
2729 | 2680 | ||
2730 | } else { // 13 seg | 2681 | dprintk("%dkhz tuner offset (frequency = %dHz & current_rf = %dHz) total_dds_offset_hz = %d", state->fe[0]->dtv_property_cache.frequency - current_rf, state->fe[0]->dtv_property_cache.frequency, current_rf, total_dds_offset_khz); |
2731 | /* P_timf_alpha = 8 , P_corm_alpha=6, P_corm_thres=0x80 alpha to check on board */ | ||
2732 | dib8000_write_word(state, 32, ((11 - mode) << 12) | (6 << 8) | 0x80); | ||
2733 | 2682 | ||
2734 | ret |= dib8000_write_word(state, 37, (10 - mode) | ((5 + mode) << 5)); | 2683 | /* apply dds offset now */ |
2684 | dib8000_set_dds(state, total_dds_offset_khz); | ||
2685 | } | ||
2686 | |||
2687 | static u16 LUT_isdbt_symbol_duration[4] = { 26, 101, 63 }; | ||
2688 | u32 dib8000_get_symbol_duration(struct dib8000_state *state) | ||
2689 | { | ||
2690 | u16 i; | ||
2735 | 2691 | ||
2692 | switch (state->fe[0]->dtv_property_cache.transmission_mode) { | ||
2693 | case TRANSMISSION_MODE_2K: | ||
2694 | i = 0; | ||
2695 | break; | ||
2696 | case TRANSMISSION_MODE_4K: | ||
2697 | i = 2; | ||
2698 | break; | ||
2699 | default: | ||
2700 | case TRANSMISSION_MODE_AUTO: | ||
2701 | case TRANSMISSION_MODE_8K: | ||
2702 | i = 1; | ||
2703 | break; | ||
2736 | } | 2704 | } |
2737 | 2705 | ||
2738 | // we achieved a coff_cpil_lock - it's time to update the timf | 2706 | return (LUT_isdbt_symbol_duration[i] / (state->fe[0]->dtv_property_cache.bandwidth_hz / 1000)) + 1; |
2739 | if (state->revision != 0x8090) | 2707 | } |
2740 | lock = dib8000_read_word(state, 568); | 2708 | |
2709 | static void dib8000_set_isdbt_loop_params(struct dib8000_state *state, enum param_loop_step loop_step) | ||
2710 | { | ||
2711 | u16 reg_32 = 0, reg_37 = 0; | ||
2712 | |||
2713 | switch (loop_step) { | ||
2714 | case LOOP_TUNE_1: | ||
2715 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) { | ||
2716 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { | ||
2717 | reg_32 = ((11 - state->mode) << 12) | (6 << 8) | 0x40; /* P_timf_alpha = (11-P_mode), P_corm_alpha=6, P_corm_thres=0x40 */ | ||
2718 | reg_37 = (3 << 5) | (0 << 4) | (10 - state->mode); /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (10-P_mode) */ | ||
2719 | } else { /* Sound Broadcasting mode 3 seg */ | ||
2720 | reg_32 = ((10 - state->mode) << 12) | (6 << 8) | 0x60; /* P_timf_alpha = (10-P_mode), P_corm_alpha=6, P_corm_thres=0x60 */ | ||
2721 | reg_37 = (3 << 5) | (0 << 4) | (9 - state->mode); /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (9-P_mode) */ | ||
2722 | } | ||
2723 | } else { /* 13-seg start conf offset loop parameters */ | ||
2724 | reg_32 = ((9 - state->mode) << 12) | (6 << 8) | 0x80; /* P_timf_alpha = (9-P_mode, P_corm_alpha=6, P_corm_thres=0x80 */ | ||
2725 | reg_37 = (3 << 5) | (0 << 4) | (8 - state->mode); /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = 9 */ | ||
2726 | } | ||
2727 | break; | ||
2728 | case LOOP_TUNE_2: | ||
2729 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) { | ||
2730 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { /* Sound Broadcasting mode 1 seg */ | ||
2731 | reg_32 = ((13-state->mode) << 12) | (6 << 8) | 0x40; /* P_timf_alpha = (13-P_mode) , P_corm_alpha=6, P_corm_thres=0x40*/ | ||
2732 | reg_37 = (12-state->mode) | ((5 + state->mode) << 5); | ||
2733 | } else { /* Sound Broadcasting mode 3 seg */ | ||
2734 | reg_32 = ((12-state->mode) << 12) | (6 << 8) | 0x60; /* P_timf_alpha = (12-P_mode) , P_corm_alpha=6, P_corm_thres=0x60 */ | ||
2735 | reg_37 = (11-state->mode) | ((5 + state->mode) << 5); | ||
2736 | } | ||
2737 | } else { /* 13 seg */ | ||
2738 | reg_32 = ((11-state->mode) << 12) | (6 << 8) | 0x80; /* P_timf_alpha = 8 , P_corm_alpha=6, P_corm_thres=0x80 */ | ||
2739 | reg_37 = ((5+state->mode) << 5) | (10 - state->mode); | ||
2740 | } | ||
2741 | break; | ||
2742 | } | ||
2743 | dib8000_write_word(state, 32, reg_32); | ||
2744 | dib8000_write_word(state, 37, reg_37); | ||
2745 | } | ||
2746 | |||
2747 | static void dib8000_demod_restart(struct dib8000_state *state) | ||
2748 | { | ||
2749 | dib8000_write_word(state, 770, 0x4000); | ||
2750 | dib8000_write_word(state, 770, 0x0000); | ||
2751 | return; | ||
2752 | } | ||
2753 | |||
2754 | static void dib8000_set_sync_wait(struct dib8000_state *state) | ||
2755 | { | ||
2756 | u16 sync_wait = 64; | ||
2757 | |||
2758 | /* P_dvsy_sync_wait - reuse mode */ | ||
2759 | switch (state->fe[0]->dtv_property_cache.transmission_mode) { | ||
2760 | case TRANSMISSION_MODE_8K: | ||
2761 | sync_wait = 256; | ||
2762 | break; | ||
2763 | case TRANSMISSION_MODE_4K: | ||
2764 | sync_wait = 128; | ||
2765 | break; | ||
2766 | default: | ||
2767 | case TRANSMISSION_MODE_2K: | ||
2768 | sync_wait = 64; | ||
2769 | break; | ||
2770 | } | ||
2771 | |||
2772 | if (state->cfg.diversity_delay == 0) | ||
2773 | sync_wait = (sync_wait * (1 << (state->fe[0]->dtv_property_cache.guard_interval)) * 3) / 2 + 48; /* add 50% SFN margin + compensate for one DVSY-fifo */ | ||
2774 | else | ||
2775 | sync_wait = (sync_wait * (1 << (state->fe[0]->dtv_property_cache.guard_interval)) * 3) / 2 + state->cfg.diversity_delay; /* add 50% SFN margin + compensate for DVSY-fifo */ | ||
2776 | |||
2777 | dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | (sync_wait << 4)); | ||
2778 | } | ||
2779 | |||
2780 | static u32 dib8000_get_timeout(struct dib8000_state *state, u32 delay, enum timeout_mode mode) | ||
2781 | { | ||
2782 | if (mode == SYMBOL_DEPENDENT_ON) | ||
2783 | return systime() + (delay * state->symbol_duration); | ||
2741 | else | 2784 | else |
2742 | lock = dib8000_read_word(state, 570); | 2785 | return systime() + delay; |
2743 | if ((lock >> 11) & 0x1) | 2786 | } |
2744 | dib8000_update_timf(state); | ||
2745 | 2787 | ||
2746 | //now that tune is finished, lock0 should lock on fec_mpeg to output this lock on MP_LOCK. It's changed in autosearch start | 2788 | static s32 dib8000_get_status(struct dvb_frontend *fe) |
2747 | dib8000_write_word(state, 6, 0x200); | 2789 | { |
2790 | struct dib8000_state *state = fe->demodulator_priv; | ||
2791 | return state->status; | ||
2792 | } | ||
2748 | 2793 | ||
2749 | if (state->revision == 0x8002) { | 2794 | enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe) |
2750 | value = dib8000_read_word(state, 903); | 2795 | { |
2751 | dib8000_write_word(state, 903, value & ~(1 << 3)); | 2796 | struct dib8000_state *state = fe->demodulator_priv; |
2752 | msleep(1); | 2797 | return state->tune_state; |
2753 | dib8000_write_word(state, 903, value | (1 << 3)); | 2798 | } |
2799 | EXPORT_SYMBOL(dib8000_get_tune_state); | ||
2800 | |||
2801 | int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) | ||
2802 | { | ||
2803 | struct dib8000_state *state = fe->demodulator_priv; | ||
2804 | |||
2805 | state->tune_state = tune_state; | ||
2806 | return 0; | ||
2807 | } | ||
2808 | EXPORT_SYMBOL(dib8000_set_tune_state); | ||
2809 | |||
2810 | static int dib8000_tune_restart_from_demod(struct dvb_frontend *fe) | ||
2811 | { | ||
2812 | struct dib8000_state *state = fe->demodulator_priv; | ||
2813 | |||
2814 | state->status = FE_STATUS_TUNE_PENDING; | ||
2815 | state->tune_state = CT_DEMOD_START; | ||
2816 | return 0; | ||
2817 | } | ||
2818 | |||
2819 | static u16 dib8000_read_lock(struct dvb_frontend *fe) | ||
2820 | { | ||
2821 | struct dib8000_state *state = fe->demodulator_priv; | ||
2822 | |||
2823 | if (state->revision == 0x8090) | ||
2824 | return dib8000_read_word(state, 570); | ||
2825 | return dib8000_read_word(state, 568); | ||
2826 | } | ||
2827 | |||
2828 | static int dib8090p_init_sdram(struct dib8000_state *state) | ||
2829 | { | ||
2830 | u16 reg = 0; | ||
2831 | dprintk("init sdram"); | ||
2832 | |||
2833 | reg = dib8000_read_word(state, 274) & 0xfff0; | ||
2834 | dib8000_write_word(state, 274, reg | 0x7); /* P_dintlv_delay_ram = 7 because of MobileSdram */ | ||
2835 | |||
2836 | dib8000_write_word(state, 1803, (7 << 2)); | ||
2837 | |||
2838 | reg = dib8000_read_word(state, 1280); | ||
2839 | dib8000_write_word(state, 1280, reg | (1 << 2)); /* force restart P_restart_sdram */ | ||
2840 | dib8000_write_word(state, 1280, reg); /* release restart P_restart_sdram */ | ||
2841 | |||
2842 | return 0; | ||
2843 | } | ||
2844 | |||
2845 | static int dib8000_tune(struct dvb_frontend *fe) | ||
2846 | { | ||
2847 | struct dib8000_state *state = fe->demodulator_priv; | ||
2848 | enum frontend_tune_state *tune_state = &state->tune_state; | ||
2849 | |||
2850 | u16 locks, deeper_interleaver = 0, i; | ||
2851 | int ret = 1; /* 1 symbol duration (in 100us unit) delay most of the time */ | ||
2852 | |||
2853 | u32 *timeout = &state->timeout; | ||
2854 | u32 now = systime(); | ||
2855 | #ifdef DIB8000_AGC_FREEZE | ||
2856 | u16 agc1, agc2; | ||
2857 | #endif | ||
2858 | |||
2859 | u32 corm[4] = {0, 0, 0, 0}; | ||
2860 | u8 find_index, max_value; | ||
2861 | |||
2862 | #if 0 | ||
2863 | if (*tune_state < CT_DEMOD_STOP) | ||
2864 | dprintk("IN: context status = %d, TUNE_STATE %d autosearch step = %u systime = %u", state->channel_parameters_set, *tune_state, state->autosearch_state, now); | ||
2865 | #endif | ||
2866 | |||
2867 | switch (*tune_state) { | ||
2868 | case CT_DEMOD_START: /* 30 */ | ||
2869 | if (state->revision == 0x8090) | ||
2870 | dib8090p_init_sdram(state); | ||
2871 | state->status = FE_STATUS_TUNE_PENDING; | ||
2872 | if ((state->fe[0]->dtv_property_cache.delivery_system != SYS_ISDBT) || | ||
2873 | (state->fe[0]->dtv_property_cache.inversion == INVERSION_AUTO) || | ||
2874 | (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) || | ||
2875 | (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) || | ||
2876 | (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) != 0) && | ||
2877 | (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0xff) && | ||
2878 | (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0) && | ||
2879 | ((state->fe[0]->dtv_property_cache.layer[0].modulation == QAM_AUTO) || | ||
2880 | (state->fe[0]->dtv_property_cache.layer[0].fec == FEC_AUTO))) || | ||
2881 | (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 1)) != 0) && | ||
2882 | (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0xff) && | ||
2883 | (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0) && | ||
2884 | ((state->fe[0]->dtv_property_cache.layer[1].modulation == QAM_AUTO) || | ||
2885 | (state->fe[0]->dtv_property_cache.layer[1].fec == FEC_AUTO))) || | ||
2886 | (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 2)) != 0) && | ||
2887 | (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0xff) && | ||
2888 | (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0) && | ||
2889 | ((state->fe[0]->dtv_property_cache.layer[2].modulation == QAM_AUTO) || | ||
2890 | (state->fe[0]->dtv_property_cache.layer[2].fec == FEC_AUTO))) || | ||
2891 | (((state->fe[0]->dtv_property_cache.layer[0].segment_count == 0) || | ||
2892 | ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) == 0)) && | ||
2893 | ((state->fe[0]->dtv_property_cache.layer[1].segment_count == 0) || | ||
2894 | ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (2 << 0)) == 0)) && | ||
2895 | ((state->fe[0]->dtv_property_cache.layer[2].segment_count == 0) || ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (3 << 0)) == 0)))) | ||
2896 | state->channel_parameters_set = 0; /* auto search */ | ||
2897 | else | ||
2898 | state->channel_parameters_set = 1; /* channel parameters are known */ | ||
2899 | |||
2900 | dib8000_viterbi_state(state, 0); /* force chan dec in restart */ | ||
2901 | |||
2902 | /* Layer monit */ | ||
2903 | dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60); | ||
2904 | |||
2905 | dib8000_set_frequency_offset(state); | ||
2906 | dib8000_set_bandwidth(fe, state->fe[0]->dtv_property_cache.bandwidth_hz / 1000); | ||
2907 | |||
2908 | if (state->channel_parameters_set == 0) { /* The channel struct is unknown, search it ! */ | ||
2909 | #ifdef DIB8000_AGC_FREEZE | ||
2910 | if (state->revision != 0x8090) { | ||
2911 | state->agc1_max = dib8000_read_word(state, 108); | ||
2912 | state->agc1_min = dib8000_read_word(state, 109); | ||
2913 | state->agc2_max = dib8000_read_word(state, 110); | ||
2914 | state->agc2_min = dib8000_read_word(state, 111); | ||
2915 | agc1 = dib8000_read_word(state, 388); | ||
2916 | agc2 = dib8000_read_word(state, 389); | ||
2917 | dib8000_write_word(state, 108, agc1); | ||
2918 | dib8000_write_word(state, 109, agc1); | ||
2919 | dib8000_write_word(state, 110, agc2); | ||
2920 | dib8000_write_word(state, 111, agc2); | ||
2921 | } | ||
2922 | #endif | ||
2923 | state->autosearch_state = AS_SEARCHING_FFT; | ||
2924 | state->found_nfft = TRANSMISSION_MODE_AUTO; | ||
2925 | state->found_guard = GUARD_INTERVAL_AUTO; | ||
2926 | *tune_state = CT_DEMOD_SEARCH_NEXT; | ||
2927 | } else { /* we already know the channel struct so TUNE only ! */ | ||
2928 | state->autosearch_state = AS_DONE; | ||
2929 | *tune_state = CT_DEMOD_STEP_3; | ||
2930 | } | ||
2931 | state->symbol_duration = dib8000_get_symbol_duration(state); | ||
2932 | break; | ||
2933 | |||
2934 | case CT_DEMOD_SEARCH_NEXT: /* 51 */ | ||
2935 | dib8000_autosearch_start(fe); | ||
2936 | if (state->revision == 0x8090) | ||
2937 | ret = 50; | ||
2938 | else | ||
2939 | ret = 15; | ||
2940 | *tune_state = CT_DEMOD_STEP_1; | ||
2941 | break; | ||
2942 | |||
2943 | case CT_DEMOD_STEP_1: /* 31 */ | ||
2944 | switch (dib8000_autosearch_irq(fe)) { | ||
2945 | case 1: /* fail */ | ||
2946 | state->status = FE_STATUS_TUNE_FAILED; | ||
2947 | state->autosearch_state = AS_DONE; | ||
2948 | *tune_state = CT_DEMOD_STOP; /* else we are done here */ | ||
2949 | break; | ||
2950 | case 2: /* Succes */ | ||
2951 | state->status = FE_STATUS_FFT_SUCCESS; /* signal to the upper layer, that there was a channel found and the parameters can be read */ | ||
2952 | *tune_state = CT_DEMOD_STEP_3; | ||
2953 | if (state->autosearch_state == AS_SEARCHING_GUARD) | ||
2954 | *tune_state = CT_DEMOD_STEP_2; | ||
2955 | else | ||
2956 | state->autosearch_state = AS_DONE; | ||
2957 | break; | ||
2958 | case 3: /* Autosearch FFT max correlation endded */ | ||
2959 | *tune_state = CT_DEMOD_STEP_2; | ||
2960 | break; | ||
2961 | } | ||
2962 | break; | ||
2963 | |||
2964 | case CT_DEMOD_STEP_2: | ||
2965 | switch (state->autosearch_state) { | ||
2966 | case AS_SEARCHING_FFT: | ||
2967 | /* searching for the correct FFT */ | ||
2968 | if (state->revision == 0x8090) { | ||
2969 | corm[2] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597)); | ||
2970 | corm[1] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599)); | ||
2971 | corm[0] = (dib8000_read_word(state, 600) << 16) | (dib8000_read_word(state, 601)); | ||
2972 | } else { | ||
2973 | corm[2] = (dib8000_read_word(state, 594) << 16) | (dib8000_read_word(state, 595)); | ||
2974 | corm[1] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597)); | ||
2975 | corm[0] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599)); | ||
2976 | } | ||
2977 | /* dprintk("corm fft: %u %u %u", corm[0], corm[1], corm[2]); */ | ||
2978 | |||
2979 | max_value = 0; | ||
2980 | for (find_index = 1 ; find_index < 3 ; find_index++) { | ||
2981 | if (corm[max_value] < corm[find_index]) | ||
2982 | max_value = find_index ; | ||
2983 | } | ||
2984 | |||
2985 | switch (max_value) { | ||
2986 | case 0: | ||
2987 | state->found_nfft = TRANSMISSION_MODE_2K; | ||
2988 | break; | ||
2989 | case 1: | ||
2990 | state->found_nfft = TRANSMISSION_MODE_4K; | ||
2991 | break; | ||
2992 | case 2: | ||
2993 | default: | ||
2994 | state->found_nfft = TRANSMISSION_MODE_8K; | ||
2995 | break; | ||
2996 | } | ||
2997 | /* dprintk("Autosearch FFT has found Mode %d", max_value + 1); */ | ||
2998 | |||
2999 | *tune_state = CT_DEMOD_SEARCH_NEXT; | ||
3000 | state->autosearch_state = AS_SEARCHING_GUARD; | ||
3001 | if (state->revision == 0x8090) | ||
3002 | ret = 50; | ||
3003 | else | ||
3004 | ret = 10; | ||
3005 | break; | ||
3006 | case AS_SEARCHING_GUARD: | ||
3007 | /* searching for the correct guard interval */ | ||
3008 | if (state->revision == 0x8090) | ||
3009 | state->found_guard = dib8000_read_word(state, 572) & 0x3; | ||
3010 | else | ||
3011 | state->found_guard = dib8000_read_word(state, 570) & 0x3; | ||
3012 | /* dprintk("guard interval found=%i", state->found_guard); */ | ||
3013 | |||
3014 | *tune_state = CT_DEMOD_STEP_3; | ||
3015 | break; | ||
3016 | default: | ||
3017 | /* the demod should never be in this state */ | ||
3018 | state->status = FE_STATUS_TUNE_FAILED; | ||
3019 | state->autosearch_state = AS_DONE; | ||
3020 | *tune_state = CT_DEMOD_STOP; /* else we are done here */ | ||
3021 | break; | ||
3022 | } | ||
3023 | break; | ||
3024 | |||
3025 | case CT_DEMOD_STEP_3: /* 33 */ | ||
3026 | state->symbol_duration = dib8000_get_symbol_duration(state); | ||
3027 | dib8000_set_isdbt_loop_params(state, LOOP_TUNE_1); | ||
3028 | dib8000_set_isdbt_common_channel(state, 0, 0);/* setting the known channel parameters here */ | ||
3029 | *tune_state = CT_DEMOD_STEP_4; | ||
3030 | break; | ||
3031 | |||
3032 | case CT_DEMOD_STEP_4: /* (34) */ | ||
3033 | dib8000_demod_restart(state); | ||
3034 | |||
3035 | dib8000_set_sync_wait(state); | ||
3036 | dib8000_set_diversity_in(state->fe[0], state->diversity_onoff); | ||
3037 | |||
3038 | locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */ | ||
3039 | /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this lenght to lock */ | ||
3040 | *timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON); | ||
3041 | *tune_state = CT_DEMOD_STEP_5; | ||
3042 | break; | ||
3043 | |||
3044 | case CT_DEMOD_STEP_5: /* (35) */ | ||
3045 | locks = dib8000_read_lock(fe); | ||
3046 | if (locks & (0x3 << 11)) { /* coff-lock and off_cpil_lock achieved */ | ||
3047 | dib8000_update_timf(state); /* we achieved a coff_cpil_lock - it's time to update the timf */ | ||
3048 | if (!state->differential_constellation) { | ||
3049 | /* 2 times lmod4_win_len + 10 symbols (pipe delay after coff + nb to compute a 1st correlation) */ | ||
3050 | *timeout = dib8000_get_timeout(state, (20 * ((dib8000_read_word(state, 188)>>5)&0x1f)), SYMBOL_DEPENDENT_ON); | ||
3051 | *tune_state = CT_DEMOD_STEP_7; | ||
3052 | } else { | ||
3053 | *tune_state = CT_DEMOD_STEP_8; | ||
3054 | } | ||
3055 | } else if (now > *timeout) { | ||
3056 | *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */ | ||
3057 | } | ||
3058 | break; | ||
3059 | |||
3060 | case CT_DEMOD_STEP_6: /* (36) if there is an input (diversity) */ | ||
3061 | if ((state->fe[1] != NULL) && (state->output_mode != OUTMODE_DIVERSITY)) { | ||
3062 | /* if there is a diversity fe in input and this fe is has not already failled : wait here until this this fe has succedeed or failled */ | ||
3063 | if (dib8000_get_status(state->fe[1]) <= FE_STATUS_STD_SUCCESS) /* Something is locked on the input fe */ | ||
3064 | *tune_state = CT_DEMOD_STEP_8; /* go for mpeg */ | ||
3065 | else if (dib8000_get_status(state->fe[1]) >= FE_STATUS_TUNE_TIME_TOO_SHORT) { /* fe in input failled also, break the current one */ | ||
3066 | *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */ | ||
3067 | dib8000_viterbi_state(state, 1); /* start viterbi chandec */ | ||
3068 | dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2); | ||
3069 | state->status = FE_STATUS_TUNE_FAILED; | ||
3070 | } | ||
3071 | } else { | ||
3072 | dib8000_viterbi_state(state, 1); /* start viterbi chandec */ | ||
3073 | dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2); | ||
3074 | *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */ | ||
3075 | state->status = FE_STATUS_TUNE_FAILED; | ||
3076 | } | ||
3077 | break; | ||
3078 | |||
3079 | case CT_DEMOD_STEP_7: /* 37 */ | ||
3080 | locks = dib8000_read_lock(fe); | ||
3081 | if (locks & (1<<10)) { /* lmod4_lock */ | ||
3082 | ret = 14; /* wait for 14 symbols */ | ||
3083 | *tune_state = CT_DEMOD_STEP_8; | ||
3084 | } else if (now > *timeout) | ||
3085 | *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */ | ||
3086 | break; | ||
3087 | |||
3088 | case CT_DEMOD_STEP_8: /* 38 */ | ||
3089 | dib8000_viterbi_state(state, 1); /* start viterbi chandec */ | ||
3090 | dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2); | ||
3091 | |||
3092 | /* mpeg will never lock on this condition because init_prbs is not set : search for it !*/ | ||
3093 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode && state->fe[0]->dtv_property_cache.isdbt_sb_subchannel == -1 && !state->differential_constellation) { | ||
3094 | state->subchannel = 0; | ||
3095 | *tune_state = CT_DEMOD_STEP_11; | ||
3096 | } else { | ||
3097 | *tune_state = CT_DEMOD_STEP_9; | ||
3098 | state->status = FE_STATUS_LOCKED; | ||
3099 | } | ||
3100 | break; | ||
3101 | |||
3102 | case CT_DEMOD_STEP_9: /* 39 */ | ||
3103 | if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */ | ||
3104 | /* defines timeout for mpeg lock depending on interleaver lenght of longest layer */ | ||
3105 | for (i = 0; i < 3; i++) { | ||
3106 | if (state->fe[0]->dtv_property_cache.layer[i].interleaving >= deeper_interleaver) { | ||
3107 | dprintk("layer%i: time interleaver = %d ", i, state->fe[0]->dtv_property_cache.layer[i].interleaving); | ||
3108 | if (state->fe[0]->dtv_property_cache.layer[i].segment_count > 0) { /* valid layer */ | ||
3109 | deeper_interleaver = state->fe[0]->dtv_property_cache.layer[0].interleaving; | ||
3110 | state->longest_intlv_layer = i; | ||
3111 | } | ||
3112 | } | ||
3113 | } | ||
3114 | |||
3115 | if (deeper_interleaver == 0) | ||
3116 | locks = 2; /* locks is the tmp local variable name */ | ||
3117 | else if (deeper_interleaver == 3) | ||
3118 | locks = 8; | ||
3119 | else | ||
3120 | locks = 2 * deeper_interleaver; | ||
3121 | |||
3122 | if (state->diversity_onoff != 0) /* because of diversity sync */ | ||
3123 | locks *= 2; | ||
3124 | |||
3125 | *timeout = now + (2000 * locks); /* give the mpeg lock 800ms if sram is present */ | ||
3126 | dprintk("Deeper interleaver mode = %d on layer %d : timeout mult factor = %d => will use timeout = %d", deeper_interleaver, state->longest_intlv_layer, locks, *timeout); | ||
3127 | |||
3128 | *tune_state = CT_DEMOD_STEP_10; | ||
3129 | } else | ||
3130 | *tune_state = CT_DEMOD_STOP; | ||
3131 | break; | ||
3132 | |||
3133 | case CT_DEMOD_STEP_10: /* 40 */ | ||
3134 | locks = dib8000_read_lock(fe); | ||
3135 | if (locks&(1<<(7-state->longest_intlv_layer))) { /* mpeg lock : check the longest one */ | ||
3136 | dprintk("Mpeg locks [ L0 : %d | L1 : %d | L2 : %d ]", (locks>>7)&0x1, (locks>>6)&0x1, (locks>>5)&0x1); | ||
3137 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode && state->fe[0]->dtv_property_cache.isdbt_sb_subchannel == -1 && !state->differential_constellation) | ||
3138 | /* signal to the upper layer, that there was a channel found and the parameters can be read */ | ||
3139 | state->status = FE_STATUS_DEMOD_SUCCESS; | ||
3140 | else | ||
3141 | state->status = FE_STATUS_DATA_LOCKED; | ||
3142 | *tune_state = CT_DEMOD_STOP; | ||
3143 | } else if (now > *timeout) { | ||
3144 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode && state->fe[0]->dtv_property_cache.isdbt_sb_subchannel == -1 && !state->differential_constellation) { /* continue to try init prbs autosearch */ | ||
3145 | state->subchannel += 3; | ||
3146 | *tune_state = CT_DEMOD_STEP_11; | ||
3147 | } else { /* we are done mpeg of the longest interleaver xas not locking but let's try if an other layer has locked in the same time */ | ||
3148 | if (locks & (0x7<<5)) { | ||
3149 | dprintk("Mpeg locks [ L0 : %d | L1 : %d | L2 : %d ]", (locks>>7)&0x1, (locks>>6)&0x1, (locks>>5)&0x1); | ||
3150 | state->status = FE_STATUS_DATA_LOCKED; | ||
3151 | } else | ||
3152 | state->status = FE_STATUS_TUNE_FAILED; | ||
3153 | *tune_state = CT_DEMOD_STOP; | ||
3154 | } | ||
3155 | } | ||
3156 | break; | ||
3157 | |||
3158 | case CT_DEMOD_STEP_11: /* 41 : init prbs autosearch */ | ||
3159 | if (state->subchannel <= 41) { | ||
3160 | dib8000_set_subchannel_prbs(state, dib8000_get_init_prbs(state, state->subchannel)); | ||
3161 | *tune_state = CT_DEMOD_STEP_9; | ||
3162 | } else { | ||
3163 | *tune_state = CT_DEMOD_STOP; | ||
3164 | state->status = FE_STATUS_TUNE_FAILED; | ||
3165 | } | ||
3166 | break; | ||
3167 | |||
3168 | default: | ||
3169 | break; | ||
3170 | } | ||
3171 | |||
3172 | /* tuning is finished - cleanup the demod */ | ||
3173 | switch (*tune_state) { | ||
3174 | case CT_DEMOD_STOP: /* (42) */ | ||
3175 | #ifdef DIB8000_AGC_FREEZE | ||
3176 | if ((state->revision != 0x8090) && (state->agc1_max != 0)) { | ||
3177 | dib8000_write_word(state, 108, state->agc1_max); | ||
3178 | dib8000_write_word(state, 109, state->agc1_min); | ||
3179 | dib8000_write_word(state, 110, state->agc2_max); | ||
3180 | dib8000_write_word(state, 111, state->agc2_min); | ||
3181 | state->agc1_max = 0; | ||
3182 | state->agc1_min = 0; | ||
3183 | state->agc2_max = 0; | ||
3184 | state->agc2_min = 0; | ||
3185 | } | ||
3186 | #endif | ||
3187 | ret = FE_CALLBACK_TIME_NEVER; | ||
3188 | break; | ||
3189 | default: | ||
3190 | break; | ||
2754 | } | 3191 | } |
2755 | 3192 | ||
3193 | if ((ret > 0) && (*tune_state > CT_DEMOD_STEP_3)) | ||
3194 | return ret * state->symbol_duration; | ||
3195 | if ((ret > 0) && (ret < state->symbol_duration)) | ||
3196 | return state->symbol_duration; /* at least one symbol */ | ||
2756 | return ret; | 3197 | return ret; |
2757 | } | 3198 | } |
2758 | 3199 | ||
@@ -2767,7 +3208,7 @@ static int dib8000_wakeup(struct dvb_frontend *fe) | |||
2767 | if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0) | 3208 | if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0) |
2768 | dprintk("could not start Slow ADC"); | 3209 | dprintk("could not start Slow ADC"); |
2769 | 3210 | ||
2770 | if (state->revision != 0x8090) | 3211 | if (state->revision == 0x8090) |
2771 | dib8000_sad_calib(state); | 3212 | dib8000_sad_calib(state); |
2772 | 3213 | ||
2773 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | 3214 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { |
@@ -2797,21 +3238,6 @@ static int dib8000_sleep(struct dvb_frontend *fe) | |||
2797 | return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF); | 3238 | return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF); |
2798 | } | 3239 | } |
2799 | 3240 | ||
2800 | enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe) | ||
2801 | { | ||
2802 | struct dib8000_state *state = fe->demodulator_priv; | ||
2803 | return state->tune_state; | ||
2804 | } | ||
2805 | EXPORT_SYMBOL(dib8000_get_tune_state); | ||
2806 | |||
2807 | int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) | ||
2808 | { | ||
2809 | struct dib8000_state *state = fe->demodulator_priv; | ||
2810 | state->tune_state = tune_state; | ||
2811 | return 0; | ||
2812 | } | ||
2813 | EXPORT_SYMBOL(dib8000_set_tune_state); | ||
2814 | |||
2815 | static int dib8000_get_frontend(struct dvb_frontend *fe) | 3241 | static int dib8000_get_frontend(struct dvb_frontend *fe) |
2816 | { | 3242 | { |
2817 | struct dib8000_state *state = fe->demodulator_priv; | 3243 | struct dib8000_state *state = fe->demodulator_priv; |
@@ -2961,10 +3387,9 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) | |||
2961 | static int dib8000_set_frontend(struct dvb_frontend *fe) | 3387 | static int dib8000_set_frontend(struct dvb_frontend *fe) |
2962 | { | 3388 | { |
2963 | struct dib8000_state *state = fe->demodulator_priv; | 3389 | struct dib8000_state *state = fe->demodulator_priv; |
2964 | u8 nbr_pending, exit_condition, index_frontend; | 3390 | int l, i, active, time, ret, time_slave = FE_CALLBACK_TIME_NEVER; |
2965 | s8 index_frontend_success = -1; | 3391 | u8 exit_condition, index_frontend; |
2966 | int time, ret; | 3392 | u32 delay, callback_time; |
2967 | int time_slave = FE_CALLBACK_TIME_NEVER; | ||
2968 | 3393 | ||
2969 | if (state->fe[0]->dtv_property_cache.frequency == 0) { | 3394 | if (state->fe[0]->dtv_property_cache.frequency == 0) { |
2970 | dprintk("dib8000: must at least specify frequency "); | 3395 | dprintk("dib8000: must at least specify frequency "); |
@@ -2981,18 +3406,36 @@ static int dib8000_set_frontend(struct dvb_frontend *fe) | |||
2981 | state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_ISDBT; | 3406 | state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_ISDBT; |
2982 | memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties)); | 3407 | memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties)); |
2983 | 3408 | ||
2984 | if (state->revision != 0x8090) | 3409 | /* set output mode and diversity input */ |
2985 | dib8000_set_output_mode(state->fe[index_frontend], | 3410 | if (state->revision != 0x8090) { |
2986 | OUTMODE_HIGH_Z); | 3411 | dib8000_set_diversity_in(state->fe[index_frontend], 1); |
2987 | else | 3412 | if (index_frontend != 0) |
2988 | dib8096p_set_output_mode(state->fe[index_frontend], | 3413 | dib8000_set_output_mode(state->fe[index_frontend], |
2989 | OUTMODE_HIGH_Z); | 3414 | OUTMODE_DIVERSITY); |
3415 | else | ||
3416 | dib8000_set_output_mode(state->fe[0], OUTMODE_HIGH_Z); | ||
3417 | } else { | ||
3418 | dib8096p_set_diversity_in(state->fe[index_frontend], 1); | ||
3419 | if (index_frontend != 0) | ||
3420 | dib8096p_set_output_mode(state->fe[index_frontend], | ||
3421 | OUTMODE_DIVERSITY); | ||
3422 | else | ||
3423 | dib8096p_set_output_mode(state->fe[0], OUTMODE_HIGH_Z); | ||
3424 | } | ||
3425 | |||
3426 | /* tune the tuner */ | ||
2990 | if (state->fe[index_frontend]->ops.tuner_ops.set_params) | 3427 | if (state->fe[index_frontend]->ops.tuner_ops.set_params) |
2991 | state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend]); | 3428 | state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend]); |
2992 | 3429 | ||
2993 | dib8000_set_tune_state(state->fe[index_frontend], CT_AGC_START); | 3430 | dib8000_set_tune_state(state->fe[index_frontend], CT_AGC_START); |
2994 | } | 3431 | } |
2995 | 3432 | ||
3433 | /* turn off the diversity of the last chip */ | ||
3434 | if (state->revision != 0x8090) | ||
3435 | dib8000_set_diversity_in(state->fe[index_frontend - 1], 0); | ||
3436 | else | ||
3437 | dib8096p_set_diversity_in(state->fe[index_frontend - 1], 0); | ||
3438 | |||
2996 | /* start up the AGC */ | 3439 | /* start up the AGC */ |
2997 | do { | 3440 | do { |
2998 | time = dib8000_agc_startup(state->fe[0]); | 3441 | time = dib8000_agc_startup(state->fe[0]); |
@@ -3019,139 +3462,88 @@ static int dib8000_set_frontend(struct dvb_frontend *fe) | |||
3019 | for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) | 3462 | for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) |
3020 | dib8000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START); | 3463 | dib8000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START); |
3021 | 3464 | ||
3022 | if ((state->fe[0]->dtv_property_cache.delivery_system != SYS_ISDBT) || | 3465 | active = 1; |
3023 | (state->fe[0]->dtv_property_cache.inversion == INVERSION_AUTO) || | 3466 | do { |
3024 | (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) || | 3467 | callback_time = FE_CALLBACK_TIME_NEVER; |
3025 | (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) || | ||
3026 | (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) != 0) && | ||
3027 | (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0xff) && | ||
3028 | (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0) && | ||
3029 | ((state->fe[0]->dtv_property_cache.layer[0].modulation == QAM_AUTO) || | ||
3030 | (state->fe[0]->dtv_property_cache.layer[0].fec == FEC_AUTO))) || | ||
3031 | (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 1)) != 0) && | ||
3032 | (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0xff) && | ||
3033 | (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0) && | ||
3034 | ((state->fe[0]->dtv_property_cache.layer[1].modulation == QAM_AUTO) || | ||
3035 | (state->fe[0]->dtv_property_cache.layer[1].fec == FEC_AUTO))) || | ||
3036 | (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 2)) != 0) && | ||
3037 | (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0xff) && | ||
3038 | (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0) && | ||
3039 | ((state->fe[0]->dtv_property_cache.layer[2].modulation == QAM_AUTO) || | ||
3040 | (state->fe[0]->dtv_property_cache.layer[2].fec == FEC_AUTO))) || | ||
3041 | (((state->fe[0]->dtv_property_cache.layer[0].segment_count == 0) || | ||
3042 | ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) == 0)) && | ||
3043 | ((state->fe[0]->dtv_property_cache.layer[1].segment_count == 0) || | ||
3044 | ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (2 << 0)) == 0)) && | ||
3045 | ((state->fe[0]->dtv_property_cache.layer[2].segment_count == 0) || ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (3 << 0)) == 0)))) { | ||
3046 | int i = 100; | ||
3047 | u8 found = 0; | ||
3048 | u8 tune_failed = 0; | ||
3049 | |||
3050 | for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | 3468 | for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { |
3051 | dib8000_set_bandwidth(state->fe[index_frontend], fe->dtv_property_cache.bandwidth_hz / 1000); | 3469 | delay = dib8000_tune(state->fe[index_frontend]); |
3052 | dib8000_autosearch_start(state->fe[index_frontend]); | 3470 | if (delay != FE_CALLBACK_TIME_NEVER) |
3053 | } | 3471 | delay += systime(); |
3054 | 3472 | ||
3055 | do { | 3473 | /* we are in autosearch */ |
3056 | msleep(20); | 3474 | if (state->channel_parameters_set == 0) { /* searching */ |
3057 | nbr_pending = 0; | 3475 | if ((dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_DEMOD_SUCCESS) || (dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_FFT_SUCCESS)) { |
3058 | exit_condition = 0; /* 0: tune pending; 1: tune failed; 2:tune success */ | 3476 | dprintk("autosearch succeeded on fe%i", index_frontend); |
3059 | for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | 3477 | dib8000_get_frontend(state->fe[index_frontend]); /* we read the channel parameters from the frontend which was successful */ |
3060 | if (((tune_failed >> index_frontend) & 0x1) == 0) { | 3478 | state->channel_parameters_set = 1; |
3061 | found = dib8000_autosearch_irq(state->fe[index_frontend]); | 3479 | |
3062 | switch (found) { | 3480 | for (l = 0; (l < MAX_NUMBER_OF_FRONTENDS) && (state->fe[l] != NULL); l++) { |
3063 | case 0: /* tune pending */ | 3481 | if (l != index_frontend) { /* and for all frontend except the successful one */ |
3064 | nbr_pending++; | 3482 | dib8000_tune_restart_from_demod(state->fe[l]); |
3065 | break; | 3483 | |
3066 | case 2: | 3484 | state->fe[l]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode; |
3067 | dprintk("autosearch succeed on the frontend%i", index_frontend); | 3485 | state->fe[l]->dtv_property_cache.inversion = state->fe[index_frontend]->dtv_property_cache.inversion; |
3068 | exit_condition = 2; | 3486 | state->fe[l]->dtv_property_cache.transmission_mode = state->fe[index_frontend]->dtv_property_cache.transmission_mode; |
3069 | index_frontend_success = index_frontend; | 3487 | state->fe[l]->dtv_property_cache.guard_interval = state->fe[index_frontend]->dtv_property_cache.guard_interval; |
3070 | break; | 3488 | state->fe[l]->dtv_property_cache.isdbt_partial_reception = state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception; |
3071 | default: | 3489 | for (i = 0; i < 3; i++) { |
3072 | dprintk("unhandled autosearch result"); | 3490 | state->fe[l]->dtv_property_cache.layer[i].segment_count = state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count; |
3073 | case 1: | 3491 | state->fe[l]->dtv_property_cache.layer[i].interleaving = state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving; |
3074 | tune_failed |= (1 << index_frontend); | 3492 | state->fe[l]->dtv_property_cache.layer[i].fec = state->fe[index_frontend]->dtv_property_cache.layer[i].fec; |
3075 | dprintk("autosearch failed for the frontend%i", index_frontend); | 3493 | state->fe[l]->dtv_property_cache.layer[i].modulation = state->fe[index_frontend]->dtv_property_cache.layer[i].modulation; |
3076 | break; | 3494 | } |
3495 | |||
3496 | } | ||
3077 | } | 3497 | } |
3078 | } | 3498 | } |
3079 | } | 3499 | } |
3080 | 3500 | if (delay < callback_time) | |
3081 | /* if all tune are done and no success, exit: tune failed */ | 3501 | callback_time = delay; |
3082 | if ((nbr_pending == 0) && (exit_condition == 0)) | 3502 | } |
3083 | exit_condition = 1; | 3503 | /* tuning is done when the master frontend is done (failed or success) */ |
3084 | } while ((exit_condition == 0) && i--); | 3504 | if (dib8000_get_status(state->fe[0]) == FE_STATUS_TUNE_FAILED || |
3085 | 3505 | dib8000_get_status(state->fe[0]) == FE_STATUS_LOCKED || | |
3086 | if (exit_condition == 1) { /* tune failed */ | 3506 | dib8000_get_status(state->fe[0]) == FE_STATUS_DATA_LOCKED) { |
3087 | dprintk("tune failed"); | 3507 | active = 0; |
3088 | return 0; | 3508 | /* we need to wait for all frontends to be finished */ |
3509 | for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
3510 | if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_DEMOD_STOP) | ||
3511 | active = 1; | ||
3512 | } | ||
3513 | if (active == 0) | ||
3514 | dprintk("tuning done with status %d", dib8000_get_status(state->fe[0])); | ||
3089 | } | 3515 | } |
3090 | 3516 | ||
3091 | dprintk("tune success on frontend%i", index_frontend_success); | 3517 | if ((active == 1) && (callback_time == FE_CALLBACK_TIME_NEVER)) { |
3092 | 3518 | dprintk("strange callback time something went wrong"); | |
3093 | dib8000_get_frontend(fe); | 3519 | active = 0; |
3094 | } | 3520 | } |
3095 | 3521 | ||
3096 | for (index_frontend = 0, ret = 0; (ret >= 0) && (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) | 3522 | while ((active == 1) && (systime() < callback_time)) |
3097 | ret = dib8000_tune(state->fe[index_frontend]); | 3523 | msleep(100); |
3524 | } while (active); | ||
3098 | 3525 | ||
3099 | /* set output mode and diversity input */ | 3526 | /* set output mode */ |
3100 | if (state->revision != 0x8090) { | 3527 | if (state->revision != 0x8090) |
3101 | dib8000_set_output_mode(state->fe[0], state->cfg.output_mode); | 3528 | dib8000_set_output_mode(state->fe[0], state->cfg.output_mode); |
3102 | for (index_frontend = 1; | 3529 | else { |
3103 | (index_frontend < MAX_NUMBER_OF_FRONTENDS) && | ||
3104 | (state->fe[index_frontend] != NULL); | ||
3105 | index_frontend++) { | ||
3106 | dib8000_set_output_mode(state->fe[index_frontend], | ||
3107 | OUTMODE_DIVERSITY); | ||
3108 | dib8000_set_diversity_in(state->fe[index_frontend-1], 1); | ||
3109 | } | ||
3110 | |||
3111 | /* turn off the diversity of the last chip */ | ||
3112 | dib8000_set_diversity_in(state->fe[index_frontend-1], 0); | ||
3113 | } else { | ||
3114 | dib8096p_set_output_mode(state->fe[0], state->cfg.output_mode); | 3530 | dib8096p_set_output_mode(state->fe[0], state->cfg.output_mode); |
3115 | if (state->cfg.enMpegOutput == 0) { | 3531 | if (state->cfg.enMpegOutput == 0) { |
3116 | dib8096p_setDibTxMux(state, MPEG_ON_DIBTX); | 3532 | dib8096p_setDibTxMux(state, MPEG_ON_DIBTX); |
3117 | dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS); | 3533 | dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS); |
3118 | } | 3534 | } |
3119 | for (index_frontend = 1; | ||
3120 | (index_frontend < MAX_NUMBER_OF_FRONTENDS) && | ||
3121 | (state->fe[index_frontend] != NULL); | ||
3122 | index_frontend++) { | ||
3123 | dib8096p_set_output_mode(state->fe[index_frontend], | ||
3124 | OUTMODE_DIVERSITY); | ||
3125 | dib8096p_set_diversity_in(state->fe[index_frontend-1], 1); | ||
3126 | } | ||
3127 | |||
3128 | /* turn off the diversity of the last chip */ | ||
3129 | dib8096p_set_diversity_in(state->fe[index_frontend-1], 0); | ||
3130 | } | 3535 | } |
3131 | 3536 | ||
3132 | return ret; | 3537 | return ret; |
3133 | } | 3538 | } |
3134 | 3539 | ||
3135 | static u16 dib8000_read_lock(struct dvb_frontend *fe) | ||
3136 | { | ||
3137 | struct dib8000_state *state = fe->demodulator_priv; | ||
3138 | |||
3139 | if (state->revision == 0x8090) | ||
3140 | return dib8000_read_word(state, 570); | ||
3141 | return dib8000_read_word(state, 568); | ||
3142 | } | ||
3143 | |||
3144 | static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat) | 3540 | static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat) |
3145 | { | 3541 | { |
3146 | struct dib8000_state *state = fe->demodulator_priv; | 3542 | struct dib8000_state *state = fe->demodulator_priv; |
3147 | u16 lock_slave = 0, lock; | 3543 | u16 lock_slave = 0, lock; |
3148 | u8 index_frontend; | 3544 | u8 index_frontend; |
3149 | 3545 | ||
3150 | if (state->revision == 0x8090) | 3546 | lock = dib8000_read_lock(fe); |
3151 | lock = dib8000_read_word(state, 570); | ||
3152 | else | ||
3153 | lock = dib8000_read_word(state, 568); | ||
3154 | |||
3155 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) | 3547 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) |
3156 | lock_slave |= dib8000_read_lock(state->fe[index_frontend]); | 3548 | lock_slave |= dib8000_read_lock(state->fe[index_frontend]); |
3157 | 3549 | ||
@@ -3545,10 +3937,11 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s | |||
3545 | dib8000_reset(fe); | 3937 | dib8000_reset(fe); |
3546 | 3938 | ||
3547 | dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5)); /* ber_rs_len = 3 */ | 3939 | dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5)); /* ber_rs_len = 3 */ |
3940 | state->current_demod_bw = 6000; | ||
3548 | 3941 | ||
3549 | return fe; | 3942 | return fe; |
3550 | 3943 | ||
3551 | error: | 3944 | error: |
3552 | kfree(state); | 3945 | kfree(state); |
3553 | return NULL; | 3946 | return NULL; |
3554 | } | 3947 | } |
diff --git a/drivers/media/dvb-frontends/dib8000.h b/drivers/media/dvb-frontends/dib8000.h index 9e7a2b170d55..b8c11e52c512 100644 --- a/drivers/media/dvb-frontends/dib8000.h +++ b/drivers/media/dvb-frontends/dib8000.h | |||
@@ -33,6 +33,8 @@ struct dib8000_config { | |||
33 | u8 output_mode; | 33 | u8 output_mode; |
34 | u8 refclksel; | 34 | u8 refclksel; |
35 | u8 enMpegOutput:1; | 35 | u8 enMpegOutput:1; |
36 | |||
37 | struct dibx000_bandwidth_config *plltable; | ||
36 | }; | 38 | }; |
37 | 39 | ||
38 | #define DEFAULT_DIB8000_I2C_ADDRESS 18 | 40 | #define DEFAULT_DIB8000_I2C_ADDRESS 18 |
@@ -58,7 +60,7 @@ extern int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ); | |||
58 | extern u32 dib8000_ctrl_timf(struct dvb_frontend *fe, | 60 | extern u32 dib8000_ctrl_timf(struct dvb_frontend *fe, |
59 | uint8_t op, uint32_t timf); | 61 | uint8_t op, uint32_t timf); |
60 | extern int dib8000_update_pll(struct dvb_frontend *fe, | 62 | extern int dib8000_update_pll(struct dvb_frontend *fe, |
61 | struct dibx000_bandwidth_config *pll); | 63 | struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio); |
62 | extern int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave); | 64 | extern int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave); |
63 | extern int dib8000_remove_slave_frontend(struct dvb_frontend *fe); | 65 | extern int dib8000_remove_slave_frontend(struct dvb_frontend *fe); |
64 | extern struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index); | 66 | extern struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index); |
@@ -147,7 +149,7 @@ static inline u32 dib8000_ctrl_timf(struct dvb_frontend *fe, | |||
147 | return 0; | 149 | return 0; |
148 | } | 150 | } |
149 | static inline int dib8000_update_pll(struct dvb_frontend *fe, | 151 | static inline int dib8000_update_pll(struct dvb_frontend *fe, |
150 | struct dibx000_bandwidth_config *pll) | 152 | struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio) |
151 | { | 153 | { |
152 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 154 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
153 | return -ENODEV; | 155 | return -ENODEV; |
diff --git a/drivers/media/dvb-frontends/dibx000_common.h b/drivers/media/dvb-frontends/dibx000_common.h index 5f484881d7b1..b538e0555c95 100644 --- a/drivers/media/dvb-frontends/dibx000_common.h +++ b/drivers/media/dvb-frontends/dibx000_common.h | |||
@@ -193,7 +193,8 @@ enum frontend_tune_state { | |||
193 | CT_DEMOD_STEP_8, | 193 | CT_DEMOD_STEP_8, |
194 | CT_DEMOD_STEP_9, | 194 | CT_DEMOD_STEP_9, |
195 | CT_DEMOD_STEP_10, | 195 | CT_DEMOD_STEP_10, |
196 | CT_DEMOD_SEARCH_NEXT = 41, | 196 | CT_DEMOD_STEP_11, |
197 | CT_DEMOD_SEARCH_NEXT = 51, | ||
197 | CT_DEMOD_STEP_LOCKED, | 198 | CT_DEMOD_STEP_LOCKED, |
198 | CT_DEMOD_STOP, | 199 | CT_DEMOD_STOP, |
199 | 200 | ||