diff options
Diffstat (limited to 'drivers/media/dvb/frontends/dib0070.c')
-rw-r--r-- | drivers/media/dvb/frontends/dib0070.c | 654 |
1 files changed, 338 insertions, 316 deletions
diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c index 2be17b93e0bd..81860b2cfe98 100644 --- a/drivers/media/dvb/frontends/dib0070.c +++ b/drivers/media/dvb/frontends/dib0070.c | |||
@@ -49,21 +49,6 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | |||
49 | #define DIB0070_P1G 0x03 | 49 | #define DIB0070_P1G 0x03 |
50 | #define DIB0070S_P1A 0x02 | 50 | #define DIB0070S_P1A 0x02 |
51 | 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 | |||
67 | struct dib0070_state { | 52 | struct dib0070_state { |
68 | struct i2c_adapter *i2c; | 53 | struct i2c_adapter *i2c; |
69 | struct dvb_frontend *fe; | 54 | struct dvb_frontend *fe; |
@@ -71,10 +56,10 @@ struct dib0070_state { | |||
71 | u16 wbd_ff_offset; | 56 | u16 wbd_ff_offset; |
72 | u8 revision; | 57 | u8 revision; |
73 | 58 | ||
74 | enum frontend_tune_state tune_state; | 59 | enum frontend_tune_state tune_state; |
75 | u32 current_rf; | 60 | u32 current_rf; |
76 | 61 | ||
77 | /* for the captrim binary search */ | 62 | /* for the captrim binary search */ |
78 | s8 step; | 63 | s8 step; |
79 | u16 adc_diff; | 64 | u16 adc_diff; |
80 | 65 | ||
@@ -85,7 +70,7 @@ struct dib0070_state { | |||
85 | const struct dib0070_tuning *current_tune_table_index; | 70 | const struct dib0070_tuning *current_tune_table_index; |
86 | const struct dib0070_lna_match *lna_match; | 71 | const struct dib0070_lna_match *lna_match; |
87 | 72 | ||
88 | u8 wbd_gain_current; | 73 | u8 wbd_gain_current; |
89 | u16 wbd_offset_3_3[2]; | 74 | u16 wbd_offset_3_3[2]; |
90 | }; | 75 | }; |
91 | 76 | ||
@@ -93,8 +78,8 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) | |||
93 | { | 78 | { |
94 | u8 b[2]; | 79 | u8 b[2]; |
95 | struct i2c_msg msg[2] = { | 80 | struct i2c_msg msg[2] = { |
96 | {.addr = state->cfg->i2c_address,.flags = 0,.buf = ®,.len = 1}, | 81 | { .addr = state->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 }, |
97 | {.addr = state->cfg->i2c_address,.flags = I2C_M_RD,.buf = b,.len = 2}, | 82 | { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 }, |
98 | }; | 83 | }; |
99 | if (i2c_transfer(state->i2c, msg, 2) != 2) { | 84 | if (i2c_transfer(state->i2c, msg, 2) != 2) { |
100 | printk(KERN_WARNING "DiB0070 I2C read failed\n"); | 85 | printk(KERN_WARNING "DiB0070 I2C read failed\n"); |
@@ -106,7 +91,7 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) | |||
106 | static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) | 91 | static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) |
107 | { | 92 | { |
108 | u8 b[3] = { reg, val >> 8, val & 0xff }; | 93 | u8 b[3] = { reg, val >> 8, val & 0xff }; |
109 | struct i2c_msg msg = {.addr = state->cfg->i2c_address,.flags = 0,.buf = b,.len = 3 }; | 94 | struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 }; |
110 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { | 95 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { |
111 | printk(KERN_WARNING "DiB0070 I2C write failed\n"); | 96 | printk(KERN_WARNING "DiB0070 I2C write failed\n"); |
112 | return -EREMOTEIO; | 97 | return -EREMOTEIO; |
@@ -124,30 +109,30 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) | |||
124 | 109 | ||
125 | static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) | 110 | static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) |
126 | { | 111 | { |
127 | struct dib0070_state *state = fe->tuner_priv; | 112 | struct dib0070_state *state = fe->tuner_priv; |
128 | u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff; | 113 | u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff; |
129 | 114 | ||
130 | if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 7000) | 115 | if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000) |
131 | tmp |= (0 << 14); | 116 | tmp |= (0 << 14); |
132 | else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 6000) | 117 | else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000) |
133 | tmp |= (1 << 14); | 118 | tmp |= (1 << 14); |
134 | else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 5000) | 119 | else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000) |
135 | tmp |= (2 << 14); | 120 | tmp |= (2 << 14); |
136 | else | 121 | else |
137 | tmp |= (3 << 14); | 122 | tmp |= (3 << 14); |
138 | 123 | ||
139 | dib0070_write_reg(state, 0x02, tmp); | 124 | dib0070_write_reg(state, 0x02, tmp); |
140 | 125 | ||
141 | /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */ | 126 | /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */ |
142 | if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) { | 127 | if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) { |
143 | u16 value = dib0070_read_reg(state, 0x17); | 128 | u16 value = dib0070_read_reg(state, 0x17); |
144 | 129 | ||
145 | dib0070_write_reg(state, 0x17, value & 0xfffc); | 130 | dib0070_write_reg(state, 0x17, value & 0xfffc); |
146 | tmp = dib0070_read_reg(state, 0x01) & 0x01ff; | 131 | tmp = dib0070_read_reg(state, 0x01) & 0x01ff; |
147 | dib0070_write_reg(state, 0x01, tmp | (60 << 9)); | 132 | dib0070_write_reg(state, 0x01, tmp | (60 << 9)); |
148 | 133 | ||
149 | dib0070_write_reg(state, 0x17, value); | 134 | dib0070_write_reg(state, 0x17, value); |
150 | } | 135 | } |
151 | return 0; | 136 | return 0; |
152 | } | 137 | } |
153 | 138 | ||
@@ -160,14 +145,14 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state | |||
160 | if (*tune_state == CT_TUNER_STEP_0) { | 145 | if (*tune_state == CT_TUNER_STEP_0) { |
161 | 146 | ||
162 | dib0070_write_reg(state, 0x0f, 0xed10); | 147 | dib0070_write_reg(state, 0x0f, 0xed10); |
163 | dib0070_write_reg(state, 0x17, 0x0034); | 148 | dib0070_write_reg(state, 0x17, 0x0034); |
164 | 149 | ||
165 | dib0070_write_reg(state, 0x18, 0x0032); | 150 | dib0070_write_reg(state, 0x18, 0x0032); |
166 | state->step = state->captrim = state->fcaptrim = 64; | 151 | state->step = state->captrim = state->fcaptrim = 64; |
167 | state->adc_diff = 3000; | 152 | state->adc_diff = 3000; |
168 | ret = 20; | 153 | ret = 20; |
169 | 154 | ||
170 | *tune_state = CT_TUNER_STEP_1; | 155 | *tune_state = CT_TUNER_STEP_1; |
171 | } else if (*tune_state == CT_TUNER_STEP_1) { | 156 | } else if (*tune_state == CT_TUNER_STEP_1) { |
172 | state->step /= 2; | 157 | state->step /= 2; |
173 | dib0070_write_reg(state, 0x14, state->lo4 | state->captrim); | 158 | dib0070_write_reg(state, 0x14, state->lo4 | state->captrim); |
@@ -178,7 +163,7 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state | |||
178 | 163 | ||
179 | adc = dib0070_read_reg(state, 0x19); | 164 | adc = dib0070_read_reg(state, 0x19); |
180 | 165 | ||
181 | dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc * (u32) 1800 / (u32) 1024); | 166 | dprintk( "CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024); |
182 | 167 | ||
183 | if (adc >= 400) { | 168 | if (adc >= 400) { |
184 | adc -= 400; | 169 | adc -= 400; |
@@ -189,10 +174,12 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state | |||
189 | } | 174 | } |
190 | 175 | ||
191 | if (adc < state->adc_diff) { | 176 | if (adc < state->adc_diff) { |
192 | dprintk("CAPTRIM=%hd is closer to target (%hd/%hd)", state->captrim, adc, state->adc_diff); | 177 | dprintk( "CAPTRIM=%hd is closer to target (%hd/%hd)", state->captrim, adc, state->adc_diff); |
193 | state->adc_diff = adc; | 178 | state->adc_diff = adc; |
194 | state->fcaptrim = state->captrim; | 179 | state->fcaptrim = state->captrim; |
195 | 180 | ||
181 | |||
182 | |||
196 | } | 183 | } |
197 | state->captrim += (step_sign * state->step); | 184 | state->captrim += (step_sign * state->step); |
198 | 185 | ||
@@ -213,8 +200,8 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state | |||
213 | 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) | 200 | 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) |
214 | { | 201 | { |
215 | struct dib0070_state *state = fe->tuner_priv; | 202 | struct dib0070_state *state = fe->tuner_priv; |
216 | u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0); | 203 | u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0); |
217 | dprintk("CTRL_LO5: 0x%x", lo5); | 204 | dprintk( "CTRL_LO5: 0x%x", lo5); |
218 | return dib0070_write_reg(state, 0x15, lo5); | 205 | return dib0070_write_reg(state, 0x15, lo5); |
219 | } | 206 | } |
220 | 207 | ||
@@ -227,171 +214,175 @@ void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open) | |||
227 | dib0070_write_reg(state, 0x1a, 0x0000); | 214 | dib0070_write_reg(state, 0x1a, 0x0000); |
228 | } else { | 215 | } else { |
229 | dib0070_write_reg(state, 0x1b, 0x4112); | 216 | dib0070_write_reg(state, 0x1b, 0x4112); |
230 | if (state->cfg->vga_filter != 0) { | 217 | if (state->cfg->vga_filter != 0) { |
231 | dib0070_write_reg(state, 0x1a, state->cfg->vga_filter); | 218 | dib0070_write_reg(state, 0x1a, state->cfg->vga_filter); |
232 | dprintk("vga filter register is set to %x", state->cfg->vga_filter); | 219 | dprintk( "vga filter register is set to %x", state->cfg->vga_filter); |
233 | } else | 220 | } else |
234 | dib0070_write_reg(state, 0x1a, 0x0009); | 221 | dib0070_write_reg(state, 0x1a, 0x0009); |
235 | } | 222 | } |
236 | } | 223 | } |
237 | 224 | ||
238 | EXPORT_SYMBOL(dib0070_ctrl_agc_filter); | 225 | EXPORT_SYMBOL(dib0070_ctrl_agc_filter); |
239 | struct dib0070_tuning { | 226 | struct dib0070_tuning { |
240 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ | 227 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ |
241 | u8 switch_trim; | 228 | u8 switch_trim; |
242 | u8 vco_band; | 229 | u8 vco_band; |
243 | u8 hfdiv; | 230 | u8 hfdiv; |
244 | u8 vco_multi; | 231 | u8 vco_multi; |
245 | u8 presc; | 232 | u8 presc; |
246 | u8 wbdmux; | 233 | u8 wbdmux; |
247 | u16 tuner_enable; | 234 | u16 tuner_enable; |
248 | }; | 235 | }; |
249 | 236 | ||
250 | struct dib0070_lna_match { | 237 | struct dib0070_lna_match { |
251 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ | 238 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ |
252 | u8 lna_band; | 239 | u8 lna_band; |
253 | }; | 240 | }; |
254 | 241 | ||
255 | static const struct dib0070_tuning dib0070s_tuning_table[] = { | 242 | static const struct dib0070_tuning dib0070s_tuning_table[] = { |
256 | {570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800}, /* UHF */ | 243 | { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */ |
257 | {700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800}, | 244 | { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 }, |
258 | {863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800}, | 245 | { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 }, |
259 | {1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, /* LBAND */ | 246 | { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */ |
260 | {1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, | 247 | { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, |
261 | {2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, | 248 | { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, |
262 | {0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000}, /* SBAND */ | 249 | { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */ |
263 | }; | 250 | }; |
264 | 251 | ||
265 | static const struct dib0070_tuning dib0070_tuning_table[] = { | 252 | static const struct dib0070_tuning dib0070_tuning_table[] = { |
266 | {115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000}, /* FM below 92MHz cannot be tuned */ | 253 | { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */ |
267 | {179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000}, /* VHF */ | 254 | { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */ |
268 | {189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000}, | 255 | { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 }, |
269 | {250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000}, | 256 | { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 }, |
270 | {569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800}, /* UHF */ | 257 | { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */ |
271 | {699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800}, | 258 | { 699999, 2, 0 ,1, 4, 2, 2, 0x4000 | 0x0800 }, |
272 | {863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800}, | 259 | { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 }, |
273 | {0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400}, /* LBAND or everything higher than UHF */ | 260 | { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */ |
274 | }; | 261 | }; |
275 | 262 | ||
276 | static const struct dib0070_lna_match dib0070_lna_flip_chip[] = { | 263 | static const struct dib0070_lna_match dib0070_lna_flip_chip[] = { |
277 | {180000, 0}, /* VHF */ | 264 | { 180000, 0 }, /* VHF */ |
278 | {188000, 1}, | 265 | { 188000, 1 }, |
279 | {196400, 2}, | 266 | { 196400, 2 }, |
280 | {250000, 3}, | 267 | { 250000, 3 }, |
281 | {550000, 0}, /* UHF */ | 268 | { 550000, 0 }, /* UHF */ |
282 | {590000, 1}, | 269 | { 590000, 1 }, |
283 | {666000, 3}, | 270 | { 666000, 3 }, |
284 | {864000, 5}, | 271 | { 864000, 5 }, |
285 | {1500000, 0}, /* LBAND or everything higher than UHF */ | 272 | { 1500000, 0 }, /* LBAND or everything higher than UHF */ |
286 | {1600000, 1}, | 273 | { 1600000, 1 }, |
287 | {2000000, 3}, | 274 | { 2000000, 3 }, |
288 | {0xffffffff, 7}, | 275 | { 0xffffffff, 7 }, |
289 | }; | 276 | }; |
290 | 277 | ||
291 | static const struct dib0070_lna_match dib0070_lna[] = { | 278 | static const struct dib0070_lna_match dib0070_lna[] = { |
292 | {180000, 0}, /* VHF */ | 279 | { 180000, 0 }, /* VHF */ |
293 | {188000, 1}, | 280 | { 188000, 1 }, |
294 | {196400, 2}, | 281 | { 196400, 2 }, |
295 | {250000, 3}, | 282 | { 250000, 3 }, |
296 | {550000, 2}, /* UHF */ | 283 | { 550000, 2 }, /* UHF */ |
297 | {650000, 3}, | 284 | { 650000, 3 }, |
298 | {750000, 5}, | 285 | { 750000, 5 }, |
299 | {850000, 6}, | 286 | { 850000, 6 }, |
300 | {864000, 7}, | 287 | { 864000, 7 }, |
301 | {1500000, 0}, /* LBAND or everything higher than UHF */ | 288 | { 1500000, 0 }, /* LBAND or everything higher than UHF */ |
302 | {1600000, 1}, | 289 | { 1600000, 1 }, |
303 | {2000000, 3}, | 290 | { 2000000, 3 }, |
304 | {0xffffffff, 7}, | 291 | { 0xffffffff, 7 }, |
305 | }; | 292 | }; |
306 | 293 | ||
307 | #define LPF 100 // define for the loop filter 100kHz by default 16-07-06 | 294 | #define LPF 100 // define for the loop filter 100kHz by default 16-07-06 |
308 | static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) | 295 | static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) |
309 | { | 296 | { |
310 | struct dib0070_state *state = fe->tuner_priv; | 297 | struct dib0070_state *state = fe->tuner_priv; |
311 | 298 | ||
312 | const struct dib0070_tuning *tune; | 299 | const struct dib0070_tuning *tune; |
313 | const struct dib0070_lna_match *lna_match; | 300 | const struct dib0070_lna_match *lna_match; |
314 | 301 | ||
315 | enum frontend_tune_state *tune_state = &state->tune_state; | 302 | enum frontend_tune_state *tune_state = &state->tune_state; |
316 | int ret = 10; /* 1ms is the default delay most of the time */ | 303 | int ret = 10; /* 1ms is the default delay most of the time */ |
317 | 304 | ||
318 | u8 band = (u8) BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000); | 305 | u8 band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000); |
319 | u32 freq = fe->dtv_property_cache.frequency / 1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf); | 306 | u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf); |
320 | 307 | ||
321 | #ifdef CONFIG_SYS_ISDBT | 308 | #ifdef CONFIG_SYS_ISDBT |
322 | if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1) | 309 | if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1) |
323 | if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) | 310 | if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) |
324 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))) | 311 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))) |
325 | || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) | 312 | || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) |
326 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2))) | 313 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2))) |
327 | || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) | 314 | || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) |
328 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))) | 315 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))) |
329 | freq += 850; | 316 | freq += 850; |
330 | #endif | 317 | #endif |
318 | if (state->current_rf != freq) { | ||
319 | |||
320 | switch (state->revision) { | ||
321 | case DIB0070S_P1A: | ||
322 | tune = dib0070s_tuning_table; | ||
323 | lna_match = dib0070_lna; | ||
324 | break; | ||
325 | default: | ||
326 | tune = dib0070_tuning_table; | ||
327 | if (state->cfg->flip_chip) | ||
328 | lna_match = dib0070_lna_flip_chip; | ||
329 | else | ||
330 | lna_match = dib0070_lna; | ||
331 | break; | ||
332 | } | ||
333 | while (freq > tune->max_freq) /* find the right one */ | ||
334 | tune++; | ||
335 | while (freq > lna_match->max_freq) /* find the right one */ | ||
336 | lna_match++; | ||
337 | |||
338 | state->current_tune_table_index = tune; | ||
339 | state->lna_match = lna_match; | ||
340 | } | ||
341 | |||
342 | if (*tune_state == CT_TUNER_START) { | ||
343 | dprintk( "Tuning for Band: %hd (%d kHz)", band, freq); | ||
331 | if (state->current_rf != freq) { | 344 | if (state->current_rf != freq) { |
345 | u8 REFDIV; | ||
346 | u32 FBDiv, Rest, FREF, VCOF_kHz; | ||
347 | u8 Den; | ||
332 | 348 | ||
333 | switch (state->revision) { | 349 | state->current_rf = freq; |
334 | case DIB0070S_P1A: | 350 | state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7); |
335 | tune = dib0070s_tuning_table; | ||
336 | lna_match = dib0070_lna; | ||
337 | break; | ||
338 | default: | ||
339 | tune = dib0070_tuning_table; | ||
340 | if (state->cfg->flip_chip) | ||
341 | lna_match = dib0070_lna_flip_chip; | ||
342 | else | ||
343 | lna_match = dib0070_lna; | ||
344 | break; | ||
345 | } | ||
346 | while (freq > tune->max_freq) /* find the right one */ | ||
347 | tune++; | ||
348 | while (freq > lna_match->max_freq) /* find the right one */ | ||
349 | lna_match++; | ||
350 | 351 | ||
351 | state->current_tune_table_index = tune; | ||
352 | state->lna_match = lna_match; | ||
353 | } | ||
354 | 352 | ||
355 | if (*tune_state == CT_TUNER_START) { | 353 | dib0070_write_reg(state, 0x17, 0x30); |
356 | dprintk("Tuning for Band: %hd (%d kHz)", band, freq); | 354 | |
357 | if (state->current_rf != freq) { | 355 | |
358 | u8 REFDIV; | 356 | VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2; |
359 | u32 FBDiv, Rest, FREF, VCOF_kHz; | 357 | |
360 | u8 Den; | 358 | switch (band) { |
361 | 359 | case BAND_VHF: | |
362 | state->current_rf = freq; | 360 | REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000); |
363 | state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7); | 361 | break; |
364 | 362 | case BAND_FM: | |
365 | dib0070_write_reg(state, 0x17, 0x30); | 363 | REFDIV = (u8) ((state->cfg->clock_khz) / 1000); |
366 | 364 | break; | |
367 | VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2; | 365 | default: |
368 | 366 | REFDIV = (u8) ( state->cfg->clock_khz / 10000); | |
369 | switch (band) { | 367 | break; |
370 | case BAND_VHF: | 368 | } |
371 | REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000); | 369 | FREF = state->cfg->clock_khz / REFDIV; |
372 | break; | 370 | |
373 | case BAND_FM: | 371 | |
374 | REFDIV = (u8) ((state->cfg->clock_khz) / 1000); | 372 | |
375 | break; | 373 | switch (state->revision) { |
376 | default: | 374 | case DIB0070S_P1A: |
377 | REFDIV = (u8) (state->cfg->clock_khz / 10000); | 375 | FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF); |
378 | break; | 376 | Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF; |
379 | } | 377 | break; |
380 | FREF = state->cfg->clock_khz / REFDIV; | 378 | |
381 | 379 | case DIB0070_P1G: | |
382 | switch (state->revision) { | 380 | case DIB0070_P1F: |
383 | case DIB0070S_P1A: | 381 | default: |
384 | FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF); | 382 | FBDiv = (freq / (FREF / 2)); |
385 | Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF; | 383 | Rest = 2 * freq - FBDiv * FREF; |
386 | break; | 384 | break; |
387 | 385 | } | |
388 | case DIB0070_P1G: | ||
389 | case DIB0070_P1F: | ||
390 | default: | ||
391 | FBDiv = (freq / (FREF / 2)); | ||
392 | Rest = 2 * freq - FBDiv * FREF; | ||
393 | break; | ||
394 | } | ||
395 | 386 | ||
396 | if (Rest < LPF) | 387 | if (Rest < LPF) |
397 | Rest = 0; | 388 | Rest = 0; |
@@ -402,98 +393,102 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par | |||
402 | FBDiv += 1; | 393 | FBDiv += 1; |
403 | } else if (Rest > (FREF - 2 * LPF)) | 394 | } else if (Rest > (FREF - 2 * LPF)) |
404 | Rest = FREF - 2 * LPF; | 395 | Rest = FREF - 2 * LPF; |
405 | Rest = (Rest * 6528) / (FREF / 10); | 396 | Rest = (Rest * 6528) / (FREF / 10); |
406 | 397 | ||
407 | Den = 1; | 398 | Den = 1; |
408 | if (Rest > 0) { | 399 | if (Rest > 0) { |
409 | state->lo4 |= (1 << 14) | (1 << 12); | 400 | state->lo4 |= (1 << 14) | (1 << 12); |
410 | Den = 255; | 401 | Den = 255; |
411 | } | 402 | } |
412 | 403 | ||
413 | dib0070_write_reg(state, 0x11, (u16) FBDiv); | ||
414 | dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV); | ||
415 | dib0070_write_reg(state, 0x13, (u16) Rest); | ||
416 | 404 | ||
417 | if (state->revision == DIB0070S_P1A) { | 405 | dib0070_write_reg(state, 0x11, (u16)FBDiv); |
406 | dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV); | ||
407 | dib0070_write_reg(state, 0x13, (u16) Rest); | ||
418 | 408 | ||
419 | if (band == BAND_SBAND) { | 409 | if (state->revision == DIB0070S_P1A) { |
420 | dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); | 410 | |
421 | dib0070_write_reg(state, 0x1d, 0xFFFF); | 411 | if (band == BAND_SBAND) { |
422 | } else | 412 | dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); |
423 | dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1); | 413 | dib0070_write_reg(state, 0x1d,0xFFFF); |
424 | } | 414 | } else |
415 | dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1); | ||
416 | } | ||
425 | 417 | ||
426 | dib0070_write_reg(state, 0x20, | 418 | dib0070_write_reg(state, 0x20, |
427 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable); | 419 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable); |
428 | 420 | ||
429 | dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF); | 421 | dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF); |
430 | dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest); | 422 | dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest); |
431 | dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1); | 423 | dprintk( "Num: %hd, Den: %hd, SD: %hd",(u16) Rest, Den, (state->lo4 >> 12) & 0x1); |
432 | dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv); | 424 | dprintk( "HFDIV code: %hd", state->current_tune_table_index->hfdiv); |
433 | dprintk("VCO = %hd", state->current_tune_table_index->vco_band); | 425 | dprintk( "VCO = %hd", state->current_tune_table_index->vco_band); |
434 | dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq); | 426 | dprintk( "VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq); |
435 | 427 | ||
436 | *tune_state = CT_TUNER_STEP_0; | 428 | *tune_state = CT_TUNER_STEP_0; |
437 | } else { /* we are already tuned to this frequency - the configuration is correct */ | 429 | } else { /* we are already tuned to this frequency - the configuration is correct */ |
438 | ret = 50; /* wakeup time */ | 430 | ret = 50; /* wakeup time */ |
439 | *tune_state = CT_TUNER_STEP_5; | 431 | *tune_state = CT_TUNER_STEP_5; |
440 | } | 432 | } |
441 | } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) { | 433 | } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) { |
442 | 434 | ||
443 | ret = dib0070_captrim(state, tune_state); | 435 | ret = dib0070_captrim(state, tune_state); |
444 | 436 | ||
445 | } else if (*tune_state == CT_TUNER_STEP_4) { | 437 | } else if (*tune_state == CT_TUNER_STEP_4) { |
446 | const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; | 438 | const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; |
447 | if (tmp != NULL) { | 439 | if (tmp != NULL) { |
448 | while (freq / 1000 > tmp->freq) /* find the right one */ | 440 | while (freq/1000 > tmp->freq) /* find the right one */ |
449 | tmp++; | 441 | tmp++; |
450 | dib0070_write_reg(state, 0x0f, | 442 | dib0070_write_reg(state, 0x0f, |
451 | (0 << 15) | (1 << 14) | (3 << 12) | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) | (state-> | 443 | (0 << 15) | (1 << 14) | (3 << 12) | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) | (state-> |
452 | current_tune_table_index-> | 444 | current_tune_table_index-> |
453 | wbdmux << 0)); | 445 | wbdmux << 0)); |
454 | state->wbd_gain_current = tmp->wbd_gain_val; | 446 | state->wbd_gain_current = tmp->wbd_gain_val; |
455 | } else { | 447 | } else { |
456 | dib0070_write_reg(state, 0x0f, | 448 | dib0070_write_reg(state, 0x0f, |
457 | (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index-> | 449 | (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index-> |
458 | wbdmux << 0)); | 450 | wbdmux << 0)); |
459 | state->wbd_gain_current = 6; | 451 | state->wbd_gain_current = 6; |
460 | } | 452 | } |
461 | 453 | ||
462 | dib0070_write_reg(state, 0x06, 0x3fff); | 454 | dib0070_write_reg(state, 0x06, 0x3fff); |
463 | dib0070_write_reg(state, 0x07, | 455 | dib0070_write_reg(state, 0x07, |
464 | (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0)); | 456 | (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0)); |
465 | dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127)); | 457 | dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127)); |
466 | dib0070_write_reg(state, 0x0d, 0x0d80); | 458 | dib0070_write_reg(state, 0x0d, 0x0d80); |
467 | 459 | ||
468 | dib0070_write_reg(state, 0x18, 0x07ff); | ||
469 | dib0070_write_reg(state, 0x17, 0x0033); | ||
470 | 460 | ||
471 | *tune_state = CT_TUNER_STEP_5; | 461 | dib0070_write_reg(state, 0x18, 0x07ff); |
472 | } else if (*tune_state == CT_TUNER_STEP_5) { | 462 | dib0070_write_reg(state, 0x17, 0x0033); |
473 | dib0070_set_bandwidth(fe, ch); | 463 | |
474 | *tune_state = CT_TUNER_STOP; | 464 | |
475 | } else { | 465 | *tune_state = CT_TUNER_STEP_5; |
476 | ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */ | 466 | } else if (*tune_state == CT_TUNER_STEP_5) { |
477 | } | 467 | dib0070_set_bandwidth(fe, ch); |
478 | return ret; | 468 | *tune_state = CT_TUNER_STOP; |
469 | } else { | ||
470 | ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */ | ||
471 | } | ||
472 | return ret; | ||
479 | } | 473 | } |
480 | 474 | ||
475 | |||
481 | static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) | 476 | static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) |
482 | { | 477 | { |
483 | struct dib0070_state *state = fe->tuner_priv; | 478 | struct dib0070_state *state = fe->tuner_priv; |
484 | uint32_t ret; | 479 | uint32_t ret; |
485 | 480 | ||
486 | state->tune_state = CT_TUNER_START; | 481 | state->tune_state = CT_TUNER_START; |
487 | 482 | ||
488 | do { | 483 | do { |
489 | ret = dib0070_tune_digital(fe, p); | 484 | ret = dib0070_tune_digital(fe, p); |
490 | if (ret != FE_CALLBACK_TIME_NEVER) | 485 | if (ret != FE_CALLBACK_TIME_NEVER) |
491 | msleep(ret / 10); | 486 | msleep(ret/10); |
492 | else | 487 | else |
493 | break; | 488 | break; |
494 | } while (state->tune_state != CT_TUNER_STOP); | 489 | } while (state->tune_state != CT_TUNER_STOP); |
495 | 490 | ||
496 | return 0; | 491 | return 0; |
497 | } | 492 | } |
498 | 493 | ||
499 | static int dib0070_wakeup(struct dvb_frontend *fe) | 494 | static int dib0070_wakeup(struct dvb_frontend *fe) |
@@ -512,92 +507,111 @@ static int dib0070_sleep(struct dvb_frontend *fe) | |||
512 | return 0; | 507 | return 0; |
513 | } | 508 | } |
514 | 509 | ||
515 | static const u16 dib0070_p1f_defaults[] = { | 510 | u8 dib0070_get_rf_output(struct dvb_frontend *fe) |
511 | { | ||
512 | struct dib0070_state *state = fe->tuner_priv; | ||
513 | return (dib0070_read_reg(state, 0x07) >> 11) & 0x3; | ||
514 | } | ||
515 | |||
516 | EXPORT_SYMBOL(dib0070_get_rf_output); | ||
517 | int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no) | ||
518 | { | ||
519 | struct dib0070_state *state = fe->tuner_priv; | ||
520 | u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff; | ||
521 | if (no > 3) no = 3; | ||
522 | if (no < 1) no = 1; | ||
523 | return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11)); | ||
524 | } | ||
525 | |||
526 | EXPORT_SYMBOL(dib0070_set_rf_output); | ||
527 | static const u16 dib0070_p1f_defaults[] = | ||
528 | |||
529 | { | ||
516 | 7, 0x02, | 530 | 7, 0x02, |
517 | 0x0008, | 531 | 0x0008, |
518 | 0x0000, | 532 | 0x0000, |
519 | 0x0000, | 533 | 0x0000, |
520 | 0x0000, | 534 | 0x0000, |
521 | 0x0000, | 535 | 0x0000, |
522 | 0x0002, | 536 | 0x0002, |
523 | 0x0100, | 537 | 0x0100, |
524 | 538 | ||
525 | 3, 0x0d, | 539 | 3, 0x0d, |
526 | 0x0d80, | 540 | 0x0d80, |
527 | 0x0001, | 541 | 0x0001, |
528 | 0x0000, | 542 | 0x0000, |
529 | 543 | ||
530 | 4, 0x11, | 544 | 4, 0x11, |
531 | 0x0000, | 545 | 0x0000, |
532 | 0x0103, | 546 | 0x0103, |
533 | 0x0000, | 547 | 0x0000, |
534 | 0x0000, | 548 | 0x0000, |
535 | 549 | ||
536 | 3, 0x16, | 550 | 3, 0x16, |
537 | 0x0004 | 0x0040, | 551 | 0x0004 | 0x0040, |
538 | 0x0030, | 552 | 0x0030, |
539 | 0x07ff, | 553 | 0x07ff, |
540 | 554 | ||
541 | 6, 0x1b, | 555 | 6, 0x1b, |
542 | 0x4112, | 556 | 0x4112, |
543 | 0xff00, | 557 | 0xff00, |
544 | 0xc07f, | 558 | 0xc07f, |
545 | 0x0000, | 559 | 0x0000, |
546 | 0x0180, | 560 | 0x0180, |
547 | 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001, | 561 | 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001, |
548 | 562 | ||
549 | 0, | 563 | 0, |
550 | }; | 564 | }; |
551 | 565 | ||
552 | static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain) | 566 | static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain) |
553 | { | 567 | { |
554 | u16 tuner_en = dib0070_read_reg(state, 0x20); | 568 | u16 tuner_en = dib0070_read_reg(state, 0x20); |
555 | u16 offset; | 569 | u16 offset; |
556 | 570 | ||
557 | dib0070_write_reg(state, 0x18, 0x07ff); | 571 | dib0070_write_reg(state, 0x18, 0x07ff); |
558 | dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); | 572 | dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); |
559 | dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0)); | 573 | dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0)); |
560 | msleep(9); | 574 | msleep(9); |
561 | offset = dib0070_read_reg(state, 0x19); | 575 | offset = dib0070_read_reg(state, 0x19); |
562 | dib0070_write_reg(state, 0x20, tuner_en); | 576 | dib0070_write_reg(state, 0x20, tuner_en); |
563 | return offset; | 577 | return offset; |
564 | } | 578 | } |
565 | 579 | ||
566 | static void dib0070_wbd_offset_calibration(struct dib0070_state *state) | 580 | static void dib0070_wbd_offset_calibration(struct dib0070_state *state) |
567 | { | 581 | { |
568 | u8 gain; | 582 | u8 gain; |
569 | for (gain = 6; gain < 8; gain++) { | 583 | for (gain = 6; gain < 8; gain++) { |
570 | state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2); | 584 | state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2); |
571 | dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain - 6]); | 585 | dprintk( "Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]); |
572 | } | 586 | } |
573 | } | 587 | } |
574 | 588 | ||
575 | u16 dib0070_wbd_offset(struct dvb_frontend *fe) | 589 | u16 dib0070_wbd_offset(struct dvb_frontend *fe) |
576 | { | 590 | { |
577 | struct dib0070_state *state = fe->tuner_priv; | 591 | struct dib0070_state *state = fe->tuner_priv; |
578 | const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; | 592 | const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; |
579 | u32 freq = fe->dtv_property_cache.frequency / 1000; | 593 | u32 freq = fe->dtv_property_cache.frequency/1000; |
580 | 594 | ||
581 | if (tmp != NULL) { | 595 | if (tmp != NULL) { |
582 | while (freq / 1000 > tmp->freq) /* find the right one */ | 596 | while (freq/1000 > tmp->freq) /* find the right one */ |
583 | tmp++; | 597 | tmp++; |
584 | state->wbd_gain_current = tmp->wbd_gain_val; | 598 | state->wbd_gain_current = tmp->wbd_gain_val; |
585 | } else | 599 | } else |
586 | state->wbd_gain_current = 6; | 600 | state->wbd_gain_current = 6; |
587 | 601 | ||
588 | return state->wbd_offset_3_3[state->wbd_gain_current - 6]; | 602 | return state->wbd_offset_3_3[state->wbd_gain_current - 6]; |
589 | } | 603 | } |
590 | |||
591 | EXPORT_SYMBOL(dib0070_wbd_offset); | 604 | EXPORT_SYMBOL(dib0070_wbd_offset); |
592 | 605 | ||
593 | #define pgm_read_word(w) (*w) | 606 | #define pgm_read_word(w) (*w) |
594 | static int dib0070_reset(struct dvb_frontend *fe) | 607 | static int dib0070_reset(struct dvb_frontend *fe) |
595 | { | 608 | { |
596 | struct dib0070_state *state = fe->tuner_priv; | 609 | struct dib0070_state *state = fe->tuner_priv; |
597 | u16 l, r, *n; | 610 | u16 l, r, *n; |
598 | 611 | ||
599 | HARD_RESET(state); | 612 | HARD_RESET(state); |
600 | 613 | ||
614 | |||
601 | #ifndef FORCE_SBAND_TUNER | 615 | #ifndef FORCE_SBAND_TUNER |
602 | if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1) | 616 | if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1) |
603 | state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff; | 617 | state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff; |
@@ -605,13 +619,13 @@ static int dib0070_reset(struct dvb_frontend *fe) | |||
605 | #else | 619 | #else |
606 | #warning forcing SBAND | 620 | #warning forcing SBAND |
607 | #endif | 621 | #endif |
608 | state->revision = DIB0070S_P1A; | 622 | state->revision = DIB0070S_P1A; |
609 | 623 | ||
610 | /* P1F or not */ | 624 | /* P1F or not */ |
611 | dprintk("Revision: %x", state->revision); | 625 | dprintk( "Revision: %x", state->revision); |
612 | 626 | ||
613 | if (state->revision == DIB0070_P1D) { | 627 | if (state->revision == DIB0070_P1D) { |
614 | dprintk("Error: this driver is not to be used meant for P1D or earlier"); | 628 | dprintk( "Error: this driver is not to be used meant for P1D or earlier"); |
615 | return -EINVAL; | 629 | return -EINVAL; |
616 | } | 630 | } |
617 | 631 | ||
@@ -620,7 +634,7 @@ static int dib0070_reset(struct dvb_frontend *fe) | |||
620 | while (l) { | 634 | while (l) { |
621 | r = pgm_read_word(n++); | 635 | r = pgm_read_word(n++); |
622 | do { | 636 | do { |
623 | dib0070_write_reg(state, (u8) r, pgm_read_word(n++)); | 637 | dib0070_write_reg(state, (u8)r, pgm_read_word(n++)); |
624 | r++; | 638 | r++; |
625 | } while (--l); | 639 | } while (--l); |
626 | l = pgm_read_word(n++); | 640 | l = pgm_read_word(n++); |
@@ -633,6 +647,7 @@ static int dib0070_reset(struct dvb_frontend *fe) | |||
633 | else | 647 | else |
634 | r = 2; | 648 | r = 2; |
635 | 649 | ||
650 | |||
636 | r |= state->cfg->osc_buffer_state << 3; | 651 | r |= state->cfg->osc_buffer_state << 3; |
637 | 652 | ||
638 | dib0070_write_reg(state, 0x10, r); | 653 | dib0070_write_reg(state, 0x10, r); |
@@ -643,16 +658,24 @@ static int dib0070_reset(struct dvb_frontend *fe) | |||
643 | dib0070_write_reg(state, 0x02, r | (1 << 5)); | 658 | dib0070_write_reg(state, 0x02, r | (1 << 5)); |
644 | } | 659 | } |
645 | 660 | ||
646 | if (state->revision == DIB0070S_P1A) | 661 | if (state->revision == DIB0070S_P1A) |
647 | dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); | 662 | dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); |
648 | else | 663 | else |
649 | dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter); | 664 | dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter); |
650 | 665 | ||
651 | dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8); | 666 | dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8); |
652 | 667 | ||
653 | dib0070_wbd_offset_calibration(state); | 668 | dib0070_wbd_offset_calibration(state); |
654 | 669 | ||
655 | return 0; | 670 | return 0; |
671 | } | ||
672 | |||
673 | static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
674 | { | ||
675 | struct dib0070_state *state = fe->tuner_priv; | ||
676 | |||
677 | *frequency = 1000 * state->current_rf; | ||
678 | return 0; | ||
656 | } | 679 | } |
657 | 680 | ||
658 | static int dib0070_release(struct dvb_frontend *fe) | 681 | static int dib0070_release(struct dvb_frontend *fe) |
@@ -664,22 +687,22 @@ static int dib0070_release(struct dvb_frontend *fe) | |||
664 | 687 | ||
665 | static const struct dvb_tuner_ops dib0070_ops = { | 688 | static const struct dvb_tuner_ops dib0070_ops = { |
666 | .info = { | 689 | .info = { |
667 | .name = "DiBcom DiB0070", | 690 | .name = "DiBcom DiB0070", |
668 | .frequency_min = 45000000, | 691 | .frequency_min = 45000000, |
669 | .frequency_max = 860000000, | 692 | .frequency_max = 860000000, |
670 | .frequency_step = 1000, | 693 | .frequency_step = 1000, |
671 | }, | 694 | }, |
672 | .release = dib0070_release, | 695 | .release = dib0070_release, |
673 | 696 | ||
674 | .init = dib0070_wakeup, | 697 | .init = dib0070_wakeup, |
675 | .sleep = dib0070_sleep, | 698 | .sleep = dib0070_sleep, |
676 | .set_params = dib0070_tune, | 699 | .set_params = dib0070_tune, |
677 | 700 | ||
678 | // .get_frequency = dib0070_get_frequency, | 701 | .get_frequency = dib0070_get_frequency, |
679 | // .get_bandwidth = dib0070_get_bandwidth | 702 | // .get_bandwidth = dib0070_get_bandwidth |
680 | }; | 703 | }; |
681 | 704 | ||
682 | struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) | 705 | struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) |
683 | { | 706 | { |
684 | struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL); | 707 | struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL); |
685 | if (state == NULL) | 708 | if (state == NULL) |
@@ -687,7 +710,7 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter | |||
687 | 710 | ||
688 | state->cfg = cfg; | 711 | state->cfg = cfg; |
689 | state->i2c = i2c; | 712 | state->i2c = i2c; |
690 | state->fe = fe; | 713 | state->fe = fe; |
691 | fe->tuner_priv = state; | 714 | fe->tuner_priv = state; |
692 | 715 | ||
693 | if (dib0070_reset(fe) != 0) | 716 | if (dib0070_reset(fe) != 0) |
@@ -699,12 +722,11 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter | |||
699 | fe->tuner_priv = state; | 722 | fe->tuner_priv = state; |
700 | return fe; | 723 | return fe; |
701 | 724 | ||
702 | free_mem: | 725 | free_mem: |
703 | kfree(state); | 726 | kfree(state); |
704 | fe->tuner_priv = NULL; | 727 | fe->tuner_priv = NULL; |
705 | return NULL; | 728 | return NULL; |
706 | } | 729 | } |
707 | |||
708 | EXPORT_SYMBOL(dib0070_attach); | 730 | EXPORT_SYMBOL(dib0070_attach); |
709 | 731 | ||
710 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | 732 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); |