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