diff options
Diffstat (limited to 'drivers/media/dvb-frontends/dib8000.c')
-rw-r--r-- | drivers/media/dvb-frontends/dib8000.c | 3560 |
1 files changed, 3560 insertions, 0 deletions
diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c new file mode 100644 index 000000000000..1f3bcb5a1de8 --- /dev/null +++ b/drivers/media/dvb-frontends/dib8000.c | |||
@@ -0,0 +1,3560 @@ | |||
1 | /* | ||
2 | * Linux-DVB Driver for DiBcom's DiB8000 chip (ISDB-T). | ||
3 | * | ||
4 | * Copyright (C) 2009 DiBcom (http://www.dibcom.fr/) | ||
5 | * | ||
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 | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | */ | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/mutex.h> | ||
14 | |||
15 | #include "dvb_math.h" | ||
16 | |||
17 | #include "dvb_frontend.h" | ||
18 | |||
19 | #include "dib8000.h" | ||
20 | |||
21 | #define LAYER_ALL -1 | ||
22 | #define LAYER_A 1 | ||
23 | #define LAYER_B 2 | ||
24 | #define LAYER_C 3 | ||
25 | |||
26 | #define FE_CALLBACK_TIME_NEVER 0xffffffff | ||
27 | #define MAX_NUMBER_OF_FRONTENDS 6 | ||
28 | |||
29 | static int debug; | ||
30 | module_param(debug, int, 0644); | ||
31 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | ||
32 | |||
33 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0) | ||
34 | |||
35 | #define FE_STATUS_TUNE_FAILED 0 | ||
36 | |||
37 | struct i2c_device { | ||
38 | struct i2c_adapter *adap; | ||
39 | u8 addr; | ||
40 | u8 *i2c_write_buffer; | ||
41 | u8 *i2c_read_buffer; | ||
42 | struct mutex *i2c_buffer_lock; | ||
43 | }; | ||
44 | |||
45 | struct dib8000_state { | ||
46 | struct dib8000_config cfg; | ||
47 | |||
48 | struct i2c_device i2c; | ||
49 | |||
50 | struct dibx000_i2c_master i2c_master; | ||
51 | |||
52 | u16 wbd_ref; | ||
53 | |||
54 | u8 current_band; | ||
55 | u32 current_bandwidth; | ||
56 | struct dibx000_agc_config *current_agc; | ||
57 | u32 timf; | ||
58 | u32 timf_default; | ||
59 | |||
60 | u8 div_force_off:1; | ||
61 | u8 div_state:1; | ||
62 | u16 div_sync_wait; | ||
63 | |||
64 | u8 agc_state; | ||
65 | u8 differential_constellation; | ||
66 | u8 diversity_onoff; | ||
67 | |||
68 | s16 ber_monitored_layer; | ||
69 | u16 gpio_dir; | ||
70 | u16 gpio_val; | ||
71 | |||
72 | u16 revision; | ||
73 | u8 isdbt_cfg_loaded; | ||
74 | enum frontend_tune_state tune_state; | ||
75 | u32 status; | ||
76 | |||
77 | struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS]; | ||
78 | |||
79 | /* for the I2C transfer */ | ||
80 | struct i2c_msg msg[2]; | ||
81 | u8 i2c_write_buffer[4]; | ||
82 | u8 i2c_read_buffer[2]; | ||
83 | struct mutex i2c_buffer_lock; | ||
84 | u8 input_mode_mpeg; | ||
85 | |||
86 | u16 tuner_enable; | ||
87 | struct i2c_adapter dib8096p_tuner_adap; | ||
88 | }; | ||
89 | |||
90 | enum dib8000_power_mode { | ||
91 | DIB8000_POWER_ALL = 0, | ||
92 | DIB8000_POWER_INTERFACE_ONLY, | ||
93 | }; | ||
94 | |||
95 | static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg) | ||
96 | { | ||
97 | u16 ret; | ||
98 | struct i2c_msg msg[2] = { | ||
99 | {.addr = i2c->addr >> 1, .flags = 0, .len = 2}, | ||
100 | {.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2}, | ||
101 | }; | ||
102 | |||
103 | if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { | ||
104 | dprintk("could not acquire lock"); | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | msg[0].buf = i2c->i2c_write_buffer; | ||
109 | msg[0].buf[0] = reg >> 8; | ||
110 | msg[0].buf[1] = reg & 0xff; | ||
111 | msg[1].buf = i2c->i2c_read_buffer; | ||
112 | |||
113 | if (i2c_transfer(i2c->adap, msg, 2) != 2) | ||
114 | dprintk("i2c read error on %d", reg); | ||
115 | |||
116 | ret = (msg[1].buf[0] << 8) | msg[1].buf[1]; | ||
117 | mutex_unlock(i2c->i2c_buffer_lock); | ||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) | ||
122 | { | ||
123 | u16 ret; | ||
124 | |||
125 | if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { | ||
126 | dprintk("could not acquire lock"); | ||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | state->i2c_write_buffer[0] = reg >> 8; | ||
131 | state->i2c_write_buffer[1] = reg & 0xff; | ||
132 | |||
133 | memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); | ||
134 | state->msg[0].addr = state->i2c.addr >> 1; | ||
135 | state->msg[0].flags = 0; | ||
136 | state->msg[0].buf = state->i2c_write_buffer; | ||
137 | state->msg[0].len = 2; | ||
138 | state->msg[1].addr = state->i2c.addr >> 1; | ||
139 | state->msg[1].flags = I2C_M_RD; | ||
140 | state->msg[1].buf = state->i2c_read_buffer; | ||
141 | state->msg[1].len = 2; | ||
142 | |||
143 | if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2) | ||
144 | dprintk("i2c read error on %d", reg); | ||
145 | |||
146 | ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; | ||
147 | mutex_unlock(&state->i2c_buffer_lock); | ||
148 | |||
149 | return ret; | ||
150 | } | ||
151 | |||
152 | static u32 dib8000_read32(struct dib8000_state *state, u16 reg) | ||
153 | { | ||
154 | u16 rw[2]; | ||
155 | |||
156 | rw[0] = dib8000_read_word(state, reg + 0); | ||
157 | rw[1] = dib8000_read_word(state, reg + 1); | ||
158 | |||
159 | return ((rw[0] << 16) | (rw[1])); | ||
160 | } | ||
161 | |||
162 | static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val) | ||
163 | { | ||
164 | struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4}; | ||
165 | int ret = 0; | ||
166 | |||
167 | if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { | ||
168 | dprintk("could not acquire lock"); | ||
169 | return -EINVAL; | ||
170 | } | ||
171 | |||
172 | msg.buf = i2c->i2c_write_buffer; | ||
173 | msg.buf[0] = (reg >> 8) & 0xff; | ||
174 | msg.buf[1] = reg & 0xff; | ||
175 | msg.buf[2] = (val >> 8) & 0xff; | ||
176 | msg.buf[3] = val & 0xff; | ||
177 | |||
178 | ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | ||
179 | mutex_unlock(i2c->i2c_buffer_lock); | ||
180 | |||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) | ||
185 | { | ||
186 | int ret; | ||
187 | |||
188 | if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { | ||
189 | dprintk("could not acquire lock"); | ||
190 | return -EINVAL; | ||
191 | } | ||
192 | |||
193 | state->i2c_write_buffer[0] = (reg >> 8) & 0xff; | ||
194 | state->i2c_write_buffer[1] = reg & 0xff; | ||
195 | state->i2c_write_buffer[2] = (val >> 8) & 0xff; | ||
196 | state->i2c_write_buffer[3] = val & 0xff; | ||
197 | |||
198 | memset(&state->msg[0], 0, sizeof(struct i2c_msg)); | ||
199 | state->msg[0].addr = state->i2c.addr >> 1; | ||
200 | state->msg[0].flags = 0; | ||
201 | state->msg[0].buf = state->i2c_write_buffer; | ||
202 | state->msg[0].len = 4; | ||
203 | |||
204 | ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? | ||
205 | -EREMOTEIO : 0); | ||
206 | mutex_unlock(&state->i2c_buffer_lock); | ||
207 | |||
208 | return ret; | ||
209 | } | ||
210 | |||
211 | static const s16 coeff_2k_sb_1seg_dqpsk[8] = { | ||
212 | (769 << 5) | 0x0a, (745 << 5) | 0x03, (595 << 5) | 0x0d, (769 << 5) | 0x0a, (920 << 5) | 0x09, (784 << 5) | 0x02, (519 << 5) | 0x0c, | ||
213 | (920 << 5) | 0x09 | ||
214 | }; | ||
215 | |||
216 | static const s16 coeff_2k_sb_1seg[8] = { | ||
217 | (692 << 5) | 0x0b, (683 << 5) | 0x01, (519 << 5) | 0x09, (692 << 5) | 0x0b, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f | ||
218 | }; | ||
219 | |||
220 | static const s16 coeff_2k_sb_3seg_0dqpsk_1dqpsk[8] = { | ||
221 | (832 << 5) | 0x10, (912 << 5) | 0x05, (900 << 5) | 0x12, (832 << 5) | 0x10, (-931 << 5) | 0x0f, (912 << 5) | 0x04, (807 << 5) | 0x11, | ||
222 | (-931 << 5) | 0x0f | ||
223 | }; | ||
224 | |||
225 | static const s16 coeff_2k_sb_3seg_0dqpsk[8] = { | ||
226 | (622 << 5) | 0x0c, (941 << 5) | 0x04, (796 << 5) | 0x10, (622 << 5) | 0x0c, (982 << 5) | 0x0c, (519 << 5) | 0x02, (572 << 5) | 0x0e, | ||
227 | (982 << 5) | 0x0c | ||
228 | }; | ||
229 | |||
230 | static const s16 coeff_2k_sb_3seg_1dqpsk[8] = { | ||
231 | (699 << 5) | 0x14, (607 << 5) | 0x04, (944 << 5) | 0x13, (699 << 5) | 0x14, (-720 << 5) | 0x0d, (640 << 5) | 0x03, (866 << 5) | 0x12, | ||
232 | (-720 << 5) | 0x0d | ||
233 | }; | ||
234 | |||
235 | static const s16 coeff_2k_sb_3seg[8] = { | ||
236 | (664 << 5) | 0x0c, (925 << 5) | 0x03, (937 << 5) | 0x10, (664 << 5) | 0x0c, (-610 << 5) | 0x0a, (697 << 5) | 0x01, (836 << 5) | 0x0e, | ||
237 | (-610 << 5) | 0x0a | ||
238 | }; | ||
239 | |||
240 | static const s16 coeff_4k_sb_1seg_dqpsk[8] = { | ||
241 | (-955 << 5) | 0x0e, (687 << 5) | 0x04, (818 << 5) | 0x10, (-955 << 5) | 0x0e, (-922 << 5) | 0x0d, (750 << 5) | 0x03, (665 << 5) | 0x0f, | ||
242 | (-922 << 5) | 0x0d | ||
243 | }; | ||
244 | |||
245 | static const s16 coeff_4k_sb_1seg[8] = { | ||
246 | (638 << 5) | 0x0d, (683 << 5) | 0x02, (638 << 5) | 0x0d, (638 << 5) | 0x0d, (-655 << 5) | 0x0a, (517 << 5) | 0x00, (698 << 5) | 0x0d, | ||
247 | (-655 << 5) | 0x0a | ||
248 | }; | ||
249 | |||
250 | static const s16 coeff_4k_sb_3seg_0dqpsk_1dqpsk[8] = { | ||
251 | (-707 << 5) | 0x14, (910 << 5) | 0x06, (889 << 5) | 0x16, (-707 << 5) | 0x14, (-958 << 5) | 0x13, (993 << 5) | 0x05, (523 << 5) | 0x14, | ||
252 | (-958 << 5) | 0x13 | ||
253 | }; | ||
254 | |||
255 | static const s16 coeff_4k_sb_3seg_0dqpsk[8] = { | ||
256 | (-723 << 5) | 0x13, (910 << 5) | 0x05, (777 << 5) | 0x14, (-723 << 5) | 0x13, (-568 << 5) | 0x0f, (547 << 5) | 0x03, (696 << 5) | 0x12, | ||
257 | (-568 << 5) | 0x0f | ||
258 | }; | ||
259 | |||
260 | static const s16 coeff_4k_sb_3seg_1dqpsk[8] = { | ||
261 | (-940 << 5) | 0x15, (607 << 5) | 0x05, (915 << 5) | 0x16, (-940 << 5) | 0x15, (-848 << 5) | 0x13, (683 << 5) | 0x04, (543 << 5) | 0x14, | ||
262 | (-848 << 5) | 0x13 | ||
263 | }; | ||
264 | |||
265 | static const s16 coeff_4k_sb_3seg[8] = { | ||
266 | (612 << 5) | 0x12, (910 << 5) | 0x04, (864 << 5) | 0x14, (612 << 5) | 0x12, (-869 << 5) | 0x13, (683 << 5) | 0x02, (869 << 5) | 0x12, | ||
267 | (-869 << 5) | 0x13 | ||
268 | }; | ||
269 | |||
270 | static const s16 coeff_8k_sb_1seg_dqpsk[8] = { | ||
271 | (-835 << 5) | 0x12, (684 << 5) | 0x05, (735 << 5) | 0x14, (-835 << 5) | 0x12, (-598 << 5) | 0x10, (781 << 5) | 0x04, (739 << 5) | 0x13, | ||
272 | (-598 << 5) | 0x10 | ||
273 | }; | ||
274 | |||
275 | static const s16 coeff_8k_sb_1seg[8] = { | ||
276 | (673 << 5) | 0x0f, (683 << 5) | 0x03, (808 << 5) | 0x12, (673 << 5) | 0x0f, (585 << 5) | 0x0f, (512 << 5) | 0x01, (780 << 5) | 0x0f, | ||
277 | (585 << 5) | 0x0f | ||
278 | }; | ||
279 | |||
280 | static const s16 coeff_8k_sb_3seg_0dqpsk_1dqpsk[8] = { | ||
281 | (863 << 5) | 0x17, (930 << 5) | 0x07, (878 << 5) | 0x19, (863 << 5) | 0x17, (0 << 5) | 0x14, (521 << 5) | 0x05, (980 << 5) | 0x18, | ||
282 | (0 << 5) | 0x14 | ||
283 | }; | ||
284 | |||
285 | static const s16 coeff_8k_sb_3seg_0dqpsk[8] = { | ||
286 | (-924 << 5) | 0x17, (910 << 5) | 0x06, (774 << 5) | 0x17, (-924 << 5) | 0x17, (-877 << 5) | 0x15, (565 << 5) | 0x04, (553 << 5) | 0x15, | ||
287 | (-877 << 5) | 0x15 | ||
288 | }; | ||
289 | |||
290 | static const s16 coeff_8k_sb_3seg_1dqpsk[8] = { | ||
291 | (-921 << 5) | 0x19, (607 << 5) | 0x06, (881 << 5) | 0x19, (-921 << 5) | 0x19, (-921 << 5) | 0x14, (713 << 5) | 0x05, (1018 << 5) | 0x18, | ||
292 | (-921 << 5) | 0x14 | ||
293 | }; | ||
294 | |||
295 | static const s16 coeff_8k_sb_3seg[8] = { | ||
296 | (514 << 5) | 0x14, (910 << 5) | 0x05, (861 << 5) | 0x17, (514 << 5) | 0x14, (690 << 5) | 0x14, (683 << 5) | 0x03, (662 << 5) | 0x15, | ||
297 | (690 << 5) | 0x14 | ||
298 | }; | ||
299 | |||
300 | static const s16 ana_fe_coeff_3seg[24] = { | ||
301 | 81, 80, 78, 74, 68, 61, 54, 45, 37, 28, 19, 11, 4, 1022, 1017, 1013, 1010, 1008, 1008, 1008, 1008, 1010, 1014, 1017 | ||
302 | }; | ||
303 | |||
304 | static const s16 ana_fe_coeff_1seg[24] = { | ||
305 | 249, 226, 164, 82, 5, 981, 970, 988, 1018, 20, 31, 26, 8, 1012, 1000, 1018, 1012, 8, 15, 14, 9, 3, 1017, 1003 | ||
306 | }; | ||
307 | |||
308 | static const s16 ana_fe_coeff_13seg[24] = { | ||
309 | 396, 305, 105, -51, -77, -12, 41, 31, -11, -30, -11, 14, 15, -2, -13, -7, 5, 8, 1, -6, -7, -3, 0, 1 | ||
310 | }; | ||
311 | |||
312 | static u16 fft_to_mode(struct dib8000_state *state) | ||
313 | { | ||
314 | u16 mode; | ||
315 | switch (state->fe[0]->dtv_property_cache.transmission_mode) { | ||
316 | case TRANSMISSION_MODE_2K: | ||
317 | mode = 1; | ||
318 | break; | ||
319 | case TRANSMISSION_MODE_4K: | ||
320 | mode = 2; | ||
321 | break; | ||
322 | default: | ||
323 | case TRANSMISSION_MODE_AUTO: | ||
324 | case TRANSMISSION_MODE_8K: | ||
325 | mode = 3; | ||
326 | break; | ||
327 | } | ||
328 | return mode; | ||
329 | } | ||
330 | |||
331 | static void dib8000_set_acquisition_mode(struct dib8000_state *state) | ||
332 | { | ||
333 | u16 nud = dib8000_read_word(state, 298); | ||
334 | nud |= (1 << 3) | (1 << 0); | ||
335 | dprintk("acquisition mode activated"); | ||
336 | dib8000_write_word(state, 298, nud); | ||
337 | } | ||
338 | static int dib8000_set_output_mode(struct dvb_frontend *fe, int mode) | ||
339 | { | ||
340 | struct dib8000_state *state = fe->demodulator_priv; | ||
341 | |||
342 | u16 outreg, fifo_threshold, smo_mode, sram = 0x0205; /* by default SDRAM deintlv is enabled */ | ||
343 | |||
344 | outreg = 0; | ||
345 | fifo_threshold = 1792; | ||
346 | smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1); | ||
347 | |||
348 | dprintk("-I- Setting output mode for demod %p to %d", | ||
349 | &state->fe[0], mode); | ||
350 | |||
351 | switch (mode) { | ||
352 | case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock | ||
353 | outreg = (1 << 10); /* 0x0400 */ | ||
354 | break; | ||
355 | case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock | ||
356 | outreg = (1 << 10) | (1 << 6); /* 0x0440 */ | ||
357 | break; | ||
358 | case OUTMODE_MPEG2_SERIAL: // STBs with serial input | ||
359 | outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */ | ||
360 | break; | ||
361 | case OUTMODE_DIVERSITY: | ||
362 | if (state->cfg.hostbus_diversity) { | ||
363 | outreg = (1 << 10) | (4 << 6); /* 0x0500 */ | ||
364 | sram &= 0xfdff; | ||
365 | } else | ||
366 | sram |= 0x0c00; | ||
367 | break; | ||
368 | case OUTMODE_MPEG2_FIFO: // e.g. USB feeding | ||
369 | smo_mode |= (3 << 1); | ||
370 | fifo_threshold = 512; | ||
371 | outreg = (1 << 10) | (5 << 6); | ||
372 | break; | ||
373 | case OUTMODE_HIGH_Z: // disable | ||
374 | outreg = 0; | ||
375 | break; | ||
376 | |||
377 | case OUTMODE_ANALOG_ADC: | ||
378 | outreg = (1 << 10) | (3 << 6); | ||
379 | dib8000_set_acquisition_mode(state); | ||
380 | break; | ||
381 | |||
382 | default: | ||
383 | dprintk("Unhandled output_mode passed to be set for demod %p", | ||
384 | &state->fe[0]); | ||
385 | return -EINVAL; | ||
386 | } | ||
387 | |||
388 | if (state->cfg.output_mpeg2_in_188_bytes) | ||
389 | smo_mode |= (1 << 5); | ||
390 | |||
391 | dib8000_write_word(state, 299, smo_mode); | ||
392 | dib8000_write_word(state, 300, fifo_threshold); /* synchronous fread */ | ||
393 | dib8000_write_word(state, 1286, outreg); | ||
394 | dib8000_write_word(state, 1291, sram); | ||
395 | |||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | static int dib8000_set_diversity_in(struct dvb_frontend *fe, int onoff) | ||
400 | { | ||
401 | struct dib8000_state *state = fe->demodulator_priv; | ||
402 | u16 sync_wait = dib8000_read_word(state, 273) & 0xfff0; | ||
403 | |||
404 | if (!state->differential_constellation) { | ||
405 | 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 | ||
407 | } else { | ||
408 | dib8000_write_word(state, 272, 0); //dvsy_off_lmod4 = 0 | ||
409 | dib8000_write_word(state, 273, sync_wait); // sync_enable = 0; comb_mode = 0 | ||
410 | } | ||
411 | state->diversity_onoff = onoff; | ||
412 | |||
413 | switch (onoff) { | ||
414 | case 0: /* only use the internal way - not the diversity input */ | ||
415 | dib8000_write_word(state, 270, 1); | ||
416 | dib8000_write_word(state, 271, 0); | ||
417 | break; | ||
418 | case 1: /* both ways */ | ||
419 | dib8000_write_word(state, 270, 6); | ||
420 | dib8000_write_word(state, 271, 6); | ||
421 | break; | ||
422 | case 2: /* only the diversity input */ | ||
423 | dib8000_write_word(state, 270, 0); | ||
424 | dib8000_write_word(state, 271, 1); | ||
425 | break; | ||
426 | } | ||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | static void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_power_mode mode) | ||
431 | { | ||
432 | /* by default everything is going to be powered off */ | ||
433 | u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0xffff, | ||
434 | reg_900 = (dib8000_read_word(state, 900) & 0xfffc) | 0x3, | ||
435 | reg_1280; | ||
436 | |||
437 | if (state->revision != 0x8090) | ||
438 | reg_1280 = (dib8000_read_word(state, 1280) & 0x00ff) | 0xff00; | ||
439 | else | ||
440 | reg_1280 = (dib8000_read_word(state, 1280) & 0x707f) | 0x8f80; | ||
441 | |||
442 | /* now, depending on the requested mode, we power on */ | ||
443 | switch (mode) { | ||
444 | /* power up everything in the demod */ | ||
445 | case DIB8000_POWER_ALL: | ||
446 | reg_774 = 0x0000; | ||
447 | reg_775 = 0x0000; | ||
448 | reg_776 = 0x0000; | ||
449 | reg_900 &= 0xfffc; | ||
450 | if (state->revision != 0x8090) | ||
451 | reg_1280 &= 0x00ff; | ||
452 | else | ||
453 | reg_1280 &= 0x707f; | ||
454 | break; | ||
455 | case DIB8000_POWER_INTERFACE_ONLY: | ||
456 | if (state->revision != 0x8090) | ||
457 | reg_1280 &= 0x00ff; | ||
458 | else | ||
459 | reg_1280 &= 0xfa7b; | ||
460 | break; | ||
461 | } | ||
462 | |||
463 | dprintk("powermode : 774 : %x ; 775 : %x; 776 : %x ; 900 : %x; 1280 : %x", reg_774, reg_775, reg_776, reg_900, reg_1280); | ||
464 | dib8000_write_word(state, 774, reg_774); | ||
465 | dib8000_write_word(state, 775, reg_775); | ||
466 | dib8000_write_word(state, 776, reg_776); | ||
467 | dib8000_write_word(state, 900, reg_900); | ||
468 | dib8000_write_word(state, 1280, reg_1280); | ||
469 | } | ||
470 | |||
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) | ||
493 | { | ||
494 | int ret = 0; | ||
495 | u16 reg, reg_907 = dib8000_read_word(state, 907); | ||
496 | u16 reg_908 = dib8000_read_word(state, 908); | ||
497 | |||
498 | switch (no) { | ||
499 | case DIBX000_SLOW_ADC_ON: | ||
500 | if (state->revision != 0x8090) { | ||
501 | reg_908 |= (1 << 1) | (1 << 0); | ||
502 | ret |= dib8000_write_word(state, 908, reg_908); | ||
503 | reg_908 &= ~(1 << 1); | ||
504 | } else { | ||
505 | reg = dib8000_read_word(state, 1925); | ||
506 | /* en_slowAdc = 1 & reset_sladc = 1 */ | ||
507 | dib8000_write_word(state, 1925, reg | | ||
508 | (1<<4) | (1<<2)); | ||
509 | |||
510 | /* read acces to make it works... strange ... */ | ||
511 | reg = dib8000_read_word(state, 1925); | ||
512 | msleep(20); | ||
513 | /* en_slowAdc = 1 & reset_sladc = 0 */ | ||
514 | dib8000_write_word(state, 1925, reg & ~(1<<4)); | ||
515 | |||
516 | reg = dib8000_read_word(state, 921) & ~((0x3 << 14) | ||
517 | | (0x3 << 12)); | ||
518 | /* ref = Vin1 => Vbg ; sel = Vin0 or Vin3 ; | ||
519 | (Vin2 = Vcm) */ | ||
520 | dib8000_write_word(state, 921, reg | (1 << 14) | ||
521 | | (3 << 12)); | ||
522 | } | ||
523 | break; | ||
524 | |||
525 | case DIBX000_SLOW_ADC_OFF: | ||
526 | if (state->revision == 0x8090) { | ||
527 | reg = dib8000_read_word(state, 1925); | ||
528 | /* reset_sladc = 1 en_slowAdc = 0 */ | ||
529 | dib8000_write_word(state, 1925, | ||
530 | (reg & ~(1<<2)) | (1<<4)); | ||
531 | } | ||
532 | reg_908 |= (1 << 1) | (1 << 0); | ||
533 | break; | ||
534 | |||
535 | case DIBX000_ADC_ON: | ||
536 | reg_907 &= 0x0fff; | ||
537 | reg_908 &= 0x0003; | ||
538 | break; | ||
539 | |||
540 | case DIBX000_ADC_OFF: // leave the VBG voltage on | ||
541 | reg_907 |= (1 << 14) | (1 << 13) | (1 << 12); | ||
542 | reg_908 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2); | ||
543 | break; | ||
544 | |||
545 | case DIBX000_VBG_ENABLE: | ||
546 | reg_907 &= ~(1 << 15); | ||
547 | break; | ||
548 | |||
549 | case DIBX000_VBG_DISABLE: | ||
550 | reg_907 |= (1 << 15); | ||
551 | break; | ||
552 | |||
553 | default: | ||
554 | break; | ||
555 | } | ||
556 | |||
557 | ret |= dib8000_write_word(state, 907, reg_907); | ||
558 | ret |= dib8000_write_word(state, 908, reg_908); | ||
559 | |||
560 | return ret; | ||
561 | } | ||
562 | |||
563 | static int dib8000_set_bandwidth(struct dvb_frontend *fe, u32 bw) | ||
564 | { | ||
565 | struct dib8000_state *state = fe->demodulator_priv; | ||
566 | u32 timf; | ||
567 | |||
568 | if (bw == 0) | ||
569 | bw = 6000; | ||
570 | |||
571 | if (state->timf == 0) { | ||
572 | dprintk("using default timf"); | ||
573 | timf = state->timf_default; | ||
574 | } else { | ||
575 | dprintk("using updated timf"); | ||
576 | timf = state->timf; | ||
577 | } | ||
578 | |||
579 | dib8000_write_word(state, 29, (u16) ((timf >> 16) & 0xffff)); | ||
580 | dib8000_write_word(state, 30, (u16) ((timf) & 0xffff)); | ||
581 | |||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | static int dib8000_sad_calib(struct dib8000_state *state) | ||
586 | { | ||
587 | if (state->revision == 0x8090) { | ||
588 | dprintk("%s: the sad calibration is not needed for the dib8096P", | ||
589 | __func__); | ||
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 | |||
596 | /* do the calibration */ | ||
597 | dib8000_write_word(state, 923, (1 << 0)); | ||
598 | dib8000_write_word(state, 923, (0 << 0)); | ||
599 | |||
600 | msleep(1); | ||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value) | ||
605 | { | ||
606 | struct dib8000_state *state = fe->demodulator_priv; | ||
607 | if (value > 4095) | ||
608 | value = 4095; | ||
609 | state->wbd_ref = value; | ||
610 | return dib8000_write_word(state, 106, value); | ||
611 | } | ||
612 | |||
613 | EXPORT_SYMBOL(dib8000_set_wbd_ref); | ||
614 | static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw) | ||
615 | { | ||
616 | dprintk("ifreq: %d %x, inversion: %d", bw->ifreq, bw->ifreq, bw->ifreq >> 25); | ||
617 | if (state->revision != 0x8090) { | ||
618 | dib8000_write_word(state, 23, | ||
619 | (u16) (((bw->internal * 1000) >> 16) & 0xffff)); | ||
620 | dib8000_write_word(state, 24, | ||
621 | (u16) ((bw->internal * 1000) & 0xffff)); | ||
622 | } else { | ||
623 | dib8000_write_word(state, 23, (u16) (((bw->internal / 2 * 1000) >> 16) & 0xffff)); | ||
624 | dib8000_write_word(state, 24, | ||
625 | (u16) ((bw->internal / 2 * 1000) & 0xffff)); | ||
626 | } | ||
627 | dib8000_write_word(state, 27, (u16) ((bw->ifreq >> 16) & 0x01ff)); | ||
628 | dib8000_write_word(state, 28, (u16) (bw->ifreq & 0xffff)); | ||
629 | dib8000_write_word(state, 26, (u16) ((bw->ifreq >> 25) & 0x0003)); | ||
630 | |||
631 | if (state->revision != 0x8090) | ||
632 | dib8000_write_word(state, 922, bw->sad_cfg); | ||
633 | } | ||
634 | |||
635 | static void dib8000_reset_pll(struct dib8000_state *state) | ||
636 | { | ||
637 | const struct dibx000_bandwidth_config *pll = state->cfg.pll; | ||
638 | u16 clk_cfg1, reg; | ||
639 | |||
640 | if (state->revision != 0x8090) { | ||
641 | dib8000_write_word(state, 901, | ||
642 | (pll->pll_prediv << 8) | (pll->pll_ratio << 0)); | ||
643 | |||
644 | clk_cfg1 = (1 << 10) | (0 << 9) | (pll->IO_CLK_en_core << 8) | | ||
645 | (pll->bypclk_div << 5) | (pll->enable_refdiv << 4) | | ||
646 | (1 << 3) | (pll->pll_range << 1) | | ||
647 | (pll->pll_reset << 0); | ||
648 | |||
649 | dib8000_write_word(state, 902, clk_cfg1); | ||
650 | clk_cfg1 = (clk_cfg1 & 0xfff7) | (pll->pll_bypass << 3); | ||
651 | dib8000_write_word(state, 902, clk_cfg1); | ||
652 | |||
653 | dprintk("clk_cfg1: 0x%04x", clk_cfg1); | ||
654 | |||
655 | /* smpl_cfg: P_refclksel=2, P_ensmplsel=1 nodivsmpl=1 */ | ||
656 | if (state->cfg.pll->ADClkSrc == 0) | ||
657 | dib8000_write_word(state, 904, | ||
658 | (0 << 15) | (0 << 12) | (0 << 10) | | ||
659 | (pll->modulo << 8) | | ||
660 | (pll->ADClkSrc << 7) | (0 << 1)); | ||
661 | else if (state->cfg.refclksel != 0) | ||
662 | dib8000_write_word(state, 904, (0 << 15) | (1 << 12) | | ||
663 | ((state->cfg.refclksel & 0x3) << 10) | | ||
664 | (pll->modulo << 8) | | ||
665 | (pll->ADClkSrc << 7) | (0 << 1)); | ||
666 | else | ||
667 | dib8000_write_word(state, 904, (0 << 15) | (1 << 12) | | ||
668 | (3 << 10) | (pll->modulo << 8) | | ||
669 | (pll->ADClkSrc << 7) | (0 << 1)); | ||
670 | } else { | ||
671 | dib8000_write_word(state, 1856, (!pll->pll_reset<<13) | | ||
672 | (pll->pll_range<<12) | (pll->pll_ratio<<6) | | ||
673 | (pll->pll_prediv)); | ||
674 | |||
675 | reg = dib8000_read_word(state, 1857); | ||
676 | dib8000_write_word(state, 1857, reg|(!pll->pll_bypass<<15)); | ||
677 | |||
678 | reg = dib8000_read_word(state, 1858); /* Force clk out pll /2 */ | ||
679 | dib8000_write_word(state, 1858, reg | 1); | ||
680 | |||
681 | dib8000_write_word(state, 904, (pll->modulo << 8)); | ||
682 | } | ||
683 | |||
684 | dib8000_reset_pll_common(state, pll); | ||
685 | } | ||
686 | |||
687 | int dib8000_update_pll(struct dvb_frontend *fe, | ||
688 | struct dibx000_bandwidth_config *pll) | ||
689 | { | ||
690 | struct dib8000_state *state = fe->demodulator_priv; | ||
691 | u16 reg_1857, reg_1856 = dib8000_read_word(state, 1856); | ||
692 | u8 loopdiv, prediv; | ||
693 | u32 internal, xtal; | ||
694 | |||
695 | /* get back old values */ | ||
696 | prediv = reg_1856 & 0x3f; | ||
697 | loopdiv = (reg_1856 >> 6) & 0x3f; | ||
698 | |||
699 | if ((pll != NULL) && (pll->pll_prediv != prediv || | ||
700 | 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); | ||
702 | reg_1856 &= 0xf000; | ||
703 | reg_1857 = dib8000_read_word(state, 1857); | ||
704 | /* disable PLL */ | ||
705 | dib8000_write_word(state, 1857, reg_1857 & ~(1 << 15)); | ||
706 | |||
707 | dib8000_write_word(state, 1856, reg_1856 | | ||
708 | ((pll->pll_ratio & 0x3f) << 6) | | ||
709 | (pll->pll_prediv & 0x3f)); | ||
710 | |||
711 | /* write new system clk into P_sec_len */ | ||
712 | internal = dib8000_read32(state, 23) / 1000; | ||
713 | dprintk("Old Internal = %d", internal); | ||
714 | xtal = 2 * (internal / loopdiv) * prediv; | ||
715 | internal = 1000 * (xtal/pll->pll_prediv) * pll->pll_ratio; | ||
716 | dprintk("Xtal = %d , New Fmem = %d New Fdemod = %d, New Fsampling = %d", xtal, internal/1000, internal/2000, internal/8000); | ||
717 | dprintk("New Internal = %d", internal); | ||
718 | |||
719 | dib8000_write_word(state, 23, | ||
720 | (u16) (((internal / 2) >> 16) & 0xffff)); | ||
721 | dib8000_write_word(state, 24, (u16) ((internal / 2) & 0xffff)); | ||
722 | /* enable PLL */ | ||
723 | dib8000_write_word(state, 1857, reg_1857 | (1 << 15)); | ||
724 | |||
725 | while (((dib8000_read_word(state, 1856)>>15)&0x1) != 1) | ||
726 | dprintk("Waiting for PLL to lock"); | ||
727 | |||
728 | /* verify */ | ||
729 | reg_1856 = dib8000_read_word(state, 1856); | ||
730 | dprintk("PLL Updated with prediv = %d and loopdiv = %d", | ||
731 | reg_1856&0x3f, (reg_1856>>6)&0x3f); | ||
732 | |||
733 | return 0; | ||
734 | } | ||
735 | return -EINVAL; | ||
736 | } | ||
737 | EXPORT_SYMBOL(dib8000_update_pll); | ||
738 | |||
739 | |||
740 | static int dib8000_reset_gpio(struct dib8000_state *st) | ||
741 | { | ||
742 | /* reset the GPIOs */ | ||
743 | dib8000_write_word(st, 1029, st->cfg.gpio_dir); | ||
744 | dib8000_write_word(st, 1030, st->cfg.gpio_val); | ||
745 | |||
746 | /* TODO 782 is P_gpio_od */ | ||
747 | |||
748 | dib8000_write_word(st, 1032, st->cfg.gpio_pwm_pos); | ||
749 | |||
750 | dib8000_write_word(st, 1037, st->cfg.pwm_freq_div); | ||
751 | return 0; | ||
752 | } | ||
753 | |||
754 | static int dib8000_cfg_gpio(struct dib8000_state *st, u8 num, u8 dir, u8 val) | ||
755 | { | ||
756 | st->cfg.gpio_dir = dib8000_read_word(st, 1029); | ||
757 | st->cfg.gpio_dir &= ~(1 << num); /* reset the direction bit */ | ||
758 | st->cfg.gpio_dir |= (dir & 0x1) << num; /* set the new direction */ | ||
759 | dib8000_write_word(st, 1029, st->cfg.gpio_dir); | ||
760 | |||
761 | st->cfg.gpio_val = dib8000_read_word(st, 1030); | ||
762 | st->cfg.gpio_val &= ~(1 << num); /* reset the direction bit */ | ||
763 | st->cfg.gpio_val |= (val & 0x01) << num; /* set the new value */ | ||
764 | dib8000_write_word(st, 1030, st->cfg.gpio_val); | ||
765 | |||
766 | dprintk("gpio dir: %x: gpio val: %x", st->cfg.gpio_dir, st->cfg.gpio_val); | ||
767 | |||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) | ||
772 | { | ||
773 | struct dib8000_state *state = fe->demodulator_priv; | ||
774 | return dib8000_cfg_gpio(state, num, dir, val); | ||
775 | } | ||
776 | |||
777 | EXPORT_SYMBOL(dib8000_set_gpio); | ||
778 | static const u16 dib8000_defaults[] = { | ||
779 | /* auto search configuration - lock0 by default waiting | ||
780 | * for cpil_lock; lock1 cpil_lock; lock2 tmcc_sync_lock */ | ||
781 | 3, 7, | ||
782 | 0x0004, | ||
783 | 0x0400, | ||
784 | 0x0814, | ||
785 | |||
786 | 12, 11, | ||
787 | 0x001b, | ||
788 | 0x7740, | ||
789 | 0x005b, | ||
790 | 0x8d80, | ||
791 | 0x01c9, | ||
792 | 0xc380, | ||
793 | 0x0000, | ||
794 | 0x0080, | ||
795 | 0x0000, | ||
796 | 0x0090, | ||
797 | 0x0001, | ||
798 | 0xd4c0, | ||
799 | |||
800 | /*1, 32, | ||
801 | 0x6680 // P_corm_thres Lock algorithms configuration */ | ||
802 | |||
803 | 11, 80, /* set ADC level to -16 */ | ||
804 | (1 << 13) - 825 - 117, | ||
805 | (1 << 13) - 837 - 117, | ||
806 | (1 << 13) - 811 - 117, | ||
807 | (1 << 13) - 766 - 117, | ||
808 | (1 << 13) - 737 - 117, | ||
809 | (1 << 13) - 693 - 117, | ||
810 | (1 << 13) - 648 - 117, | ||
811 | (1 << 13) - 619 - 117, | ||
812 | (1 << 13) - 575 - 117, | ||
813 | (1 << 13) - 531 - 117, | ||
814 | (1 << 13) - 501 - 117, | ||
815 | |||
816 | 4, 108, | ||
817 | 0, | ||
818 | 0, | ||
819 | 0, | ||
820 | 0, | ||
821 | |||
822 | 1, 175, | ||
823 | 0x0410, | ||
824 | 1, 179, | ||
825 | 8192, // P_fft_nb_to_cut | ||
826 | |||
827 | 6, 181, | ||
828 | 0x2800, // P_coff_corthres_ ( 2k 4k 8k ) 0x2800 | ||
829 | 0x2800, | ||
830 | 0x2800, | ||
831 | 0x2800, // P_coff_cpilthres_ ( 2k 4k 8k ) 0x2800 | ||
832 | 0x2800, | ||
833 | 0x2800, | ||
834 | |||
835 | 2, 193, | ||
836 | 0x0666, // P_pha3_thres | ||
837 | 0x0000, // P_cti_use_cpe, P_cti_use_prog | ||
838 | |||
839 | 2, 205, | ||
840 | 0x200f, // P_cspu_regul, P_cspu_win_cut | ||
841 | 0x000f, // P_des_shift_work | ||
842 | |||
843 | 5, 215, | ||
844 | 0x023d, // P_adp_regul_cnt | ||
845 | 0x00a4, // P_adp_noise_cnt | ||
846 | 0x00a4, // P_adp_regul_ext | ||
847 | 0x7ff0, // P_adp_noise_ext | ||
848 | 0x3ccc, // P_adp_fil | ||
849 | |||
850 | 1, 230, | ||
851 | 0x0000, // P_2d_byp_ti_num | ||
852 | |||
853 | 1, 263, | ||
854 | 0x800, //P_equal_thres_wgn | ||
855 | |||
856 | 1, 268, | ||
857 | (2 << 9) | 39, // P_equal_ctrl_synchro, P_equal_speedmode | ||
858 | |||
859 | 1, 270, | ||
860 | 0x0001, // P_div_lock0_wait | ||
861 | 1, 285, | ||
862 | 0x0020, //p_fec_ | ||
863 | 1, 299, | ||
864 | 0x0062, /* P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard */ | ||
865 | |||
866 | 1, 338, | ||
867 | (1 << 12) | // P_ctrl_corm_thres4pre_freq_inh=1 | ||
868 | (1 << 10) | | ||
869 | (0 << 9) | /* P_ctrl_pre_freq_inh=0 */ | ||
870 | (3 << 5) | /* P_ctrl_pre_freq_step=3 */ | ||
871 | (1 << 0), /* P_pre_freq_win_len=1 */ | ||
872 | |||
873 | 0, | ||
874 | }; | ||
875 | |||
876 | static u16 dib8000_identify(struct i2c_device *client) | ||
877 | { | ||
878 | u16 value; | ||
879 | |||
880 | //because of glitches sometimes | ||
881 | value = dib8000_i2c_read16(client, 896); | ||
882 | |||
883 | if ((value = dib8000_i2c_read16(client, 896)) != 0x01b3) { | ||
884 | dprintk("wrong Vendor ID (read=0x%x)", value); | ||
885 | return 0; | ||
886 | } | ||
887 | |||
888 | value = dib8000_i2c_read16(client, 897); | ||
889 | if (value != 0x8000 && value != 0x8001 && | ||
890 | value != 0x8002 && value != 0x8090) { | ||
891 | dprintk("wrong Device ID (%x)", value); | ||
892 | return 0; | ||
893 | } | ||
894 | |||
895 | switch (value) { | ||
896 | case 0x8000: | ||
897 | dprintk("found DiB8000A"); | ||
898 | break; | ||
899 | case 0x8001: | ||
900 | dprintk("found DiB8000B"); | ||
901 | break; | ||
902 | case 0x8002: | ||
903 | dprintk("found DiB8000C"); | ||
904 | break; | ||
905 | case 0x8090: | ||
906 | dprintk("found DiB8096P"); | ||
907 | break; | ||
908 | } | ||
909 | return value; | ||
910 | } | ||
911 | |||
912 | static int dib8000_reset(struct dvb_frontend *fe) | ||
913 | { | ||
914 | struct dib8000_state *state = fe->demodulator_priv; | ||
915 | |||
916 | if ((state->revision = dib8000_identify(&state->i2c)) == 0) | ||
917 | return -EINVAL; | ||
918 | |||
919 | /* sram lead in, rdy */ | ||
920 | if (state->revision != 0x8090) | ||
921 | dib8000_write_word(state, 1287, 0x0003); | ||
922 | |||
923 | if (state->revision == 0x8000) | ||
924 | dprintk("error : dib8000 MA not supported"); | ||
925 | |||
926 | dibx000_reset_i2c_master(&state->i2c_master); | ||
927 | |||
928 | dib8000_set_power_mode(state, DIB8000_POWER_ALL); | ||
929 | |||
930 | /* 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); | ||
932 | |||
933 | /* restart all parts */ | ||
934 | dib8000_write_word(state, 770, 0xffff); | ||
935 | dib8000_write_word(state, 771, 0xffff); | ||
936 | dib8000_write_word(state, 772, 0xfffc); | ||
937 | if (state->revision == 0x8090) | ||
938 | dib8000_write_word(state, 1280, 0x0045); | ||
939 | else | ||
940 | dib8000_write_word(state, 1280, 0x004d); | ||
941 | dib8000_write_word(state, 1281, 0x000c); | ||
942 | |||
943 | dib8000_write_word(state, 770, 0x0000); | ||
944 | dib8000_write_word(state, 771, 0x0000); | ||
945 | dib8000_write_word(state, 772, 0x0000); | ||
946 | dib8000_write_word(state, 898, 0x0004); // sad | ||
947 | dib8000_write_word(state, 1280, 0x0000); | ||
948 | dib8000_write_word(state, 1281, 0x0000); | ||
949 | |||
950 | /* drives */ | ||
951 | if (state->revision != 0x8090) { | ||
952 | if (state->cfg.drives) | ||
953 | dib8000_write_word(state, 906, state->cfg.drives); | ||
954 | else { | ||
955 | dprintk("using standard PAD-drive-settings, please adjust settings in config-struct to be optimal."); | ||
956 | /* min drive SDRAM - not optimal - adjust */ | ||
957 | dib8000_write_word(state, 906, 0x2d98); | ||
958 | } | ||
959 | } | ||
960 | |||
961 | dib8000_reset_pll(state); | ||
962 | if (state->revision != 0x8090) | ||
963 | dib8000_write_word(state, 898, 0x0004); | ||
964 | |||
965 | if (dib8000_reset_gpio(state) != 0) | ||
966 | dprintk("GPIO reset was not successful."); | ||
967 | |||
968 | if ((state->revision != 0x8090) && | ||
969 | (dib8000_set_output_mode(fe, OUTMODE_HIGH_Z) != 0)) | ||
970 | dprintk("OUTPUT_MODE could not be resetted."); | ||
971 | |||
972 | state->current_agc = NULL; | ||
973 | |||
974 | // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ... | ||
975 | /* P_iqc_ca2 = 0; P_iqc_impnc_on = 0; P_iqc_mode = 0; */ | ||
976 | if (state->cfg.pll->ifreq == 0) | ||
977 | dib8000_write_word(state, 40, 0x0755); /* P_iqc_corr_inh = 0 enable IQcorr block */ | ||
978 | else | ||
979 | dib8000_write_word(state, 40, 0x1f55); /* P_iqc_corr_inh = 1 disable IQcorr block */ | ||
980 | |||
981 | { | ||
982 | u16 l = 0, r; | ||
983 | const u16 *n; | ||
984 | n = dib8000_defaults; | ||
985 | l = *n++; | ||
986 | while (l) { | ||
987 | r = *n++; | ||
988 | do { | ||
989 | dib8000_write_word(state, r, *n++); | ||
990 | r++; | ||
991 | } while (--l); | ||
992 | l = *n++; | ||
993 | } | ||
994 | } | ||
995 | if (state->revision != 0x8090) | ||
996 | dib8000_write_word(state, 903, (0 << 4) | 2); | ||
997 | state->isdbt_cfg_loaded = 0; | ||
998 | |||
999 | //div_cfg override for special configs | ||
1000 | if (state->cfg.div_cfg != 0) | ||
1001 | dib8000_write_word(state, 903, state->cfg.div_cfg); | ||
1002 | |||
1003 | /* unforce divstr regardless whether i2c enumeration was done or not */ | ||
1004 | dib8000_write_word(state, 1285, dib8000_read_word(state, 1285) & ~(1 << 1)); | ||
1005 | |||
1006 | dib8000_set_bandwidth(fe, 6000); | ||
1007 | |||
1008 | dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON); | ||
1009 | if (state->revision != 0x8090) { | ||
1010 | dib8000_sad_calib(state); | ||
1011 | dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF); | ||
1012 | } | ||
1013 | |||
1014 | dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY); | ||
1015 | |||
1016 | return 0; | ||
1017 | } | ||
1018 | |||
1019 | static void dib8000_restart_agc(struct dib8000_state *state) | ||
1020 | { | ||
1021 | // P_restart_iqc & P_restart_agc | ||
1022 | dib8000_write_word(state, 770, 0x0a00); | ||
1023 | dib8000_write_word(state, 770, 0x0000); | ||
1024 | } | ||
1025 | |||
1026 | static int dib8000_update_lna(struct dib8000_state *state) | ||
1027 | { | ||
1028 | u16 dyn_gain; | ||
1029 | |||
1030 | if (state->cfg.update_lna) { | ||
1031 | // read dyn_gain here (because it is demod-dependent and not tuner) | ||
1032 | dyn_gain = dib8000_read_word(state, 390); | ||
1033 | |||
1034 | if (state->cfg.update_lna(state->fe[0], dyn_gain)) { | ||
1035 | dib8000_restart_agc(state); | ||
1036 | return 1; | ||
1037 | } | ||
1038 | } | ||
1039 | return 0; | ||
1040 | } | ||
1041 | |||
1042 | static int dib8000_set_agc_config(struct dib8000_state *state, u8 band) | ||
1043 | { | ||
1044 | struct dibx000_agc_config *agc = NULL; | ||
1045 | int i; | ||
1046 | u16 reg; | ||
1047 | |||
1048 | if (state->current_band == band && state->current_agc != NULL) | ||
1049 | return 0; | ||
1050 | state->current_band = band; | ||
1051 | |||
1052 | for (i = 0; i < state->cfg.agc_config_count; i++) | ||
1053 | if (state->cfg.agc[i].band_caps & band) { | ||
1054 | agc = &state->cfg.agc[i]; | ||
1055 | break; | ||
1056 | } | ||
1057 | |||
1058 | if (agc == NULL) { | ||
1059 | dprintk("no valid AGC configuration found for band 0x%02x", band); | ||
1060 | return -EINVAL; | ||
1061 | } | ||
1062 | |||
1063 | state->current_agc = agc; | ||
1064 | |||
1065 | /* AGC */ | ||
1066 | dib8000_write_word(state, 76, agc->setup); | ||
1067 | dib8000_write_word(state, 77, agc->inv_gain); | ||
1068 | dib8000_write_word(state, 78, agc->time_stabiliz); | ||
1069 | dib8000_write_word(state, 101, (agc->alpha_level << 12) | agc->thlock); | ||
1070 | |||
1071 | // Demod AGC loop configuration | ||
1072 | dib8000_write_word(state, 102, (agc->alpha_mant << 5) | agc->alpha_exp); | ||
1073 | dib8000_write_word(state, 103, (agc->beta_mant << 6) | agc->beta_exp); | ||
1074 | |||
1075 | dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d", | ||
1076 | state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); | ||
1077 | |||
1078 | /* AGC continued */ | ||
1079 | if (state->wbd_ref != 0) | ||
1080 | dib8000_write_word(state, 106, state->wbd_ref); | ||
1081 | else // use default | ||
1082 | dib8000_write_word(state, 106, agc->wbd_ref); | ||
1083 | |||
1084 | if (state->revision == 0x8090) { | ||
1085 | reg = dib8000_read_word(state, 922) & (0x3 << 2); | ||
1086 | dib8000_write_word(state, 922, reg | (agc->wbd_sel << 2)); | ||
1087 | } | ||
1088 | |||
1089 | dib8000_write_word(state, 107, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8)); | ||
1090 | dib8000_write_word(state, 108, agc->agc1_max); | ||
1091 | dib8000_write_word(state, 109, agc->agc1_min); | ||
1092 | dib8000_write_word(state, 110, agc->agc2_max); | ||
1093 | dib8000_write_word(state, 111, agc->agc2_min); | ||
1094 | dib8000_write_word(state, 112, (agc->agc1_pt1 << 8) | agc->agc1_pt2); | ||
1095 | dib8000_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2); | ||
1096 | dib8000_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2); | ||
1097 | dib8000_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2); | ||
1098 | |||
1099 | dib8000_write_word(state, 75, agc->agc1_pt3); | ||
1100 | if (state->revision != 0x8090) | ||
1101 | dib8000_write_word(state, 923, | ||
1102 | (dib8000_read_word(state, 923) & 0xffe3) | | ||
1103 | (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); | ||
1104 | |||
1105 | return 0; | ||
1106 | } | ||
1107 | |||
1108 | void dib8000_pwm_agc_reset(struct dvb_frontend *fe) | ||
1109 | { | ||
1110 | struct dib8000_state *state = fe->demodulator_priv; | ||
1111 | dib8000_set_adc_state(state, DIBX000_ADC_ON); | ||
1112 | dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))); | ||
1113 | } | ||
1114 | EXPORT_SYMBOL(dib8000_pwm_agc_reset); | ||
1115 | |||
1116 | static int dib8000_agc_soft_split(struct dib8000_state *state) | ||
1117 | { | ||
1118 | u16 agc, split_offset; | ||
1119 | |||
1120 | if (!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0) | ||
1121 | return FE_CALLBACK_TIME_NEVER; | ||
1122 | |||
1123 | // n_agc_global | ||
1124 | agc = dib8000_read_word(state, 390); | ||
1125 | |||
1126 | if (agc > state->current_agc->split.min_thres) | ||
1127 | split_offset = state->current_agc->split.min; | ||
1128 | else if (agc < state->current_agc->split.max_thres) | ||
1129 | split_offset = state->current_agc->split.max; | ||
1130 | else | ||
1131 | split_offset = state->current_agc->split.max * | ||
1132 | (agc - state->current_agc->split.min_thres) / | ||
1133 | (state->current_agc->split.max_thres - state->current_agc->split.min_thres); | ||
1134 | |||
1135 | dprintk("AGC split_offset: %d", split_offset); | ||
1136 | |||
1137 | // P_agc_force_split and P_agc_split_offset | ||
1138 | dib8000_write_word(state, 107, (dib8000_read_word(state, 107) & 0xff00) | split_offset); | ||
1139 | return 5000; | ||
1140 | } | ||
1141 | |||
1142 | static int dib8000_agc_startup(struct dvb_frontend *fe) | ||
1143 | { | ||
1144 | struct dib8000_state *state = fe->demodulator_priv; | ||
1145 | enum frontend_tune_state *tune_state = &state->tune_state; | ||
1146 | int ret = 0; | ||
1147 | u16 reg, upd_demod_gain_period = 0x8000; | ||
1148 | |||
1149 | switch (*tune_state) { | ||
1150 | case CT_AGC_START: | ||
1151 | // set power-up level: interf+analog+AGC | ||
1152 | |||
1153 | if (state->revision != 0x8090) | ||
1154 | dib8000_set_adc_state(state, DIBX000_ADC_ON); | ||
1155 | else { | ||
1156 | dib8000_set_power_mode(state, DIB8000_POWER_ALL); | ||
1157 | |||
1158 | reg = dib8000_read_word(state, 1947)&0xff00; | ||
1159 | dib8000_write_word(state, 1946, | ||
1160 | upd_demod_gain_period & 0xFFFF); | ||
1161 | /* bit 14 = enDemodGain */ | ||
1162 | dib8000_write_word(state, 1947, reg | (1<<14) | | ||
1163 | ((upd_demod_gain_period >> 16) & 0xFF)); | ||
1164 | |||
1165 | /* enable adc i & q */ | ||
1166 | reg = dib8000_read_word(state, 1920); | ||
1167 | dib8000_write_word(state, 1920, (reg | 0x3) & | ||
1168 | (~(1 << 7))); | ||
1169 | } | ||
1170 | |||
1171 | if (dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))) != 0) { | ||
1172 | *tune_state = CT_AGC_STOP; | ||
1173 | state->status = FE_STATUS_TUNE_FAILED; | ||
1174 | break; | ||
1175 | } | ||
1176 | |||
1177 | ret = 70; | ||
1178 | *tune_state = CT_AGC_STEP_0; | ||
1179 | break; | ||
1180 | |||
1181 | case CT_AGC_STEP_0: | ||
1182 | //AGC initialization | ||
1183 | if (state->cfg.agc_control) | ||
1184 | state->cfg.agc_control(fe, 1); | ||
1185 | |||
1186 | dib8000_restart_agc(state); | ||
1187 | |||
1188 | // wait AGC rough lock time | ||
1189 | ret = 50; | ||
1190 | *tune_state = CT_AGC_STEP_1; | ||
1191 | break; | ||
1192 | |||
1193 | case CT_AGC_STEP_1: | ||
1194 | // wait AGC accurate lock time | ||
1195 | ret = 70; | ||
1196 | |||
1197 | if (dib8000_update_lna(state)) | ||
1198 | // wait only AGC rough lock time | ||
1199 | ret = 50; | ||
1200 | else | ||
1201 | *tune_state = CT_AGC_STEP_2; | ||
1202 | break; | ||
1203 | |||
1204 | case CT_AGC_STEP_2: | ||
1205 | dib8000_agc_soft_split(state); | ||
1206 | |||
1207 | if (state->cfg.agc_control) | ||
1208 | state->cfg.agc_control(fe, 0); | ||
1209 | |||
1210 | *tune_state = CT_AGC_STOP; | ||
1211 | break; | ||
1212 | default: | ||
1213 | ret = dib8000_agc_soft_split(state); | ||
1214 | break; | ||
1215 | } | ||
1216 | return ret; | ||
1217 | |||
1218 | } | ||
1219 | |||
1220 | static void dib8096p_host_bus_drive(struct dib8000_state *state, u8 drive) | ||
1221 | { | ||
1222 | u16 reg; | ||
1223 | |||
1224 | drive &= 0x7; | ||
1225 | |||
1226 | /* drive host bus 2, 3, 4 */ | ||
1227 | reg = dib8000_read_word(state, 1798) & | ||
1228 | ~(0x7 | (0x7 << 6) | (0x7 << 12)); | ||
1229 | reg |= (drive<<12) | (drive<<6) | drive; | ||
1230 | dib8000_write_word(state, 1798, reg); | ||
1231 | |||
1232 | /* drive host bus 5,6 */ | ||
1233 | reg = dib8000_read_word(state, 1799) & ~((0x7 << 2) | (0x7 << 8)); | ||
1234 | reg |= (drive<<8) | (drive<<2); | ||
1235 | dib8000_write_word(state, 1799, reg); | ||
1236 | |||
1237 | /* drive host bus 7, 8, 9 */ | ||
1238 | reg = dib8000_read_word(state, 1800) & | ||
1239 | ~(0x7 | (0x7 << 6) | (0x7 << 12)); | ||
1240 | reg |= (drive<<12) | (drive<<6) | drive; | ||
1241 | dib8000_write_word(state, 1800, reg); | ||
1242 | |||
1243 | /* drive host bus 10, 11 */ | ||
1244 | reg = dib8000_read_word(state, 1801) & ~((0x7 << 2) | (0x7 << 8)); | ||
1245 | reg |= (drive<<8) | (drive<<2); | ||
1246 | dib8000_write_word(state, 1801, reg); | ||
1247 | |||
1248 | /* drive host bus 12, 13, 14 */ | ||
1249 | reg = dib8000_read_word(state, 1802) & | ||
1250 | ~(0x7 | (0x7 << 6) | (0x7 << 12)); | ||
1251 | reg |= (drive<<12) | (drive<<6) | drive; | ||
1252 | dib8000_write_word(state, 1802, reg); | ||
1253 | } | ||
1254 | |||
1255 | static u32 dib8096p_calcSyncFreq(u32 P_Kin, u32 P_Kout, | ||
1256 | u32 insertExtSynchro, u32 syncSize) | ||
1257 | { | ||
1258 | u32 quantif = 3; | ||
1259 | u32 nom = (insertExtSynchro * P_Kin+syncSize); | ||
1260 | u32 denom = P_Kout; | ||
1261 | u32 syncFreq = ((nom << quantif) / denom); | ||
1262 | |||
1263 | if ((syncFreq & ((1 << quantif) - 1)) != 0) | ||
1264 | syncFreq = (syncFreq >> quantif) + 1; | ||
1265 | else | ||
1266 | syncFreq = (syncFreq >> quantif); | ||
1267 | |||
1268 | if (syncFreq != 0) | ||
1269 | syncFreq = syncFreq - 1; | ||
1270 | |||
1271 | return syncFreq; | ||
1272 | } | ||
1273 | |||
1274 | static void dib8096p_cfg_DibTx(struct dib8000_state *state, u32 P_Kin, | ||
1275 | u32 P_Kout, u32 insertExtSynchro, u32 synchroMode, | ||
1276 | u32 syncWord, u32 syncSize) | ||
1277 | { | ||
1278 | dprintk("Configure DibStream Tx"); | ||
1279 | |||
1280 | dib8000_write_word(state, 1615, 1); | ||
1281 | dib8000_write_word(state, 1603, P_Kin); | ||
1282 | dib8000_write_word(state, 1605, P_Kout); | ||
1283 | dib8000_write_word(state, 1606, insertExtSynchro); | ||
1284 | dib8000_write_word(state, 1608, synchroMode); | ||
1285 | dib8000_write_word(state, 1609, (syncWord >> 16) & 0xffff); | ||
1286 | dib8000_write_word(state, 1610, syncWord & 0xffff); | ||
1287 | dib8000_write_word(state, 1612, syncSize); | ||
1288 | dib8000_write_word(state, 1615, 0); | ||
1289 | } | ||
1290 | |||
1291 | static void dib8096p_cfg_DibRx(struct dib8000_state *state, u32 P_Kin, | ||
1292 | u32 P_Kout, u32 synchroMode, u32 insertExtSynchro, | ||
1293 | u32 syncWord, u32 syncSize, u32 dataOutRate) | ||
1294 | { | ||
1295 | u32 syncFreq; | ||
1296 | |||
1297 | dprintk("Configure DibStream Rx synchroMode = %d", synchroMode); | ||
1298 | |||
1299 | if ((P_Kin != 0) && (P_Kout != 0)) { | ||
1300 | syncFreq = dib8096p_calcSyncFreq(P_Kin, P_Kout, | ||
1301 | insertExtSynchro, syncSize); | ||
1302 | dib8000_write_word(state, 1542, syncFreq); | ||
1303 | } | ||
1304 | |||
1305 | dib8000_write_word(state, 1554, 1); | ||
1306 | dib8000_write_word(state, 1536, P_Kin); | ||
1307 | dib8000_write_word(state, 1537, P_Kout); | ||
1308 | dib8000_write_word(state, 1539, synchroMode); | ||
1309 | dib8000_write_word(state, 1540, (syncWord >> 16) & 0xffff); | ||
1310 | dib8000_write_word(state, 1541, syncWord & 0xffff); | ||
1311 | dib8000_write_word(state, 1543, syncSize); | ||
1312 | dib8000_write_word(state, 1544, dataOutRate); | ||
1313 | dib8000_write_word(state, 1554, 0); | ||
1314 | } | ||
1315 | |||
1316 | static void dib8096p_enMpegMux(struct dib8000_state *state, int onoff) | ||
1317 | { | ||
1318 | u16 reg_1287; | ||
1319 | |||
1320 | reg_1287 = dib8000_read_word(state, 1287); | ||
1321 | |||
1322 | switch (onoff) { | ||
1323 | case 1: | ||
1324 | reg_1287 &= ~(1 << 8); | ||
1325 | break; | ||
1326 | case 0: | ||
1327 | reg_1287 |= (1 << 8); | ||
1328 | break; | ||
1329 | } | ||
1330 | |||
1331 | dib8000_write_word(state, 1287, reg_1287); | ||
1332 | } | ||
1333 | |||
1334 | static void dib8096p_configMpegMux(struct dib8000_state *state, | ||
1335 | u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2) | ||
1336 | { | ||
1337 | u16 reg_1287; | ||
1338 | |||
1339 | dprintk("Enable Mpeg mux"); | ||
1340 | |||
1341 | dib8096p_enMpegMux(state, 0); | ||
1342 | |||
1343 | /* If the input mode is MPEG do not divide the serial clock */ | ||
1344 | if ((enSerialMode == 1) && (state->input_mode_mpeg == 1)) | ||
1345 | enSerialClkDiv2 = 0; | ||
1346 | |||
1347 | reg_1287 = ((pulseWidth & 0x1f) << 3) | | ||
1348 | ((enSerialMode & 0x1) << 2) | (enSerialClkDiv2 & 0x1); | ||
1349 | dib8000_write_word(state, 1287, reg_1287); | ||
1350 | |||
1351 | dib8096p_enMpegMux(state, 1); | ||
1352 | } | ||
1353 | |||
1354 | static void dib8096p_setDibTxMux(struct dib8000_state *state, int mode) | ||
1355 | { | ||
1356 | u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 7); | ||
1357 | |||
1358 | switch (mode) { | ||
1359 | case MPEG_ON_DIBTX: | ||
1360 | dprintk("SET MPEG ON DIBSTREAM TX"); | ||
1361 | dib8096p_cfg_DibTx(state, 8, 5, 0, 0, 0, 0); | ||
1362 | reg_1288 |= (1 << 9); break; | ||
1363 | case DIV_ON_DIBTX: | ||
1364 | dprintk("SET DIV_OUT ON DIBSTREAM TX"); | ||
1365 | dib8096p_cfg_DibTx(state, 5, 5, 0, 0, 0, 0); | ||
1366 | reg_1288 |= (1 << 8); break; | ||
1367 | case ADC_ON_DIBTX: | ||
1368 | dprintk("SET ADC_OUT ON DIBSTREAM TX"); | ||
1369 | dib8096p_cfg_DibTx(state, 20, 5, 10, 0, 0, 0); | ||
1370 | reg_1288 |= (1 << 7); break; | ||
1371 | default: | ||
1372 | break; | ||
1373 | } | ||
1374 | dib8000_write_word(state, 1288, reg_1288); | ||
1375 | } | ||
1376 | |||
1377 | static void dib8096p_setHostBusMux(struct dib8000_state *state, int mode) | ||
1378 | { | ||
1379 | u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 4); | ||
1380 | |||
1381 | switch (mode) { | ||
1382 | case DEMOUT_ON_HOSTBUS: | ||
1383 | dprintk("SET DEM OUT OLD INTERF ON HOST BUS"); | ||
1384 | dib8096p_enMpegMux(state, 0); | ||
1385 | reg_1288 |= (1 << 6); | ||
1386 | break; | ||
1387 | case DIBTX_ON_HOSTBUS: | ||
1388 | dprintk("SET DIBSTREAM TX ON HOST BUS"); | ||
1389 | dib8096p_enMpegMux(state, 0); | ||
1390 | reg_1288 |= (1 << 5); | ||
1391 | break; | ||
1392 | case MPEG_ON_HOSTBUS: | ||
1393 | dprintk("SET MPEG MUX ON HOST BUS"); | ||
1394 | reg_1288 |= (1 << 4); | ||
1395 | break; | ||
1396 | default: | ||
1397 | break; | ||
1398 | } | ||
1399 | dib8000_write_word(state, 1288, reg_1288); | ||
1400 | } | ||
1401 | |||
1402 | static int dib8096p_set_diversity_in(struct dvb_frontend *fe, int onoff) | ||
1403 | { | ||
1404 | struct dib8000_state *state = fe->demodulator_priv; | ||
1405 | u16 reg_1287; | ||
1406 | |||
1407 | switch (onoff) { | ||
1408 | case 0: /* only use the internal way - not the diversity input */ | ||
1409 | dprintk("%s mode OFF : by default Enable Mpeg INPUT", | ||
1410 | __func__); | ||
1411 | /* outputRate = 8 */ | ||
1412 | dib8096p_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0); | ||
1413 | |||
1414 | /* Do not divide the serial clock of MPEG MUX in | ||
1415 | SERIAL MODE in case input mode MPEG is used */ | ||
1416 | reg_1287 = dib8000_read_word(state, 1287); | ||
1417 | /* enSerialClkDiv2 == 1 ? */ | ||
1418 | if ((reg_1287 & 0x1) == 1) { | ||
1419 | /* force enSerialClkDiv2 = 0 */ | ||
1420 | reg_1287 &= ~0x1; | ||
1421 | dib8000_write_word(state, 1287, reg_1287); | ||
1422 | } | ||
1423 | state->input_mode_mpeg = 1; | ||
1424 | break; | ||
1425 | case 1: /* both ways */ | ||
1426 | case 2: /* only the diversity input */ | ||
1427 | dprintk("%s ON : Enable diversity INPUT", __func__); | ||
1428 | dib8096p_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0); | ||
1429 | state->input_mode_mpeg = 0; | ||
1430 | break; | ||
1431 | } | ||
1432 | |||
1433 | dib8000_set_diversity_in(state->fe[0], onoff); | ||
1434 | return 0; | ||
1435 | } | ||
1436 | |||
1437 | static int dib8096p_set_output_mode(struct dvb_frontend *fe, int mode) | ||
1438 | { | ||
1439 | struct dib8000_state *state = fe->demodulator_priv; | ||
1440 | u16 outreg, smo_mode, fifo_threshold; | ||
1441 | u8 prefer_mpeg_mux_use = 1; | ||
1442 | int ret = 0; | ||
1443 | |||
1444 | dib8096p_host_bus_drive(state, 1); | ||
1445 | |||
1446 | fifo_threshold = 1792; | ||
1447 | smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1); | ||
1448 | outreg = dib8000_read_word(state, 1286) & | ||
1449 | ~((1 << 10) | (0x7 << 6) | (1 << 1)); | ||
1450 | |||
1451 | switch (mode) { | ||
1452 | case OUTMODE_HIGH_Z: | ||
1453 | outreg = 0; | ||
1454 | break; | ||
1455 | |||
1456 | case OUTMODE_MPEG2_SERIAL: | ||
1457 | if (prefer_mpeg_mux_use) { | ||
1458 | dprintk("dib8096P setting output mode TS_SERIAL using Mpeg Mux"); | ||
1459 | dib8096p_configMpegMux(state, 3, 1, 1); | ||
1460 | dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS); | ||
1461 | } else {/* Use Smooth block */ | ||
1462 | dprintk("dib8096P setting output mode TS_SERIAL using Smooth bloc"); | ||
1463 | dib8096p_setHostBusMux(state, | ||
1464 | DEMOUT_ON_HOSTBUS); | ||
1465 | outreg |= (2 << 6) | (0 << 1); | ||
1466 | } | ||
1467 | break; | ||
1468 | |||
1469 | case OUTMODE_MPEG2_PAR_GATED_CLK: | ||
1470 | if (prefer_mpeg_mux_use) { | ||
1471 | dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Mpeg Mux"); | ||
1472 | dib8096p_configMpegMux(state, 2, 0, 0); | ||
1473 | dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS); | ||
1474 | } else { /* Use Smooth block */ | ||
1475 | dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Smooth block"); | ||
1476 | dib8096p_setHostBusMux(state, | ||
1477 | DEMOUT_ON_HOSTBUS); | ||
1478 | outreg |= (0 << 6); | ||
1479 | } | ||
1480 | break; | ||
1481 | |||
1482 | case OUTMODE_MPEG2_PAR_CONT_CLK: /* Using Smooth block only */ | ||
1483 | dprintk("dib8096P setting output mode TS_PARALLEL_CONT using Smooth block"); | ||
1484 | dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS); | ||
1485 | outreg |= (1 << 6); | ||
1486 | break; | ||
1487 | |||
1488 | case OUTMODE_MPEG2_FIFO: | ||
1489 | /* Using Smooth block because not supported | ||
1490 | by new Mpeg Mux bloc */ | ||
1491 | dprintk("dib8096P setting output mode TS_FIFO using Smooth block"); | ||
1492 | dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS); | ||
1493 | outreg |= (5 << 6); | ||
1494 | smo_mode |= (3 << 1); | ||
1495 | fifo_threshold = 512; | ||
1496 | break; | ||
1497 | |||
1498 | case OUTMODE_DIVERSITY: | ||
1499 | dprintk("dib8096P setting output mode MODE_DIVERSITY"); | ||
1500 | dib8096p_setDibTxMux(state, DIV_ON_DIBTX); | ||
1501 | dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS); | ||
1502 | break; | ||
1503 | |||
1504 | case OUTMODE_ANALOG_ADC: | ||
1505 | dprintk("dib8096P setting output mode MODE_ANALOG_ADC"); | ||
1506 | dib8096p_setDibTxMux(state, ADC_ON_DIBTX); | ||
1507 | dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS); | ||
1508 | break; | ||
1509 | } | ||
1510 | |||
1511 | if (mode != OUTMODE_HIGH_Z) | ||
1512 | outreg |= (1<<10); | ||
1513 | |||
1514 | dprintk("output_mpeg2_in_188_bytes = %d", | ||
1515 | state->cfg.output_mpeg2_in_188_bytes); | ||
1516 | if (state->cfg.output_mpeg2_in_188_bytes) | ||
1517 | smo_mode |= (1 << 5); | ||
1518 | |||
1519 | ret |= dib8000_write_word(state, 299, smo_mode); | ||
1520 | /* synchronous fread */ | ||
1521 | ret |= dib8000_write_word(state, 299 + 1, fifo_threshold); | ||
1522 | ret |= dib8000_write_word(state, 1286, outreg); | ||
1523 | |||
1524 | return ret; | ||
1525 | } | ||
1526 | |||
1527 | static int map_addr_to_serpar_number(struct i2c_msg *msg) | ||
1528 | { | ||
1529 | if (msg->buf[0] <= 15) | ||
1530 | msg->buf[0] -= 1; | ||
1531 | else if (msg->buf[0] == 17) | ||
1532 | msg->buf[0] = 15; | ||
1533 | else if (msg->buf[0] == 16) | ||
1534 | msg->buf[0] = 17; | ||
1535 | else if (msg->buf[0] == 19) | ||
1536 | msg->buf[0] = 16; | ||
1537 | else if (msg->buf[0] >= 21 && msg->buf[0] <= 25) | ||
1538 | msg->buf[0] -= 3; | ||
1539 | else if (msg->buf[0] == 28) | ||
1540 | msg->buf[0] = 23; | ||
1541 | else if (msg->buf[0] == 99) | ||
1542 | msg->buf[0] = 99; | ||
1543 | else | ||
1544 | return -EINVAL; | ||
1545 | return 0; | ||
1546 | } | ||
1547 | |||
1548 | static int dib8096p_tuner_write_serpar(struct i2c_adapter *i2c_adap, | ||
1549 | struct i2c_msg msg[], int num) | ||
1550 | { | ||
1551 | struct dib8000_state *state = i2c_get_adapdata(i2c_adap); | ||
1552 | u8 n_overflow = 1; | ||
1553 | u16 i = 1000; | ||
1554 | u16 serpar_num = msg[0].buf[0]; | ||
1555 | |||
1556 | while (n_overflow == 1 && i) { | ||
1557 | n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1; | ||
1558 | i--; | ||
1559 | if (i == 0) | ||
1560 | dprintk("Tuner ITF: write busy (overflow)"); | ||
1561 | } | ||
1562 | dib8000_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f)); | ||
1563 | dib8000_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]); | ||
1564 | |||
1565 | return num; | ||
1566 | } | ||
1567 | |||
1568 | static int dib8096p_tuner_read_serpar(struct i2c_adapter *i2c_adap, | ||
1569 | struct i2c_msg msg[], int num) | ||
1570 | { | ||
1571 | struct dib8000_state *state = i2c_get_adapdata(i2c_adap); | ||
1572 | u8 n_overflow = 1, n_empty = 1; | ||
1573 | u16 i = 1000; | ||
1574 | u16 serpar_num = msg[0].buf[0]; | ||
1575 | u16 read_word; | ||
1576 | |||
1577 | while (n_overflow == 1 && i) { | ||
1578 | n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1; | ||
1579 | i--; | ||
1580 | if (i == 0) | ||
1581 | dprintk("TunerITF: read busy (overflow)"); | ||
1582 | } | ||
1583 | dib8000_write_word(state, 1985, (0<<6) | (serpar_num&0x3f)); | ||
1584 | |||
1585 | i = 1000; | ||
1586 | while (n_empty == 1 && i) { | ||
1587 | n_empty = dib8000_read_word(state, 1984)&0x1; | ||
1588 | i--; | ||
1589 | if (i == 0) | ||
1590 | dprintk("TunerITF: read busy (empty)"); | ||
1591 | } | ||
1592 | |||
1593 | read_word = dib8000_read_word(state, 1987); | ||
1594 | msg[1].buf[0] = (read_word >> 8) & 0xff; | ||
1595 | msg[1].buf[1] = (read_word) & 0xff; | ||
1596 | |||
1597 | return num; | ||
1598 | } | ||
1599 | |||
1600 | static int dib8096p_tuner_rw_serpar(struct i2c_adapter *i2c_adap, | ||
1601 | struct i2c_msg msg[], int num) | ||
1602 | { | ||
1603 | if (map_addr_to_serpar_number(&msg[0]) == 0) { | ||
1604 | if (num == 1) /* write */ | ||
1605 | return dib8096p_tuner_write_serpar(i2c_adap, msg, 1); | ||
1606 | else /* read */ | ||
1607 | return dib8096p_tuner_read_serpar(i2c_adap, msg, 2); | ||
1608 | } | ||
1609 | return num; | ||
1610 | } | ||
1611 | |||
1612 | static int dib8096p_rw_on_apb(struct i2c_adapter *i2c_adap, | ||
1613 | struct i2c_msg msg[], int num, u16 apb_address) | ||
1614 | { | ||
1615 | struct dib8000_state *state = i2c_get_adapdata(i2c_adap); | ||
1616 | u16 word; | ||
1617 | |||
1618 | if (num == 1) { /* write */ | ||
1619 | dib8000_write_word(state, apb_address, | ||
1620 | ((msg[0].buf[1] << 8) | (msg[0].buf[2]))); | ||
1621 | } else { | ||
1622 | word = dib8000_read_word(state, apb_address); | ||
1623 | msg[1].buf[0] = (word >> 8) & 0xff; | ||
1624 | msg[1].buf[1] = (word) & 0xff; | ||
1625 | } | ||
1626 | return num; | ||
1627 | } | ||
1628 | |||
1629 | static int dib8096p_tuner_xfer(struct i2c_adapter *i2c_adap, | ||
1630 | struct i2c_msg msg[], int num) | ||
1631 | { | ||
1632 | struct dib8000_state *state = i2c_get_adapdata(i2c_adap); | ||
1633 | u16 apb_address = 0, word; | ||
1634 | int i = 0; | ||
1635 | |||
1636 | switch (msg[0].buf[0]) { | ||
1637 | case 0x12: | ||
1638 | apb_address = 1920; | ||
1639 | break; | ||
1640 | case 0x14: | ||
1641 | apb_address = 1921; | ||
1642 | break; | ||
1643 | case 0x24: | ||
1644 | apb_address = 1922; | ||
1645 | break; | ||
1646 | case 0x1a: | ||
1647 | apb_address = 1923; | ||
1648 | break; | ||
1649 | case 0x22: | ||
1650 | apb_address = 1924; | ||
1651 | break; | ||
1652 | case 0x33: | ||
1653 | apb_address = 1926; | ||
1654 | break; | ||
1655 | case 0x34: | ||
1656 | apb_address = 1927; | ||
1657 | break; | ||
1658 | case 0x35: | ||
1659 | apb_address = 1928; | ||
1660 | break; | ||
1661 | case 0x36: | ||
1662 | apb_address = 1929; | ||
1663 | break; | ||
1664 | case 0x37: | ||
1665 | apb_address = 1930; | ||
1666 | break; | ||
1667 | case 0x38: | ||
1668 | apb_address = 1931; | ||
1669 | break; | ||
1670 | case 0x39: | ||
1671 | apb_address = 1932; | ||
1672 | break; | ||
1673 | case 0x2a: | ||
1674 | apb_address = 1935; | ||
1675 | break; | ||
1676 | case 0x2b: | ||
1677 | apb_address = 1936; | ||
1678 | break; | ||
1679 | case 0x2c: | ||
1680 | apb_address = 1937; | ||
1681 | break; | ||
1682 | case 0x2d: | ||
1683 | apb_address = 1938; | ||
1684 | break; | ||
1685 | case 0x2e: | ||
1686 | apb_address = 1939; | ||
1687 | break; | ||
1688 | case 0x2f: | ||
1689 | apb_address = 1940; | ||
1690 | break; | ||
1691 | case 0x30: | ||
1692 | apb_address = 1941; | ||
1693 | break; | ||
1694 | case 0x31: | ||
1695 | apb_address = 1942; | ||
1696 | break; | ||
1697 | case 0x32: | ||
1698 | apb_address = 1943; | ||
1699 | break; | ||
1700 | case 0x3e: | ||
1701 | apb_address = 1944; | ||
1702 | break; | ||
1703 | case 0x3f: | ||
1704 | apb_address = 1945; | ||
1705 | break; | ||
1706 | case 0x40: | ||
1707 | apb_address = 1948; | ||
1708 | break; | ||
1709 | case 0x25: | ||
1710 | apb_address = 936; | ||
1711 | break; | ||
1712 | case 0x26: | ||
1713 | apb_address = 937; | ||
1714 | break; | ||
1715 | case 0x27: | ||
1716 | apb_address = 938; | ||
1717 | break; | ||
1718 | case 0x28: | ||
1719 | apb_address = 939; | ||
1720 | break; | ||
1721 | case 0x1d: | ||
1722 | /* get sad sel request */ | ||
1723 | i = ((dib8000_read_word(state, 921) >> 12)&0x3); | ||
1724 | word = dib8000_read_word(state, 924+i); | ||
1725 | msg[1].buf[0] = (word >> 8) & 0xff; | ||
1726 | msg[1].buf[1] = (word) & 0xff; | ||
1727 | return num; | ||
1728 | case 0x1f: | ||
1729 | if (num == 1) { /* write */ | ||
1730 | word = (u16) ((msg[0].buf[1] << 8) | | ||
1731 | msg[0].buf[2]); | ||
1732 | /* in the VGAMODE Sel are located on bit 0/1 */ | ||
1733 | word &= 0x3; | ||
1734 | word = (dib8000_read_word(state, 921) & | ||
1735 | ~(3<<12)) | (word<<12); | ||
1736 | /* Set the proper input */ | ||
1737 | dib8000_write_word(state, 921, word); | ||
1738 | return num; | ||
1739 | } | ||
1740 | } | ||
1741 | |||
1742 | if (apb_address != 0) /* R/W acces via APB */ | ||
1743 | return dib8096p_rw_on_apb(i2c_adap, msg, num, apb_address); | ||
1744 | else /* R/W access via SERPAR */ | ||
1745 | return dib8096p_tuner_rw_serpar(i2c_adap, msg, num); | ||
1746 | |||
1747 | return 0; | ||
1748 | } | ||
1749 | |||
1750 | static u32 dib8096p_i2c_func(struct i2c_adapter *adapter) | ||
1751 | { | ||
1752 | return I2C_FUNC_I2C; | ||
1753 | } | ||
1754 | |||
1755 | static struct i2c_algorithm dib8096p_tuner_xfer_algo = { | ||
1756 | .master_xfer = dib8096p_tuner_xfer, | ||
1757 | .functionality = dib8096p_i2c_func, | ||
1758 | }; | ||
1759 | |||
1760 | struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe) | ||
1761 | { | ||
1762 | struct dib8000_state *st = fe->demodulator_priv; | ||
1763 | return &st->dib8096p_tuner_adap; | ||
1764 | } | ||
1765 | EXPORT_SYMBOL(dib8096p_get_i2c_tuner); | ||
1766 | |||
1767 | int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff) | ||
1768 | { | ||
1769 | struct dib8000_state *state = fe->demodulator_priv; | ||
1770 | u16 en_cur_state; | ||
1771 | |||
1772 | dprintk("sleep dib8096p: %d", onoff); | ||
1773 | |||
1774 | en_cur_state = dib8000_read_word(state, 1922); | ||
1775 | |||
1776 | /* LNAs and MIX are ON and therefore it is a valid configuration */ | ||
1777 | if (en_cur_state > 0xff) | ||
1778 | state->tuner_enable = en_cur_state ; | ||
1779 | |||
1780 | if (onoff) | ||
1781 | en_cur_state &= 0x00ff; | ||
1782 | else { | ||
1783 | if (state->tuner_enable != 0) | ||
1784 | en_cur_state = state->tuner_enable; | ||
1785 | } | ||
1786 | |||
1787 | dib8000_write_word(state, 1922, en_cur_state); | ||
1788 | |||
1789 | return 0; | ||
1790 | } | ||
1791 | EXPORT_SYMBOL(dib8096p_tuner_sleep); | ||
1792 | |||
1793 | static const s32 lut_1000ln_mant[] = | ||
1794 | { | ||
1795 | 908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600 | ||
1796 | }; | ||
1797 | |||
1798 | s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode) | ||
1799 | { | ||
1800 | struct dib8000_state *state = fe->demodulator_priv; | ||
1801 | u32 ix = 0, tmp_val = 0, exp = 0, mant = 0; | ||
1802 | s32 val; | ||
1803 | |||
1804 | val = dib8000_read32(state, 384); | ||
1805 | if (mode) { | ||
1806 | tmp_val = val; | ||
1807 | while (tmp_val >>= 1) | ||
1808 | exp++; | ||
1809 | mant = (val * 1000 / (1<<exp)); | ||
1810 | ix = (u8)((mant-1000)/100); /* index of the LUT */ | ||
1811 | val = (lut_1000ln_mant[ix] + 693*(exp-20) - 6908); | ||
1812 | val = (val*256)/1000; | ||
1813 | } | ||
1814 | return val; | ||
1815 | } | ||
1816 | EXPORT_SYMBOL(dib8000_get_adc_power); | ||
1817 | |||
1818 | int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ) | ||
1819 | { | ||
1820 | struct dib8000_state *state = fe->demodulator_priv; | ||
1821 | int val = 0; | ||
1822 | |||
1823 | switch (IQ) { | ||
1824 | case 1: | ||
1825 | val = dib8000_read_word(state, 403); | ||
1826 | break; | ||
1827 | case 0: | ||
1828 | val = dib8000_read_word(state, 404); | ||
1829 | break; | ||
1830 | } | ||
1831 | if (val & 0x200) | ||
1832 | val -= 1024; | ||
1833 | |||
1834 | return val; | ||
1835 | } | ||
1836 | EXPORT_SYMBOL(dib8090p_get_dc_power); | ||
1837 | |||
1838 | static void dib8000_update_timf(struct dib8000_state *state) | ||
1839 | { | ||
1840 | u32 timf = state->timf = dib8000_read32(state, 435); | ||
1841 | |||
1842 | dib8000_write_word(state, 29, (u16) (timf >> 16)); | ||
1843 | dib8000_write_word(state, 30, (u16) (timf & 0xffff)); | ||
1844 | dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default); | ||
1845 | } | ||
1846 | |||
1847 | u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf) | ||
1848 | { | ||
1849 | struct dib8000_state *state = fe->demodulator_priv; | ||
1850 | |||
1851 | switch (op) { | ||
1852 | case DEMOD_TIMF_SET: | ||
1853 | state->timf = timf; | ||
1854 | break; | ||
1855 | case DEMOD_TIMF_UPDATE: | ||
1856 | dib8000_update_timf(state); | ||
1857 | break; | ||
1858 | case DEMOD_TIMF_GET: | ||
1859 | break; | ||
1860 | } | ||
1861 | dib8000_set_bandwidth(state->fe[0], 6000); | ||
1862 | |||
1863 | return state->timf; | ||
1864 | } | ||
1865 | EXPORT_SYMBOL(dib8000_ctrl_timf); | ||
1866 | |||
1867 | static const u16 adc_target_16dB[11] = { | ||
1868 | (1 << 13) - 825 - 117, | ||
1869 | (1 << 13) - 837 - 117, | ||
1870 | (1 << 13) - 811 - 117, | ||
1871 | (1 << 13) - 766 - 117, | ||
1872 | (1 << 13) - 737 - 117, | ||
1873 | (1 << 13) - 693 - 117, | ||
1874 | (1 << 13) - 648 - 117, | ||
1875 | (1 << 13) - 619 - 117, | ||
1876 | (1 << 13) - 575 - 117, | ||
1877 | (1 << 13) - 531 - 117, | ||
1878 | (1 << 13) - 501 - 117 | ||
1879 | }; | ||
1880 | static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 }; | ||
1881 | |||
1882 | static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosearching) | ||
1883 | { | ||
1884 | u16 mode, max_constellation, seg_diff_mask = 0, nbseg_diff = 0; | ||
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 | |||
2013 | case TRANSMISSION_MODE_4K: | ||
2014 | switch (sub_channel) { | ||
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; | ||
2142 | break; | ||
2143 | case QPSK: | ||
2144 | constellation = 1; | ||
2145 | break; | ||
2146 | case QAM_16: | ||
2147 | constellation = 2; | ||
2148 | break; | ||
2149 | case QAM_64: | ||
2150 | default: | ||
2151 | constellation = 3; | ||
2152 | break; | ||
2153 | } | ||
2154 | |||
2155 | switch (state->fe[0]->dtv_property_cache.layer[i].fec) { | ||
2156 | case FEC_1_2: | ||
2157 | crate = 1; | ||
2158 | break; | ||
2159 | case FEC_2_3: | ||
2160 | crate = 2; | ||
2161 | break; | ||
2162 | case FEC_3_4: | ||
2163 | crate = 3; | ||
2164 | break; | ||
2165 | case FEC_5_6: | ||
2166 | crate = 5; | ||
2167 | break; | ||
2168 | case FEC_7_8: | ||
2169 | default: | ||
2170 | crate = 7; | ||
2171 | break; | ||
2172 | } | ||
2173 | |||
2174 | if ((state->fe[0]->dtv_property_cache.layer[i].interleaving > 0) && | ||
2175 | ((state->fe[0]->dtv_property_cache.layer[i].interleaving <= 3) || | ||
2176 | (state->fe[0]->dtv_property_cache.layer[i].interleaving == 4 && state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1)) | ||
2177 | ) | ||
2178 | timeI = state->fe[0]->dtv_property_cache.layer[i].interleaving; | ||
2179 | else | ||
2180 | timeI = 0; | ||
2181 | dib8000_write_word(state, 2 + i, (constellation << 10) | ((state->fe[0]->dtv_property_cache.layer[i].segment_count & 0xf) << 6) | | ||
2182 | (crate << 3) | timeI); | ||
2183 | if (state->fe[0]->dtv_property_cache.layer[i].segment_count > 0) { | ||
2184 | switch (max_constellation) { | ||
2185 | case DQPSK: | ||
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; | ||
2191 | case QAM_16: | ||
2192 | if (state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_64) | ||
2193 | max_constellation = state->fe[0]->dtv_property_cache.layer[i].modulation; | ||
2194 | break; | ||
2195 | } | ||
2196 | } | ||
2197 | } | ||
2198 | |||
2199 | mode = fft_to_mode(state); | ||
2200 | |||
2201 | //dib8000_write_word(state, 5, 13); /*p_last_seg = 13*/ | ||
2202 | |||
2203 | dib8000_write_word(state, 274, (dib8000_read_word(state, 274) & 0xffcf) | | ||
2204 | ((state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 5) | ((state->fe[0]->dtv_property_cache. | ||
2205 | isdbt_sb_mode & 1) << 4)); | ||
2206 | |||
2207 | dprintk("mode = %d ; guard = %d", mode, state->fe[0]->dtv_property_cache.guard_interval); | ||
2208 | |||
2209 | /* signal optimization parameter */ | ||
2210 | |||
2211 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception) { | ||
2212 | seg_diff_mask = (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) << permu_seg[0]; | ||
2213 | for (i = 1; i < 3; i++) | ||
2214 | nbseg_diff += | ||
2215 | (state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count; | ||
2216 | for (i = 0; i < nbseg_diff; i++) | ||
2217 | seg_diff_mask |= 1 << permu_seg[i + 1]; | ||
2218 | } else { | ||
2219 | for (i = 0; i < 3; i++) | ||
2220 | nbseg_diff += | ||
2221 | (state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count; | ||
2222 | for (i = 0; i < nbseg_diff; i++) | ||
2223 | seg_diff_mask |= 1 << permu_seg[i]; | ||
2224 | } | ||
2225 | dprintk("nbseg_diff = %X (%d)", seg_diff_mask, seg_diff_mask); | ||
2226 | |||
2227 | state->differential_constellation = (seg_diff_mask != 0); | ||
2228 | if (state->revision != 0x8090) | ||
2229 | dib8000_set_diversity_in(state->fe[0], state->diversity_onoff); | ||
2230 | else | ||
2231 | dib8096p_set_diversity_in(state->fe[0], state->diversity_onoff); | ||
2232 | |||
2233 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | ||
2234 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1) | ||
2235 | seg_mask13 = 0x00E0; | ||
2236 | else // 1-segment | ||
2237 | seg_mask13 = 0x0040; | ||
2238 | } else | ||
2239 | seg_mask13 = 0x1fff; | ||
2240 | |||
2241 | // WRITE: Mode & Diff mask | ||
2242 | dib8000_write_word(state, 0, (mode << 13) | seg_diff_mask); | ||
2243 | |||
2244 | if ((seg_diff_mask) || (state->fe[0]->dtv_property_cache.isdbt_sb_mode)) | ||
2245 | dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200); | ||
2246 | else | ||
2247 | dib8000_write_word(state, 268, (2 << 9) | 39); //init value | ||
2248 | |||
2249 | // ---- SMALL ---- | ||
2250 | // P_small_seg_diff | ||
2251 | dib8000_write_word(state, 352, seg_diff_mask); // ADDR 352 | ||
2252 | |||
2253 | dib8000_write_word(state, 353, seg_mask13); // ADDR 353 | ||
2254 | |||
2255 | /* // P_small_narrow_band=0, P_small_last_seg=13, P_small_offset_num_car=5 */ | ||
2256 | |||
2257 | // ---- SMALL ---- | ||
2258 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | ||
2259 | switch (state->fe[0]->dtv_property_cache.transmission_mode) { | ||
2260 | case TRANSMISSION_MODE_2K: | ||
2261 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { | ||
2262 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) | ||
2263 | ncoeff = coeff_2k_sb_1seg_dqpsk; | ||
2264 | else // QPSK or QAM | ||
2265 | ncoeff = coeff_2k_sb_1seg; | ||
2266 | } else { // 3-segments | ||
2267 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { | ||
2268 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) | ||
2269 | ncoeff = coeff_2k_sb_3seg_0dqpsk_1dqpsk; | ||
2270 | else // QPSK or QAM on external segments | ||
2271 | ncoeff = coeff_2k_sb_3seg_0dqpsk; | ||
2272 | } else { // QPSK or QAM on central segment | ||
2273 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) | ||
2274 | ncoeff = coeff_2k_sb_3seg_1dqpsk; | ||
2275 | else // QPSK or QAM on external segments | ||
2276 | ncoeff = coeff_2k_sb_3seg; | ||
2277 | } | ||
2278 | } | ||
2279 | break; | ||
2280 | |||
2281 | case TRANSMISSION_MODE_4K: | ||
2282 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { | ||
2283 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) | ||
2284 | ncoeff = coeff_4k_sb_1seg_dqpsk; | ||
2285 | else // QPSK or QAM | ||
2286 | ncoeff = coeff_4k_sb_1seg; | ||
2287 | } else { // 3-segments | ||
2288 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { | ||
2289 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) { | ||
2290 | ncoeff = coeff_4k_sb_3seg_0dqpsk_1dqpsk; | ||
2291 | } else { // QPSK or QAM on external segments | ||
2292 | ncoeff = coeff_4k_sb_3seg_0dqpsk; | ||
2293 | } | ||
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 | } | ||
2300 | } | ||
2301 | break; | ||
2302 | |||
2303 | case TRANSMISSION_MODE_AUTO: | ||
2304 | case TRANSMISSION_MODE_8K: | ||
2305 | default: | ||
2306 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { | ||
2307 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) | ||
2308 | ncoeff = coeff_8k_sb_1seg_dqpsk; | ||
2309 | else // QPSK or QAM | ||
2310 | ncoeff = coeff_8k_sb_1seg; | ||
2311 | } else { // 3-segments | ||
2312 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { | ||
2313 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) { | ||
2314 | ncoeff = coeff_8k_sb_3seg_0dqpsk_1dqpsk; | ||
2315 | } else { // QPSK or QAM on external segments | ||
2316 | ncoeff = coeff_8k_sb_3seg_0dqpsk; | ||
2317 | } | ||
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 | } | ||
2324 | } | ||
2325 | break; | ||
2326 | } | ||
2327 | for (i = 0; i < 8; i++) | ||
2328 | dib8000_write_word(state, 343 + i, ncoeff[i]); | ||
2329 | } | ||
2330 | |||
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 | ||
2332 | dib8000_write_word(state, 351, | ||
2333 | (state->fe[0]->dtv_property_cache.isdbt_sb_mode << 9) | (state->fe[0]->dtv_property_cache.isdbt_sb_mode << 8) | (13 << 4) | 5); | ||
2334 | |||
2335 | // ---- COFF ---- | ||
2336 | // Carloff, the most robust | ||
2337 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | ||
2338 | |||
2339 | // P_coff_cpil_alpha=4, P_coff_inh=0, P_coff_cpil_winlen=64 | ||
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 | ||
2341 | dib8000_write_word(state, 187, | ||
2342 | (4 << 12) | (0 << 11) | (63 << 5) | (0x3 << 3) | ((~state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 2) | ||
2343 | | 0x3); | ||
2344 | |||
2345 | /* // P_small_coef_ext_enable = 1 */ | ||
2346 | /* dib8000_write_word(state, 351, dib8000_read_word(state, 351) | 0x200); */ | ||
2347 | |||
2348 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { | ||
2349 | |||
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) | ||
2351 | if (mode == 3) | ||
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 | |||
2395 | } else if (state->isdbt_cfg_loaded == 0) { // if not Sound Broadcasting mode : put default values for 13 segments | ||
2396 | dib8000_write_word(state, 180, (16 << 6) | 9); | ||
2397 | dib8000_write_word(state, 187, (4 << 12) | (8 << 5) | 0x2); | ||
2398 | coff_pow = 0x2800; | ||
2399 | for (i = 0; i < 6; i++) | ||
2400 | dib8000_write_word(state, 181 + i, coff_pow); | ||
2401 | |||
2402 | // P_ctrl_corm_thres4pre_freq_inh=1, P_ctrl_pre_freq_mode_sat=1, | ||
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 | ||
2404 | dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (3 << 5) | 1); | ||
2405 | |||
2406 | // P_ctrl_pre_freq_win_len=8, P_ctrl_pre_freq_thres_lockin=6 | ||
2407 | dib8000_write_word(state, 340, (8 << 6) | (6 << 0)); | ||
2408 | // P_ctrl_pre_freq_thres_lockout=4, P_small_use_tmcc/ac/cp=1 | ||
2409 | dib8000_write_word(state, 341, (4 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); | ||
2410 | } | ||
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 | |||
2417 | /* make the cpil_coff_lock more robust but slower p_coff_winlen | ||
2418 | * 6bits; p_coff_thres_lock 6bits (for coff lock if needed) | ||
2419 | */ | ||
2420 | /* if ( ( nbseg_diff>0)&&(nbseg_diff<13)) | ||
2421 | dib8000_write_word(state, 187, (dib8000_read_word(state, 187) & 0xfffb) | (1 << 3)); */ | ||
2422 | |||
2423 | dib8000_write_word(state, 189, ~seg_mask13 | seg_diff_mask); /* P_lmod4_seg_inh */ | ||
2424 | dib8000_write_word(state, 192, ~seg_mask13 | seg_diff_mask); /* P_pha3_seg_inh */ | ||
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 | ||
2435 | dib8000_write_word(state, 288, 0x1fff); //disable equalisation of the tmcc when autosearch to be able to find the DQPSK channels. | ||
2436 | dprintk("287 = %X (%d)", ~seg_mask13 | 0x1000, ~seg_mask13 | 0x1000); | ||
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 | |||
2466 | /* P_dvsy_sync_wait - reuse mode */ | ||
2467 | switch (state->fe[0]->dtv_property_cache.transmission_mode) { | ||
2468 | case TRANSMISSION_MODE_8K: | ||
2469 | mode = 256; | ||
2470 | break; | ||
2471 | case TRANSMISSION_MODE_4K: | ||
2472 | mode = 128; | ||
2473 | break; | ||
2474 | default: | ||
2475 | case TRANSMISSION_MODE_2K: | ||
2476 | mode = 64; | ||
2477 | break; | ||
2478 | } | ||
2479 | if (state->cfg.diversity_delay == 0) | ||
2480 | mode = (mode * (1 << (guard)) * 3) / 2 + 48; // add 50% SFN margin + compensate for one DVSY-fifo | ||
2481 | else | ||
2482 | mode = (mode * (1 << (guard)) * 3) / 2 + state->cfg.diversity_delay; // add 50% SFN margin + compensate for DVSY-fifo | ||
2483 | mode <<= 4; | ||
2484 | dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | mode); | ||
2485 | |||
2486 | /* channel estimation fine configuration */ | ||
2487 | switch (max_constellation) { | ||
2488 | case QAM_64: | ||
2489 | ana_gain = 0x7; // -1 : avoid def_est saturation when ADC target is -16dB | ||
2490 | coeff[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ | ||
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 | } | ||
2512 | for (mode = 0; mode < 4; mode++) | ||
2513 | dib8000_write_word(state, 215 + mode, coeff[mode]); | ||
2514 | |||
2515 | // update ana_gain depending on max constellation | ||
2516 | dib8000_write_word(state, 116, ana_gain); | ||
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 | |||
2526 | // ---- ANA_FE ---- | ||
2527 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) { | ||
2528 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1) | ||
2529 | ana_fe = ana_fe_coeff_3seg; | ||
2530 | else // 1-segment | ||
2531 | ana_fe = ana_fe_coeff_1seg; | ||
2532 | } else | ||
2533 | ana_fe = ana_fe_coeff_13seg; | ||
2534 | |||
2535 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1 || state->isdbt_cfg_loaded == 0) | ||
2536 | for (mode = 0; mode < 24; mode++) | ||
2537 | dib8000_write_word(state, 117 + mode, ana_fe[mode]); | ||
2538 | |||
2539 | // ---- CHAN_BLK ---- | ||
2540 | for (i = 0; i < 13; i++) { | ||
2541 | if ((((~seg_diff_mask) >> i) & 1) == 1) { | ||
2542 | P_cfr_left_edge += (1 << i) * ((i == 0) || ((((seg_mask13 & (~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)); | ||
2544 | } | ||
2545 | } | ||
2546 | 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 | ||
2548 | // "P_cspu_left_edge" not used => do not care | ||
2549 | // "P_cspu_right_edge" not used => do not care | ||
2550 | |||
2551 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | ||
2552 | dib8000_write_word(state, 228, 1); // P_2d_mode_byp=1 | ||
2553 | dib8000_write_word(state, 205, dib8000_read_word(state, 205) & 0xfff0); // P_cspu_win_cut = 0 | ||
2554 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0 | ||
2555 | && state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K) { | ||
2556 | //dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); // P_adp_pass = 0 | ||
2557 | dib8000_write_word(state, 265, 15); // P_equal_noise_sel = 15 | ||
2558 | } | ||
2559 | } else if (state->isdbt_cfg_loaded == 0) { | ||
2560 | dib8000_write_word(state, 228, 0); // default value | ||
2561 | dib8000_write_word(state, 265, 31); // default value | ||
2562 | dib8000_write_word(state, 205, 0x200f); // init value | ||
2563 | } | ||
2564 | // ---- TMCC ---- | ||
2565 | for (i = 0; i < 3; i++) | ||
2566 | tmcc_pow += | ||
2567 | (((state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * 4 + 1) * state->fe[0]->dtv_property_cache.layer[i].segment_count); | ||
2568 | // Quantif of "P_tmcc_dec_thres_?k" is (0, 5+mode, 9); | ||
2569 | // Threshold is set at 1/4 of max power. | ||
2570 | tmcc_pow *= (1 << (9 - 2)); | ||
2571 | |||
2572 | dib8000_write_word(state, 290, tmcc_pow); // P_tmcc_dec_thres_2k | ||
2573 | dib8000_write_word(state, 291, tmcc_pow); // P_tmcc_dec_thres_4k | ||
2574 | dib8000_write_word(state, 292, tmcc_pow); // P_tmcc_dec_thres_8k | ||
2575 | //dib8000_write_word(state, 287, (1 << 13) | 0x1000 ); | ||
2576 | // ---- PHA3 ---- | ||
2577 | |||
2578 | if (state->isdbt_cfg_loaded == 0) | ||
2579 | dib8000_write_word(state, 250, 3285); /*p_2d_hspeed_thr0 */ | ||
2580 | |||
2581 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) | ||
2582 | state->isdbt_cfg_loaded = 0; | ||
2583 | else | ||
2584 | state->isdbt_cfg_loaded = 1; | ||
2585 | |||
2586 | } | ||
2587 | |||
2588 | static int dib8000_autosearch_start(struct dvb_frontend *fe) | ||
2589 | { | ||
2590 | u8 factor; | ||
2591 | u32 value; | ||
2592 | struct dib8000_state *state = fe->demodulator_priv; | ||
2593 | |||
2594 | int slist = 0; | ||
2595 | |||
2596 | state->fe[0]->dtv_property_cache.inversion = 0; | ||
2597 | if (!state->fe[0]->dtv_property_cache.isdbt_sb_mode) | ||
2598 | state->fe[0]->dtv_property_cache.layer[0].segment_count = 13; | ||
2599 | state->fe[0]->dtv_property_cache.layer[0].modulation = QAM_64; | ||
2600 | state->fe[0]->dtv_property_cache.layer[0].fec = FEC_2_3; | ||
2601 | state->fe[0]->dtv_property_cache.layer[0].interleaving = 0; | ||
2602 | |||
2603 | //choose the right list, in sb, always do everything | ||
2604 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) { | ||
2605 | state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; | ||
2606 | state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; | ||
2607 | slist = 7; | ||
2608 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); | ||
2609 | } else { | ||
2610 | if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) { | ||
2611 | if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) { | ||
2612 | slist = 7; | ||
2613 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); // P_mode = 1 to have autosearch start ok with mode2 | ||
2614 | } else | ||
2615 | slist = 3; | ||
2616 | } else { | ||
2617 | if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) { | ||
2618 | slist = 2; | ||
2619 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); // P_mode = 1 | ||
2620 | } else | ||
2621 | slist = 0; | ||
2622 | } | ||
2623 | |||
2624 | if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) | ||
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 | |||
2635 | //set lock_mask values | ||
2636 | dib8000_write_word(state, 6, 0x4); | ||
2637 | dib8000_write_word(state, 7, 0x8); | ||
2638 | dib8000_write_word(state, 8, 0x1000); | ||
2639 | |||
2640 | //set lock_mask wait time values | ||
2641 | value = 50 * state->cfg.pll->internal * factor; | ||
2642 | dib8000_write_word(state, 11, (u16) ((value >> 16) & 0xffff)); // lock0 wait time | ||
2643 | dib8000_write_word(state, 12, (u16) (value & 0xffff)); // lock0 wait time | ||
2644 | value = 100 * state->cfg.pll->internal * factor; | ||
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 | |||
2651 | value = dib8000_read_word(state, 0); | ||
2652 | dib8000_write_word(state, 0, (u16) ((1 << 15) | value)); | ||
2653 | dib8000_read_word(state, 1284); // reset the INT. n_irq_pending | ||
2654 | dib8000_write_word(state, 0, (u16) value); | ||
2655 | |||
2656 | } | ||
2657 | |||
2658 | return 0; | ||
2659 | } | ||
2660 | |||
2661 | static int dib8000_autosearch_irq(struct dvb_frontend *fe) | ||
2662 | { | ||
2663 | struct dib8000_state *state = fe->demodulator_priv; | ||
2664 | u16 irq_pending = dib8000_read_word(state, 1284); | ||
2665 | |||
2666 | if (irq_pending & 0x1) { // failed | ||
2667 | dprintk("dib8000_autosearch_irq failed"); | ||
2668 | return 1; | ||
2669 | } | ||
2670 | |||
2671 | if (irq_pending & 0x2) { // succeeded | ||
2672 | dprintk("dib8000_autosearch_irq succeeded"); | ||
2673 | return 2; | ||
2674 | } | ||
2675 | |||
2676 | return 0; // still pending | ||
2677 | } | ||
2678 | |||
2679 | static int dib8000_tune(struct dvb_frontend *fe) | ||
2680 | { | ||
2681 | struct dib8000_state *state = fe->demodulator_priv; | ||
2682 | int ret = 0; | ||
2683 | u16 lock, value, mode; | ||
2684 | |||
2685 | // we are already tuned - just resuming from suspend | ||
2686 | if (state == NULL) | ||
2687 | return -EINVAL; | ||
2688 | |||
2689 | mode = fft_to_mode(state); | ||
2690 | |||
2691 | dib8000_set_bandwidth(fe, state->fe[0]->dtv_property_cache.bandwidth_hz / 1000); | ||
2692 | dib8000_set_channel(state, 0, 0); | ||
2693 | |||
2694 | // restart demod | ||
2695 | ret |= dib8000_write_word(state, 770, 0x4000); | ||
2696 | ret |= dib8000_write_word(state, 770, 0x0000); | ||
2697 | msleep(45); | ||
2698 | |||
2699 | /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3 */ | ||
2700 | /* ret |= dib8000_write_word(state, 29, (0 << 9) | (4 << 5) | (0 << 4) | (3 << 0) ); workaround inh_isi stays at 1 */ | ||
2701 | |||
2702 | // never achieved a lock before - wait for timfreq to update | ||
2703 | if (state->timf == 0) { | ||
2704 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | ||
2705 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) | ||
2706 | msleep(300); | ||
2707 | else // Sound Broadcasting mode 3 seg | ||
2708 | msleep(500); | ||
2709 | } else // 13 seg | ||
2710 | msleep(200); | ||
2711 | } | ||
2712 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | ||
2713 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { | ||
2714 | |||
2715 | /* P_timf_alpha = (13-P_mode) , P_corm_alpha=6, P_corm_thres=0x40 alpha to check on board */ | ||
2716 | dib8000_write_word(state, 32, ((13 - mode) << 12) | (6 << 8) | 0x40); | ||
2717 | //dib8000_write_word(state, 32, (8 << 12) | (6 << 8) | 0x80); | ||
2718 | |||
2719 | /* P_ctrl_sfreq_step= (12-P_mode) P_ctrl_sfreq_inh =0 P_ctrl_pha_off_max */ | ||
2720 | ret |= dib8000_write_word(state, 37, (12 - mode) | ((5 + mode) << 5)); | ||
2721 | |||
2722 | } else { // Sound Broadcasting mode 3 seg | ||
2723 | |||
2724 | /* P_timf_alpha = (12-P_mode) , P_corm_alpha=6, P_corm_thres=0x60 alpha to check on board */ | ||
2725 | dib8000_write_word(state, 32, ((12 - mode) << 12) | (6 << 8) | 0x60); | ||
2726 | |||
2727 | ret |= dib8000_write_word(state, 37, (11 - mode) | ((5 + mode) << 5)); | ||
2728 | } | ||
2729 | |||
2730 | } else { // 13 seg | ||
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 | |||
2734 | ret |= dib8000_write_word(state, 37, (10 - mode) | ((5 + mode) << 5)); | ||
2735 | |||
2736 | } | ||
2737 | |||
2738 | // we achieved a coff_cpil_lock - it's time to update the timf | ||
2739 | if (state->revision != 0x8090) | ||
2740 | lock = dib8000_read_word(state, 568); | ||
2741 | else | ||
2742 | lock = dib8000_read_word(state, 570); | ||
2743 | if ((lock >> 11) & 0x1) | ||
2744 | dib8000_update_timf(state); | ||
2745 | |||
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 | ||
2747 | dib8000_write_word(state, 6, 0x200); | ||
2748 | |||
2749 | if (state->revision == 0x8002) { | ||
2750 | value = dib8000_read_word(state, 903); | ||
2751 | dib8000_write_word(state, 903, value & ~(1 << 3)); | ||
2752 | msleep(1); | ||
2753 | dib8000_write_word(state, 903, value | (1 << 3)); | ||
2754 | } | ||
2755 | |||
2756 | return ret; | ||
2757 | } | ||
2758 | |||
2759 | static int dib8000_wakeup(struct dvb_frontend *fe) | ||
2760 | { | ||
2761 | struct dib8000_state *state = fe->demodulator_priv; | ||
2762 | u8 index_frontend; | ||
2763 | int ret; | ||
2764 | |||
2765 | dib8000_set_power_mode(state, DIB8000_POWER_ALL); | ||
2766 | dib8000_set_adc_state(state, DIBX000_ADC_ON); | ||
2767 | if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0) | ||
2768 | dprintk("could not start Slow ADC"); | ||
2769 | |||
2770 | if (state->revision != 0x8090) | ||
2771 | dib8000_sad_calib(state); | ||
2772 | |||
2773 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
2774 | ret = state->fe[index_frontend]->ops.init(state->fe[index_frontend]); | ||
2775 | if (ret < 0) | ||
2776 | return ret; | ||
2777 | } | ||
2778 | |||
2779 | return 0; | ||
2780 | } | ||
2781 | |||
2782 | static int dib8000_sleep(struct dvb_frontend *fe) | ||
2783 | { | ||
2784 | struct dib8000_state *state = fe->demodulator_priv; | ||
2785 | u8 index_frontend; | ||
2786 | int ret; | ||
2787 | |||
2788 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
2789 | ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]); | ||
2790 | if (ret < 0) | ||
2791 | return ret; | ||
2792 | } | ||
2793 | |||
2794 | if (state->revision != 0x8090) | ||
2795 | dib8000_set_output_mode(fe, OUTMODE_HIGH_Z); | ||
2796 | dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY); | ||
2797 | return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF); | ||
2798 | } | ||
2799 | |||
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) | ||
2816 | { | ||
2817 | struct dib8000_state *state = fe->demodulator_priv; | ||
2818 | u16 i, val = 0; | ||
2819 | fe_status_t stat; | ||
2820 | u8 index_frontend, sub_index_frontend; | ||
2821 | |||
2822 | fe->dtv_property_cache.bandwidth_hz = 6000000; | ||
2823 | |||
2824 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
2825 | state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat); | ||
2826 | if (stat&FE_HAS_SYNC) { | ||
2827 | dprintk("TMCC lock on the slave%i", index_frontend); | ||
2828 | /* synchronize the cache with the other frontends */ | ||
2829 | state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]); | ||
2830 | for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) { | ||
2831 | if (sub_index_frontend != index_frontend) { | ||
2832 | state->fe[sub_index_frontend]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode; | ||
2833 | state->fe[sub_index_frontend]->dtv_property_cache.inversion = state->fe[index_frontend]->dtv_property_cache.inversion; | ||
2834 | state->fe[sub_index_frontend]->dtv_property_cache.transmission_mode = state->fe[index_frontend]->dtv_property_cache.transmission_mode; | ||
2835 | state->fe[sub_index_frontend]->dtv_property_cache.guard_interval = state->fe[index_frontend]->dtv_property_cache.guard_interval; | ||
2836 | state->fe[sub_index_frontend]->dtv_property_cache.isdbt_partial_reception = state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception; | ||
2837 | for (i = 0; i < 3; i++) { | ||
2838 | state->fe[sub_index_frontend]->dtv_property_cache.layer[i].segment_count = state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count; | ||
2839 | state->fe[sub_index_frontend]->dtv_property_cache.layer[i].interleaving = state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving; | ||
2840 | state->fe[sub_index_frontend]->dtv_property_cache.layer[i].fec = state->fe[index_frontend]->dtv_property_cache.layer[i].fec; | ||
2841 | state->fe[sub_index_frontend]->dtv_property_cache.layer[i].modulation = state->fe[index_frontend]->dtv_property_cache.layer[i].modulation; | ||
2842 | } | ||
2843 | } | ||
2844 | } | ||
2845 | return 0; | ||
2846 | } | ||
2847 | } | ||
2848 | |||
2849 | fe->dtv_property_cache.isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1; | ||
2850 | |||
2851 | if (state->revision == 0x8090) | ||
2852 | val = dib8000_read_word(state, 572); | ||
2853 | else | ||
2854 | val = dib8000_read_word(state, 570); | ||
2855 | fe->dtv_property_cache.inversion = (val & 0x40) >> 6; | ||
2856 | switch ((val & 0x30) >> 4) { | ||
2857 | case 1: | ||
2858 | fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K; | ||
2859 | break; | ||
2860 | case 3: | ||
2861 | default: | ||
2862 | fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; | ||
2863 | break; | ||
2864 | } | ||
2865 | |||
2866 | switch (val & 0x3) { | ||
2867 | case 0: | ||
2868 | fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32; | ||
2869 | dprintk("dib8000_get_frontend GI = 1/32 "); | ||
2870 | break; | ||
2871 | case 1: | ||
2872 | fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16; | ||
2873 | dprintk("dib8000_get_frontend GI = 1/16 "); | ||
2874 | break; | ||
2875 | case 2: | ||
2876 | dprintk("dib8000_get_frontend GI = 1/8 "); | ||
2877 | fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; | ||
2878 | break; | ||
2879 | case 3: | ||
2880 | dprintk("dib8000_get_frontend GI = 1/4 "); | ||
2881 | fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4; | ||
2882 | break; | ||
2883 | } | ||
2884 | |||
2885 | val = dib8000_read_word(state, 505); | ||
2886 | fe->dtv_property_cache.isdbt_partial_reception = val & 1; | ||
2887 | dprintk("dib8000_get_frontend : partial_reception = %d ", fe->dtv_property_cache.isdbt_partial_reception); | ||
2888 | |||
2889 | for (i = 0; i < 3; i++) { | ||
2890 | val = dib8000_read_word(state, 493 + i); | ||
2891 | fe->dtv_property_cache.layer[i].segment_count = val & 0x0F; | ||
2892 | dprintk("dib8000_get_frontend : Layer %d segments = %d ", i, fe->dtv_property_cache.layer[i].segment_count); | ||
2893 | |||
2894 | val = dib8000_read_word(state, 499 + i); | ||
2895 | fe->dtv_property_cache.layer[i].interleaving = val & 0x3; | ||
2896 | dprintk("dib8000_get_frontend : Layer %d time_intlv = %d ", i, fe->dtv_property_cache.layer[i].interleaving); | ||
2897 | |||
2898 | val = dib8000_read_word(state, 481 + i); | ||
2899 | switch (val & 0x7) { | ||
2900 | case 1: | ||
2901 | fe->dtv_property_cache.layer[i].fec = FEC_1_2; | ||
2902 | dprintk("dib8000_get_frontend : Layer %d Code Rate = 1/2 ", i); | ||
2903 | break; | ||
2904 | case 2: | ||
2905 | fe->dtv_property_cache.layer[i].fec = FEC_2_3; | ||
2906 | dprintk("dib8000_get_frontend : Layer %d Code Rate = 2/3 ", i); | ||
2907 | break; | ||
2908 | case 3: | ||
2909 | fe->dtv_property_cache.layer[i].fec = FEC_3_4; | ||
2910 | dprintk("dib8000_get_frontend : Layer %d Code Rate = 3/4 ", i); | ||
2911 | break; | ||
2912 | case 5: | ||
2913 | fe->dtv_property_cache.layer[i].fec = FEC_5_6; | ||
2914 | dprintk("dib8000_get_frontend : Layer %d Code Rate = 5/6 ", i); | ||
2915 | break; | ||
2916 | default: | ||
2917 | fe->dtv_property_cache.layer[i].fec = FEC_7_8; | ||
2918 | dprintk("dib8000_get_frontend : Layer %d Code Rate = 7/8 ", i); | ||
2919 | break; | ||
2920 | } | ||
2921 | |||
2922 | val = dib8000_read_word(state, 487 + i); | ||
2923 | switch (val & 0x3) { | ||
2924 | case 0: | ||
2925 | dprintk("dib8000_get_frontend : Layer %d DQPSK ", i); | ||
2926 | fe->dtv_property_cache.layer[i].modulation = DQPSK; | ||
2927 | break; | ||
2928 | case 1: | ||
2929 | fe->dtv_property_cache.layer[i].modulation = QPSK; | ||
2930 | dprintk("dib8000_get_frontend : Layer %d QPSK ", i); | ||
2931 | break; | ||
2932 | case 2: | ||
2933 | fe->dtv_property_cache.layer[i].modulation = QAM_16; | ||
2934 | dprintk("dib8000_get_frontend : Layer %d QAM16 ", i); | ||
2935 | break; | ||
2936 | case 3: | ||
2937 | default: | ||
2938 | dprintk("dib8000_get_frontend : Layer %d QAM64 ", i); | ||
2939 | fe->dtv_property_cache.layer[i].modulation = QAM_64; | ||
2940 | break; | ||
2941 | } | ||
2942 | } | ||
2943 | |||
2944 | /* synchronize the cache with the other frontends */ | ||
2945 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
2946 | state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode = fe->dtv_property_cache.isdbt_sb_mode; | ||
2947 | state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion; | ||
2948 | state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode; | ||
2949 | state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval; | ||
2950 | state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception = fe->dtv_property_cache.isdbt_partial_reception; | ||
2951 | for (i = 0; i < 3; i++) { | ||
2952 | state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count = fe->dtv_property_cache.layer[i].segment_count; | ||
2953 | state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving = fe->dtv_property_cache.layer[i].interleaving; | ||
2954 | state->fe[index_frontend]->dtv_property_cache.layer[i].fec = fe->dtv_property_cache.layer[i].fec; | ||
2955 | state->fe[index_frontend]->dtv_property_cache.layer[i].modulation = fe->dtv_property_cache.layer[i].modulation; | ||
2956 | } | ||
2957 | } | ||
2958 | return 0; | ||
2959 | } | ||
2960 | |||
2961 | static int dib8000_set_frontend(struct dvb_frontend *fe) | ||
2962 | { | ||
2963 | struct dib8000_state *state = fe->demodulator_priv; | ||
2964 | u8 nbr_pending, exit_condition, index_frontend; | ||
2965 | s8 index_frontend_success = -1; | ||
2966 | int time, ret; | ||
2967 | int time_slave = FE_CALLBACK_TIME_NEVER; | ||
2968 | |||
2969 | if (state->fe[0]->dtv_property_cache.frequency == 0) { | ||
2970 | dprintk("dib8000: must at least specify frequency "); | ||
2971 | return 0; | ||
2972 | } | ||
2973 | |||
2974 | if (state->fe[0]->dtv_property_cache.bandwidth_hz == 0) { | ||
2975 | dprintk("dib8000: no bandwidth specified, set to default "); | ||
2976 | state->fe[0]->dtv_property_cache.bandwidth_hz = 6000000; | ||
2977 | } | ||
2978 | |||
2979 | for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
2980 | /* synchronization of the cache */ | ||
2981 | 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)); | ||
2983 | |||
2984 | if (state->revision != 0x8090) | ||
2985 | dib8000_set_output_mode(state->fe[index_frontend], | ||
2986 | OUTMODE_HIGH_Z); | ||
2987 | else | ||
2988 | dib8096p_set_output_mode(state->fe[index_frontend], | ||
2989 | OUTMODE_HIGH_Z); | ||
2990 | if (state->fe[index_frontend]->ops.tuner_ops.set_params) | ||
2991 | state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend]); | ||
2992 | |||
2993 | dib8000_set_tune_state(state->fe[index_frontend], CT_AGC_START); | ||
2994 | } | ||
2995 | |||
2996 | /* start up the AGC */ | ||
2997 | do { | ||
2998 | time = dib8000_agc_startup(state->fe[0]); | ||
2999 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
3000 | time_slave = dib8000_agc_startup(state->fe[index_frontend]); | ||
3001 | if (time == FE_CALLBACK_TIME_NEVER) | ||
3002 | time = time_slave; | ||
3003 | else if ((time_slave != FE_CALLBACK_TIME_NEVER) && (time_slave > time)) | ||
3004 | time = time_slave; | ||
3005 | } | ||
3006 | if (time != FE_CALLBACK_TIME_NEVER) | ||
3007 | msleep(time / 10); | ||
3008 | else | ||
3009 | break; | ||
3010 | exit_condition = 1; | ||
3011 | for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
3012 | if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_AGC_STOP) { | ||
3013 | exit_condition = 0; | ||
3014 | break; | ||
3015 | } | ||
3016 | } | ||
3017 | } while (exit_condition == 0); | ||
3018 | |||
3019 | 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); | ||
3021 | |||
3022 | if ((state->fe[0]->dtv_property_cache.delivery_system != SYS_ISDBT) || | ||
3023 | (state->fe[0]->dtv_property_cache.inversion == INVERSION_AUTO) || | ||
3024 | (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) || | ||
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++) { | ||
3051 | dib8000_set_bandwidth(state->fe[index_frontend], fe->dtv_property_cache.bandwidth_hz / 1000); | ||
3052 | dib8000_autosearch_start(state->fe[index_frontend]); | ||
3053 | } | ||
3054 | |||
3055 | do { | ||
3056 | msleep(20); | ||
3057 | nbr_pending = 0; | ||
3058 | exit_condition = 0; /* 0: tune pending; 1: tune failed; 2:tune success */ | ||
3059 | for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
3060 | if (((tune_failed >> index_frontend) & 0x1) == 0) { | ||
3061 | found = dib8000_autosearch_irq(state->fe[index_frontend]); | ||
3062 | switch (found) { | ||
3063 | case 0: /* tune pending */ | ||
3064 | nbr_pending++; | ||
3065 | break; | ||
3066 | case 2: | ||
3067 | dprintk("autosearch succeed on the frontend%i", index_frontend); | ||
3068 | exit_condition = 2; | ||
3069 | index_frontend_success = index_frontend; | ||
3070 | break; | ||
3071 | default: | ||
3072 | dprintk("unhandled autosearch result"); | ||
3073 | case 1: | ||
3074 | tune_failed |= (1 << index_frontend); | ||
3075 | dprintk("autosearch failed for the frontend%i", index_frontend); | ||
3076 | break; | ||
3077 | } | ||
3078 | } | ||
3079 | } | ||
3080 | |||
3081 | /* if all tune are done and no success, exit: tune failed */ | ||
3082 | if ((nbr_pending == 0) && (exit_condition == 0)) | ||
3083 | exit_condition = 1; | ||
3084 | } while ((exit_condition == 0) && i--); | ||
3085 | |||
3086 | if (exit_condition == 1) { /* tune failed */ | ||
3087 | dprintk("tune failed"); | ||
3088 | return 0; | ||
3089 | } | ||
3090 | |||
3091 | dprintk("tune success on frontend%i", index_frontend_success); | ||
3092 | |||
3093 | dib8000_get_frontend(fe); | ||
3094 | } | ||
3095 | |||
3096 | for (index_frontend = 0, ret = 0; (ret >= 0) && (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) | ||
3097 | ret = dib8000_tune(state->fe[index_frontend]); | ||
3098 | |||
3099 | /* set output mode and diversity input */ | ||
3100 | if (state->revision != 0x8090) { | ||
3101 | dib8000_set_output_mode(state->fe[0], state->cfg.output_mode); | ||
3102 | for (index_frontend = 1; | ||
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); | ||
3115 | if (state->cfg.enMpegOutput == 0) { | ||
3116 | dib8096p_setDibTxMux(state, MPEG_ON_DIBTX); | ||
3117 | dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS); | ||
3118 | } | ||
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 | } | ||
3131 | |||
3132 | return ret; | ||
3133 | } | ||
3134 | |||
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) | ||
3145 | { | ||
3146 | struct dib8000_state *state = fe->demodulator_priv; | ||
3147 | u16 lock_slave = 0, lock; | ||
3148 | u8 index_frontend; | ||
3149 | |||
3150 | if (state->revision == 0x8090) | ||
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++) | ||
3156 | lock_slave |= dib8000_read_lock(state->fe[index_frontend]); | ||
3157 | |||
3158 | *stat = 0; | ||
3159 | |||
3160 | if (((lock >> 13) & 1) || ((lock_slave >> 13) & 1)) | ||
3161 | *stat |= FE_HAS_SIGNAL; | ||
3162 | |||
3163 | if (((lock >> 8) & 1) || ((lock_slave >> 8) & 1)) /* Equal */ | ||
3164 | *stat |= FE_HAS_CARRIER; | ||
3165 | |||
3166 | if ((((lock >> 1) & 0xf) == 0xf) || (((lock_slave >> 1) & 0xf) == 0xf)) /* TMCC_SYNC */ | ||
3167 | *stat |= FE_HAS_SYNC; | ||
3168 | |||
3169 | if ((((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) && ((lock >> 5) & 7)) /* FEC MPEG */ | ||
3170 | *stat |= FE_HAS_LOCK; | ||
3171 | |||
3172 | if (((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) { | ||
3173 | lock = dib8000_read_word(state, 554); /* Viterbi Layer A */ | ||
3174 | if (lock & 0x01) | ||
3175 | *stat |= FE_HAS_VITERBI; | ||
3176 | |||
3177 | lock = dib8000_read_word(state, 555); /* Viterbi Layer B */ | ||
3178 | if (lock & 0x01) | ||
3179 | *stat |= FE_HAS_VITERBI; | ||
3180 | |||
3181 | lock = dib8000_read_word(state, 556); /* Viterbi Layer C */ | ||
3182 | if (lock & 0x01) | ||
3183 | *stat |= FE_HAS_VITERBI; | ||
3184 | } | ||
3185 | |||
3186 | return 0; | ||
3187 | } | ||
3188 | |||
3189 | static int dib8000_read_ber(struct dvb_frontend *fe, u32 * ber) | ||
3190 | { | ||
3191 | struct dib8000_state *state = fe->demodulator_priv; | ||
3192 | |||
3193 | /* 13 segments */ | ||
3194 | if (state->revision == 0x8090) | ||
3195 | *ber = (dib8000_read_word(state, 562) << 16) | | ||
3196 | dib8000_read_word(state, 563); | ||
3197 | else | ||
3198 | *ber = (dib8000_read_word(state, 560) << 16) | | ||
3199 | dib8000_read_word(state, 561); | ||
3200 | return 0; | ||
3201 | } | ||
3202 | |||
3203 | static int dib8000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) | ||
3204 | { | ||
3205 | struct dib8000_state *state = fe->demodulator_priv; | ||
3206 | |||
3207 | /* packet error on 13 seg */ | ||
3208 | if (state->revision == 0x8090) | ||
3209 | *unc = dib8000_read_word(state, 567); | ||
3210 | else | ||
3211 | *unc = dib8000_read_word(state, 565); | ||
3212 | return 0; | ||
3213 | } | ||
3214 | |||
3215 | static int dib8000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) | ||
3216 | { | ||
3217 | struct dib8000_state *state = fe->demodulator_priv; | ||
3218 | u8 index_frontend; | ||
3219 | u16 val; | ||
3220 | |||
3221 | *strength = 0; | ||
3222 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
3223 | state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val); | ||
3224 | if (val > 65535 - *strength) | ||
3225 | *strength = 65535; | ||
3226 | else | ||
3227 | *strength += val; | ||
3228 | } | ||
3229 | |||
3230 | val = 65535 - dib8000_read_word(state, 390); | ||
3231 | if (val > 65535 - *strength) | ||
3232 | *strength = 65535; | ||
3233 | else | ||
3234 | *strength += val; | ||
3235 | return 0; | ||
3236 | } | ||
3237 | |||
3238 | static u32 dib8000_get_snr(struct dvb_frontend *fe) | ||
3239 | { | ||
3240 | struct dib8000_state *state = fe->demodulator_priv; | ||
3241 | u32 n, s, exp; | ||
3242 | u16 val; | ||
3243 | |||
3244 | if (state->revision != 0x8090) | ||
3245 | val = dib8000_read_word(state, 542); | ||
3246 | else | ||
3247 | val = dib8000_read_word(state, 544); | ||
3248 | n = (val >> 6) & 0xff; | ||
3249 | exp = (val & 0x3f); | ||
3250 | if ((exp & 0x20) != 0) | ||
3251 | exp -= 0x40; | ||
3252 | n <<= exp+16; | ||
3253 | |||
3254 | if (state->revision != 0x8090) | ||
3255 | val = dib8000_read_word(state, 543); | ||
3256 | else | ||
3257 | val = dib8000_read_word(state, 545); | ||
3258 | s = (val >> 6) & 0xff; | ||
3259 | exp = (val & 0x3f); | ||
3260 | if ((exp & 0x20) != 0) | ||
3261 | exp -= 0x40; | ||
3262 | s <<= exp+16; | ||
3263 | |||
3264 | if (n > 0) { | ||
3265 | u32 t = (s/n) << 16; | ||
3266 | return t + ((s << 16) - n*t) / n; | ||
3267 | } | ||
3268 | return 0xffffffff; | ||
3269 | } | ||
3270 | |||
3271 | static int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr) | ||
3272 | { | ||
3273 | struct dib8000_state *state = fe->demodulator_priv; | ||
3274 | u8 index_frontend; | ||
3275 | u32 snr_master; | ||
3276 | |||
3277 | snr_master = dib8000_get_snr(fe); | ||
3278 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) | ||
3279 | snr_master += dib8000_get_snr(state->fe[index_frontend]); | ||
3280 | |||
3281 | if ((snr_master >> 16) != 0) { | ||
3282 | snr_master = 10*intlog10(snr_master>>16); | ||
3283 | *snr = snr_master / ((1 << 24) / 10); | ||
3284 | } | ||
3285 | else | ||
3286 | *snr = 0; | ||
3287 | |||
3288 | return 0; | ||
3289 | } | ||
3290 | |||
3291 | int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave) | ||
3292 | { | ||
3293 | struct dib8000_state *state = fe->demodulator_priv; | ||
3294 | u8 index_frontend = 1; | ||
3295 | |||
3296 | while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL)) | ||
3297 | index_frontend++; | ||
3298 | if (index_frontend < MAX_NUMBER_OF_FRONTENDS) { | ||
3299 | dprintk("set slave fe %p to index %i", fe_slave, index_frontend); | ||
3300 | state->fe[index_frontend] = fe_slave; | ||
3301 | return 0; | ||
3302 | } | ||
3303 | |||
3304 | dprintk("too many slave frontend"); | ||
3305 | return -ENOMEM; | ||
3306 | } | ||
3307 | EXPORT_SYMBOL(dib8000_set_slave_frontend); | ||
3308 | |||
3309 | int dib8000_remove_slave_frontend(struct dvb_frontend *fe) | ||
3310 | { | ||
3311 | struct dib8000_state *state = fe->demodulator_priv; | ||
3312 | u8 index_frontend = 1; | ||
3313 | |||
3314 | while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL)) | ||
3315 | index_frontend++; | ||
3316 | if (index_frontend != 1) { | ||
3317 | dprintk("remove slave fe %p (index %i)", state->fe[index_frontend-1], index_frontend-1); | ||
3318 | state->fe[index_frontend] = NULL; | ||
3319 | return 0; | ||
3320 | } | ||
3321 | |||
3322 | dprintk("no frontend to be removed"); | ||
3323 | return -ENODEV; | ||
3324 | } | ||
3325 | EXPORT_SYMBOL(dib8000_remove_slave_frontend); | ||
3326 | |||
3327 | struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index) | ||
3328 | { | ||
3329 | struct dib8000_state *state = fe->demodulator_priv; | ||
3330 | |||
3331 | if (slave_index >= MAX_NUMBER_OF_FRONTENDS) | ||
3332 | return NULL; | ||
3333 | return state->fe[slave_index]; | ||
3334 | } | ||
3335 | EXPORT_SYMBOL(dib8000_get_slave_frontend); | ||
3336 | |||
3337 | |||
3338 | int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, | ||
3339 | u8 default_addr, u8 first_addr, u8 is_dib8096p) | ||
3340 | { | ||
3341 | int k = 0, ret = 0; | ||
3342 | u8 new_addr = 0; | ||
3343 | struct i2c_device client = {.adap = host }; | ||
3344 | |||
3345 | client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL); | ||
3346 | if (!client.i2c_write_buffer) { | ||
3347 | dprintk("%s: not enough memory", __func__); | ||
3348 | return -ENOMEM; | ||
3349 | } | ||
3350 | client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL); | ||
3351 | if (!client.i2c_read_buffer) { | ||
3352 | dprintk("%s: not enough memory", __func__); | ||
3353 | ret = -ENOMEM; | ||
3354 | goto error_memory_read; | ||
3355 | } | ||
3356 | client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL); | ||
3357 | if (!client.i2c_buffer_lock) { | ||
3358 | dprintk("%s: not enough memory", __func__); | ||
3359 | ret = -ENOMEM; | ||
3360 | goto error_memory_lock; | ||
3361 | } | ||
3362 | mutex_init(client.i2c_buffer_lock); | ||
3363 | |||
3364 | for (k = no_of_demods - 1; k >= 0; k--) { | ||
3365 | /* designated i2c address */ | ||
3366 | new_addr = first_addr + (k << 1); | ||
3367 | |||
3368 | client.addr = new_addr; | ||
3369 | if (!is_dib8096p) | ||
3370 | dib8000_i2c_write16(&client, 1287, 0x0003); /* sram lead in, rdy */ | ||
3371 | if (dib8000_identify(&client) == 0) { | ||
3372 | /* sram lead in, rdy */ | ||
3373 | if (!is_dib8096p) | ||
3374 | dib8000_i2c_write16(&client, 1287, 0x0003); | ||
3375 | client.addr = default_addr; | ||
3376 | if (dib8000_identify(&client) == 0) { | ||
3377 | dprintk("#%d: not identified", k); | ||
3378 | ret = -EINVAL; | ||
3379 | goto error; | ||
3380 | } | ||
3381 | } | ||
3382 | |||
3383 | /* start diversity to pull_down div_str - just for i2c-enumeration */ | ||
3384 | dib8000_i2c_write16(&client, 1286, (1 << 10) | (4 << 6)); | ||
3385 | |||
3386 | /* set new i2c address and force divstart */ | ||
3387 | dib8000_i2c_write16(&client, 1285, (new_addr << 2) | 0x2); | ||
3388 | client.addr = new_addr; | ||
3389 | dib8000_identify(&client); | ||
3390 | |||
3391 | dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr); | ||
3392 | } | ||
3393 | |||
3394 | for (k = 0; k < no_of_demods; k++) { | ||
3395 | new_addr = first_addr | (k << 1); | ||
3396 | client.addr = new_addr; | ||
3397 | |||
3398 | // unforce divstr | ||
3399 | dib8000_i2c_write16(&client, 1285, new_addr << 2); | ||
3400 | |||
3401 | /* deactivate div - it was just for i2c-enumeration */ | ||
3402 | dib8000_i2c_write16(&client, 1286, 0); | ||
3403 | } | ||
3404 | |||
3405 | error: | ||
3406 | kfree(client.i2c_buffer_lock); | ||
3407 | error_memory_lock: | ||
3408 | kfree(client.i2c_read_buffer); | ||
3409 | error_memory_read: | ||
3410 | kfree(client.i2c_write_buffer); | ||
3411 | |||
3412 | return ret; | ||
3413 | } | ||
3414 | |||
3415 | EXPORT_SYMBOL(dib8000_i2c_enumeration); | ||
3416 | static int dib8000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune) | ||
3417 | { | ||
3418 | tune->min_delay_ms = 1000; | ||
3419 | tune->step_size = 0; | ||
3420 | tune->max_drift = 0; | ||
3421 | return 0; | ||
3422 | } | ||
3423 | |||
3424 | static void dib8000_release(struct dvb_frontend *fe) | ||
3425 | { | ||
3426 | struct dib8000_state *st = fe->demodulator_priv; | ||
3427 | u8 index_frontend; | ||
3428 | |||
3429 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (st->fe[index_frontend] != NULL); index_frontend++) | ||
3430 | dvb_frontend_detach(st->fe[index_frontend]); | ||
3431 | |||
3432 | dibx000_exit_i2c_master(&st->i2c_master); | ||
3433 | i2c_del_adapter(&st->dib8096p_tuner_adap); | ||
3434 | kfree(st->fe[0]); | ||
3435 | kfree(st); | ||
3436 | } | ||
3437 | |||
3438 | struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating) | ||
3439 | { | ||
3440 | struct dib8000_state *st = fe->demodulator_priv; | ||
3441 | return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); | ||
3442 | } | ||
3443 | |||
3444 | EXPORT_SYMBOL(dib8000_get_i2c_master); | ||
3445 | |||
3446 | int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) | ||
3447 | { | ||
3448 | struct dib8000_state *st = fe->demodulator_priv; | ||
3449 | u16 val = dib8000_read_word(st, 299) & 0xffef; | ||
3450 | val |= (onoff & 0x1) << 4; | ||
3451 | |||
3452 | dprintk("pid filter enabled %d", onoff); | ||
3453 | return dib8000_write_word(st, 299, val); | ||
3454 | } | ||
3455 | EXPORT_SYMBOL(dib8000_pid_filter_ctrl); | ||
3456 | |||
3457 | int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) | ||
3458 | { | ||
3459 | struct dib8000_state *st = fe->demodulator_priv; | ||
3460 | dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff); | ||
3461 | return dib8000_write_word(st, 305 + id, onoff ? (1 << 13) | pid : 0); | ||
3462 | } | ||
3463 | EXPORT_SYMBOL(dib8000_pid_filter); | ||
3464 | |||
3465 | static const struct dvb_frontend_ops dib8000_ops = { | ||
3466 | .delsys = { SYS_ISDBT }, | ||
3467 | .info = { | ||
3468 | .name = "DiBcom 8000 ISDB-T", | ||
3469 | .frequency_min = 44250000, | ||
3470 | .frequency_max = 867250000, | ||
3471 | .frequency_stepsize = 62500, | ||
3472 | .caps = FE_CAN_INVERSION_AUTO | | ||
3473 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
3474 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
3475 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
3476 | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO, | ||
3477 | }, | ||
3478 | |||
3479 | .release = dib8000_release, | ||
3480 | |||
3481 | .init = dib8000_wakeup, | ||
3482 | .sleep = dib8000_sleep, | ||
3483 | |||
3484 | .set_frontend = dib8000_set_frontend, | ||
3485 | .get_tune_settings = dib8000_fe_get_tune_settings, | ||
3486 | .get_frontend = dib8000_get_frontend, | ||
3487 | |||
3488 | .read_status = dib8000_read_status, | ||
3489 | .read_ber = dib8000_read_ber, | ||
3490 | .read_signal_strength = dib8000_read_signal_strength, | ||
3491 | .read_snr = dib8000_read_snr, | ||
3492 | .read_ucblocks = dib8000_read_unc_blocks, | ||
3493 | }; | ||
3494 | |||
3495 | struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg) | ||
3496 | { | ||
3497 | struct dvb_frontend *fe; | ||
3498 | struct dib8000_state *state; | ||
3499 | |||
3500 | dprintk("dib8000_attach"); | ||
3501 | |||
3502 | state = kzalloc(sizeof(struct dib8000_state), GFP_KERNEL); | ||
3503 | if (state == NULL) | ||
3504 | return NULL; | ||
3505 | fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL); | ||
3506 | if (fe == NULL) | ||
3507 | goto error; | ||
3508 | |||
3509 | memcpy(&state->cfg, cfg, sizeof(struct dib8000_config)); | ||
3510 | state->i2c.adap = i2c_adap; | ||
3511 | state->i2c.addr = i2c_addr; | ||
3512 | state->i2c.i2c_write_buffer = state->i2c_write_buffer; | ||
3513 | state->i2c.i2c_read_buffer = state->i2c_read_buffer; | ||
3514 | mutex_init(&state->i2c_buffer_lock); | ||
3515 | state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock; | ||
3516 | state->gpio_val = cfg->gpio_val; | ||
3517 | state->gpio_dir = cfg->gpio_dir; | ||
3518 | |||
3519 | /* Ensure the output mode remains at the previous default if it's | ||
3520 | * not specifically set by the caller. | ||
3521 | */ | ||
3522 | if ((state->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (state->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK)) | ||
3523 | state->cfg.output_mode = OUTMODE_MPEG2_FIFO; | ||
3524 | |||
3525 | state->fe[0] = fe; | ||
3526 | fe->demodulator_priv = state; | ||
3527 | memcpy(&state->fe[0]->ops, &dib8000_ops, sizeof(struct dvb_frontend_ops)); | ||
3528 | |||
3529 | state->timf_default = cfg->pll->timf; | ||
3530 | |||
3531 | if (dib8000_identify(&state->i2c) == 0) | ||
3532 | goto error; | ||
3533 | |||
3534 | dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr); | ||
3535 | |||
3536 | /* init 8096p tuner adapter */ | ||
3537 | strncpy(state->dib8096p_tuner_adap.name, "DiB8096P tuner interface", | ||
3538 | sizeof(state->dib8096p_tuner_adap.name)); | ||
3539 | state->dib8096p_tuner_adap.algo = &dib8096p_tuner_xfer_algo; | ||
3540 | state->dib8096p_tuner_adap.algo_data = NULL; | ||
3541 | state->dib8096p_tuner_adap.dev.parent = state->i2c.adap->dev.parent; | ||
3542 | i2c_set_adapdata(&state->dib8096p_tuner_adap, state); | ||
3543 | i2c_add_adapter(&state->dib8096p_tuner_adap); | ||
3544 | |||
3545 | dib8000_reset(fe); | ||
3546 | |||
3547 | dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5)); /* ber_rs_len = 3 */ | ||
3548 | |||
3549 | return fe; | ||
3550 | |||
3551 | error: | ||
3552 | kfree(state); | ||
3553 | return NULL; | ||
3554 | } | ||
3555 | |||
3556 | EXPORT_SYMBOL(dib8000_attach); | ||
3557 | |||
3558 | MODULE_AUTHOR("Olivier Grenie <Olivier.Grenie@dibcom.fr, " "Patrick Boettcher <pboettcher@dibcom.fr>"); | ||
3559 | MODULE_DESCRIPTION("Driver for the DiBcom 8000 ISDB-T demodulator"); | ||
3560 | MODULE_LICENSE("GPL"); | ||