diff options
Diffstat (limited to 'drivers/media/dvb/frontends/dib8000.c')
-rw-r--r-- | drivers/media/dvb/frontends/dib8000.c | 2669 |
1 files changed, 2669 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c new file mode 100644 index 00000000000..fe284d5292f --- /dev/null +++ b/drivers/media/dvb/frontends/dib8000.c | |||
@@ -0,0 +1,2669 @@ | |||
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 | }; | ||
85 | |||
86 | enum dib8000_power_mode { | ||
87 | DIB8000M_POWER_ALL = 0, | ||
88 | DIB8000M_POWER_INTERFACE_ONLY, | ||
89 | }; | ||
90 | |||
91 | static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg) | ||
92 | { | ||
93 | u16 ret; | ||
94 | struct i2c_msg msg[2] = { | ||
95 | {.addr = i2c->addr >> 1, .flags = 0, .len = 2}, | ||
96 | {.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2}, | ||
97 | }; | ||
98 | |||
99 | if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { | ||
100 | dprintk("could not acquire lock"); | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | msg[0].buf = i2c->i2c_write_buffer; | ||
105 | msg[0].buf[0] = reg >> 8; | ||
106 | msg[0].buf[1] = reg & 0xff; | ||
107 | msg[1].buf = i2c->i2c_read_buffer; | ||
108 | |||
109 | if (i2c_transfer(i2c->adap, msg, 2) != 2) | ||
110 | dprintk("i2c read error on %d", reg); | ||
111 | |||
112 | ret = (msg[1].buf[0] << 8) | msg[1].buf[1]; | ||
113 | mutex_unlock(i2c->i2c_buffer_lock); | ||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) | ||
118 | { | ||
119 | u16 ret; | ||
120 | |||
121 | if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { | ||
122 | dprintk("could not acquire lock"); | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | state->i2c_write_buffer[0] = reg >> 8; | ||
127 | state->i2c_write_buffer[1] = reg & 0xff; | ||
128 | |||
129 | memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); | ||
130 | state->msg[0].addr = state->i2c.addr >> 1; | ||
131 | state->msg[0].flags = 0; | ||
132 | state->msg[0].buf = state->i2c_write_buffer; | ||
133 | state->msg[0].len = 2; | ||
134 | state->msg[1].addr = state->i2c.addr >> 1; | ||
135 | state->msg[1].flags = I2C_M_RD; | ||
136 | state->msg[1].buf = state->i2c_read_buffer; | ||
137 | state->msg[1].len = 2; | ||
138 | |||
139 | if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2) | ||
140 | dprintk("i2c read error on %d", reg); | ||
141 | |||
142 | ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; | ||
143 | mutex_unlock(&state->i2c_buffer_lock); | ||
144 | |||
145 | return ret; | ||
146 | } | ||
147 | |||
148 | static u32 dib8000_read32(struct dib8000_state *state, u16 reg) | ||
149 | { | ||
150 | u16 rw[2]; | ||
151 | |||
152 | rw[0] = dib8000_read_word(state, reg + 0); | ||
153 | rw[1] = dib8000_read_word(state, reg + 1); | ||
154 | |||
155 | return ((rw[0] << 16) | (rw[1])); | ||
156 | } | ||
157 | |||
158 | static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val) | ||
159 | { | ||
160 | struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4}; | ||
161 | int ret = 0; | ||
162 | |||
163 | if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { | ||
164 | dprintk("could not acquire lock"); | ||
165 | return -EINVAL; | ||
166 | } | ||
167 | |||
168 | msg.buf = i2c->i2c_write_buffer; | ||
169 | msg.buf[0] = (reg >> 8) & 0xff; | ||
170 | msg.buf[1] = reg & 0xff; | ||
171 | msg.buf[2] = (val >> 8) & 0xff; | ||
172 | msg.buf[3] = val & 0xff; | ||
173 | |||
174 | ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | ||
175 | mutex_unlock(i2c->i2c_buffer_lock); | ||
176 | |||
177 | return ret; | ||
178 | } | ||
179 | |||
180 | static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) | ||
181 | { | ||
182 | int ret; | ||
183 | |||
184 | if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { | ||
185 | dprintk("could not acquire lock"); | ||
186 | return -EINVAL; | ||
187 | } | ||
188 | |||
189 | state->i2c_write_buffer[0] = (reg >> 8) & 0xff; | ||
190 | state->i2c_write_buffer[1] = reg & 0xff; | ||
191 | state->i2c_write_buffer[2] = (val >> 8) & 0xff; | ||
192 | state->i2c_write_buffer[3] = val & 0xff; | ||
193 | |||
194 | memset(&state->msg[0], 0, sizeof(struct i2c_msg)); | ||
195 | state->msg[0].addr = state->i2c.addr >> 1; | ||
196 | state->msg[0].flags = 0; | ||
197 | state->msg[0].buf = state->i2c_write_buffer; | ||
198 | state->msg[0].len = 4; | ||
199 | |||
200 | ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? | ||
201 | -EREMOTEIO : 0); | ||
202 | mutex_unlock(&state->i2c_buffer_lock); | ||
203 | |||
204 | return ret; | ||
205 | } | ||
206 | |||
207 | static const s16 coeff_2k_sb_1seg_dqpsk[8] = { | ||
208 | (769 << 5) | 0x0a, (745 << 5) | 0x03, (595 << 5) | 0x0d, (769 << 5) | 0x0a, (920 << 5) | 0x09, (784 << 5) | 0x02, (519 << 5) | 0x0c, | ||
209 | (920 << 5) | 0x09 | ||
210 | }; | ||
211 | |||
212 | static const s16 coeff_2k_sb_1seg[8] = { | ||
213 | (692 << 5) | 0x0b, (683 << 5) | 0x01, (519 << 5) | 0x09, (692 << 5) | 0x0b, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f | ||
214 | }; | ||
215 | |||
216 | static const s16 coeff_2k_sb_3seg_0dqpsk_1dqpsk[8] = { | ||
217 | (832 << 5) | 0x10, (912 << 5) | 0x05, (900 << 5) | 0x12, (832 << 5) | 0x10, (-931 << 5) | 0x0f, (912 << 5) | 0x04, (807 << 5) | 0x11, | ||
218 | (-931 << 5) | 0x0f | ||
219 | }; | ||
220 | |||
221 | static const s16 coeff_2k_sb_3seg_0dqpsk[8] = { | ||
222 | (622 << 5) | 0x0c, (941 << 5) | 0x04, (796 << 5) | 0x10, (622 << 5) | 0x0c, (982 << 5) | 0x0c, (519 << 5) | 0x02, (572 << 5) | 0x0e, | ||
223 | (982 << 5) | 0x0c | ||
224 | }; | ||
225 | |||
226 | static const s16 coeff_2k_sb_3seg_1dqpsk[8] = { | ||
227 | (699 << 5) | 0x14, (607 << 5) | 0x04, (944 << 5) | 0x13, (699 << 5) | 0x14, (-720 << 5) | 0x0d, (640 << 5) | 0x03, (866 << 5) | 0x12, | ||
228 | (-720 << 5) | 0x0d | ||
229 | }; | ||
230 | |||
231 | static const s16 coeff_2k_sb_3seg[8] = { | ||
232 | (664 << 5) | 0x0c, (925 << 5) | 0x03, (937 << 5) | 0x10, (664 << 5) | 0x0c, (-610 << 5) | 0x0a, (697 << 5) | 0x01, (836 << 5) | 0x0e, | ||
233 | (-610 << 5) | 0x0a | ||
234 | }; | ||
235 | |||
236 | static const s16 coeff_4k_sb_1seg_dqpsk[8] = { | ||
237 | (-955 << 5) | 0x0e, (687 << 5) | 0x04, (818 << 5) | 0x10, (-955 << 5) | 0x0e, (-922 << 5) | 0x0d, (750 << 5) | 0x03, (665 << 5) | 0x0f, | ||
238 | (-922 << 5) | 0x0d | ||
239 | }; | ||
240 | |||
241 | static const s16 coeff_4k_sb_1seg[8] = { | ||
242 | (638 << 5) | 0x0d, (683 << 5) | 0x02, (638 << 5) | 0x0d, (638 << 5) | 0x0d, (-655 << 5) | 0x0a, (517 << 5) | 0x00, (698 << 5) | 0x0d, | ||
243 | (-655 << 5) | 0x0a | ||
244 | }; | ||
245 | |||
246 | static const s16 coeff_4k_sb_3seg_0dqpsk_1dqpsk[8] = { | ||
247 | (-707 << 5) | 0x14, (910 << 5) | 0x06, (889 << 5) | 0x16, (-707 << 5) | 0x14, (-958 << 5) | 0x13, (993 << 5) | 0x05, (523 << 5) | 0x14, | ||
248 | (-958 << 5) | 0x13 | ||
249 | }; | ||
250 | |||
251 | static const s16 coeff_4k_sb_3seg_0dqpsk[8] = { | ||
252 | (-723 << 5) | 0x13, (910 << 5) | 0x05, (777 << 5) | 0x14, (-723 << 5) | 0x13, (-568 << 5) | 0x0f, (547 << 5) | 0x03, (696 << 5) | 0x12, | ||
253 | (-568 << 5) | 0x0f | ||
254 | }; | ||
255 | |||
256 | static const s16 coeff_4k_sb_3seg_1dqpsk[8] = { | ||
257 | (-940 << 5) | 0x15, (607 << 5) | 0x05, (915 << 5) | 0x16, (-940 << 5) | 0x15, (-848 << 5) | 0x13, (683 << 5) | 0x04, (543 << 5) | 0x14, | ||
258 | (-848 << 5) | 0x13 | ||
259 | }; | ||
260 | |||
261 | static const s16 coeff_4k_sb_3seg[8] = { | ||
262 | (612 << 5) | 0x12, (910 << 5) | 0x04, (864 << 5) | 0x14, (612 << 5) | 0x12, (-869 << 5) | 0x13, (683 << 5) | 0x02, (869 << 5) | 0x12, | ||
263 | (-869 << 5) | 0x13 | ||
264 | }; | ||
265 | |||
266 | static const s16 coeff_8k_sb_1seg_dqpsk[8] = { | ||
267 | (-835 << 5) | 0x12, (684 << 5) | 0x05, (735 << 5) | 0x14, (-835 << 5) | 0x12, (-598 << 5) | 0x10, (781 << 5) | 0x04, (739 << 5) | 0x13, | ||
268 | (-598 << 5) | 0x10 | ||
269 | }; | ||
270 | |||
271 | static const s16 coeff_8k_sb_1seg[8] = { | ||
272 | (673 << 5) | 0x0f, (683 << 5) | 0x03, (808 << 5) | 0x12, (673 << 5) | 0x0f, (585 << 5) | 0x0f, (512 << 5) | 0x01, (780 << 5) | 0x0f, | ||
273 | (585 << 5) | 0x0f | ||
274 | }; | ||
275 | |||
276 | static const s16 coeff_8k_sb_3seg_0dqpsk_1dqpsk[8] = { | ||
277 | (863 << 5) | 0x17, (930 << 5) | 0x07, (878 << 5) | 0x19, (863 << 5) | 0x17, (0 << 5) | 0x14, (521 << 5) | 0x05, (980 << 5) | 0x18, | ||
278 | (0 << 5) | 0x14 | ||
279 | }; | ||
280 | |||
281 | static const s16 coeff_8k_sb_3seg_0dqpsk[8] = { | ||
282 | (-924 << 5) | 0x17, (910 << 5) | 0x06, (774 << 5) | 0x17, (-924 << 5) | 0x17, (-877 << 5) | 0x15, (565 << 5) | 0x04, (553 << 5) | 0x15, | ||
283 | (-877 << 5) | 0x15 | ||
284 | }; | ||
285 | |||
286 | static const s16 coeff_8k_sb_3seg_1dqpsk[8] = { | ||
287 | (-921 << 5) | 0x19, (607 << 5) | 0x06, (881 << 5) | 0x19, (-921 << 5) | 0x19, (-921 << 5) | 0x14, (713 << 5) | 0x05, (1018 << 5) | 0x18, | ||
288 | (-921 << 5) | 0x14 | ||
289 | }; | ||
290 | |||
291 | static const s16 coeff_8k_sb_3seg[8] = { | ||
292 | (514 << 5) | 0x14, (910 << 5) | 0x05, (861 << 5) | 0x17, (514 << 5) | 0x14, (690 << 5) | 0x14, (683 << 5) | 0x03, (662 << 5) | 0x15, | ||
293 | (690 << 5) | 0x14 | ||
294 | }; | ||
295 | |||
296 | static const s16 ana_fe_coeff_3seg[24] = { | ||
297 | 81, 80, 78, 74, 68, 61, 54, 45, 37, 28, 19, 11, 4, 1022, 1017, 1013, 1010, 1008, 1008, 1008, 1008, 1010, 1014, 1017 | ||
298 | }; | ||
299 | |||
300 | static const s16 ana_fe_coeff_1seg[24] = { | ||
301 | 249, 226, 164, 82, 5, 981, 970, 988, 1018, 20, 31, 26, 8, 1012, 1000, 1018, 1012, 8, 15, 14, 9, 3, 1017, 1003 | ||
302 | }; | ||
303 | |||
304 | static const s16 ana_fe_coeff_13seg[24] = { | ||
305 | 396, 305, 105, -51, -77, -12, 41, 31, -11, -30, -11, 14, 15, -2, -13, -7, 5, 8, 1, -6, -7, -3, 0, 1 | ||
306 | }; | ||
307 | |||
308 | static u16 fft_to_mode(struct dib8000_state *state) | ||
309 | { | ||
310 | u16 mode; | ||
311 | switch (state->fe[0]->dtv_property_cache.transmission_mode) { | ||
312 | case TRANSMISSION_MODE_2K: | ||
313 | mode = 1; | ||
314 | break; | ||
315 | case TRANSMISSION_MODE_4K: | ||
316 | mode = 2; | ||
317 | break; | ||
318 | default: | ||
319 | case TRANSMISSION_MODE_AUTO: | ||
320 | case TRANSMISSION_MODE_8K: | ||
321 | mode = 3; | ||
322 | break; | ||
323 | } | ||
324 | return mode; | ||
325 | } | ||
326 | |||
327 | static void dib8000_set_acquisition_mode(struct dib8000_state *state) | ||
328 | { | ||
329 | u16 nud = dib8000_read_word(state, 298); | ||
330 | nud |= (1 << 3) | (1 << 0); | ||
331 | dprintk("acquisition mode activated"); | ||
332 | dib8000_write_word(state, 298, nud); | ||
333 | } | ||
334 | static int dib8000_set_output_mode(struct dvb_frontend *fe, int mode) | ||
335 | { | ||
336 | struct dib8000_state *state = fe->demodulator_priv; | ||
337 | |||
338 | u16 outreg, fifo_threshold, smo_mode, sram = 0x0205; /* by default SDRAM deintlv is enabled */ | ||
339 | |||
340 | outreg = 0; | ||
341 | fifo_threshold = 1792; | ||
342 | smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1); | ||
343 | |||
344 | dprintk("-I- Setting output mode for demod %p to %d", | ||
345 | &state->fe[0], mode); | ||
346 | |||
347 | switch (mode) { | ||
348 | case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock | ||
349 | outreg = (1 << 10); /* 0x0400 */ | ||
350 | break; | ||
351 | case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock | ||
352 | outreg = (1 << 10) | (1 << 6); /* 0x0440 */ | ||
353 | break; | ||
354 | case OUTMODE_MPEG2_SERIAL: // STBs with serial input | ||
355 | outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */ | ||
356 | break; | ||
357 | case OUTMODE_DIVERSITY: | ||
358 | if (state->cfg.hostbus_diversity) { | ||
359 | outreg = (1 << 10) | (4 << 6); /* 0x0500 */ | ||
360 | sram &= 0xfdff; | ||
361 | } else | ||
362 | sram |= 0x0c00; | ||
363 | break; | ||
364 | case OUTMODE_MPEG2_FIFO: // e.g. USB feeding | ||
365 | smo_mode |= (3 << 1); | ||
366 | fifo_threshold = 512; | ||
367 | outreg = (1 << 10) | (5 << 6); | ||
368 | break; | ||
369 | case OUTMODE_HIGH_Z: // disable | ||
370 | outreg = 0; | ||
371 | break; | ||
372 | |||
373 | case OUTMODE_ANALOG_ADC: | ||
374 | outreg = (1 << 10) | (3 << 6); | ||
375 | dib8000_set_acquisition_mode(state); | ||
376 | break; | ||
377 | |||
378 | default: | ||
379 | dprintk("Unhandled output_mode passed to be set for demod %p", | ||
380 | &state->fe[0]); | ||
381 | return -EINVAL; | ||
382 | } | ||
383 | |||
384 | if (state->cfg.output_mpeg2_in_188_bytes) | ||
385 | smo_mode |= (1 << 5); | ||
386 | |||
387 | dib8000_write_word(state, 299, smo_mode); | ||
388 | dib8000_write_word(state, 300, fifo_threshold); /* synchronous fread */ | ||
389 | dib8000_write_word(state, 1286, outreg); | ||
390 | dib8000_write_word(state, 1291, sram); | ||
391 | |||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | static int dib8000_set_diversity_in(struct dvb_frontend *fe, int onoff) | ||
396 | { | ||
397 | struct dib8000_state *state = fe->demodulator_priv; | ||
398 | u16 sync_wait = dib8000_read_word(state, 273) & 0xfff0; | ||
399 | |||
400 | if (!state->differential_constellation) { | ||
401 | dib8000_write_word(state, 272, 1 << 9); //dvsy_off_lmod4 = 1 | ||
402 | dib8000_write_word(state, 273, sync_wait | (1 << 2) | 2); // sync_enable = 1; comb_mode = 2 | ||
403 | } else { | ||
404 | dib8000_write_word(state, 272, 0); //dvsy_off_lmod4 = 0 | ||
405 | dib8000_write_word(state, 273, sync_wait); // sync_enable = 0; comb_mode = 0 | ||
406 | } | ||
407 | state->diversity_onoff = onoff; | ||
408 | |||
409 | switch (onoff) { | ||
410 | case 0: /* only use the internal way - not the diversity input */ | ||
411 | dib8000_write_word(state, 270, 1); | ||
412 | dib8000_write_word(state, 271, 0); | ||
413 | break; | ||
414 | case 1: /* both ways */ | ||
415 | dib8000_write_word(state, 270, 6); | ||
416 | dib8000_write_word(state, 271, 6); | ||
417 | break; | ||
418 | case 2: /* only the diversity input */ | ||
419 | dib8000_write_word(state, 270, 0); | ||
420 | dib8000_write_word(state, 271, 1); | ||
421 | break; | ||
422 | } | ||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | static void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_power_mode mode) | ||
427 | { | ||
428 | /* by default everything is going to be powered off */ | ||
429 | u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0xffff, | ||
430 | reg_900 = (dib8000_read_word(state, 900) & 0xfffc) | 0x3, | ||
431 | reg_1280 = (dib8000_read_word(state, 1280) & 0x00ff) | 0xff00; | ||
432 | |||
433 | /* now, depending on the requested mode, we power on */ | ||
434 | switch (mode) { | ||
435 | /* power up everything in the demod */ | ||
436 | case DIB8000M_POWER_ALL: | ||
437 | reg_774 = 0x0000; | ||
438 | reg_775 = 0x0000; | ||
439 | reg_776 = 0x0000; | ||
440 | reg_900 &= 0xfffc; | ||
441 | reg_1280 &= 0x00ff; | ||
442 | break; | ||
443 | case DIB8000M_POWER_INTERFACE_ONLY: | ||
444 | reg_1280 &= 0x00ff; | ||
445 | break; | ||
446 | } | ||
447 | |||
448 | dprintk("powermode : 774 : %x ; 775 : %x; 776 : %x ; 900 : %x; 1280 : %x", reg_774, reg_775, reg_776, reg_900, reg_1280); | ||
449 | dib8000_write_word(state, 774, reg_774); | ||
450 | dib8000_write_word(state, 775, reg_775); | ||
451 | dib8000_write_word(state, 776, reg_776); | ||
452 | dib8000_write_word(state, 900, reg_900); | ||
453 | dib8000_write_word(state, 1280, reg_1280); | ||
454 | } | ||
455 | |||
456 | static int dib8000_set_adc_state(struct dib8000_state *state, enum dibx000_adc_states no) | ||
457 | { | ||
458 | int ret = 0; | ||
459 | u16 reg_907 = dib8000_read_word(state, 907), reg_908 = dib8000_read_word(state, 908); | ||
460 | |||
461 | switch (no) { | ||
462 | case DIBX000_SLOW_ADC_ON: | ||
463 | reg_908 |= (1 << 1) | (1 << 0); | ||
464 | ret |= dib8000_write_word(state, 908, reg_908); | ||
465 | reg_908 &= ~(1 << 1); | ||
466 | break; | ||
467 | |||
468 | case DIBX000_SLOW_ADC_OFF: | ||
469 | reg_908 |= (1 << 1) | (1 << 0); | ||
470 | break; | ||
471 | |||
472 | case DIBX000_ADC_ON: | ||
473 | reg_907 &= 0x0fff; | ||
474 | reg_908 &= 0x0003; | ||
475 | break; | ||
476 | |||
477 | case DIBX000_ADC_OFF: // leave the VBG voltage on | ||
478 | reg_907 |= (1 << 14) | (1 << 13) | (1 << 12); | ||
479 | reg_908 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2); | ||
480 | break; | ||
481 | |||
482 | case DIBX000_VBG_ENABLE: | ||
483 | reg_907 &= ~(1 << 15); | ||
484 | break; | ||
485 | |||
486 | case DIBX000_VBG_DISABLE: | ||
487 | reg_907 |= (1 << 15); | ||
488 | break; | ||
489 | |||
490 | default: | ||
491 | break; | ||
492 | } | ||
493 | |||
494 | ret |= dib8000_write_word(state, 907, reg_907); | ||
495 | ret |= dib8000_write_word(state, 908, reg_908); | ||
496 | |||
497 | return ret; | ||
498 | } | ||
499 | |||
500 | static int dib8000_set_bandwidth(struct dvb_frontend *fe, u32 bw) | ||
501 | { | ||
502 | struct dib8000_state *state = fe->demodulator_priv; | ||
503 | u32 timf; | ||
504 | |||
505 | if (bw == 0) | ||
506 | bw = 6000; | ||
507 | |||
508 | if (state->timf == 0) { | ||
509 | dprintk("using default timf"); | ||
510 | timf = state->timf_default; | ||
511 | } else { | ||
512 | dprintk("using updated timf"); | ||
513 | timf = state->timf; | ||
514 | } | ||
515 | |||
516 | dib8000_write_word(state, 29, (u16) ((timf >> 16) & 0xffff)); | ||
517 | dib8000_write_word(state, 30, (u16) ((timf) & 0xffff)); | ||
518 | |||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | static int dib8000_sad_calib(struct dib8000_state *state) | ||
523 | { | ||
524 | /* internal */ | ||
525 | dib8000_write_word(state, 923, (0 << 1) | (0 << 0)); | ||
526 | dib8000_write_word(state, 924, 776); // 0.625*3.3 / 4096 | ||
527 | |||
528 | /* do the calibration */ | ||
529 | dib8000_write_word(state, 923, (1 << 0)); | ||
530 | dib8000_write_word(state, 923, (0 << 0)); | ||
531 | |||
532 | msleep(1); | ||
533 | return 0; | ||
534 | } | ||
535 | |||
536 | int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value) | ||
537 | { | ||
538 | struct dib8000_state *state = fe->demodulator_priv; | ||
539 | if (value > 4095) | ||
540 | value = 4095; | ||
541 | state->wbd_ref = value; | ||
542 | return dib8000_write_word(state, 106, value); | ||
543 | } | ||
544 | |||
545 | EXPORT_SYMBOL(dib8000_set_wbd_ref); | ||
546 | static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw) | ||
547 | { | ||
548 | dprintk("ifreq: %d %x, inversion: %d", bw->ifreq, bw->ifreq, bw->ifreq >> 25); | ||
549 | dib8000_write_word(state, 23, (u16) (((bw->internal * 1000) >> 16) & 0xffff)); /* P_sec_len */ | ||
550 | dib8000_write_word(state, 24, (u16) ((bw->internal * 1000) & 0xffff)); | ||
551 | dib8000_write_word(state, 27, (u16) ((bw->ifreq >> 16) & 0x01ff)); | ||
552 | dib8000_write_word(state, 28, (u16) (bw->ifreq & 0xffff)); | ||
553 | dib8000_write_word(state, 26, (u16) ((bw->ifreq >> 25) & 0x0003)); | ||
554 | |||
555 | dib8000_write_word(state, 922, bw->sad_cfg); | ||
556 | } | ||
557 | |||
558 | static void dib8000_reset_pll(struct dib8000_state *state) | ||
559 | { | ||
560 | const struct dibx000_bandwidth_config *pll = state->cfg.pll; | ||
561 | u16 clk_cfg1; | ||
562 | |||
563 | // clk_cfg0 | ||
564 | dib8000_write_word(state, 901, (pll->pll_prediv << 8) | (pll->pll_ratio << 0)); | ||
565 | |||
566 | // clk_cfg1 | ||
567 | clk_cfg1 = (1 << 10) | (0 << 9) | (pll->IO_CLK_en_core << 8) | | ||
568 | (pll->bypclk_div << 5) | (pll->enable_refdiv << 4) | (1 << 3) | | ||
569 | (pll->pll_range << 1) | (pll->pll_reset << 0); | ||
570 | |||
571 | dib8000_write_word(state, 902, clk_cfg1); | ||
572 | clk_cfg1 = (clk_cfg1 & 0xfff7) | (pll->pll_bypass << 3); | ||
573 | dib8000_write_word(state, 902, clk_cfg1); | ||
574 | |||
575 | dprintk("clk_cfg1: 0x%04x", clk_cfg1); /* 0x507 1 0 1 000 0 0 11 1 */ | ||
576 | |||
577 | /* smpl_cfg: P_refclksel=2, P_ensmplsel=1 nodivsmpl=1 */ | ||
578 | if (state->cfg.pll->ADClkSrc == 0) | ||
579 | dib8000_write_word(state, 904, (0 << 15) | (0 << 12) | (0 << 10) | | ||
580 | (pll->modulo << 8) | (pll->ADClkSrc << 7) | (0 << 1)); | ||
581 | else if (state->cfg.refclksel != 0) | ||
582 | dib8000_write_word(state, 904, (0 << 15) | (1 << 12) | | ||
583 | ((state->cfg.refclksel & 0x3) << 10) | (pll->modulo << 8) | | ||
584 | (pll->ADClkSrc << 7) | (0 << 1)); | ||
585 | else | ||
586 | dib8000_write_word(state, 904, (0 << 15) | (1 << 12) | (3 << 10) | (pll->modulo << 8) | (pll->ADClkSrc << 7) | (0 << 1)); | ||
587 | |||
588 | dib8000_reset_pll_common(state, pll); | ||
589 | } | ||
590 | |||
591 | static int dib8000_reset_gpio(struct dib8000_state *st) | ||
592 | { | ||
593 | /* reset the GPIOs */ | ||
594 | dib8000_write_word(st, 1029, st->cfg.gpio_dir); | ||
595 | dib8000_write_word(st, 1030, st->cfg.gpio_val); | ||
596 | |||
597 | /* TODO 782 is P_gpio_od */ | ||
598 | |||
599 | dib8000_write_word(st, 1032, st->cfg.gpio_pwm_pos); | ||
600 | |||
601 | dib8000_write_word(st, 1037, st->cfg.pwm_freq_div); | ||
602 | return 0; | ||
603 | } | ||
604 | |||
605 | static int dib8000_cfg_gpio(struct dib8000_state *st, u8 num, u8 dir, u8 val) | ||
606 | { | ||
607 | st->cfg.gpio_dir = dib8000_read_word(st, 1029); | ||
608 | st->cfg.gpio_dir &= ~(1 << num); /* reset the direction bit */ | ||
609 | st->cfg.gpio_dir |= (dir & 0x1) << num; /* set the new direction */ | ||
610 | dib8000_write_word(st, 1029, st->cfg.gpio_dir); | ||
611 | |||
612 | st->cfg.gpio_val = dib8000_read_word(st, 1030); | ||
613 | st->cfg.gpio_val &= ~(1 << num); /* reset the direction bit */ | ||
614 | st->cfg.gpio_val |= (val & 0x01) << num; /* set the new value */ | ||
615 | dib8000_write_word(st, 1030, st->cfg.gpio_val); | ||
616 | |||
617 | dprintk("gpio dir: %x: gpio val: %x", st->cfg.gpio_dir, st->cfg.gpio_val); | ||
618 | |||
619 | return 0; | ||
620 | } | ||
621 | |||
622 | int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) | ||
623 | { | ||
624 | struct dib8000_state *state = fe->demodulator_priv; | ||
625 | return dib8000_cfg_gpio(state, num, dir, val); | ||
626 | } | ||
627 | |||
628 | EXPORT_SYMBOL(dib8000_set_gpio); | ||
629 | static const u16 dib8000_defaults[] = { | ||
630 | /* auto search configuration - lock0 by default waiting | ||
631 | * for cpil_lock; lock1 cpil_lock; lock2 tmcc_sync_lock */ | ||
632 | 3, 7, | ||
633 | 0x0004, | ||
634 | 0x0400, | ||
635 | 0x0814, | ||
636 | |||
637 | 12, 11, | ||
638 | 0x001b, | ||
639 | 0x7740, | ||
640 | 0x005b, | ||
641 | 0x8d80, | ||
642 | 0x01c9, | ||
643 | 0xc380, | ||
644 | 0x0000, | ||
645 | 0x0080, | ||
646 | 0x0000, | ||
647 | 0x0090, | ||
648 | 0x0001, | ||
649 | 0xd4c0, | ||
650 | |||
651 | /*1, 32, | ||
652 | 0x6680 // P_corm_thres Lock algorithms configuration */ | ||
653 | |||
654 | 11, 80, /* set ADC level to -16 */ | ||
655 | (1 << 13) - 825 - 117, | ||
656 | (1 << 13) - 837 - 117, | ||
657 | (1 << 13) - 811 - 117, | ||
658 | (1 << 13) - 766 - 117, | ||
659 | (1 << 13) - 737 - 117, | ||
660 | (1 << 13) - 693 - 117, | ||
661 | (1 << 13) - 648 - 117, | ||
662 | (1 << 13) - 619 - 117, | ||
663 | (1 << 13) - 575 - 117, | ||
664 | (1 << 13) - 531 - 117, | ||
665 | (1 << 13) - 501 - 117, | ||
666 | |||
667 | 4, 108, | ||
668 | 0, | ||
669 | 0, | ||
670 | 0, | ||
671 | 0, | ||
672 | |||
673 | 1, 175, | ||
674 | 0x0410, | ||
675 | 1, 179, | ||
676 | 8192, // P_fft_nb_to_cut | ||
677 | |||
678 | 6, 181, | ||
679 | 0x2800, // P_coff_corthres_ ( 2k 4k 8k ) 0x2800 | ||
680 | 0x2800, | ||
681 | 0x2800, | ||
682 | 0x2800, // P_coff_cpilthres_ ( 2k 4k 8k ) 0x2800 | ||
683 | 0x2800, | ||
684 | 0x2800, | ||
685 | |||
686 | 2, 193, | ||
687 | 0x0666, // P_pha3_thres | ||
688 | 0x0000, // P_cti_use_cpe, P_cti_use_prog | ||
689 | |||
690 | 2, 205, | ||
691 | 0x200f, // P_cspu_regul, P_cspu_win_cut | ||
692 | 0x000f, // P_des_shift_work | ||
693 | |||
694 | 5, 215, | ||
695 | 0x023d, // P_adp_regul_cnt | ||
696 | 0x00a4, // P_adp_noise_cnt | ||
697 | 0x00a4, // P_adp_regul_ext | ||
698 | 0x7ff0, // P_adp_noise_ext | ||
699 | 0x3ccc, // P_adp_fil | ||
700 | |||
701 | 1, 230, | ||
702 | 0x0000, // P_2d_byp_ti_num | ||
703 | |||
704 | 1, 263, | ||
705 | 0x800, //P_equal_thres_wgn | ||
706 | |||
707 | 1, 268, | ||
708 | (2 << 9) | 39, // P_equal_ctrl_synchro, P_equal_speedmode | ||
709 | |||
710 | 1, 270, | ||
711 | 0x0001, // P_div_lock0_wait | ||
712 | 1, 285, | ||
713 | 0x0020, //p_fec_ | ||
714 | 1, 299, | ||
715 | 0x0062, /* P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard */ | ||
716 | |||
717 | 1, 338, | ||
718 | (1 << 12) | // P_ctrl_corm_thres4pre_freq_inh=1 | ||
719 | (1 << 10) | | ||
720 | (0 << 9) | /* P_ctrl_pre_freq_inh=0 */ | ||
721 | (3 << 5) | /* P_ctrl_pre_freq_step=3 */ | ||
722 | (1 << 0), /* P_pre_freq_win_len=1 */ | ||
723 | |||
724 | 1, 903, | ||
725 | (0 << 4) | 2, // P_divclksel=0 P_divbitsel=2 (was clk=3,bit=1 for MPW) | ||
726 | |||
727 | 0, | ||
728 | }; | ||
729 | |||
730 | static u16 dib8000_identify(struct i2c_device *client) | ||
731 | { | ||
732 | u16 value; | ||
733 | |||
734 | //because of glitches sometimes | ||
735 | value = dib8000_i2c_read16(client, 896); | ||
736 | |||
737 | if ((value = dib8000_i2c_read16(client, 896)) != 0x01b3) { | ||
738 | dprintk("wrong Vendor ID (read=0x%x)", value); | ||
739 | return 0; | ||
740 | } | ||
741 | |||
742 | value = dib8000_i2c_read16(client, 897); | ||
743 | if (value != 0x8000 && value != 0x8001 && value != 0x8002) { | ||
744 | dprintk("wrong Device ID (%x)", value); | ||
745 | return 0; | ||
746 | } | ||
747 | |||
748 | switch (value) { | ||
749 | case 0x8000: | ||
750 | dprintk("found DiB8000A"); | ||
751 | break; | ||
752 | case 0x8001: | ||
753 | dprintk("found DiB8000B"); | ||
754 | break; | ||
755 | case 0x8002: | ||
756 | dprintk("found DiB8000C"); | ||
757 | break; | ||
758 | } | ||
759 | return value; | ||
760 | } | ||
761 | |||
762 | static int dib8000_reset(struct dvb_frontend *fe) | ||
763 | { | ||
764 | struct dib8000_state *state = fe->demodulator_priv; | ||
765 | |||
766 | dib8000_write_word(state, 1287, 0x0003); /* sram lead in, rdy */ | ||
767 | |||
768 | if ((state->revision = dib8000_identify(&state->i2c)) == 0) | ||
769 | return -EINVAL; | ||
770 | |||
771 | if (state->revision == 0x8000) | ||
772 | dprintk("error : dib8000 MA not supported"); | ||
773 | |||
774 | dibx000_reset_i2c_master(&state->i2c_master); | ||
775 | |||
776 | dib8000_set_power_mode(state, DIB8000M_POWER_ALL); | ||
777 | |||
778 | /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */ | ||
779 | dib8000_set_adc_state(state, DIBX000_VBG_ENABLE); | ||
780 | |||
781 | /* restart all parts */ | ||
782 | dib8000_write_word(state, 770, 0xffff); | ||
783 | dib8000_write_word(state, 771, 0xffff); | ||
784 | dib8000_write_word(state, 772, 0xfffc); | ||
785 | dib8000_write_word(state, 898, 0x000c); // sad | ||
786 | dib8000_write_word(state, 1280, 0x004d); | ||
787 | dib8000_write_word(state, 1281, 0x000c); | ||
788 | |||
789 | dib8000_write_word(state, 770, 0x0000); | ||
790 | dib8000_write_word(state, 771, 0x0000); | ||
791 | dib8000_write_word(state, 772, 0x0000); | ||
792 | dib8000_write_word(state, 898, 0x0004); // sad | ||
793 | dib8000_write_word(state, 1280, 0x0000); | ||
794 | dib8000_write_word(state, 1281, 0x0000); | ||
795 | |||
796 | /* drives */ | ||
797 | if (state->cfg.drives) | ||
798 | dib8000_write_word(state, 906, state->cfg.drives); | ||
799 | else { | ||
800 | dprintk("using standard PAD-drive-settings, please adjust settings in config-struct to be optimal."); | ||
801 | dib8000_write_word(state, 906, 0x2d98); // min drive SDRAM - not optimal - adjust | ||
802 | } | ||
803 | |||
804 | dib8000_reset_pll(state); | ||
805 | |||
806 | if (dib8000_reset_gpio(state) != 0) | ||
807 | dprintk("GPIO reset was not successful."); | ||
808 | |||
809 | if (dib8000_set_output_mode(fe, OUTMODE_HIGH_Z) != 0) | ||
810 | dprintk("OUTPUT_MODE could not be resetted."); | ||
811 | |||
812 | state->current_agc = NULL; | ||
813 | |||
814 | // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ... | ||
815 | /* P_iqc_ca2 = 0; P_iqc_impnc_on = 0; P_iqc_mode = 0; */ | ||
816 | if (state->cfg.pll->ifreq == 0) | ||
817 | dib8000_write_word(state, 40, 0x0755); /* P_iqc_corr_inh = 0 enable IQcorr block */ | ||
818 | else | ||
819 | dib8000_write_word(state, 40, 0x1f55); /* P_iqc_corr_inh = 1 disable IQcorr block */ | ||
820 | |||
821 | { | ||
822 | u16 l = 0, r; | ||
823 | const u16 *n; | ||
824 | n = dib8000_defaults; | ||
825 | l = *n++; | ||
826 | while (l) { | ||
827 | r = *n++; | ||
828 | do { | ||
829 | dib8000_write_word(state, r, *n++); | ||
830 | r++; | ||
831 | } while (--l); | ||
832 | l = *n++; | ||
833 | } | ||
834 | } | ||
835 | state->isdbt_cfg_loaded = 0; | ||
836 | |||
837 | //div_cfg override for special configs | ||
838 | if (state->cfg.div_cfg != 0) | ||
839 | dib8000_write_word(state, 903, state->cfg.div_cfg); | ||
840 | |||
841 | /* unforce divstr regardless whether i2c enumeration was done or not */ | ||
842 | dib8000_write_word(state, 1285, dib8000_read_word(state, 1285) & ~(1 << 1)); | ||
843 | |||
844 | dib8000_set_bandwidth(fe, 6000); | ||
845 | |||
846 | dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON); | ||
847 | dib8000_sad_calib(state); | ||
848 | dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF); | ||
849 | |||
850 | dib8000_set_power_mode(state, DIB8000M_POWER_INTERFACE_ONLY); | ||
851 | |||
852 | return 0; | ||
853 | } | ||
854 | |||
855 | static void dib8000_restart_agc(struct dib8000_state *state) | ||
856 | { | ||
857 | // P_restart_iqc & P_restart_agc | ||
858 | dib8000_write_word(state, 770, 0x0a00); | ||
859 | dib8000_write_word(state, 770, 0x0000); | ||
860 | } | ||
861 | |||
862 | static int dib8000_update_lna(struct dib8000_state *state) | ||
863 | { | ||
864 | u16 dyn_gain; | ||
865 | |||
866 | if (state->cfg.update_lna) { | ||
867 | // read dyn_gain here (because it is demod-dependent and not tuner) | ||
868 | dyn_gain = dib8000_read_word(state, 390); | ||
869 | |||
870 | if (state->cfg.update_lna(state->fe[0], dyn_gain)) { | ||
871 | dib8000_restart_agc(state); | ||
872 | return 1; | ||
873 | } | ||
874 | } | ||
875 | return 0; | ||
876 | } | ||
877 | |||
878 | static int dib8000_set_agc_config(struct dib8000_state *state, u8 band) | ||
879 | { | ||
880 | struct dibx000_agc_config *agc = NULL; | ||
881 | int i; | ||
882 | if (state->current_band == band && state->current_agc != NULL) | ||
883 | return 0; | ||
884 | state->current_band = band; | ||
885 | |||
886 | for (i = 0; i < state->cfg.agc_config_count; i++) | ||
887 | if (state->cfg.agc[i].band_caps & band) { | ||
888 | agc = &state->cfg.agc[i]; | ||
889 | break; | ||
890 | } | ||
891 | |||
892 | if (agc == NULL) { | ||
893 | dprintk("no valid AGC configuration found for band 0x%02x", band); | ||
894 | return -EINVAL; | ||
895 | } | ||
896 | |||
897 | state->current_agc = agc; | ||
898 | |||
899 | /* AGC */ | ||
900 | dib8000_write_word(state, 76, agc->setup); | ||
901 | dib8000_write_word(state, 77, agc->inv_gain); | ||
902 | dib8000_write_word(state, 78, agc->time_stabiliz); | ||
903 | dib8000_write_word(state, 101, (agc->alpha_level << 12) | agc->thlock); | ||
904 | |||
905 | // Demod AGC loop configuration | ||
906 | dib8000_write_word(state, 102, (agc->alpha_mant << 5) | agc->alpha_exp); | ||
907 | dib8000_write_word(state, 103, (agc->beta_mant << 6) | agc->beta_exp); | ||
908 | |||
909 | dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d", | ||
910 | state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); | ||
911 | |||
912 | /* AGC continued */ | ||
913 | if (state->wbd_ref != 0) | ||
914 | dib8000_write_word(state, 106, state->wbd_ref); | ||
915 | else // use default | ||
916 | dib8000_write_word(state, 106, agc->wbd_ref); | ||
917 | dib8000_write_word(state, 107, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8)); | ||
918 | dib8000_write_word(state, 108, agc->agc1_max); | ||
919 | dib8000_write_word(state, 109, agc->agc1_min); | ||
920 | dib8000_write_word(state, 110, agc->agc2_max); | ||
921 | dib8000_write_word(state, 111, agc->agc2_min); | ||
922 | dib8000_write_word(state, 112, (agc->agc1_pt1 << 8) | agc->agc1_pt2); | ||
923 | dib8000_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2); | ||
924 | dib8000_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2); | ||
925 | dib8000_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2); | ||
926 | |||
927 | dib8000_write_word(state, 75, agc->agc1_pt3); | ||
928 | dib8000_write_word(state, 923, (dib8000_read_word(state, 923) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); /*LB : 929 -> 923 */ | ||
929 | |||
930 | return 0; | ||
931 | } | ||
932 | |||
933 | void dib8000_pwm_agc_reset(struct dvb_frontend *fe) | ||
934 | { | ||
935 | struct dib8000_state *state = fe->demodulator_priv; | ||
936 | dib8000_set_adc_state(state, DIBX000_ADC_ON); | ||
937 | dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))); | ||
938 | } | ||
939 | EXPORT_SYMBOL(dib8000_pwm_agc_reset); | ||
940 | |||
941 | static int dib8000_agc_soft_split(struct dib8000_state *state) | ||
942 | { | ||
943 | u16 agc, split_offset; | ||
944 | |||
945 | if (!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0) | ||
946 | return FE_CALLBACK_TIME_NEVER; | ||
947 | |||
948 | // n_agc_global | ||
949 | agc = dib8000_read_word(state, 390); | ||
950 | |||
951 | if (agc > state->current_agc->split.min_thres) | ||
952 | split_offset = state->current_agc->split.min; | ||
953 | else if (agc < state->current_agc->split.max_thres) | ||
954 | split_offset = state->current_agc->split.max; | ||
955 | else | ||
956 | split_offset = state->current_agc->split.max * | ||
957 | (agc - state->current_agc->split.min_thres) / | ||
958 | (state->current_agc->split.max_thres - state->current_agc->split.min_thres); | ||
959 | |||
960 | dprintk("AGC split_offset: %d", split_offset); | ||
961 | |||
962 | // P_agc_force_split and P_agc_split_offset | ||
963 | dib8000_write_word(state, 107, (dib8000_read_word(state, 107) & 0xff00) | split_offset); | ||
964 | return 5000; | ||
965 | } | ||
966 | |||
967 | static int dib8000_agc_startup(struct dvb_frontend *fe) | ||
968 | { | ||
969 | struct dib8000_state *state = fe->demodulator_priv; | ||
970 | enum frontend_tune_state *tune_state = &state->tune_state; | ||
971 | |||
972 | int ret = 0; | ||
973 | |||
974 | switch (*tune_state) { | ||
975 | case CT_AGC_START: | ||
976 | // set power-up level: interf+analog+AGC | ||
977 | |||
978 | dib8000_set_adc_state(state, DIBX000_ADC_ON); | ||
979 | |||
980 | if (dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))) != 0) { | ||
981 | *tune_state = CT_AGC_STOP; | ||
982 | state->status = FE_STATUS_TUNE_FAILED; | ||
983 | break; | ||
984 | } | ||
985 | |||
986 | ret = 70; | ||
987 | *tune_state = CT_AGC_STEP_0; | ||
988 | break; | ||
989 | |||
990 | case CT_AGC_STEP_0: | ||
991 | //AGC initialization | ||
992 | if (state->cfg.agc_control) | ||
993 | state->cfg.agc_control(fe, 1); | ||
994 | |||
995 | dib8000_restart_agc(state); | ||
996 | |||
997 | // wait AGC rough lock time | ||
998 | ret = 50; | ||
999 | *tune_state = CT_AGC_STEP_1; | ||
1000 | break; | ||
1001 | |||
1002 | case CT_AGC_STEP_1: | ||
1003 | // wait AGC accurate lock time | ||
1004 | ret = 70; | ||
1005 | |||
1006 | if (dib8000_update_lna(state)) | ||
1007 | // wait only AGC rough lock time | ||
1008 | ret = 50; | ||
1009 | else | ||
1010 | *tune_state = CT_AGC_STEP_2; | ||
1011 | break; | ||
1012 | |||
1013 | case CT_AGC_STEP_2: | ||
1014 | dib8000_agc_soft_split(state); | ||
1015 | |||
1016 | if (state->cfg.agc_control) | ||
1017 | state->cfg.agc_control(fe, 0); | ||
1018 | |||
1019 | *tune_state = CT_AGC_STOP; | ||
1020 | break; | ||
1021 | default: | ||
1022 | ret = dib8000_agc_soft_split(state); | ||
1023 | break; | ||
1024 | } | ||
1025 | return ret; | ||
1026 | |||
1027 | } | ||
1028 | |||
1029 | static const s32 lut_1000ln_mant[] = | ||
1030 | { | ||
1031 | 908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600 | ||
1032 | }; | ||
1033 | |||
1034 | s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode) | ||
1035 | { | ||
1036 | struct dib8000_state *state = fe->demodulator_priv; | ||
1037 | u32 ix = 0, tmp_val = 0, exp = 0, mant = 0; | ||
1038 | s32 val; | ||
1039 | |||
1040 | val = dib8000_read32(state, 384); | ||
1041 | if (mode) { | ||
1042 | tmp_val = val; | ||
1043 | while (tmp_val >>= 1) | ||
1044 | exp++; | ||
1045 | mant = (val * 1000 / (1<<exp)); | ||
1046 | ix = (u8)((mant-1000)/100); /* index of the LUT */ | ||
1047 | val = (lut_1000ln_mant[ix] + 693*(exp-20) - 6908); | ||
1048 | val = (val*256)/1000; | ||
1049 | } | ||
1050 | return val; | ||
1051 | } | ||
1052 | EXPORT_SYMBOL(dib8000_get_adc_power); | ||
1053 | |||
1054 | static void dib8000_update_timf(struct dib8000_state *state) | ||
1055 | { | ||
1056 | u32 timf = state->timf = dib8000_read32(state, 435); | ||
1057 | |||
1058 | dib8000_write_word(state, 29, (u16) (timf >> 16)); | ||
1059 | dib8000_write_word(state, 30, (u16) (timf & 0xffff)); | ||
1060 | dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default); | ||
1061 | } | ||
1062 | |||
1063 | static const u16 adc_target_16dB[11] = { | ||
1064 | (1 << 13) - 825 - 117, | ||
1065 | (1 << 13) - 837 - 117, | ||
1066 | (1 << 13) - 811 - 117, | ||
1067 | (1 << 13) - 766 - 117, | ||
1068 | (1 << 13) - 737 - 117, | ||
1069 | (1 << 13) - 693 - 117, | ||
1070 | (1 << 13) - 648 - 117, | ||
1071 | (1 << 13) - 619 - 117, | ||
1072 | (1 << 13) - 575 - 117, | ||
1073 | (1 << 13) - 531 - 117, | ||
1074 | (1 << 13) - 501 - 117 | ||
1075 | }; | ||
1076 | static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 }; | ||
1077 | |||
1078 | static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosearching) | ||
1079 | { | ||
1080 | u16 mode, max_constellation, seg_diff_mask = 0, nbseg_diff = 0; | ||
1081 | u8 guard, crate, constellation, timeI; | ||
1082 | u16 i, coeff[4], P_cfr_left_edge = 0, P_cfr_right_edge = 0, seg_mask13 = 0x1fff; // All 13 segments enabled | ||
1083 | const s16 *ncoeff = NULL, *ana_fe; | ||
1084 | u16 tmcc_pow = 0; | ||
1085 | u16 coff_pow = 0x2800; | ||
1086 | u16 init_prbs = 0xfff; | ||
1087 | u16 ana_gain = 0; | ||
1088 | |||
1089 | if (state->ber_monitored_layer != LAYER_ALL) | ||
1090 | dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & 0x60) | state->ber_monitored_layer); | ||
1091 | else | ||
1092 | dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60); | ||
1093 | |||
1094 | i = dib8000_read_word(state, 26) & 1; // P_dds_invspec | ||
1095 | dib8000_write_word(state, 26, state->fe[0]->dtv_property_cache.inversion^i); | ||
1096 | |||
1097 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) { | ||
1098 | //compute new dds_freq for the seg and adjust prbs | ||
1099 | int seg_offset = | ||
1100 | state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx - | ||
1101 | (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) - | ||
1102 | (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2); | ||
1103 | int clk = state->cfg.pll->internal; | ||
1104 | u32 segtodds = ((u32) (430 << 23) / clk) << 3; // segtodds = SegBW / Fclk * pow(2,26) | ||
1105 | int dds_offset = seg_offset * segtodds; | ||
1106 | int new_dds, sub_channel; | ||
1107 | if ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) | ||
1108 | dds_offset -= (int)(segtodds / 2); | ||
1109 | |||
1110 | if (state->cfg.pll->ifreq == 0) { | ||
1111 | if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0) { | ||
1112 | dib8000_write_word(state, 26, dib8000_read_word(state, 26) | 1); | ||
1113 | new_dds = dds_offset; | ||
1114 | } else | ||
1115 | new_dds = dds_offset; | ||
1116 | |||
1117 | // We shift tuning frequency if the wanted segment is : | ||
1118 | // - the segment of center frequency with an odd total number of segments | ||
1119 | // - the segment to the left of center frequency with an even total number of segments | ||
1120 | // - the segment to the right of center frequency with an even total number of segments | ||
1121 | if ((state->fe[0]->dtv_property_cache.delivery_system == SYS_ISDBT) | ||
1122 | && (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) | ||
1123 | && (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) | ||
1124 | && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx == | ||
1125 | ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))) | ||
1126 | || (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) | ||
1127 | && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx == (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2))) | ||
1128 | || (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) | ||
1129 | && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx == | ||
1130 | ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))) | ||
1131 | )) { | ||
1132 | new_dds -= ((u32) (850 << 22) / clk) << 4; // new_dds = 850 (freq shift in KHz) / Fclk * pow(2,26) | ||
1133 | } | ||
1134 | } else { | ||
1135 | if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0) | ||
1136 | new_dds = state->cfg.pll->ifreq - dds_offset; | ||
1137 | else | ||
1138 | new_dds = state->cfg.pll->ifreq + dds_offset; | ||
1139 | } | ||
1140 | dib8000_write_word(state, 27, (u16) ((new_dds >> 16) & 0x01ff)); | ||
1141 | dib8000_write_word(state, 28, (u16) (new_dds & 0xffff)); | ||
1142 | if (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) | ||
1143 | sub_channel = ((state->fe[0]->dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset) + 1) % 41) / 3; | ||
1144 | else | ||
1145 | sub_channel = ((state->fe[0]->dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset)) % 41) / 3; | ||
1146 | sub_channel -= 6; | ||
1147 | |||
1148 | if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K | ||
1149 | || state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_4K) { | ||
1150 | dib8000_write_word(state, 219, dib8000_read_word(state, 219) | 0x1); //adp_pass =1 | ||
1151 | dib8000_write_word(state, 190, dib8000_read_word(state, 190) | (0x1 << 14)); //pha3_force_pha_shift = 1 | ||
1152 | } else { | ||
1153 | dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); //adp_pass =0 | ||
1154 | dib8000_write_word(state, 190, dib8000_read_word(state, 190) & 0xbfff); //pha3_force_pha_shift = 0 | ||
1155 | } | ||
1156 | |||
1157 | switch (state->fe[0]->dtv_property_cache.transmission_mode) { | ||
1158 | case TRANSMISSION_MODE_2K: | ||
1159 | switch (sub_channel) { | ||
1160 | case -6: | ||
1161 | init_prbs = 0x0; | ||
1162 | break; // 41, 0, 1 | ||
1163 | case -5: | ||
1164 | init_prbs = 0x423; | ||
1165 | break; // 02~04 | ||
1166 | case -4: | ||
1167 | init_prbs = 0x9; | ||
1168 | break; // 05~07 | ||
1169 | case -3: | ||
1170 | init_prbs = 0x5C7; | ||
1171 | break; // 08~10 | ||
1172 | case -2: | ||
1173 | init_prbs = 0x7A6; | ||
1174 | break; // 11~13 | ||
1175 | case -1: | ||
1176 | init_prbs = 0x3D8; | ||
1177 | break; // 14~16 | ||
1178 | case 0: | ||
1179 | init_prbs = 0x527; | ||
1180 | break; // 17~19 | ||
1181 | case 1: | ||
1182 | init_prbs = 0x7FF; | ||
1183 | break; // 20~22 | ||
1184 | case 2: | ||
1185 | init_prbs = 0x79B; | ||
1186 | break; // 23~25 | ||
1187 | case 3: | ||
1188 | init_prbs = 0x3D6; | ||
1189 | break; // 26~28 | ||
1190 | case 4: | ||
1191 | init_prbs = 0x3A2; | ||
1192 | break; // 29~31 | ||
1193 | case 5: | ||
1194 | init_prbs = 0x53B; | ||
1195 | break; // 32~34 | ||
1196 | case 6: | ||
1197 | init_prbs = 0x2F4; | ||
1198 | break; // 35~37 | ||
1199 | default: | ||
1200 | case 7: | ||
1201 | init_prbs = 0x213; | ||
1202 | break; // 38~40 | ||
1203 | } | ||
1204 | break; | ||
1205 | |||
1206 | case TRANSMISSION_MODE_4K: | ||
1207 | switch (sub_channel) { | ||
1208 | case -6: | ||
1209 | init_prbs = 0x0; | ||
1210 | break; // 41, 0, 1 | ||
1211 | case -5: | ||
1212 | init_prbs = 0x208; | ||
1213 | break; // 02~04 | ||
1214 | case -4: | ||
1215 | init_prbs = 0xC3; | ||
1216 | break; // 05~07 | ||
1217 | case -3: | ||
1218 | init_prbs = 0x7B9; | ||
1219 | break; // 08~10 | ||
1220 | case -2: | ||
1221 | init_prbs = 0x423; | ||
1222 | break; // 11~13 | ||
1223 | case -1: | ||
1224 | init_prbs = 0x5C7; | ||
1225 | break; // 14~16 | ||
1226 | case 0: | ||
1227 | init_prbs = 0x3D8; | ||
1228 | break; // 17~19 | ||
1229 | case 1: | ||
1230 | init_prbs = 0x7FF; | ||
1231 | break; // 20~22 | ||
1232 | case 2: | ||
1233 | init_prbs = 0x3D6; | ||
1234 | break; // 23~25 | ||
1235 | case 3: | ||
1236 | init_prbs = 0x53B; | ||
1237 | break; // 26~28 | ||
1238 | case 4: | ||
1239 | init_prbs = 0x213; | ||
1240 | break; // 29~31 | ||
1241 | case 5: | ||
1242 | init_prbs = 0x29; | ||
1243 | break; // 32~34 | ||
1244 | case 6: | ||
1245 | init_prbs = 0xD0; | ||
1246 | break; // 35~37 | ||
1247 | default: | ||
1248 | case 7: | ||
1249 | init_prbs = 0x48E; | ||
1250 | break; // 38~40 | ||
1251 | } | ||
1252 | break; | ||
1253 | |||
1254 | default: | ||
1255 | case TRANSMISSION_MODE_8K: | ||
1256 | switch (sub_channel) { | ||
1257 | case -6: | ||
1258 | init_prbs = 0x0; | ||
1259 | break; // 41, 0, 1 | ||
1260 | case -5: | ||
1261 | init_prbs = 0x740; | ||
1262 | break; // 02~04 | ||
1263 | case -4: | ||
1264 | init_prbs = 0x069; | ||
1265 | break; // 05~07 | ||
1266 | case -3: | ||
1267 | init_prbs = 0x7DD; | ||
1268 | break; // 08~10 | ||
1269 | case -2: | ||
1270 | init_prbs = 0x208; | ||
1271 | break; // 11~13 | ||
1272 | case -1: | ||
1273 | init_prbs = 0x7B9; | ||
1274 | break; // 14~16 | ||
1275 | case 0: | ||
1276 | init_prbs = 0x5C7; | ||
1277 | break; // 17~19 | ||
1278 | case 1: | ||
1279 | init_prbs = 0x7FF; | ||
1280 | break; // 20~22 | ||
1281 | case 2: | ||
1282 | init_prbs = 0x53B; | ||
1283 | break; // 23~25 | ||
1284 | case 3: | ||
1285 | init_prbs = 0x29; | ||
1286 | break; // 26~28 | ||
1287 | case 4: | ||
1288 | init_prbs = 0x48E; | ||
1289 | break; // 29~31 | ||
1290 | case 5: | ||
1291 | init_prbs = 0x4C4; | ||
1292 | break; // 32~34 | ||
1293 | case 6: | ||
1294 | init_prbs = 0x367; | ||
1295 | break; // 33~37 | ||
1296 | default: | ||
1297 | case 7: | ||
1298 | init_prbs = 0x684; | ||
1299 | break; // 38~40 | ||
1300 | } | ||
1301 | break; | ||
1302 | } | ||
1303 | } else { | ||
1304 | dib8000_write_word(state, 27, (u16) ((state->cfg.pll->ifreq >> 16) & 0x01ff)); | ||
1305 | dib8000_write_word(state, 28, (u16) (state->cfg.pll->ifreq & 0xffff)); | ||
1306 | dib8000_write_word(state, 26, (u16) ((state->cfg.pll->ifreq >> 25) & 0x0003)); | ||
1307 | } | ||
1308 | /*P_mode == ?? */ | ||
1309 | dib8000_write_word(state, 10, (seq << 4)); | ||
1310 | // dib8000_write_word(state, 287, (dib8000_read_word(state, 287) & 0xe000) | 0x1000); | ||
1311 | |||
1312 | switch (state->fe[0]->dtv_property_cache.guard_interval) { | ||
1313 | case GUARD_INTERVAL_1_32: | ||
1314 | guard = 0; | ||
1315 | break; | ||
1316 | case GUARD_INTERVAL_1_16: | ||
1317 | guard = 1; | ||
1318 | break; | ||
1319 | case GUARD_INTERVAL_1_8: | ||
1320 | guard = 2; | ||
1321 | break; | ||
1322 | case GUARD_INTERVAL_1_4: | ||
1323 | default: | ||
1324 | guard = 3; | ||
1325 | break; | ||
1326 | } | ||
1327 | |||
1328 | dib8000_write_word(state, 1, (init_prbs << 2) | (guard & 0x3)); // ADDR 1 | ||
1329 | |||
1330 | max_constellation = DQPSK; | ||
1331 | for (i = 0; i < 3; i++) { | ||
1332 | switch (state->fe[0]->dtv_property_cache.layer[i].modulation) { | ||
1333 | case DQPSK: | ||
1334 | constellation = 0; | ||
1335 | break; | ||
1336 | case QPSK: | ||
1337 | constellation = 1; | ||
1338 | break; | ||
1339 | case QAM_16: | ||
1340 | constellation = 2; | ||
1341 | break; | ||
1342 | case QAM_64: | ||
1343 | default: | ||
1344 | constellation = 3; | ||
1345 | break; | ||
1346 | } | ||
1347 | |||
1348 | switch (state->fe[0]->dtv_property_cache.layer[i].fec) { | ||
1349 | case FEC_1_2: | ||
1350 | crate = 1; | ||
1351 | break; | ||
1352 | case FEC_2_3: | ||
1353 | crate = 2; | ||
1354 | break; | ||
1355 | case FEC_3_4: | ||
1356 | crate = 3; | ||
1357 | break; | ||
1358 | case FEC_5_6: | ||
1359 | crate = 5; | ||
1360 | break; | ||
1361 | case FEC_7_8: | ||
1362 | default: | ||
1363 | crate = 7; | ||
1364 | break; | ||
1365 | } | ||
1366 | |||
1367 | if ((state->fe[0]->dtv_property_cache.layer[i].interleaving > 0) && | ||
1368 | ((state->fe[0]->dtv_property_cache.layer[i].interleaving <= 3) || | ||
1369 | (state->fe[0]->dtv_property_cache.layer[i].interleaving == 4 && state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1)) | ||
1370 | ) | ||
1371 | timeI = state->fe[0]->dtv_property_cache.layer[i].interleaving; | ||
1372 | else | ||
1373 | timeI = 0; | ||
1374 | dib8000_write_word(state, 2 + i, (constellation << 10) | ((state->fe[0]->dtv_property_cache.layer[i].segment_count & 0xf) << 6) | | ||
1375 | (crate << 3) | timeI); | ||
1376 | if (state->fe[0]->dtv_property_cache.layer[i].segment_count > 0) { | ||
1377 | switch (max_constellation) { | ||
1378 | case DQPSK: | ||
1379 | case QPSK: | ||
1380 | if (state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_16 || | ||
1381 | state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_64) | ||
1382 | max_constellation = state->fe[0]->dtv_property_cache.layer[i].modulation; | ||
1383 | break; | ||
1384 | case QAM_16: | ||
1385 | if (state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_64) | ||
1386 | max_constellation = state->fe[0]->dtv_property_cache.layer[i].modulation; | ||
1387 | break; | ||
1388 | } | ||
1389 | } | ||
1390 | } | ||
1391 | |||
1392 | mode = fft_to_mode(state); | ||
1393 | |||
1394 | //dib8000_write_word(state, 5, 13); /*p_last_seg = 13*/ | ||
1395 | |||
1396 | dib8000_write_word(state, 274, (dib8000_read_word(state, 274) & 0xffcf) | | ||
1397 | ((state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 5) | ((state->fe[0]->dtv_property_cache. | ||
1398 | isdbt_sb_mode & 1) << 4)); | ||
1399 | |||
1400 | dprintk("mode = %d ; guard = %d", mode, state->fe[0]->dtv_property_cache.guard_interval); | ||
1401 | |||
1402 | /* signal optimization parameter */ | ||
1403 | |||
1404 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception) { | ||
1405 | seg_diff_mask = (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) << permu_seg[0]; | ||
1406 | for (i = 1; i < 3; i++) | ||
1407 | nbseg_diff += | ||
1408 | (state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count; | ||
1409 | for (i = 0; i < nbseg_diff; i++) | ||
1410 | seg_diff_mask |= 1 << permu_seg[i + 1]; | ||
1411 | } else { | ||
1412 | for (i = 0; i < 3; i++) | ||
1413 | nbseg_diff += | ||
1414 | (state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count; | ||
1415 | for (i = 0; i < nbseg_diff; i++) | ||
1416 | seg_diff_mask |= 1 << permu_seg[i]; | ||
1417 | } | ||
1418 | dprintk("nbseg_diff = %X (%d)", seg_diff_mask, seg_diff_mask); | ||
1419 | |||
1420 | state->differential_constellation = (seg_diff_mask != 0); | ||
1421 | dib8000_set_diversity_in(state->fe[0], state->diversity_onoff); | ||
1422 | |||
1423 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | ||
1424 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1) | ||
1425 | seg_mask13 = 0x00E0; | ||
1426 | else // 1-segment | ||
1427 | seg_mask13 = 0x0040; | ||
1428 | } else | ||
1429 | seg_mask13 = 0x1fff; | ||
1430 | |||
1431 | // WRITE: Mode & Diff mask | ||
1432 | dib8000_write_word(state, 0, (mode << 13) | seg_diff_mask); | ||
1433 | |||
1434 | if ((seg_diff_mask) || (state->fe[0]->dtv_property_cache.isdbt_sb_mode)) | ||
1435 | dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200); | ||
1436 | else | ||
1437 | dib8000_write_word(state, 268, (2 << 9) | 39); //init value | ||
1438 | |||
1439 | // ---- SMALL ---- | ||
1440 | // P_small_seg_diff | ||
1441 | dib8000_write_word(state, 352, seg_diff_mask); // ADDR 352 | ||
1442 | |||
1443 | dib8000_write_word(state, 353, seg_mask13); // ADDR 353 | ||
1444 | |||
1445 | /* // P_small_narrow_band=0, P_small_last_seg=13, P_small_offset_num_car=5 */ | ||
1446 | |||
1447 | // ---- SMALL ---- | ||
1448 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | ||
1449 | switch (state->fe[0]->dtv_property_cache.transmission_mode) { | ||
1450 | case TRANSMISSION_MODE_2K: | ||
1451 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { | ||
1452 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) | ||
1453 | ncoeff = coeff_2k_sb_1seg_dqpsk; | ||
1454 | else // QPSK or QAM | ||
1455 | ncoeff = coeff_2k_sb_1seg; | ||
1456 | } else { // 3-segments | ||
1457 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { | ||
1458 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) | ||
1459 | ncoeff = coeff_2k_sb_3seg_0dqpsk_1dqpsk; | ||
1460 | else // QPSK or QAM on external segments | ||
1461 | ncoeff = coeff_2k_sb_3seg_0dqpsk; | ||
1462 | } else { // QPSK or QAM on central segment | ||
1463 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) | ||
1464 | ncoeff = coeff_2k_sb_3seg_1dqpsk; | ||
1465 | else // QPSK or QAM on external segments | ||
1466 | ncoeff = coeff_2k_sb_3seg; | ||
1467 | } | ||
1468 | } | ||
1469 | break; | ||
1470 | |||
1471 | case TRANSMISSION_MODE_4K: | ||
1472 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { | ||
1473 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) | ||
1474 | ncoeff = coeff_4k_sb_1seg_dqpsk; | ||
1475 | else // QPSK or QAM | ||
1476 | ncoeff = coeff_4k_sb_1seg; | ||
1477 | } else { // 3-segments | ||
1478 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { | ||
1479 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) { | ||
1480 | ncoeff = coeff_4k_sb_3seg_0dqpsk_1dqpsk; | ||
1481 | } else { // QPSK or QAM on external segments | ||
1482 | ncoeff = coeff_4k_sb_3seg_0dqpsk; | ||
1483 | } | ||
1484 | } else { // QPSK or QAM on central segment | ||
1485 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) { | ||
1486 | ncoeff = coeff_4k_sb_3seg_1dqpsk; | ||
1487 | } else // QPSK or QAM on external segments | ||
1488 | ncoeff = coeff_4k_sb_3seg; | ||
1489 | } | ||
1490 | } | ||
1491 | break; | ||
1492 | |||
1493 | case TRANSMISSION_MODE_AUTO: | ||
1494 | case TRANSMISSION_MODE_8K: | ||
1495 | default: | ||
1496 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { | ||
1497 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) | ||
1498 | ncoeff = coeff_8k_sb_1seg_dqpsk; | ||
1499 | else // QPSK or QAM | ||
1500 | ncoeff = coeff_8k_sb_1seg; | ||
1501 | } else { // 3-segments | ||
1502 | if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { | ||
1503 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) { | ||
1504 | ncoeff = coeff_8k_sb_3seg_0dqpsk_1dqpsk; | ||
1505 | } else { // QPSK or QAM on external segments | ||
1506 | ncoeff = coeff_8k_sb_3seg_0dqpsk; | ||
1507 | } | ||
1508 | } else { // QPSK or QAM on central segment | ||
1509 | if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) { | ||
1510 | ncoeff = coeff_8k_sb_3seg_1dqpsk; | ||
1511 | } else // QPSK or QAM on external segments | ||
1512 | ncoeff = coeff_8k_sb_3seg; | ||
1513 | } | ||
1514 | } | ||
1515 | break; | ||
1516 | } | ||
1517 | for (i = 0; i < 8; i++) | ||
1518 | dib8000_write_word(state, 343 + i, ncoeff[i]); | ||
1519 | } | ||
1520 | |||
1521 | // P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5 | ||
1522 | dib8000_write_word(state, 351, | ||
1523 | (state->fe[0]->dtv_property_cache.isdbt_sb_mode << 9) | (state->fe[0]->dtv_property_cache.isdbt_sb_mode << 8) | (13 << 4) | 5); | ||
1524 | |||
1525 | // ---- COFF ---- | ||
1526 | // Carloff, the most robust | ||
1527 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | ||
1528 | |||
1529 | // P_coff_cpil_alpha=4, P_coff_inh=0, P_coff_cpil_winlen=64 | ||
1530 | // 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 | ||
1531 | dib8000_write_word(state, 187, | ||
1532 | (4 << 12) | (0 << 11) | (63 << 5) | (0x3 << 3) | ((~state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 2) | ||
1533 | | 0x3); | ||
1534 | |||
1535 | /* // P_small_coef_ext_enable = 1 */ | ||
1536 | /* dib8000_write_word(state, 351, dib8000_read_word(state, 351) | 0x200); */ | ||
1537 | |||
1538 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { | ||
1539 | |||
1540 | // 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) | ||
1541 | if (mode == 3) | ||
1542 | dib8000_write_word(state, 180, 0x1fcf | ((mode - 1) << 14)); | ||
1543 | else | ||
1544 | dib8000_write_word(state, 180, 0x0fcf | ((mode - 1) << 14)); | ||
1545 | // P_ctrl_corm_thres4pre_freq_inh=1,P_ctrl_pre_freq_mode_sat=1, | ||
1546 | // P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 5, P_pre_freq_win_len=4 | ||
1547 | dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (5 << 5) | 4); | ||
1548 | // P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8 | ||
1549 | dib8000_write_word(state, 340, (16 << 6) | (8 << 0)); | ||
1550 | // P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1 | ||
1551 | dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); | ||
1552 | |||
1553 | // P_coff_corthres_8k, 4k, 2k and P_coff_cpilthres_8k, 4k, 2k | ||
1554 | dib8000_write_word(state, 181, 300); | ||
1555 | dib8000_write_word(state, 182, 150); | ||
1556 | dib8000_write_word(state, 183, 80); | ||
1557 | dib8000_write_word(state, 184, 300); | ||
1558 | dib8000_write_word(state, 185, 150); | ||
1559 | dib8000_write_word(state, 186, 80); | ||
1560 | } else { // Sound Broadcasting mode 3 seg | ||
1561 | // P_coff_one_seg_sym= 1, P_coff_one_seg_width= 1, P_coff_winlen=63, P_coff_thres_lock=15 | ||
1562 | /* if (mode == 3) */ | ||
1563 | /* dib8000_write_word(state, 180, 0x2fca | ((0) << 14)); */ | ||
1564 | /* else */ | ||
1565 | /* dib8000_write_word(state, 180, 0x2fca | ((1) << 14)); */ | ||
1566 | dib8000_write_word(state, 180, 0x1fcf | (1 << 14)); | ||
1567 | |||
1568 | // P_ctrl_corm_thres4pre_freq_inh = 1, P_ctrl_pre_freq_mode_sat=1, | ||
1569 | // P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 4, P_pre_freq_win_len=4 | ||
1570 | dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (4 << 5) | 4); | ||
1571 | // P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8 | ||
1572 | dib8000_write_word(state, 340, (16 << 6) | (8 << 0)); | ||
1573 | //P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1 | ||
1574 | dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); | ||
1575 | |||
1576 | // P_coff_corthres_8k, 4k, 2k and P_coff_cpilthres_8k, 4k, 2k | ||
1577 | dib8000_write_word(state, 181, 350); | ||
1578 | dib8000_write_word(state, 182, 300); | ||
1579 | dib8000_write_word(state, 183, 250); | ||
1580 | dib8000_write_word(state, 184, 350); | ||
1581 | dib8000_write_word(state, 185, 300); | ||
1582 | dib8000_write_word(state, 186, 250); | ||
1583 | } | ||
1584 | |||
1585 | } else if (state->isdbt_cfg_loaded == 0) { // if not Sound Broadcasting mode : put default values for 13 segments | ||
1586 | dib8000_write_word(state, 180, (16 << 6) | 9); | ||
1587 | dib8000_write_word(state, 187, (4 << 12) | (8 << 5) | 0x2); | ||
1588 | coff_pow = 0x2800; | ||
1589 | for (i = 0; i < 6; i++) | ||
1590 | dib8000_write_word(state, 181 + i, coff_pow); | ||
1591 | |||
1592 | // P_ctrl_corm_thres4pre_freq_inh=1, P_ctrl_pre_freq_mode_sat=1, | ||
1593 | // 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 | ||
1594 | dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (3 << 5) | 1); | ||
1595 | |||
1596 | // P_ctrl_pre_freq_win_len=8, P_ctrl_pre_freq_thres_lockin=6 | ||
1597 | dib8000_write_word(state, 340, (8 << 6) | (6 << 0)); | ||
1598 | // P_ctrl_pre_freq_thres_lockout=4, P_small_use_tmcc/ac/cp=1 | ||
1599 | dib8000_write_word(state, 341, (4 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); | ||
1600 | } | ||
1601 | // ---- FFT ---- | ||
1602 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1 && state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) | ||
1603 | dib8000_write_word(state, 178, 64); // P_fft_powrange=64 | ||
1604 | else | ||
1605 | dib8000_write_word(state, 178, 32); // P_fft_powrange=32 | ||
1606 | |||
1607 | /* make the cpil_coff_lock more robust but slower p_coff_winlen | ||
1608 | * 6bits; p_coff_thres_lock 6bits (for coff lock if needed) | ||
1609 | */ | ||
1610 | /* if ( ( nbseg_diff>0)&&(nbseg_diff<13)) | ||
1611 | dib8000_write_word(state, 187, (dib8000_read_word(state, 187) & 0xfffb) | (1 << 3)); */ | ||
1612 | |||
1613 | dib8000_write_word(state, 189, ~seg_mask13 | seg_diff_mask); /* P_lmod4_seg_inh */ | ||
1614 | dib8000_write_word(state, 192, ~seg_mask13 | seg_diff_mask); /* P_pha3_seg_inh */ | ||
1615 | dib8000_write_word(state, 225, ~seg_mask13 | seg_diff_mask); /* P_tac_seg_inh */ | ||
1616 | if ((!state->fe[0]->dtv_property_cache.isdbt_sb_mode) && (state->cfg.pll->ifreq == 0)) | ||
1617 | dib8000_write_word(state, 266, ~seg_mask13 | seg_diff_mask | 0x40); /* P_equal_noise_seg_inh */ | ||
1618 | else | ||
1619 | dib8000_write_word(state, 266, ~seg_mask13 | seg_diff_mask); /* P_equal_noise_seg_inh */ | ||
1620 | dib8000_write_word(state, 287, ~seg_mask13 | 0x1000); /* P_tmcc_seg_inh */ | ||
1621 | //dib8000_write_word(state, 288, ~seg_mask13 | seg_diff_mask); /* P_tmcc_seg_eq_inh */ | ||
1622 | if (!autosearching) | ||
1623 | dib8000_write_word(state, 288, (~seg_mask13 | seg_diff_mask) & 0x1fff); /* P_tmcc_seg_eq_inh */ | ||
1624 | else | ||
1625 | dib8000_write_word(state, 288, 0x1fff); //disable equalisation of the tmcc when autosearch to be able to find the DQPSK channels. | ||
1626 | dprintk("287 = %X (%d)", ~seg_mask13 | 0x1000, ~seg_mask13 | 0x1000); | ||
1627 | |||
1628 | dib8000_write_word(state, 211, seg_mask13 & (~seg_diff_mask)); /* P_des_seg_enabled */ | ||
1629 | |||
1630 | /* offset loop parameters */ | ||
1631 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | ||
1632 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) | ||
1633 | /* P_timf_alpha = (11-P_mode), P_corm_alpha=6, P_corm_thres=0x80 */ | ||
1634 | dib8000_write_word(state, 32, ((11 - mode) << 12) | (6 << 8) | 0x40); | ||
1635 | |||
1636 | else // Sound Broadcasting mode 3 seg | ||
1637 | /* P_timf_alpha = (10-P_mode), P_corm_alpha=6, P_corm_thres=0x80 */ | ||
1638 | dib8000_write_word(state, 32, ((10 - mode) << 12) | (6 << 8) | 0x60); | ||
1639 | } else | ||
1640 | // TODO in 13 seg, timf_alpha can always be the same or not ? | ||
1641 | /* P_timf_alpha = (9-P_mode, P_corm_alpha=6, P_corm_thres=0x80 */ | ||
1642 | dib8000_write_word(state, 32, ((9 - mode) << 12) | (6 << 8) | 0x80); | ||
1643 | |||
1644 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | ||
1645 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) | ||
1646 | /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (11-P_mode) */ | ||
1647 | dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (10 - mode)); | ||
1648 | |||
1649 | else // Sound Broadcasting mode 3 seg | ||
1650 | /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (10-P_mode) */ | ||
1651 | dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (9 - mode)); | ||
1652 | } else | ||
1653 | /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = 9 */ | ||
1654 | dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (8 - mode)); | ||
1655 | |||
1656 | /* P_dvsy_sync_wait - reuse mode */ | ||
1657 | switch (state->fe[0]->dtv_property_cache.transmission_mode) { | ||
1658 | case TRANSMISSION_MODE_8K: | ||
1659 | mode = 256; | ||
1660 | break; | ||
1661 | case TRANSMISSION_MODE_4K: | ||
1662 | mode = 128; | ||
1663 | break; | ||
1664 | default: | ||
1665 | case TRANSMISSION_MODE_2K: | ||
1666 | mode = 64; | ||
1667 | break; | ||
1668 | } | ||
1669 | if (state->cfg.diversity_delay == 0) | ||
1670 | mode = (mode * (1 << (guard)) * 3) / 2 + 48; // add 50% SFN margin + compensate for one DVSY-fifo | ||
1671 | else | ||
1672 | mode = (mode * (1 << (guard)) * 3) / 2 + state->cfg.diversity_delay; // add 50% SFN margin + compensate for DVSY-fifo | ||
1673 | mode <<= 4; | ||
1674 | dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | mode); | ||
1675 | |||
1676 | /* channel estimation fine configuration */ | ||
1677 | switch (max_constellation) { | ||
1678 | case QAM_64: | ||
1679 | ana_gain = 0x7; // -1 : avoid def_est saturation when ADC target is -16dB | ||
1680 | coeff[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ | ||
1681 | coeff[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ | ||
1682 | coeff[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | ||
1683 | coeff[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ | ||
1684 | //if (!state->cfg.hostbus_diversity) //if diversity, we should prehaps use the configuration of the max_constallation -1 | ||
1685 | break; | ||
1686 | case QAM_16: | ||
1687 | ana_gain = 0x7; // -1 : avoid def_est saturation when ADC target is -16dB | ||
1688 | coeff[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ | ||
1689 | coeff[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ | ||
1690 | coeff[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | ||
1691 | coeff[3] = 0xfff0; /* P_adp_noise_ext -0.002 */ | ||
1692 | //if (!((state->cfg.hostbus_diversity) && (max_constellation == QAM_16))) | ||
1693 | break; | ||
1694 | default: | ||
1695 | ana_gain = 0; // 0 : goes along with ADC target at -22dB to keep good mobile performance and lock at sensitivity level | ||
1696 | coeff[0] = 0x099a; /* P_adp_regul_cnt 0.3 */ | ||
1697 | coeff[1] = 0xffae; /* P_adp_noise_cnt -0.01 */ | ||
1698 | coeff[2] = 0x0333; /* P_adp_regul_ext 0.1 */ | ||
1699 | coeff[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ | ||
1700 | break; | ||
1701 | } | ||
1702 | for (mode = 0; mode < 4; mode++) | ||
1703 | dib8000_write_word(state, 215 + mode, coeff[mode]); | ||
1704 | |||
1705 | // update ana_gain depending on max constellation | ||
1706 | dib8000_write_word(state, 116, ana_gain); | ||
1707 | // update ADC target depending on ana_gain | ||
1708 | if (ana_gain) { // set -16dB ADC target for ana_gain=-1 | ||
1709 | for (i = 0; i < 10; i++) | ||
1710 | dib8000_write_word(state, 80 + i, adc_target_16dB[i]); | ||
1711 | } else { // set -22dB ADC target for ana_gain=0 | ||
1712 | for (i = 0; i < 10; i++) | ||
1713 | dib8000_write_word(state, 80 + i, adc_target_16dB[i] - 355); | ||
1714 | } | ||
1715 | |||
1716 | // ---- ANA_FE ---- | ||
1717 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) { | ||
1718 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1) | ||
1719 | ana_fe = ana_fe_coeff_3seg; | ||
1720 | else // 1-segment | ||
1721 | ana_fe = ana_fe_coeff_1seg; | ||
1722 | } else | ||
1723 | ana_fe = ana_fe_coeff_13seg; | ||
1724 | |||
1725 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1 || state->isdbt_cfg_loaded == 0) | ||
1726 | for (mode = 0; mode < 24; mode++) | ||
1727 | dib8000_write_word(state, 117 + mode, ana_fe[mode]); | ||
1728 | |||
1729 | // ---- CHAN_BLK ---- | ||
1730 | for (i = 0; i < 13; i++) { | ||
1731 | if ((((~seg_diff_mask) >> i) & 1) == 1) { | ||
1732 | P_cfr_left_edge += (1 << i) * ((i == 0) || ((((seg_mask13 & (~seg_diff_mask)) >> (i - 1)) & 1) == 0)); | ||
1733 | P_cfr_right_edge += (1 << i) * ((i == 12) || ((((seg_mask13 & (~seg_diff_mask)) >> (i + 1)) & 1) == 0)); | ||
1734 | } | ||
1735 | } | ||
1736 | dib8000_write_word(state, 222, P_cfr_left_edge); // P_cfr_left_edge | ||
1737 | dib8000_write_word(state, 223, P_cfr_right_edge); // P_cfr_right_edge | ||
1738 | // "P_cspu_left_edge" not used => do not care | ||
1739 | // "P_cspu_right_edge" not used => do not care | ||
1740 | |||
1741 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | ||
1742 | dib8000_write_word(state, 228, 1); // P_2d_mode_byp=1 | ||
1743 | dib8000_write_word(state, 205, dib8000_read_word(state, 205) & 0xfff0); // P_cspu_win_cut = 0 | ||
1744 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0 | ||
1745 | && state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K) { | ||
1746 | //dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); // P_adp_pass = 0 | ||
1747 | dib8000_write_word(state, 265, 15); // P_equal_noise_sel = 15 | ||
1748 | } | ||
1749 | } else if (state->isdbt_cfg_loaded == 0) { | ||
1750 | dib8000_write_word(state, 228, 0); // default value | ||
1751 | dib8000_write_word(state, 265, 31); // default value | ||
1752 | dib8000_write_word(state, 205, 0x200f); // init value | ||
1753 | } | ||
1754 | // ---- TMCC ---- | ||
1755 | for (i = 0; i < 3; i++) | ||
1756 | tmcc_pow += | ||
1757 | (((state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * 4 + 1) * state->fe[0]->dtv_property_cache.layer[i].segment_count); | ||
1758 | // Quantif of "P_tmcc_dec_thres_?k" is (0, 5+mode, 9); | ||
1759 | // Threshold is set at 1/4 of max power. | ||
1760 | tmcc_pow *= (1 << (9 - 2)); | ||
1761 | |||
1762 | dib8000_write_word(state, 290, tmcc_pow); // P_tmcc_dec_thres_2k | ||
1763 | dib8000_write_word(state, 291, tmcc_pow); // P_tmcc_dec_thres_4k | ||
1764 | dib8000_write_word(state, 292, tmcc_pow); // P_tmcc_dec_thres_8k | ||
1765 | //dib8000_write_word(state, 287, (1 << 13) | 0x1000 ); | ||
1766 | // ---- PHA3 ---- | ||
1767 | |||
1768 | if (state->isdbt_cfg_loaded == 0) | ||
1769 | dib8000_write_word(state, 250, 3285); /*p_2d_hspeed_thr0 */ | ||
1770 | |||
1771 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) | ||
1772 | state->isdbt_cfg_loaded = 0; | ||
1773 | else | ||
1774 | state->isdbt_cfg_loaded = 1; | ||
1775 | |||
1776 | } | ||
1777 | |||
1778 | static int dib8000_autosearch_start(struct dvb_frontend *fe) | ||
1779 | { | ||
1780 | u8 factor; | ||
1781 | u32 value; | ||
1782 | struct dib8000_state *state = fe->demodulator_priv; | ||
1783 | |||
1784 | int slist = 0; | ||
1785 | |||
1786 | state->fe[0]->dtv_property_cache.inversion = 0; | ||
1787 | if (!state->fe[0]->dtv_property_cache.isdbt_sb_mode) | ||
1788 | state->fe[0]->dtv_property_cache.layer[0].segment_count = 13; | ||
1789 | state->fe[0]->dtv_property_cache.layer[0].modulation = QAM_64; | ||
1790 | state->fe[0]->dtv_property_cache.layer[0].fec = FEC_2_3; | ||
1791 | state->fe[0]->dtv_property_cache.layer[0].interleaving = 0; | ||
1792 | |||
1793 | //choose the right list, in sb, always do everything | ||
1794 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) { | ||
1795 | state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; | ||
1796 | state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; | ||
1797 | slist = 7; | ||
1798 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); | ||
1799 | } else { | ||
1800 | if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) { | ||
1801 | if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) { | ||
1802 | slist = 7; | ||
1803 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); // P_mode = 1 to have autosearch start ok with mode2 | ||
1804 | } else | ||
1805 | slist = 3; | ||
1806 | } else { | ||
1807 | if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) { | ||
1808 | slist = 2; | ||
1809 | dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); // P_mode = 1 | ||
1810 | } else | ||
1811 | slist = 0; | ||
1812 | } | ||
1813 | |||
1814 | if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) | ||
1815 | state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; | ||
1816 | if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) | ||
1817 | state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; | ||
1818 | |||
1819 | dprintk("using list for autosearch : %d", slist); | ||
1820 | dib8000_set_channel(state, (unsigned char)slist, 1); | ||
1821 | //dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); // P_mode = 1 | ||
1822 | |||
1823 | factor = 1; | ||
1824 | |||
1825 | //set lock_mask values | ||
1826 | dib8000_write_word(state, 6, 0x4); | ||
1827 | dib8000_write_word(state, 7, 0x8); | ||
1828 | dib8000_write_word(state, 8, 0x1000); | ||
1829 | |||
1830 | //set lock_mask wait time values | ||
1831 | value = 50 * state->cfg.pll->internal * factor; | ||
1832 | dib8000_write_word(state, 11, (u16) ((value >> 16) & 0xffff)); // lock0 wait time | ||
1833 | dib8000_write_word(state, 12, (u16) (value & 0xffff)); // lock0 wait time | ||
1834 | value = 100 * state->cfg.pll->internal * factor; | ||
1835 | dib8000_write_word(state, 13, (u16) ((value >> 16) & 0xffff)); // lock1 wait time | ||
1836 | dib8000_write_word(state, 14, (u16) (value & 0xffff)); // lock1 wait time | ||
1837 | value = 1000 * state->cfg.pll->internal * factor; | ||
1838 | dib8000_write_word(state, 15, (u16) ((value >> 16) & 0xffff)); // lock2 wait time | ||
1839 | dib8000_write_word(state, 16, (u16) (value & 0xffff)); // lock2 wait time | ||
1840 | |||
1841 | value = dib8000_read_word(state, 0); | ||
1842 | dib8000_write_word(state, 0, (u16) ((1 << 15) | value)); | ||
1843 | dib8000_read_word(state, 1284); // reset the INT. n_irq_pending | ||
1844 | dib8000_write_word(state, 0, (u16) value); | ||
1845 | |||
1846 | } | ||
1847 | |||
1848 | return 0; | ||
1849 | } | ||
1850 | |||
1851 | static int dib8000_autosearch_irq(struct dvb_frontend *fe) | ||
1852 | { | ||
1853 | struct dib8000_state *state = fe->demodulator_priv; | ||
1854 | u16 irq_pending = dib8000_read_word(state, 1284); | ||
1855 | |||
1856 | if (irq_pending & 0x1) { // failed | ||
1857 | dprintk("dib8000_autosearch_irq failed"); | ||
1858 | return 1; | ||
1859 | } | ||
1860 | |||
1861 | if (irq_pending & 0x2) { // succeeded | ||
1862 | dprintk("dib8000_autosearch_irq succeeded"); | ||
1863 | return 2; | ||
1864 | } | ||
1865 | |||
1866 | return 0; // still pending | ||
1867 | } | ||
1868 | |||
1869 | static int dib8000_tune(struct dvb_frontend *fe) | ||
1870 | { | ||
1871 | struct dib8000_state *state = fe->demodulator_priv; | ||
1872 | int ret = 0; | ||
1873 | u16 value, mode = fft_to_mode(state); | ||
1874 | |||
1875 | // we are already tuned - just resuming from suspend | ||
1876 | if (state == NULL) | ||
1877 | return -EINVAL; | ||
1878 | |||
1879 | dib8000_set_bandwidth(fe, state->fe[0]->dtv_property_cache.bandwidth_hz / 1000); | ||
1880 | dib8000_set_channel(state, 0, 0); | ||
1881 | |||
1882 | // restart demod | ||
1883 | ret |= dib8000_write_word(state, 770, 0x4000); | ||
1884 | ret |= dib8000_write_word(state, 770, 0x0000); | ||
1885 | msleep(45); | ||
1886 | |||
1887 | /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3 */ | ||
1888 | /* ret |= dib8000_write_word(state, 29, (0 << 9) | (4 << 5) | (0 << 4) | (3 << 0) ); workaround inh_isi stays at 1 */ | ||
1889 | |||
1890 | // never achieved a lock before - wait for timfreq to update | ||
1891 | if (state->timf == 0) { | ||
1892 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | ||
1893 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) | ||
1894 | msleep(300); | ||
1895 | else // Sound Broadcasting mode 3 seg | ||
1896 | msleep(500); | ||
1897 | } else // 13 seg | ||
1898 | msleep(200); | ||
1899 | } | ||
1900 | if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { | ||
1901 | if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { | ||
1902 | |||
1903 | /* P_timf_alpha = (13-P_mode) , P_corm_alpha=6, P_corm_thres=0x40 alpha to check on board */ | ||
1904 | dib8000_write_word(state, 32, ((13 - mode) << 12) | (6 << 8) | 0x40); | ||
1905 | //dib8000_write_word(state, 32, (8 << 12) | (6 << 8) | 0x80); | ||
1906 | |||
1907 | /* P_ctrl_sfreq_step= (12-P_mode) P_ctrl_sfreq_inh =0 P_ctrl_pha_off_max */ | ||
1908 | ret |= dib8000_write_word(state, 37, (12 - mode) | ((5 + mode) << 5)); | ||
1909 | |||
1910 | } else { // Sound Broadcasting mode 3 seg | ||
1911 | |||
1912 | /* P_timf_alpha = (12-P_mode) , P_corm_alpha=6, P_corm_thres=0x60 alpha to check on board */ | ||
1913 | dib8000_write_word(state, 32, ((12 - mode) << 12) | (6 << 8) | 0x60); | ||
1914 | |||
1915 | ret |= dib8000_write_word(state, 37, (11 - mode) | ((5 + mode) << 5)); | ||
1916 | } | ||
1917 | |||
1918 | } else { // 13 seg | ||
1919 | /* P_timf_alpha = 8 , P_corm_alpha=6, P_corm_thres=0x80 alpha to check on board */ | ||
1920 | dib8000_write_word(state, 32, ((11 - mode) << 12) | (6 << 8) | 0x80); | ||
1921 | |||
1922 | ret |= dib8000_write_word(state, 37, (10 - mode) | ((5 + mode) << 5)); | ||
1923 | |||
1924 | } | ||
1925 | |||
1926 | // we achieved a coff_cpil_lock - it's time to update the timf | ||
1927 | if ((dib8000_read_word(state, 568) >> 11) & 0x1) | ||
1928 | dib8000_update_timf(state); | ||
1929 | |||
1930 | //now that tune is finished, lock0 should lock on fec_mpeg to output this lock on MP_LOCK. It's changed in autosearch start | ||
1931 | dib8000_write_word(state, 6, 0x200); | ||
1932 | |||
1933 | if (state->revision == 0x8002) { | ||
1934 | value = dib8000_read_word(state, 903); | ||
1935 | dib8000_write_word(state, 903, value & ~(1 << 3)); | ||
1936 | msleep(1); | ||
1937 | dib8000_write_word(state, 903, value | (1 << 3)); | ||
1938 | } | ||
1939 | |||
1940 | return ret; | ||
1941 | } | ||
1942 | |||
1943 | static int dib8000_wakeup(struct dvb_frontend *fe) | ||
1944 | { | ||
1945 | struct dib8000_state *state = fe->demodulator_priv; | ||
1946 | u8 index_frontend; | ||
1947 | int ret; | ||
1948 | |||
1949 | dib8000_set_power_mode(state, DIB8000M_POWER_ALL); | ||
1950 | dib8000_set_adc_state(state, DIBX000_ADC_ON); | ||
1951 | if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0) | ||
1952 | dprintk("could not start Slow ADC"); | ||
1953 | |||
1954 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
1955 | ret = state->fe[index_frontend]->ops.init(state->fe[index_frontend]); | ||
1956 | if (ret < 0) | ||
1957 | return ret; | ||
1958 | } | ||
1959 | |||
1960 | return 0; | ||
1961 | } | ||
1962 | |||
1963 | static int dib8000_sleep(struct dvb_frontend *fe) | ||
1964 | { | ||
1965 | struct dib8000_state *state = fe->demodulator_priv; | ||
1966 | u8 index_frontend; | ||
1967 | int ret; | ||
1968 | |||
1969 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
1970 | ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]); | ||
1971 | if (ret < 0) | ||
1972 | return ret; | ||
1973 | } | ||
1974 | |||
1975 | dib8000_set_output_mode(fe, OUTMODE_HIGH_Z); | ||
1976 | dib8000_set_power_mode(state, DIB8000M_POWER_INTERFACE_ONLY); | ||
1977 | return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF); | ||
1978 | } | ||
1979 | |||
1980 | enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe) | ||
1981 | { | ||
1982 | struct dib8000_state *state = fe->demodulator_priv; | ||
1983 | return state->tune_state; | ||
1984 | } | ||
1985 | EXPORT_SYMBOL(dib8000_get_tune_state); | ||
1986 | |||
1987 | int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) | ||
1988 | { | ||
1989 | struct dib8000_state *state = fe->demodulator_priv; | ||
1990 | state->tune_state = tune_state; | ||
1991 | return 0; | ||
1992 | } | ||
1993 | EXPORT_SYMBOL(dib8000_set_tune_state); | ||
1994 | |||
1995 | static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) | ||
1996 | { | ||
1997 | struct dib8000_state *state = fe->demodulator_priv; | ||
1998 | u16 i, val = 0; | ||
1999 | fe_status_t stat; | ||
2000 | u8 index_frontend, sub_index_frontend; | ||
2001 | |||
2002 | fe->dtv_property_cache.bandwidth_hz = 6000000; | ||
2003 | |||
2004 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
2005 | state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat); | ||
2006 | if (stat&FE_HAS_SYNC) { | ||
2007 | dprintk("TMCC lock on the slave%i", index_frontend); | ||
2008 | /* synchronize the cache with the other frontends */ | ||
2009 | state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], fep); | ||
2010 | for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) { | ||
2011 | if (sub_index_frontend != index_frontend) { | ||
2012 | state->fe[sub_index_frontend]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode; | ||
2013 | state->fe[sub_index_frontend]->dtv_property_cache.inversion = state->fe[index_frontend]->dtv_property_cache.inversion; | ||
2014 | state->fe[sub_index_frontend]->dtv_property_cache.transmission_mode = state->fe[index_frontend]->dtv_property_cache.transmission_mode; | ||
2015 | state->fe[sub_index_frontend]->dtv_property_cache.guard_interval = state->fe[index_frontend]->dtv_property_cache.guard_interval; | ||
2016 | state->fe[sub_index_frontend]->dtv_property_cache.isdbt_partial_reception = state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception; | ||
2017 | for (i = 0; i < 3; i++) { | ||
2018 | state->fe[sub_index_frontend]->dtv_property_cache.layer[i].segment_count = state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count; | ||
2019 | state->fe[sub_index_frontend]->dtv_property_cache.layer[i].interleaving = state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving; | ||
2020 | state->fe[sub_index_frontend]->dtv_property_cache.layer[i].fec = state->fe[index_frontend]->dtv_property_cache.layer[i].fec; | ||
2021 | state->fe[sub_index_frontend]->dtv_property_cache.layer[i].modulation = state->fe[index_frontend]->dtv_property_cache.layer[i].modulation; | ||
2022 | } | ||
2023 | } | ||
2024 | } | ||
2025 | return 0; | ||
2026 | } | ||
2027 | } | ||
2028 | |||
2029 | fe->dtv_property_cache.isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1; | ||
2030 | |||
2031 | val = dib8000_read_word(state, 570); | ||
2032 | fe->dtv_property_cache.inversion = (val & 0x40) >> 6; | ||
2033 | switch ((val & 0x30) >> 4) { | ||
2034 | case 1: | ||
2035 | fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K; | ||
2036 | break; | ||
2037 | case 3: | ||
2038 | default: | ||
2039 | fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; | ||
2040 | break; | ||
2041 | } | ||
2042 | |||
2043 | switch (val & 0x3) { | ||
2044 | case 0: | ||
2045 | fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32; | ||
2046 | dprintk("dib8000_get_frontend GI = 1/32 "); | ||
2047 | break; | ||
2048 | case 1: | ||
2049 | fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16; | ||
2050 | dprintk("dib8000_get_frontend GI = 1/16 "); | ||
2051 | break; | ||
2052 | case 2: | ||
2053 | dprintk("dib8000_get_frontend GI = 1/8 "); | ||
2054 | fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; | ||
2055 | break; | ||
2056 | case 3: | ||
2057 | dprintk("dib8000_get_frontend GI = 1/4 "); | ||
2058 | fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4; | ||
2059 | break; | ||
2060 | } | ||
2061 | |||
2062 | val = dib8000_read_word(state, 505); | ||
2063 | fe->dtv_property_cache.isdbt_partial_reception = val & 1; | ||
2064 | dprintk("dib8000_get_frontend : partial_reception = %d ", fe->dtv_property_cache.isdbt_partial_reception); | ||
2065 | |||
2066 | for (i = 0; i < 3; i++) { | ||
2067 | val = dib8000_read_word(state, 493 + i); | ||
2068 | fe->dtv_property_cache.layer[i].segment_count = val & 0x0F; | ||
2069 | dprintk("dib8000_get_frontend : Layer %d segments = %d ", i, fe->dtv_property_cache.layer[i].segment_count); | ||
2070 | |||
2071 | val = dib8000_read_word(state, 499 + i); | ||
2072 | fe->dtv_property_cache.layer[i].interleaving = val & 0x3; | ||
2073 | dprintk("dib8000_get_frontend : Layer %d time_intlv = %d ", i, fe->dtv_property_cache.layer[i].interleaving); | ||
2074 | |||
2075 | val = dib8000_read_word(state, 481 + i); | ||
2076 | switch (val & 0x7) { | ||
2077 | case 1: | ||
2078 | fe->dtv_property_cache.layer[i].fec = FEC_1_2; | ||
2079 | dprintk("dib8000_get_frontend : Layer %d Code Rate = 1/2 ", i); | ||
2080 | break; | ||
2081 | case 2: | ||
2082 | fe->dtv_property_cache.layer[i].fec = FEC_2_3; | ||
2083 | dprintk("dib8000_get_frontend : Layer %d Code Rate = 2/3 ", i); | ||
2084 | break; | ||
2085 | case 3: | ||
2086 | fe->dtv_property_cache.layer[i].fec = FEC_3_4; | ||
2087 | dprintk("dib8000_get_frontend : Layer %d Code Rate = 3/4 ", i); | ||
2088 | break; | ||
2089 | case 5: | ||
2090 | fe->dtv_property_cache.layer[i].fec = FEC_5_6; | ||
2091 | dprintk("dib8000_get_frontend : Layer %d Code Rate = 5/6 ", i); | ||
2092 | break; | ||
2093 | default: | ||
2094 | fe->dtv_property_cache.layer[i].fec = FEC_7_8; | ||
2095 | dprintk("dib8000_get_frontend : Layer %d Code Rate = 7/8 ", i); | ||
2096 | break; | ||
2097 | } | ||
2098 | |||
2099 | val = dib8000_read_word(state, 487 + i); | ||
2100 | switch (val & 0x3) { | ||
2101 | case 0: | ||
2102 | dprintk("dib8000_get_frontend : Layer %d DQPSK ", i); | ||
2103 | fe->dtv_property_cache.layer[i].modulation = DQPSK; | ||
2104 | break; | ||
2105 | case 1: | ||
2106 | fe->dtv_property_cache.layer[i].modulation = QPSK; | ||
2107 | dprintk("dib8000_get_frontend : Layer %d QPSK ", i); | ||
2108 | break; | ||
2109 | case 2: | ||
2110 | fe->dtv_property_cache.layer[i].modulation = QAM_16; | ||
2111 | dprintk("dib8000_get_frontend : Layer %d QAM16 ", i); | ||
2112 | break; | ||
2113 | case 3: | ||
2114 | default: | ||
2115 | dprintk("dib8000_get_frontend : Layer %d QAM64 ", i); | ||
2116 | fe->dtv_property_cache.layer[i].modulation = QAM_64; | ||
2117 | break; | ||
2118 | } | ||
2119 | } | ||
2120 | |||
2121 | /* synchronize the cache with the other frontends */ | ||
2122 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
2123 | state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode = fe->dtv_property_cache.isdbt_sb_mode; | ||
2124 | state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion; | ||
2125 | state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode; | ||
2126 | state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval; | ||
2127 | state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception = fe->dtv_property_cache.isdbt_partial_reception; | ||
2128 | for (i = 0; i < 3; i++) { | ||
2129 | state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count = fe->dtv_property_cache.layer[i].segment_count; | ||
2130 | state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving = fe->dtv_property_cache.layer[i].interleaving; | ||
2131 | state->fe[index_frontend]->dtv_property_cache.layer[i].fec = fe->dtv_property_cache.layer[i].fec; | ||
2132 | state->fe[index_frontend]->dtv_property_cache.layer[i].modulation = fe->dtv_property_cache.layer[i].modulation; | ||
2133 | } | ||
2134 | } | ||
2135 | return 0; | ||
2136 | } | ||
2137 | |||
2138 | static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) | ||
2139 | { | ||
2140 | struct dib8000_state *state = fe->demodulator_priv; | ||
2141 | u8 nbr_pending, exit_condition, index_frontend; | ||
2142 | s8 index_frontend_success = -1; | ||
2143 | int time, ret; | ||
2144 | int time_slave = FE_CALLBACK_TIME_NEVER; | ||
2145 | |||
2146 | if (state->fe[0]->dtv_property_cache.frequency == 0) { | ||
2147 | dprintk("dib8000: must at least specify frequency "); | ||
2148 | return 0; | ||
2149 | } | ||
2150 | |||
2151 | if (state->fe[0]->dtv_property_cache.bandwidth_hz == 0) { | ||
2152 | dprintk("dib8000: no bandwidth specified, set to default "); | ||
2153 | state->fe[0]->dtv_property_cache.bandwidth_hz = 6000000; | ||
2154 | } | ||
2155 | |||
2156 | for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
2157 | /* synchronization of the cache */ | ||
2158 | state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_ISDBT; | ||
2159 | memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties)); | ||
2160 | |||
2161 | dib8000_set_output_mode(state->fe[index_frontend], OUTMODE_HIGH_Z); | ||
2162 | if (state->fe[index_frontend]->ops.tuner_ops.set_params) | ||
2163 | state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend], fep); | ||
2164 | |||
2165 | dib8000_set_tune_state(state->fe[index_frontend], CT_AGC_START); | ||
2166 | } | ||
2167 | |||
2168 | /* start up the AGC */ | ||
2169 | do { | ||
2170 | time = dib8000_agc_startup(state->fe[0]); | ||
2171 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
2172 | time_slave = dib8000_agc_startup(state->fe[index_frontend]); | ||
2173 | if (time == FE_CALLBACK_TIME_NEVER) | ||
2174 | time = time_slave; | ||
2175 | else if ((time_slave != FE_CALLBACK_TIME_NEVER) && (time_slave > time)) | ||
2176 | time = time_slave; | ||
2177 | } | ||
2178 | if (time != FE_CALLBACK_TIME_NEVER) | ||
2179 | msleep(time / 10); | ||
2180 | else | ||
2181 | break; | ||
2182 | exit_condition = 1; | ||
2183 | for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
2184 | if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_AGC_STOP) { | ||
2185 | exit_condition = 0; | ||
2186 | break; | ||
2187 | } | ||
2188 | } | ||
2189 | } while (exit_condition == 0); | ||
2190 | |||
2191 | for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) | ||
2192 | dib8000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START); | ||
2193 | |||
2194 | if ((state->fe[0]->dtv_property_cache.delivery_system != SYS_ISDBT) || | ||
2195 | (state->fe[0]->dtv_property_cache.inversion == INVERSION_AUTO) || | ||
2196 | (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) || | ||
2197 | (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) || | ||
2198 | (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) != 0) && | ||
2199 | (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0xff) && | ||
2200 | (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0) && | ||
2201 | ((state->fe[0]->dtv_property_cache.layer[0].modulation == QAM_AUTO) || | ||
2202 | (state->fe[0]->dtv_property_cache.layer[0].fec == FEC_AUTO))) || | ||
2203 | (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 1)) != 0) && | ||
2204 | (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0xff) && | ||
2205 | (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0) && | ||
2206 | ((state->fe[0]->dtv_property_cache.layer[1].modulation == QAM_AUTO) || | ||
2207 | (state->fe[0]->dtv_property_cache.layer[1].fec == FEC_AUTO))) || | ||
2208 | (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 2)) != 0) && | ||
2209 | (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0xff) && | ||
2210 | (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0) && | ||
2211 | ((state->fe[0]->dtv_property_cache.layer[2].modulation == QAM_AUTO) || | ||
2212 | (state->fe[0]->dtv_property_cache.layer[2].fec == FEC_AUTO))) || | ||
2213 | (((state->fe[0]->dtv_property_cache.layer[0].segment_count == 0) || | ||
2214 | ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) == 0)) && | ||
2215 | ((state->fe[0]->dtv_property_cache.layer[1].segment_count == 0) || | ||
2216 | ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (2 << 0)) == 0)) && | ||
2217 | ((state->fe[0]->dtv_property_cache.layer[2].segment_count == 0) || ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (3 << 0)) == 0)))) { | ||
2218 | int i = 80000; | ||
2219 | u8 found = 0; | ||
2220 | u8 tune_failed = 0; | ||
2221 | |||
2222 | for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
2223 | dib8000_set_bandwidth(state->fe[index_frontend], fe->dtv_property_cache.bandwidth_hz / 1000); | ||
2224 | dib8000_autosearch_start(state->fe[index_frontend]); | ||
2225 | } | ||
2226 | |||
2227 | do { | ||
2228 | msleep(20); | ||
2229 | nbr_pending = 0; | ||
2230 | exit_condition = 0; /* 0: tune pending; 1: tune failed; 2:tune success */ | ||
2231 | for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
2232 | if (((tune_failed >> index_frontend) & 0x1) == 0) { | ||
2233 | found = dib8000_autosearch_irq(state->fe[index_frontend]); | ||
2234 | switch (found) { | ||
2235 | case 0: /* tune pending */ | ||
2236 | nbr_pending++; | ||
2237 | break; | ||
2238 | case 2: | ||
2239 | dprintk("autosearch succeed on the frontend%i", index_frontend); | ||
2240 | exit_condition = 2; | ||
2241 | index_frontend_success = index_frontend; | ||
2242 | break; | ||
2243 | default: | ||
2244 | dprintk("unhandled autosearch result"); | ||
2245 | case 1: | ||
2246 | dprintk("autosearch failed for the frontend%i", index_frontend); | ||
2247 | break; | ||
2248 | } | ||
2249 | } | ||
2250 | } | ||
2251 | |||
2252 | /* if all tune are done and no success, exit: tune failed */ | ||
2253 | if ((nbr_pending == 0) && (exit_condition == 0)) | ||
2254 | exit_condition = 1; | ||
2255 | } while ((exit_condition == 0) && i--); | ||
2256 | |||
2257 | if (exit_condition == 1) { /* tune failed */ | ||
2258 | dprintk("tune failed"); | ||
2259 | return 0; | ||
2260 | } | ||
2261 | |||
2262 | dprintk("tune success on frontend%i", index_frontend_success); | ||
2263 | |||
2264 | dib8000_get_frontend(fe, fep); | ||
2265 | } | ||
2266 | |||
2267 | for (index_frontend = 0, ret = 0; (ret >= 0) && (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) | ||
2268 | ret = dib8000_tune(state->fe[index_frontend]); | ||
2269 | |||
2270 | /* set output mode and diversity input */ | ||
2271 | dib8000_set_output_mode(state->fe[0], state->cfg.output_mode); | ||
2272 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
2273 | dib8000_set_output_mode(state->fe[index_frontend], OUTMODE_DIVERSITY); | ||
2274 | dib8000_set_diversity_in(state->fe[index_frontend-1], 1); | ||
2275 | } | ||
2276 | |||
2277 | /* turn off the diversity of the last chip */ | ||
2278 | dib8000_set_diversity_in(state->fe[index_frontend-1], 0); | ||
2279 | |||
2280 | return ret; | ||
2281 | } | ||
2282 | |||
2283 | static u16 dib8000_read_lock(struct dvb_frontend *fe) | ||
2284 | { | ||
2285 | struct dib8000_state *state = fe->demodulator_priv; | ||
2286 | |||
2287 | return dib8000_read_word(state, 568); | ||
2288 | } | ||
2289 | |||
2290 | static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat) | ||
2291 | { | ||
2292 | struct dib8000_state *state = fe->demodulator_priv; | ||
2293 | u16 lock_slave = 0, lock = dib8000_read_word(state, 568); | ||
2294 | u8 index_frontend; | ||
2295 | |||
2296 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) | ||
2297 | lock_slave |= dib8000_read_lock(state->fe[index_frontend]); | ||
2298 | |||
2299 | *stat = 0; | ||
2300 | |||
2301 | if (((lock >> 13) & 1) || ((lock_slave >> 13) & 1)) | ||
2302 | *stat |= FE_HAS_SIGNAL; | ||
2303 | |||
2304 | if (((lock >> 8) & 1) || ((lock_slave >> 8) & 1)) /* Equal */ | ||
2305 | *stat |= FE_HAS_CARRIER; | ||
2306 | |||
2307 | if ((((lock >> 1) & 0xf) == 0xf) || (((lock_slave >> 1) & 0xf) == 0xf)) /* TMCC_SYNC */ | ||
2308 | *stat |= FE_HAS_SYNC; | ||
2309 | |||
2310 | if ((((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) && ((lock >> 5) & 7)) /* FEC MPEG */ | ||
2311 | *stat |= FE_HAS_LOCK; | ||
2312 | |||
2313 | if (((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) { | ||
2314 | lock = dib8000_read_word(state, 554); /* Viterbi Layer A */ | ||
2315 | if (lock & 0x01) | ||
2316 | *stat |= FE_HAS_VITERBI; | ||
2317 | |||
2318 | lock = dib8000_read_word(state, 555); /* Viterbi Layer B */ | ||
2319 | if (lock & 0x01) | ||
2320 | *stat |= FE_HAS_VITERBI; | ||
2321 | |||
2322 | lock = dib8000_read_word(state, 556); /* Viterbi Layer C */ | ||
2323 | if (lock & 0x01) | ||
2324 | *stat |= FE_HAS_VITERBI; | ||
2325 | } | ||
2326 | |||
2327 | return 0; | ||
2328 | } | ||
2329 | |||
2330 | static int dib8000_read_ber(struct dvb_frontend *fe, u32 * ber) | ||
2331 | { | ||
2332 | struct dib8000_state *state = fe->demodulator_priv; | ||
2333 | *ber = (dib8000_read_word(state, 560) << 16) | dib8000_read_word(state, 561); // 13 segments | ||
2334 | return 0; | ||
2335 | } | ||
2336 | |||
2337 | static int dib8000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) | ||
2338 | { | ||
2339 | struct dib8000_state *state = fe->demodulator_priv; | ||
2340 | *unc = dib8000_read_word(state, 565); // packet error on 13 seg | ||
2341 | return 0; | ||
2342 | } | ||
2343 | |||
2344 | static int dib8000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) | ||
2345 | { | ||
2346 | struct dib8000_state *state = fe->demodulator_priv; | ||
2347 | u8 index_frontend; | ||
2348 | u16 val; | ||
2349 | |||
2350 | *strength = 0; | ||
2351 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { | ||
2352 | state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val); | ||
2353 | if (val > 65535 - *strength) | ||
2354 | *strength = 65535; | ||
2355 | else | ||
2356 | *strength += val; | ||
2357 | } | ||
2358 | |||
2359 | val = 65535 - dib8000_read_word(state, 390); | ||
2360 | if (val > 65535 - *strength) | ||
2361 | *strength = 65535; | ||
2362 | else | ||
2363 | *strength += val; | ||
2364 | return 0; | ||
2365 | } | ||
2366 | |||
2367 | static u32 dib8000_get_snr(struct dvb_frontend *fe) | ||
2368 | { | ||
2369 | struct dib8000_state *state = fe->demodulator_priv; | ||
2370 | u32 n, s, exp; | ||
2371 | u16 val; | ||
2372 | |||
2373 | val = dib8000_read_word(state, 542); | ||
2374 | n = (val >> 6) & 0xff; | ||
2375 | exp = (val & 0x3f); | ||
2376 | if ((exp & 0x20) != 0) | ||
2377 | exp -= 0x40; | ||
2378 | n <<= exp+16; | ||
2379 | |||
2380 | val = dib8000_read_word(state, 543); | ||
2381 | s = (val >> 6) & 0xff; | ||
2382 | exp = (val & 0x3f); | ||
2383 | if ((exp & 0x20) != 0) | ||
2384 | exp -= 0x40; | ||
2385 | s <<= exp+16; | ||
2386 | |||
2387 | if (n > 0) { | ||
2388 | u32 t = (s/n) << 16; | ||
2389 | return t + ((s << 16) - n*t) / n; | ||
2390 | } | ||
2391 | return 0xffffffff; | ||
2392 | } | ||
2393 | |||
2394 | static int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr) | ||
2395 | { | ||
2396 | struct dib8000_state *state = fe->demodulator_priv; | ||
2397 | u8 index_frontend; | ||
2398 | u32 snr_master; | ||
2399 | |||
2400 | snr_master = dib8000_get_snr(fe); | ||
2401 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) | ||
2402 | snr_master += dib8000_get_snr(state->fe[index_frontend]); | ||
2403 | |||
2404 | if (snr_master != 0) { | ||
2405 | snr_master = 10*intlog10(snr_master>>16); | ||
2406 | *snr = snr_master / ((1 << 24) / 10); | ||
2407 | } | ||
2408 | else | ||
2409 | *snr = 0; | ||
2410 | |||
2411 | return 0; | ||
2412 | } | ||
2413 | |||
2414 | int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave) | ||
2415 | { | ||
2416 | struct dib8000_state *state = fe->demodulator_priv; | ||
2417 | u8 index_frontend = 1; | ||
2418 | |||
2419 | while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL)) | ||
2420 | index_frontend++; | ||
2421 | if (index_frontend < MAX_NUMBER_OF_FRONTENDS) { | ||
2422 | dprintk("set slave fe %p to index %i", fe_slave, index_frontend); | ||
2423 | state->fe[index_frontend] = fe_slave; | ||
2424 | return 0; | ||
2425 | } | ||
2426 | |||
2427 | dprintk("too many slave frontend"); | ||
2428 | return -ENOMEM; | ||
2429 | } | ||
2430 | EXPORT_SYMBOL(dib8000_set_slave_frontend); | ||
2431 | |||
2432 | int dib8000_remove_slave_frontend(struct dvb_frontend *fe) | ||
2433 | { | ||
2434 | struct dib8000_state *state = fe->demodulator_priv; | ||
2435 | u8 index_frontend = 1; | ||
2436 | |||
2437 | while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL)) | ||
2438 | index_frontend++; | ||
2439 | if (index_frontend != 1) { | ||
2440 | dprintk("remove slave fe %p (index %i)", state->fe[index_frontend-1], index_frontend-1); | ||
2441 | state->fe[index_frontend] = NULL; | ||
2442 | return 0; | ||
2443 | } | ||
2444 | |||
2445 | dprintk("no frontend to be removed"); | ||
2446 | return -ENODEV; | ||
2447 | } | ||
2448 | EXPORT_SYMBOL(dib8000_remove_slave_frontend); | ||
2449 | |||
2450 | struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index) | ||
2451 | { | ||
2452 | struct dib8000_state *state = fe->demodulator_priv; | ||
2453 | |||
2454 | if (slave_index >= MAX_NUMBER_OF_FRONTENDS) | ||
2455 | return NULL; | ||
2456 | return state->fe[slave_index]; | ||
2457 | } | ||
2458 | EXPORT_SYMBOL(dib8000_get_slave_frontend); | ||
2459 | |||
2460 | |||
2461 | int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr) | ||
2462 | { | ||
2463 | int k = 0, ret = 0; | ||
2464 | u8 new_addr = 0; | ||
2465 | struct i2c_device client = {.adap = host }; | ||
2466 | |||
2467 | client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL); | ||
2468 | if (!client.i2c_write_buffer) { | ||
2469 | dprintk("%s: not enough memory", __func__); | ||
2470 | return -ENOMEM; | ||
2471 | } | ||
2472 | client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL); | ||
2473 | if (!client.i2c_read_buffer) { | ||
2474 | dprintk("%s: not enough memory", __func__); | ||
2475 | ret = -ENOMEM; | ||
2476 | goto error_memory_read; | ||
2477 | } | ||
2478 | client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL); | ||
2479 | if (!client.i2c_buffer_lock) { | ||
2480 | dprintk("%s: not enough memory", __func__); | ||
2481 | ret = -ENOMEM; | ||
2482 | goto error_memory_lock; | ||
2483 | } | ||
2484 | mutex_init(client.i2c_buffer_lock); | ||
2485 | |||
2486 | for (k = no_of_demods - 1; k >= 0; k--) { | ||
2487 | /* designated i2c address */ | ||
2488 | new_addr = first_addr + (k << 1); | ||
2489 | |||
2490 | client.addr = new_addr; | ||
2491 | dib8000_i2c_write16(&client, 1287, 0x0003); /* sram lead in, rdy */ | ||
2492 | if (dib8000_identify(&client) == 0) { | ||
2493 | dib8000_i2c_write16(&client, 1287, 0x0003); /* sram lead in, rdy */ | ||
2494 | client.addr = default_addr; | ||
2495 | if (dib8000_identify(&client) == 0) { | ||
2496 | dprintk("#%d: not identified", k); | ||
2497 | ret = -EINVAL; | ||
2498 | goto error; | ||
2499 | } | ||
2500 | } | ||
2501 | |||
2502 | /* start diversity to pull_down div_str - just for i2c-enumeration */ | ||
2503 | dib8000_i2c_write16(&client, 1286, (1 << 10) | (4 << 6)); | ||
2504 | |||
2505 | /* set new i2c address and force divstart */ | ||
2506 | dib8000_i2c_write16(&client, 1285, (new_addr << 2) | 0x2); | ||
2507 | client.addr = new_addr; | ||
2508 | dib8000_identify(&client); | ||
2509 | |||
2510 | dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr); | ||
2511 | } | ||
2512 | |||
2513 | for (k = 0; k < no_of_demods; k++) { | ||
2514 | new_addr = first_addr | (k << 1); | ||
2515 | client.addr = new_addr; | ||
2516 | |||
2517 | // unforce divstr | ||
2518 | dib8000_i2c_write16(&client, 1285, new_addr << 2); | ||
2519 | |||
2520 | /* deactivate div - it was just for i2c-enumeration */ | ||
2521 | dib8000_i2c_write16(&client, 1286, 0); | ||
2522 | } | ||
2523 | |||
2524 | error: | ||
2525 | kfree(client.i2c_buffer_lock); | ||
2526 | error_memory_lock: | ||
2527 | kfree(client.i2c_read_buffer); | ||
2528 | error_memory_read: | ||
2529 | kfree(client.i2c_write_buffer); | ||
2530 | |||
2531 | return ret; | ||
2532 | } | ||
2533 | |||
2534 | EXPORT_SYMBOL(dib8000_i2c_enumeration); | ||
2535 | static int dib8000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune) | ||
2536 | { | ||
2537 | tune->min_delay_ms = 1000; | ||
2538 | tune->step_size = 0; | ||
2539 | tune->max_drift = 0; | ||
2540 | return 0; | ||
2541 | } | ||
2542 | |||
2543 | static void dib8000_release(struct dvb_frontend *fe) | ||
2544 | { | ||
2545 | struct dib8000_state *st = fe->demodulator_priv; | ||
2546 | u8 index_frontend; | ||
2547 | |||
2548 | for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (st->fe[index_frontend] != NULL); index_frontend++) | ||
2549 | dvb_frontend_detach(st->fe[index_frontend]); | ||
2550 | |||
2551 | dibx000_exit_i2c_master(&st->i2c_master); | ||
2552 | kfree(st->fe[0]); | ||
2553 | kfree(st); | ||
2554 | } | ||
2555 | |||
2556 | struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating) | ||
2557 | { | ||
2558 | struct dib8000_state *st = fe->demodulator_priv; | ||
2559 | return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); | ||
2560 | } | ||
2561 | |||
2562 | EXPORT_SYMBOL(dib8000_get_i2c_master); | ||
2563 | |||
2564 | int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) | ||
2565 | { | ||
2566 | struct dib8000_state *st = fe->demodulator_priv; | ||
2567 | u16 val = dib8000_read_word(st, 299) & 0xffef; | ||
2568 | val |= (onoff & 0x1) << 4; | ||
2569 | |||
2570 | dprintk("pid filter enabled %d", onoff); | ||
2571 | return dib8000_write_word(st, 299, val); | ||
2572 | } | ||
2573 | EXPORT_SYMBOL(dib8000_pid_filter_ctrl); | ||
2574 | |||
2575 | int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) | ||
2576 | { | ||
2577 | struct dib8000_state *st = fe->demodulator_priv; | ||
2578 | dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff); | ||
2579 | return dib8000_write_word(st, 305 + id, onoff ? (1 << 13) | pid : 0); | ||
2580 | } | ||
2581 | EXPORT_SYMBOL(dib8000_pid_filter); | ||
2582 | |||
2583 | static const struct dvb_frontend_ops dib8000_ops = { | ||
2584 | .info = { | ||
2585 | .name = "DiBcom 8000 ISDB-T", | ||
2586 | .type = FE_OFDM, | ||
2587 | .frequency_min = 44250000, | ||
2588 | .frequency_max = 867250000, | ||
2589 | .frequency_stepsize = 62500, | ||
2590 | .caps = FE_CAN_INVERSION_AUTO | | ||
2591 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
2592 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
2593 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
2594 | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO, | ||
2595 | }, | ||
2596 | |||
2597 | .release = dib8000_release, | ||
2598 | |||
2599 | .init = dib8000_wakeup, | ||
2600 | .sleep = dib8000_sleep, | ||
2601 | |||
2602 | .set_frontend = dib8000_set_frontend, | ||
2603 | .get_tune_settings = dib8000_fe_get_tune_settings, | ||
2604 | .get_frontend = dib8000_get_frontend, | ||
2605 | |||
2606 | .read_status = dib8000_read_status, | ||
2607 | .read_ber = dib8000_read_ber, | ||
2608 | .read_signal_strength = dib8000_read_signal_strength, | ||
2609 | .read_snr = dib8000_read_snr, | ||
2610 | .read_ucblocks = dib8000_read_unc_blocks, | ||
2611 | }; | ||
2612 | |||
2613 | struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg) | ||
2614 | { | ||
2615 | struct dvb_frontend *fe; | ||
2616 | struct dib8000_state *state; | ||
2617 | |||
2618 | dprintk("dib8000_attach"); | ||
2619 | |||
2620 | state = kzalloc(sizeof(struct dib8000_state), GFP_KERNEL); | ||
2621 | if (state == NULL) | ||
2622 | return NULL; | ||
2623 | fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL); | ||
2624 | if (fe == NULL) | ||
2625 | goto error; | ||
2626 | |||
2627 | memcpy(&state->cfg, cfg, sizeof(struct dib8000_config)); | ||
2628 | state->i2c.adap = i2c_adap; | ||
2629 | state->i2c.addr = i2c_addr; | ||
2630 | state->i2c.i2c_write_buffer = state->i2c_write_buffer; | ||
2631 | state->i2c.i2c_read_buffer = state->i2c_read_buffer; | ||
2632 | mutex_init(&state->i2c_buffer_lock); | ||
2633 | state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock; | ||
2634 | state->gpio_val = cfg->gpio_val; | ||
2635 | state->gpio_dir = cfg->gpio_dir; | ||
2636 | |||
2637 | /* Ensure the output mode remains at the previous default if it's | ||
2638 | * not specifically set by the caller. | ||
2639 | */ | ||
2640 | if ((state->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (state->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK)) | ||
2641 | state->cfg.output_mode = OUTMODE_MPEG2_FIFO; | ||
2642 | |||
2643 | state->fe[0] = fe; | ||
2644 | fe->demodulator_priv = state; | ||
2645 | memcpy(&state->fe[0]->ops, &dib8000_ops, sizeof(struct dvb_frontend_ops)); | ||
2646 | |||
2647 | state->timf_default = cfg->pll->timf; | ||
2648 | |||
2649 | if (dib8000_identify(&state->i2c) == 0) | ||
2650 | goto error; | ||
2651 | |||
2652 | dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr); | ||
2653 | |||
2654 | dib8000_reset(fe); | ||
2655 | |||
2656 | dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5)); /* ber_rs_len = 3 */ | ||
2657 | |||
2658 | return fe; | ||
2659 | |||
2660 | error: | ||
2661 | kfree(state); | ||
2662 | return NULL; | ||
2663 | } | ||
2664 | |||
2665 | EXPORT_SYMBOL(dib8000_attach); | ||
2666 | |||
2667 | MODULE_AUTHOR("Olivier Grenie <Olivier.Grenie@dibcom.fr, " "Patrick Boettcher <pboettcher@dibcom.fr>"); | ||
2668 | MODULE_DESCRIPTION("Driver for the DiBcom 8000 ISDB-T demodulator"); | ||
2669 | MODULE_LICENSE("GPL"); | ||