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