diff options
author | Patrick Boettcher <Patrick.Boettcher@dibcom.fr> | 2009-08-03 12:43:40 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-18 23:14:27 -0400 |
commit | 7e5ce6515d0deb76a49dcb4112a6dff5d950bfb6 (patch) | |
tree | b83f9dfd22cdd5e421715d86946f50eef2ec6ba6 /drivers/media/dvb | |
parent | e7b7949a95441affe937fa25f4d6d8f3df0ca271 (diff) |
V4L/DVB (12898): DiB0070: Update to latest internal release
General update of the dib0070-driver based on DiBcom's latest release.
New driver features can enable better performance in some reception situations.
Signed-off-by: Patrick Boettcher <Patrick.Boettcher@dibcom.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r-- | drivers/media/dvb/dvb-usb/dib0700_devices.c | 7 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dib0070.c | 673 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dib0070.h | 11 |
3 files changed, 407 insertions, 284 deletions
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 10a89b0e5189..10ade261b0ab 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c | |||
@@ -1098,11 +1098,13 @@ static struct dibx000_agc_config dib7070_agc_config = { | |||
1098 | 1098 | ||
1099 | static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) | 1099 | static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) |
1100 | { | 1100 | { |
1101 | deb_info("reset: %d", onoff); | ||
1101 | return dib7000p_set_gpio(fe, 8, 0, !onoff); | 1102 | return dib7000p_set_gpio(fe, 8, 0, !onoff); |
1102 | } | 1103 | } |
1103 | 1104 | ||
1104 | static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) | 1105 | static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) |
1105 | { | 1106 | { |
1107 | deb_info("sleep: %d", onoff); | ||
1106 | return dib7000p_set_gpio(fe, 9, 0, onoff); | 1108 | return dib7000p_set_gpio(fe, 9, 0, onoff); |
1107 | } | 1109 | } |
1108 | 1110 | ||
@@ -1112,13 +1114,14 @@ static struct dib0070_config dib7070p_dib0070_config[2] = { | |||
1112 | .reset = dib7070_tuner_reset, | 1114 | .reset = dib7070_tuner_reset, |
1113 | .sleep = dib7070_tuner_sleep, | 1115 | .sleep = dib7070_tuner_sleep, |
1114 | .clock_khz = 12000, | 1116 | .clock_khz = 12000, |
1115 | .clock_pad_drive = 4 | 1117 | .clock_pad_drive = 4, |
1118 | .charge_pump = 2, | ||
1116 | }, { | 1119 | }, { |
1117 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, | 1120 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, |
1118 | .reset = dib7070_tuner_reset, | 1121 | .reset = dib7070_tuner_reset, |
1119 | .sleep = dib7070_tuner_sleep, | 1122 | .sleep = dib7070_tuner_sleep, |
1120 | .clock_khz = 12000, | 1123 | .clock_khz = 12000, |
1121 | 1124 | .charge_pump = 2, | |
1122 | } | 1125 | } |
1123 | }; | 1126 | }; |
1124 | 1127 | ||
diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c index da92cbe1b8ea..2eb9bdb4dbb3 100644 --- a/drivers/media/dvb/frontends/dib0070.c +++ b/drivers/media/dvb/frontends/dib0070.c | |||
@@ -1,12 +1,29 @@ | |||
1 | /* | 1 | /* |
2 | * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner. | 2 | * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner. |
3 | * | 3 | * |
4 | * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/) | 4 | * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License as | 7 | * modify it under the terms of the GNU General Public License as |
8 | * published by the Free Software Foundation, version 2. | 8 | * published by the Free Software Foundation; either version 2 of the |
9 | * License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | * | ||
22 | * This code is more or less generated from another driver, please | ||
23 | * excuse some codingstyle oddities. | ||
24 | * | ||
9 | */ | 25 | */ |
26 | |||
10 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
11 | #include <linux/i2c.h> | 28 | #include <linux/i2c.h> |
12 | 29 | ||
@@ -19,19 +36,57 @@ static int debug; | |||
19 | module_param(debug, int, 0644); | 36 | module_param(debug, int, 0644); |
20 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | 37 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); |
21 | 38 | ||
22 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB0070: "); printk(args); printk("\n"); } } while (0) | 39 | #define dprintk(args...) do { \ |
40 | if (debug) { \ | ||
41 | printk(KERN_DEBUG "DiB0070: "); \ | ||
42 | printk(args); \ | ||
43 | printk("\n"); \ | ||
44 | } \ | ||
45 | } while (0) | ||
23 | 46 | ||
24 | #define DIB0070_P1D 0x00 | 47 | #define DIB0070_P1D 0x00 |
25 | #define DIB0070_P1F 0x01 | 48 | #define DIB0070_P1F 0x01 |
26 | #define DIB0070_P1G 0x03 | 49 | #define DIB0070_P1G 0x03 |
27 | #define DIB0070S_P1A 0x02 | 50 | #define DIB0070S_P1A 0x02 |
28 | 51 | ||
52 | enum frontend_tune_state { | ||
53 | CT_TUNER_START = 10, | ||
54 | CT_TUNER_STEP_0, | ||
55 | CT_TUNER_STEP_1, | ||
56 | CT_TUNER_STEP_2, | ||
57 | CT_TUNER_STEP_3, | ||
58 | CT_TUNER_STEP_4, | ||
59 | CT_TUNER_STEP_5, | ||
60 | CT_TUNER_STEP_6, | ||
61 | CT_TUNER_STEP_7, | ||
62 | CT_TUNER_STOP, | ||
63 | }; | ||
64 | |||
65 | #define FE_CALLBACK_TIME_NEVER 0xffffffff | ||
66 | |||
29 | struct dib0070_state { | 67 | struct dib0070_state { |
30 | struct i2c_adapter *i2c; | 68 | struct i2c_adapter *i2c; |
31 | struct dvb_frontend *fe; | 69 | struct dvb_frontend *fe; |
32 | const struct dib0070_config *cfg; | 70 | const struct dib0070_config *cfg; |
33 | u16 wbd_ff_offset; | 71 | u16 wbd_ff_offset; |
34 | u8 revision; | 72 | u8 revision; |
73 | |||
74 | enum frontend_tune_state tune_state; | ||
75 | u32 current_rf; | ||
76 | |||
77 | /* for the captrim binary search */ | ||
78 | s8 step; | ||
79 | u16 adc_diff; | ||
80 | |||
81 | s8 captrim; | ||
82 | s8 fcaptrim; | ||
83 | u16 lo4; | ||
84 | |||
85 | const struct dib0070_tuning *current_tune_table_index; | ||
86 | const struct dib0070_lna_match *lna_match; | ||
87 | |||
88 | u8 wbd_gain_current; | ||
89 | u16 wbd_offset_3_3[2]; | ||
35 | }; | 90 | }; |
36 | 91 | ||
37 | static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) | 92 | static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) |
@@ -59,55 +114,71 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) | |||
59 | return 0; | 114 | return 0; |
60 | } | 115 | } |
61 | 116 | ||
62 | #define HARD_RESET(state) do { if (state->cfg->reset) { state->cfg->reset(state->fe,1); msleep(10); state->cfg->reset(state->fe,0); msleep(10); } } while (0) | 117 | #define HARD_RESET(state) do { \ |
118 | state->cfg->sleep(state->fe, 0); \ | ||
119 | if (state->cfg->reset) { \ | ||
120 | state->cfg->reset(state->fe,1); msleep(10); \ | ||
121 | state->cfg->reset(state->fe,0); msleep(10); \ | ||
122 | } \ | ||
123 | } while (0) | ||
63 | 124 | ||
64 | static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) | 125 | static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) |
65 | { | 126 | { |
66 | struct dib0070_state *st = fe->tuner_priv; | 127 | struct dib0070_state *st = fe->tuner_priv; |
67 | u16 tmp = 0; | 128 | u16 tmp = dib0070_read_reg(st, 0x02) & 0x3fff; |
68 | tmp = dib0070_read_reg(st, 0x02) & 0x3fff; | 129 | |
69 | 130 | if (fe->dtv_property_cache.bandwidth_hz/1000 > 7000) | |
70 | switch(BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth)) { | 131 | tmp |= (0 << 14); |
71 | case 8000: | 132 | else if (fe->dtv_property_cache.bandwidth_hz/1000 > 6000) |
72 | tmp |= (0 << 14); | 133 | tmp |= (1 << 14); |
73 | break; | 134 | else if (fe->dtv_property_cache.bandwidth_hz/1000 > 5000) |
74 | case 7000: | 135 | tmp |= (2 << 14); |
75 | tmp |= (1 << 14); | 136 | else |
76 | break; | 137 | tmp |= (3 << 14); |
77 | case 6000: | 138 | |
78 | tmp |= (2 << 14); | 139 | dib0070_write_reg(st, 0x02, tmp); |
79 | break; | 140 | |
80 | case 5000: | 141 | /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */ |
81 | default: | 142 | if (fe->dtv_property_cache.delivery_system == SYS_ISDBT) { |
82 | tmp |= (3 << 14); | 143 | u16 value = dib0070_read_reg(st, 0x17); |
83 | break; | 144 | |
84 | } | 145 | dib0070_write_reg(st, 0x17, value & 0xfffc); |
85 | dib0070_write_reg(st, 0x02, tmp); | 146 | tmp = dib0070_read_reg(st, 0x01) & 0x01ff; |
147 | dib0070_write_reg(st, 0x01, tmp | (60 << 9)); | ||
148 | |||
149 | dib0070_write_reg(st, 0x17, value); | ||
150 | } | ||
86 | return 0; | 151 | return 0; |
87 | } | 152 | } |
88 | 153 | ||
89 | static void dib0070_captrim(struct dib0070_state *st, u16 LO4) | 154 | static int dib0070_captrim(struct dib0070_state *st, enum frontend_tune_state *tune_state) |
90 | { | 155 | { |
91 | int8_t captrim, fcaptrim, step_sign, step; | 156 | int8_t step_sign; |
92 | u16 adc, adc_diff = 3000; | 157 | u16 adc; |
158 | int ret = 0; | ||
93 | 159 | ||
160 | if (*tune_state == CT_TUNER_STEP_0) { | ||
94 | 161 | ||
162 | dib0070_write_reg(st, 0x0f, 0xed10); | ||
163 | dib0070_write_reg(st, 0x17, 0x0034); | ||
95 | 164 | ||
96 | dib0070_write_reg(st, 0x0f, 0xed10); | 165 | dib0070_write_reg(st, 0x18, 0x0032); |
97 | dib0070_write_reg(st, 0x17, 0x0034); | 166 | st->step = st->captrim = st->fcaptrim = 64; |
167 | st->adc_diff = 3000; | ||
168 | ret = 20; | ||
98 | 169 | ||
99 | dib0070_write_reg(st, 0x18, 0x0032); | 170 | *tune_state = CT_TUNER_STEP_1; |
100 | msleep(2); | 171 | } else if (*tune_state == CT_TUNER_STEP_1) { |
172 | st->step /= 2; | ||
173 | dib0070_write_reg(st, 0x14, st->lo4 | st->captrim); | ||
174 | ret = 15; | ||
101 | 175 | ||
102 | step = captrim = fcaptrim = 64; | 176 | *tune_state = CT_TUNER_STEP_2; |
177 | } else if (*tune_state == CT_TUNER_STEP_2) { | ||
103 | 178 | ||
104 | do { | ||
105 | step /= 2; | ||
106 | dib0070_write_reg(st, 0x14, LO4 | captrim); | ||
107 | msleep(1); | ||
108 | adc = dib0070_read_reg(st, 0x19); | 179 | adc = dib0070_read_reg(st, 0x19); |
109 | 180 | ||
110 | dprintk( "CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", captrim, adc, (u32) adc*(u32)1800/(u32)1024); | 181 | dprintk( "CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", st->captrim, adc, (u32) adc*(u32)1800/(u32)1024); |
111 | 182 | ||
112 | if (adc >= 400) { | 183 | if (adc >= 400) { |
113 | adc -= 400; | 184 | adc -= 400; |
@@ -117,266 +188,305 @@ static void dib0070_captrim(struct dib0070_state *st, u16 LO4) | |||
117 | step_sign = 1; | 188 | step_sign = 1; |
118 | } | 189 | } |
119 | 190 | ||
120 | if (adc < adc_diff) { | 191 | if (adc < st->adc_diff) { |
121 | dprintk( "CAPTRIM=%hd is closer to target (%hd/%hd)", captrim, adc, adc_diff); | 192 | dprintk( "CAPTRIM=%hd is closer to target (%hd/%hd)", st->captrim, adc, st->adc_diff); |
122 | adc_diff = adc; | 193 | st->adc_diff = adc; |
123 | fcaptrim = captrim; | 194 | st->fcaptrim = st->captrim; |
124 | 195 | ||
125 | 196 | ||
126 | 197 | ||
127 | } | 198 | } |
128 | captrim += (step_sign * step); | 199 | st->captrim += (step_sign * st->step); |
129 | } while (step >= 1); | 200 | |
201 | if (st->step >= 1) | ||
202 | *tune_state = CT_TUNER_STEP_1; | ||
203 | else | ||
204 | *tune_state = CT_TUNER_STEP_3; | ||
205 | |||
206 | } else if (*tune_state == CT_TUNER_STEP_3) { | ||
207 | dib0070_write_reg(st, 0x14, st->lo4 | st->fcaptrim); | ||
208 | dib0070_write_reg(st, 0x18, 0x07ff); | ||
209 | *tune_state = CT_TUNER_STEP_4; | ||
210 | } | ||
130 | 211 | ||
131 | dib0070_write_reg(st, 0x14, LO4 | fcaptrim); | 212 | return ret; |
132 | dib0070_write_reg(st, 0x18, 0x07ff); | ||
133 | } | 213 | } |
134 | 214 | ||
135 | #define LPF 100 // define for the loop filter 100kHz by default 16-07-06 | 215 | static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt) |
136 | #define LO4_SET_VCO_HFDIV(l, v, h) l |= ((v) << 11) | ((h) << 7) | ||
137 | #define LO4_SET_SD(l, s) l |= ((s) << 14) | ((s) << 12) | ||
138 | #define LO4_SET_CTRIM(l, c) l |= (c) << 10 | ||
139 | static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) | ||
140 | { | 216 | { |
141 | struct dib0070_state *st = fe->tuner_priv; | 217 | struct dib0070_state *state = fe->tuner_priv; |
142 | u32 freq = ch->frequency/1000 + (BAND_OF_FREQUENCY(ch->frequency/1000) == BAND_VHF ? st->cfg->freq_offset_khz_vhf : st->cfg->freq_offset_khz_uhf); | 218 | u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0); |
219 | dprintk( "CTRL_LO5: 0x%x", lo5); | ||
220 | return dib0070_write_reg(state, 0x15, lo5); | ||
221 | } | ||
143 | 222 | ||
144 | u8 band = BAND_OF_FREQUENCY(freq), c; | 223 | struct dib0070_tuning |
224 | { | ||
225 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ | ||
226 | u8 switch_trim; | ||
227 | u8 vco_band; | ||
228 | u8 hfdiv; | ||
229 | u8 vco_multi; | ||
230 | u8 presc; | ||
231 | u8 wbdmux; | ||
232 | u16 tuner_enable; | ||
233 | }; | ||
145 | 234 | ||
146 | /*******************VCO***********************************/ | 235 | struct dib0070_lna_match |
147 | u16 lo4 = 0; | 236 | { |
237 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ | ||
238 | u8 lna_band; | ||
239 | }; | ||
148 | 240 | ||
149 | u8 REFDIV, PRESC = 2; | 241 | static const struct dib0070_tuning dib0070s_tuning_table[] = |
150 | u32 FBDiv, Rest, FREF, VCOF_kHz; | ||
151 | u16 Num, Den; | ||
152 | /*******************FrontEnd******************************/ | ||
153 | u16 value = 0; | ||
154 | 242 | ||
155 | dprintk( "Tuning for Band: %hd (%d kHz)", band, freq); | 243 | { |
244 | { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */ | ||
245 | { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 }, | ||
246 | { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 }, | ||
247 | { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */ | ||
248 | { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, | ||
249 | { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, | ||
250 | { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */ | ||
251 | }; | ||
156 | 252 | ||
253 | static const struct dib0070_tuning dib0070_tuning_table[] = | ||
157 | 254 | ||
158 | dib0070_write_reg(st, 0x17, 0x30); | 255 | { |
256 | { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */ | ||
257 | { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */ | ||
258 | { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 }, | ||
259 | { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 }, | ||
260 | { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */ | ||
261 | { 699999, 2, 0 ,1, 4, 2, 2, 0x4000 | 0x0800 }, | ||
262 | { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 }, | ||
263 | { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */ | ||
264 | }; | ||
159 | 265 | ||
160 | dib0070_set_bandwidth(fe, ch); /* c is used as HF */ | 266 | static const struct dib0070_lna_match dib0070_lna_flip_chip[] = |
161 | switch (st->revision) { | ||
162 | case DIB0070S_P1A: | ||
163 | switch (band) { | ||
164 | case BAND_LBAND: | ||
165 | LO4_SET_VCO_HFDIV(lo4, 1, 1); | ||
166 | c = 2; | ||
167 | break; | ||
168 | case BAND_SBAND: | ||
169 | LO4_SET_VCO_HFDIV(lo4, 0, 0); | ||
170 | LO4_SET_CTRIM(lo4, 1); | ||
171 | c = 1; | ||
172 | break; | ||
173 | case BAND_UHF: | ||
174 | default: | ||
175 | if (freq < 570000) { | ||
176 | LO4_SET_VCO_HFDIV(lo4, 1, 3); | ||
177 | PRESC = 6; c = 6; | ||
178 | } else if (freq < 680000) { | ||
179 | LO4_SET_VCO_HFDIV(lo4, 0, 2); | ||
180 | c = 4; | ||
181 | } else { | ||
182 | LO4_SET_VCO_HFDIV(lo4, 1, 2); | ||
183 | c = 4; | ||
184 | } | ||
185 | break; | ||
186 | } break; | ||
187 | |||
188 | case DIB0070_P1G: | ||
189 | case DIB0070_P1F: | ||
190 | default: | ||
191 | switch (band) { | ||
192 | case BAND_FM: | ||
193 | LO4_SET_VCO_HFDIV(lo4, 0, 7); | ||
194 | c = 24; | ||
195 | break; | ||
196 | case BAND_LBAND: | ||
197 | LO4_SET_VCO_HFDIV(lo4, 1, 0); | ||
198 | c = 2; | ||
199 | break; | ||
200 | case BAND_VHF: | ||
201 | if (freq < 180000) { | ||
202 | LO4_SET_VCO_HFDIV(lo4, 0, 3); | ||
203 | c = 16; | ||
204 | } else if (freq < 190000) { | ||
205 | LO4_SET_VCO_HFDIV(lo4, 1, 3); | ||
206 | c = 16; | ||
207 | } else { | ||
208 | LO4_SET_VCO_HFDIV(lo4, 0, 6); | ||
209 | c = 12; | ||
210 | } | ||
211 | break; | ||
212 | |||
213 | case BAND_UHF: | ||
214 | default: | ||
215 | if (freq < 570000) { | ||
216 | LO4_SET_VCO_HFDIV(lo4, 1, 5); | ||
217 | c = 6; | ||
218 | } else if (freq < 700000) { | ||
219 | LO4_SET_VCO_HFDIV(lo4, 0, 1); | ||
220 | c = 4; | ||
221 | } else { | ||
222 | LO4_SET_VCO_HFDIV(lo4, 1, 1); | ||
223 | c = 4; | ||
224 | } | ||
225 | break; | ||
226 | } | ||
227 | break; | ||
228 | } | ||
229 | 267 | ||
230 | dprintk( "HFDIV code: %hd", (lo4 >> 7) & 0xf); | 268 | { |
231 | dprintk( "VCO = %hd", (lo4 >> 11) & 0x3); | 269 | { 180000, 0 }, /* VHF */ |
270 | { 188000, 1 }, | ||
271 | { 196400, 2 }, | ||
272 | { 250000, 3 }, | ||
273 | { 550000, 0 }, /* UHF */ | ||
274 | { 590000, 1 }, | ||
275 | { 666000, 3 }, | ||
276 | { 864000, 5 }, | ||
277 | { 1500000, 0 }, /* LBAND or everything higher than UHF */ | ||
278 | { 1600000, 1 }, | ||
279 | { 2000000, 3 }, | ||
280 | { 0xffffffff, 7 }, | ||
281 | }; | ||
232 | 282 | ||
283 | static const struct dib0070_lna_match dib0070_lna[] = | ||
233 | 284 | ||
234 | VCOF_kHz = (c * freq) * 2; | 285 | { |
235 | dprintk( "VCOF in kHz: %d ((%hd*%d) << 1))",VCOF_kHz, c, freq); | 286 | { 180000, 0 }, /* VHF */ |
287 | { 188000, 1 }, | ||
288 | { 196400, 2 }, | ||
289 | { 250000, 3 }, | ||
290 | { 550000, 2 }, /* UHF */ | ||
291 | { 650000, 3 }, | ||
292 | { 750000, 5 }, | ||
293 | { 850000, 6 }, | ||
294 | { 864000, 7 }, | ||
295 | { 1500000, 0 }, /* LBAND or everything higher than UHF */ | ||
296 | { 1600000, 1 }, | ||
297 | { 2000000, 3 }, | ||
298 | { 0xffffffff, 7 }, | ||
299 | }; | ||
236 | 300 | ||
237 | switch (band) { | 301 | #define LPF 100 // define for the loop filter 100kHz by default 16-07-06 |
238 | case BAND_VHF: | 302 | static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) |
239 | REFDIV = (u8) ((st->cfg->clock_khz + 9999) / 10000); | 303 | { |
240 | break; | 304 | struct dib0070_state *st = fe->tuner_priv; |
241 | case BAND_FM: | 305 | |
242 | REFDIV = (u8) ((st->cfg->clock_khz) / 1000); | 306 | const struct dib0070_tuning *tune; |
243 | break; | 307 | const struct dib0070_lna_match *lna_match; |
244 | default: | 308 | |
245 | REFDIV = (u8) ( st->cfg->clock_khz / 10000); | 309 | enum frontend_tune_state *tune_state = &st->tune_state; |
246 | break; | 310 | int ret = 10; /* 1ms is the default delay most of the time */ |
247 | } | ||
248 | FREF = st->cfg->clock_khz / REFDIV; | ||
249 | 311 | ||
250 | dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF); | 312 | u8 band = (u8)BAND_OF_FREQUENCY(ch->frequency/1000); |
313 | u32 freq = ch->frequency/1000 + (band == BAND_VHF ? st->cfg->freq_offset_khz_vhf : st->cfg->freq_offset_khz_uhf); | ||
251 | 314 | ||
252 | 315 | ||
253 | 316 | ||
317 | |||
318 | |||
319 | #ifdef CONFIG_STANDARD_ISDBT | ||
320 | if (fe->dtv_property_cache.delivery_system == SYS_ISDBT && ch->u.isdbt.sb_mode == 1) | ||
321 | if ( ( (ch->u.isdbt.sb_conn_total_seg % 2) && (ch->u.isdbt.sb_wanted_seg == ((ch->u.isdbt.sb_conn_total_seg/2) + 1) ) ) || | ||
322 | ( ( (ch->u.isdbt.sb_conn_total_seg % 2) == 0) && (ch->u.isdbt.sb_wanted_seg == (ch->u.isdbt.sb_conn_total_seg/2) ) ) || | ||
323 | ( ( (ch->u.isdbt.sb_conn_total_seg % 2) == 0) && (ch->u.isdbt.sb_wanted_seg == ((ch->u.isdbt.sb_conn_total_seg/2)+1))) ) | ||
324 | freq += 850; | ||
325 | #endif | ||
326 | if (st->current_rf != freq) { | ||
327 | |||
254 | switch (st->revision) { | 328 | switch (st->revision) { |
255 | case DIB0070S_P1A: | 329 | case DIB0070S_P1A: |
256 | FBDiv = (VCOF_kHz / PRESC / FREF); | 330 | tune = dib0070s_tuning_table; |
257 | Rest = (VCOF_kHz / PRESC) - FBDiv * FREF; | 331 | lna_match = dib0070_lna; |
258 | break; | 332 | break; |
259 | 333 | default: | |
260 | case DIB0070_P1G: | 334 | tune = dib0070_tuning_table; |
261 | case DIB0070_P1F: | 335 | if (st->cfg->flip_chip) |
262 | default: | 336 | lna_match = dib0070_lna_flip_chip; |
263 | FBDiv = (freq / (FREF / 2)); | 337 | else |
264 | Rest = 2 * freq - FBDiv * FREF; | 338 | lna_match = dib0070_lna; |
265 | break; | 339 | break; |
266 | } | 340 | } |
341 | while (freq > tune->max_freq) /* find the right one */ | ||
342 | tune++; | ||
343 | while (freq > lna_match->max_freq) /* find the right one */ | ||
344 | lna_match++; | ||
267 | 345 | ||
346 | st->current_tune_table_index = tune; | ||
347 | st->lna_match = lna_match; | ||
348 | } | ||
268 | 349 | ||
269 | if (Rest < LPF) Rest = 0; | 350 | if (*tune_state == CT_TUNER_START) { |
270 | else if (Rest < 2 * LPF) Rest = 2 * LPF; | 351 | dprintk( "Tuning for Band: %hd (%d kHz)", band, freq); |
271 | else if (Rest > (FREF - LPF)) { Rest = 0 ; FBDiv += 1; } | 352 | if (st->current_rf != freq) { |
272 | else if (Rest > (FREF - 2 * LPF)) Rest = FREF - 2 * LPF; | 353 | u8 REFDIV; |
273 | Rest = (Rest * 6528) / (FREF / 10); | 354 | u32 FBDiv, Rest, FREF, VCOF_kHz; |
274 | dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest); | 355 | u8 Den; |
275 | 356 | ||
276 | Num = 0; | 357 | st->current_rf = freq; |
277 | Den = 1; | 358 | st->lo4 = (st->current_tune_table_index->vco_band << 11) | (st->current_tune_table_index->hfdiv << 7); |
278 | 359 | ||
279 | if (Rest > 0) { | ||
280 | LO4_SET_SD(lo4, 1); | ||
281 | Den = 255; | ||
282 | Num = (u16)Rest; | ||
283 | } | ||
284 | dprintk( "Num: %hd, Den: %hd, SD: %hd",Num, Den, (lo4 >> 12) & 0x1); | ||
285 | 360 | ||
361 | dib0070_write_reg(st, 0x17, 0x30); | ||
286 | 362 | ||
287 | 363 | ||
288 | dib0070_write_reg(st, 0x11, (u16)FBDiv); | 364 | VCOF_kHz = st->current_tune_table_index->vco_multi * freq * 2; |
289 | 365 | ||
366 | switch (band) { | ||
367 | case BAND_VHF: | ||
368 | REFDIV = (u8) ((st->cfg->clock_khz + 9999) / 10000); | ||
369 | break; | ||
370 | case BAND_FM: | ||
371 | REFDIV = (u8) ((st->cfg->clock_khz) / 1000); | ||
372 | break; | ||
373 | default: | ||
374 | REFDIV = (u8) ( st->cfg->clock_khz / 10000); | ||
375 | break; | ||
376 | } | ||
377 | FREF = st->cfg->clock_khz / REFDIV; | ||
290 | 378 | ||
291 | dib0070_write_reg(st, 0x12, (Den << 8) | REFDIV); | ||
292 | 379 | ||
293 | 380 | ||
294 | dib0070_write_reg(st, 0x13, Num); | 381 | switch (st->revision) { |
382 | case DIB0070S_P1A: | ||
383 | FBDiv = (VCOF_kHz / st->current_tune_table_index->presc / FREF); | ||
384 | Rest = (VCOF_kHz / st->current_tune_table_index->presc) - FBDiv * FREF; | ||
385 | break; | ||
295 | 386 | ||
387 | case DIB0070_P1G: | ||
388 | case DIB0070_P1F: | ||
389 | default: | ||
390 | FBDiv = (freq / (FREF / 2)); | ||
391 | Rest = 2 * freq - FBDiv * FREF; | ||
392 | break; | ||
393 | } | ||
296 | 394 | ||
297 | value = 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001; | ||
298 | 395 | ||
299 | switch (band) { | 396 | if (Rest < LPF) Rest = 0; |
300 | case BAND_UHF: value |= 0x4000 | 0x0800; break; | 397 | else if (Rest < 2 * LPF) Rest = 2 * LPF; |
301 | case BAND_LBAND: value |= 0x2000 | 0x0400; break; | 398 | else if (Rest > (FREF - LPF)) { Rest = 0 ; FBDiv += 1; } |
302 | default: value |= 0x8000 | 0x1000; break; | 399 | else if (Rest > (FREF - 2 * LPF)) Rest = FREF - 2 * LPF; |
303 | } | 400 | Rest = (Rest * 6528) / (FREF / 10); |
304 | dib0070_write_reg(st, 0x20, value); | ||
305 | 401 | ||
306 | dib0070_captrim(st, lo4); | 402 | Den = 1; |
307 | if (st->revision == DIB0070S_P1A) { | 403 | if (Rest > 0) { |
308 | if (band == BAND_SBAND) | 404 | st->lo4 |= (1 << 14) | (1 << 12); |
309 | dib0070_write_reg(st, 0x15, 0x16e2); | 405 | Den = 255; |
310 | else | 406 | } |
311 | dib0070_write_reg(st, 0x15, 0x56e5); | ||
312 | } | ||
313 | 407 | ||
314 | 408 | ||
409 | dib0070_write_reg(st, 0x11, (u16)FBDiv); | ||
410 | dib0070_write_reg(st, 0x12, (Den << 8) | REFDIV); | ||
411 | dib0070_write_reg(st, 0x13, (u16) Rest); | ||
315 | 412 | ||
316 | switch (band) { | 413 | if (st->revision == DIB0070S_P1A) { |
317 | case BAND_UHF: value = 0x7c82; break; | ||
318 | case BAND_LBAND: value = 0x7c84; break; | ||
319 | default: value = 0x7c81; break; | ||
320 | } | ||
321 | dib0070_write_reg(st, 0x0f, value); | ||
322 | dib0070_write_reg(st, 0x06, 0x3fff); | ||
323 | 414 | ||
324 | /* Front End */ | 415 | if (band == BAND_SBAND) { |
325 | /* c == TUNE, value = SWITCH */ | 416 | dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); |
326 | c = 0; | 417 | dib0070_write_reg(st, 0x1d,0xFFFF); |
327 | value = 0; | 418 | } else |
328 | switch (band) { | 419 | dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1); |
329 | case BAND_FM: | 420 | } |
330 | c = 0; value = 1; | ||
331 | break; | ||
332 | 421 | ||
333 | case BAND_VHF: | ||
334 | if (freq <= 180000) c = 0; | ||
335 | else if (freq <= 188200) c = 1; | ||
336 | else if (freq <= 196400) c = 2; | ||
337 | else c = 3; | ||
338 | value = 1; | ||
339 | break; | ||
340 | 422 | ||
341 | case BAND_LBAND: | 423 | dib0070_write_reg(st, 0x20, 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | st->current_tune_table_index->tuner_enable); |
342 | if (freq <= 1500000) c = 0; | ||
343 | else if (freq <= 1600000) c = 1; | ||
344 | else c = 3; | ||
345 | break; | ||
346 | 424 | ||
347 | case BAND_SBAND: | 425 | dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF); |
348 | c = 7; | 426 | dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest); |
349 | dib0070_write_reg(st, 0x1d,0xFFFF); | 427 | dprintk( "Num: %hd, Den: %hd, SD: %hd",(u16) Rest, Den, (st->lo4 >> 12) & 0x1); |
350 | break; | 428 | dprintk( "HFDIV code: %hd", st->current_tune_table_index->hfdiv); |
429 | dprintk( "VCO = %hd", st->current_tune_table_index->vco_band); | ||
430 | dprintk( "VCOF: ((%hd*%d) << 1))", st->current_tune_table_index->vco_multi, freq); | ||
351 | 431 | ||
352 | case BAND_UHF: | 432 | *tune_state = CT_TUNER_STEP_0; |
353 | default: | 433 | } else { /* we are already tuned to this frequency - the configuration is correct */ |
354 | if (st->cfg->flip_chip) { | 434 | ret = 50; /* wakeup time */ |
355 | if (freq <= 550000) c = 0; | 435 | *tune_state = CT_TUNER_STEP_5; |
356 | else if (freq <= 590000) c = 1; | 436 | } |
357 | else if (freq <= 666000) c = 3; | 437 | } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) { |
358 | else c = 5; | 438 | |
359 | } else { | 439 | ret = dib0070_captrim(st, tune_state); |
360 | if (freq <= 550000) c = 2; | 440 | |
361 | else if (freq <= 650000) c = 3; | 441 | } else if (*tune_state == CT_TUNER_STEP_4) { |
362 | else if (freq <= 750000) c = 5; | 442 | const struct dib0070_wbd_gain_cfg *tmp = st->cfg->wbd_gain; |
363 | else if (freq <= 850000) c = 6; | 443 | if (tmp != NULL) { |
364 | else c = 7; | 444 | while (freq/1000 > tmp->freq) /* find the right one */ |
365 | } | 445 | tmp++; |
366 | value = 2; | 446 | dib0070_write_reg(st, 0x0f, (0 << 15) | (1 << 14) | (3 << 12) | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) | (st->current_tune_table_index->wbdmux << 0)); |
367 | break; | 447 | st->wbd_gain_current = tmp->wbd_gain_val; |
448 | } else { | ||
449 | dib0070_write_reg(st, 0x0f, (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (st->current_tune_table_index->wbdmux << 0)); | ||
450 | st->wbd_gain_current = 6; | ||
368 | } | 451 | } |
369 | 452 | ||
370 | /* default: LNA_MATCH=7, BIAS=3 */ | 453 | dib0070_write_reg(st, 0x06, 0x3fff); |
371 | dib0070_write_reg(st, 0x07, (value << 11) | (7 << 8) | (c << 3) | (3 << 0)); | 454 | dib0070_write_reg(st, 0x07, (st->current_tune_table_index->switch_trim << 11) | (7 << 8) | (st->lna_match->lna_band << 3) | (3 << 0)); |
372 | dib0070_write_reg(st, 0x08, (c << 10) | (3 << 7) | (127)); | 455 | dib0070_write_reg(st, 0x08, (st->lna_match->lna_band << 10) | (3 << 7) | (127)); |
373 | dib0070_write_reg(st, 0x0d, 0x0d80); | 456 | dib0070_write_reg(st, 0x0d, 0x0d80); |
374 | 457 | ||
375 | 458 | ||
376 | dib0070_write_reg(st, 0x18, 0x07ff); | 459 | dib0070_write_reg(st, 0x18, 0x07ff); |
377 | dib0070_write_reg(st, 0x17, 0x0033); | 460 | dib0070_write_reg(st, 0x17, 0x0033); |
378 | 461 | ||
379 | return 0; | 462 | |
463 | *tune_state = CT_TUNER_STEP_5; | ||
464 | } else if (*tune_state == CT_TUNER_STEP_5) { | ||
465 | dib0070_set_bandwidth(fe, ch); | ||
466 | *tune_state = CT_TUNER_STOP; | ||
467 | } else { | ||
468 | ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */ | ||
469 | } | ||
470 | return ret; | ||
471 | } | ||
472 | |||
473 | |||
474 | static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) | ||
475 | { | ||
476 | struct dib0070_state *state = fe->tuner_priv; | ||
477 | uint32_t ret; | ||
478 | |||
479 | state->tune_state = CT_TUNER_START; | ||
480 | |||
481 | do { | ||
482 | ret = dib0070_tune_digital(fe, p); | ||
483 | if (ret != FE_CALLBACK_TIME_NEVER) | ||
484 | msleep(ret/10); | ||
485 | else | ||
486 | break; | ||
487 | } while (state->tune_state != CT_TUNER_STOP); | ||
488 | |||
489 | return 0; | ||
380 | } | 490 | } |
381 | 491 | ||
382 | static int dib0070_wakeup(struct dvb_frontend *fe) | 492 | static int dib0070_wakeup(struct dvb_frontend *fe) |
@@ -395,7 +505,7 @@ static int dib0070_sleep(struct dvb_frontend *fe) | |||
395 | return 0; | 505 | return 0; |
396 | } | 506 | } |
397 | 507 | ||
398 | static u16 dib0070_p1f_defaults[] = | 508 | static const u16 dib0070_p1f_defaults[] = |
399 | 509 | ||
400 | { | 510 | { |
401 | 7, 0x02, | 511 | 7, 0x02, |
@@ -434,45 +544,40 @@ static u16 dib0070_p1f_defaults[] = | |||
434 | 0, | 544 | 0, |
435 | }; | 545 | }; |
436 | 546 | ||
437 | static void dib0070_wbd_calibration(struct dvb_frontend *fe) | 547 | static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain) |
438 | { | 548 | { |
439 | u16 wbd_offs; | 549 | u16 tuner_en = dib0070_read_reg(state, 0x20); |
440 | struct dib0070_state *state = fe->tuner_priv; | 550 | u16 offset; |
441 | 551 | ||
442 | if (state->cfg->sleep) | 552 | dib0070_write_reg(state, 0x18, 0x07ff); |
443 | state->cfg->sleep(fe, 0); | 553 | dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); |
444 | 554 | dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0)); | |
445 | dib0070_write_reg(state, 0x0f, 0x6d81); | 555 | msleep(9); |
446 | dib0070_write_reg(state, 0x20, 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); | 556 | offset = dib0070_read_reg(state, 0x19); |
447 | msleep(9); | 557 | dib0070_write_reg(state, 0x20, tuner_en); |
448 | wbd_offs = dib0070_read_reg(state, 0x19); | 558 | return offset; |
449 | dib0070_write_reg(state, 0x20, 0); | 559 | } |
450 | state->wbd_ff_offset = ((wbd_offs * 8 * 18 / 33 + 1) / 2); | ||
451 | dprintk( "WBDStart = %d (Vargen) - FF = %hd", (u32) wbd_offs * 1800/1024, state->wbd_ff_offset); | ||
452 | |||
453 | if (state->cfg->sleep) | ||
454 | state->cfg->sleep(fe, 1); | ||
455 | 560 | ||
561 | static void dib0070_wbd_offset_calibration(struct dib0070_state *state) | ||
562 | { | ||
563 | u8 gain; | ||
564 | for (gain = 6; gain < 8; gain++) { | ||
565 | state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2); | ||
566 | dprintk( "Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]); | ||
567 | } | ||
456 | } | 568 | } |
457 | 569 | ||
458 | u16 dib0070_wbd_offset(struct dvb_frontend *fe) | 570 | u16 dib0070_wbd_offset(struct dvb_frontend *fe) |
459 | { | 571 | { |
460 | struct dib0070_state *st = fe->tuner_priv; | 572 | struct dib0070_state *st = fe->tuner_priv; |
461 | return st->wbd_ff_offset; | 573 | return st->wbd_offset_3_3[st->wbd_gain_current - 6]; |
462 | } | 574 | } |
463 | 575 | ||
464 | EXPORT_SYMBOL(dib0070_wbd_offset); | 576 | EXPORT_SYMBOL(dib0070_wbd_offset); |
465 | static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt) | ||
466 | { | ||
467 | struct dib0070_state *state = fe->tuner_priv; | ||
468 | u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0); | ||
469 | dprintk( "CTRL_LO5: 0x%x", lo5); | ||
470 | return dib0070_write_reg(state, 0x15, lo5); | ||
471 | } | ||
472 | |||
473 | #define pgm_read_word(w) (*w) | 577 | #define pgm_read_word(w) (*w) |
474 | static int dib0070_reset(struct dib0070_state *state) | 578 | static int dib0070_reset(struct dvb_frontend *fe) |
475 | { | 579 | { |
580 | struct dib0070_state *state = fe->tuner_priv; | ||
476 | u16 l, r, *n; | 581 | u16 l, r, *n; |
477 | 582 | ||
478 | HARD_RESET(state); | 583 | HARD_RESET(state); |
@@ -482,6 +587,8 @@ static int dib0070_reset(struct dib0070_state *state) | |||
482 | if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1) | 587 | if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1) |
483 | state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff; | 588 | state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff; |
484 | else | 589 | else |
590 | #else | ||
591 | #warning forcing SBAND | ||
485 | #endif | 592 | #endif |
486 | state->revision = DIB0070S_P1A; | 593 | state->revision = DIB0070S_P1A; |
487 | 594 | ||
@@ -511,24 +618,27 @@ static int dib0070_reset(struct dib0070_state *state) | |||
511 | else | 618 | else |
512 | r = 2; | 619 | r = 2; |
513 | 620 | ||
621 | |||
514 | r |= state->cfg->osc_buffer_state << 3; | 622 | r |= state->cfg->osc_buffer_state << 3; |
515 | 623 | ||
516 | dib0070_write_reg(state, 0x10, r); | 624 | dib0070_write_reg(state, 0x10, r); |
517 | dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 4)); | 625 | dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5)); |
518 | 626 | ||
519 | if (state->cfg->invert_iq) { | 627 | if (state->cfg->invert_iq) { |
520 | r = dib0070_read_reg(state, 0x02) & 0xffdf; | 628 | r = dib0070_read_reg(state, 0x02) & 0xffdf; |
521 | dib0070_write_reg(state, 0x02, r | (1 << 5)); | 629 | dib0070_write_reg(state, 0x02, r | (1 << 5)); |
522 | } | 630 | } |
523 | 631 | ||
524 | 632 | if (state->revision == DIB0070S_P1A) | |
525 | if (state->revision == DIB0070S_P1A) | 633 | dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); |
526 | dib0070_set_ctrl_lo5(state->fe, 4, 7, 3, 1); | 634 | else |
527 | else | 635 | dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter); |
528 | dib0070_set_ctrl_lo5(state->fe, 4, 4, 2, 0); | ||
529 | 636 | ||
530 | dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8); | 637 | dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8); |
531 | return 0; | 638 | |
639 | dib0070_wbd_offset_calibration(state); | ||
640 | |||
641 | return 0; | ||
532 | } | 642 | } |
533 | 643 | ||
534 | 644 | ||
@@ -539,7 +649,7 @@ static int dib0070_release(struct dvb_frontend *fe) | |||
539 | return 0; | 649 | return 0; |
540 | } | 650 | } |
541 | 651 | ||
542 | static struct dvb_tuner_ops dib0070_ops = { | 652 | static const struct dvb_tuner_ops dib0070_ops = { |
543 | .info = { | 653 | .info = { |
544 | .name = "DiBcom DiB0070", | 654 | .name = "DiBcom DiB0070", |
545 | .frequency_min = 45000000, | 655 | .frequency_min = 45000000, |
@@ -550,7 +660,8 @@ static struct dvb_tuner_ops dib0070_ops = { | |||
550 | 660 | ||
551 | .init = dib0070_wakeup, | 661 | .init = dib0070_wakeup, |
552 | .sleep = dib0070_sleep, | 662 | .sleep = dib0070_sleep, |
553 | .set_params = dib0070_tune_digital, | 663 | .set_params = dib0070_tune, |
664 | |||
554 | // .get_frequency = dib0070_get_frequency, | 665 | // .get_frequency = dib0070_get_frequency, |
555 | // .get_bandwidth = dib0070_get_bandwidth | 666 | // .get_bandwidth = dib0070_get_bandwidth |
556 | }; | 667 | }; |
@@ -566,11 +677,9 @@ struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter | |||
566 | state->fe = fe; | 677 | state->fe = fe; |
567 | fe->tuner_priv = state; | 678 | fe->tuner_priv = state; |
568 | 679 | ||
569 | if (dib0070_reset(state) != 0) | 680 | if (dib0070_reset(fe) != 0) |
570 | goto free_mem; | 681 | goto free_mem; |
571 | 682 | ||
572 | dib0070_wbd_calibration(fe); | ||
573 | |||
574 | printk(KERN_INFO "DiB0070: successfully identified\n"); | 683 | printk(KERN_INFO "DiB0070: successfully identified\n"); |
575 | memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops)); | 684 | memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops)); |
576 | 685 | ||
diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h index 9670f5d20cfb..8c1c51cfaff1 100644 --- a/drivers/media/dvb/frontends/dib0070.h +++ b/drivers/media/dvb/frontends/dib0070.h | |||
@@ -15,6 +15,11 @@ struct i2c_adapter; | |||
15 | 15 | ||
16 | #define DEFAULT_DIB0070_I2C_ADDRESS 0x60 | 16 | #define DEFAULT_DIB0070_I2C_ADDRESS 0x60 |
17 | 17 | ||
18 | struct dib0070_wbd_gain_cfg { | ||
19 | u16 freq; | ||
20 | u16 wbd_gain_val; | ||
21 | }; | ||
22 | |||
18 | struct dib0070_config { | 23 | struct dib0070_config { |
19 | u8 i2c_address; | 24 | u8 i2c_address; |
20 | 25 | ||
@@ -35,6 +40,12 @@ struct dib0070_config { | |||
35 | u8 force_crystal_mode; /* if == 0 -> decision is made in the driver default: <24 -> 2, >=24 -> 1 */ | 40 | u8 force_crystal_mode; /* if == 0 -> decision is made in the driver default: <24 -> 2, >=24 -> 1 */ |
36 | 41 | ||
37 | u8 flip_chip; | 42 | u8 flip_chip; |
43 | u8 enable_third_order_filter; | ||
44 | u8 charge_pump; | ||
45 | |||
46 | const struct dib0070_wbd_gain_cfg * wbd_gain; | ||
47 | |||
48 | u8 vga_filter; | ||
38 | }; | 49 | }; |
39 | 50 | ||
40 | #if defined(CONFIG_DVB_TUNER_DIB0070) || (defined(CONFIG_DVB_TUNER_DIB0070_MODULE) && defined(MODULE)) | 51 | #if defined(CONFIG_DVB_TUNER_DIB0070) || (defined(CONFIG_DVB_TUNER_DIB0070_MODULE) && defined(MODULE)) |