]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - drivers/media/dvb/frontends/dib3000mc.c
V4L/DVB (4528): PATCH: Club 3D zap250mini
[mirror_ubuntu-focal-kernel.git] / drivers / media / dvb / frontends / dib3000mc.c
CommitLineData
1da177e4 1/*
b7571f8d 2 * Driver for DiBcom DiB3000MC/P-demodulator.
1da177e4 3 *
b7571f8d 4 * Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/)
1da177e4
LT
5 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
6 *
b7571f8d 7 * This code is partially based on the previous dib3000mc.c .
1da177e4 8 *
b7571f8d 9 * This program is free software; you can redistribute it and/or
1da177e4
LT
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2.
1da177e4 12 */
b7571f8d 13
1da177e4 14#include <linux/kernel.h>
b7571f8d
PB
15#include <linux/i2c.h>
16//#include <linux/init.h>
17//#include <linux/delay.h>
18//#include <linux/string.h>
19//#include <linux/slab.h>
20
21#include "dvb_frontend.h"
22
23#include "dib3000mc.h"
24
1da177e4
LT
25static int debug;
26module_param(debug, int, 0644);
b7571f8d 27MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
1da177e4 28
b7571f8d
PB
29#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); } } while (0)
30
31struct dib3000mc_state {
32 struct dvb_frontend demod;
33 struct dib3000mc_config *cfg;
34
35 u8 i2c_addr;
36 struct i2c_adapter *i2c_adap;
37
38 struct dibx000_i2c_master i2c_master;
39
40 fe_bandwidth_t current_bandwidth;
41
42 u16 dev_id;
43};
44
45static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg)
46{
47 u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
48 u8 rb[2];
49 struct i2c_msg msg[2] = {
50 { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 },
51 { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
52 };
53
54 if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
55 dprintk("i2c read error on %d\n",reg);
56
57 return (rb[0] << 8) | rb[1];
58}
59
60static int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val)
61{
62 u8 b[4] = {
63 (reg >> 8) & 0xff, reg & 0xff,
64 (val >> 8) & 0xff, val & 0xff,
65 };
66 struct i2c_msg msg = {
67 .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
68 };
69 return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
70}
71
b7571f8d
PB
72
73static int dib3000mc_identify(struct dib3000mc_state *state)
1da177e4 74{
b7571f8d
PB
75 u16 value;
76 if ((value = dib3000mc_read_word(state, 1025)) != 0x01b3) {
77 dprintk("-E- DiB3000MC/P: wrong Vendor ID (read=0x%x)\n",value);
78 return -EREMOTEIO;
79 }
1da177e4 80
b7571f8d
PB
81 value = dib3000mc_read_word(state, 1026);
82 if (value != 0x3001 && value != 0x3002) {
83 dprintk("-E- DiB3000MC/P: wrong Device ID (%x)\n",value);
84 return -EREMOTEIO;
1da177e4 85 }
b7571f8d
PB
86 state->dev_id = value;
87
88 dprintk("-I- found DiB3000MC/P: %x\n",state->dev_id);
89
90 return 0;
91}
92
93static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u8 bw, u8 update_offset)
94{
95/*
96 u32 timf_msb, timf_lsb, i;
97 int tim_sgn ;
98 LUInt comp1, comp2, comp ;
99// u32 tim_offset ;
100 comp = 27700 * BW_INDEX_TO_KHZ(bw) / 1000;
101 timf_msb = (comp >> 16) & 0x00FF;
102 timf_lsb = comp & 0xFFFF;
1da177e4
LT
103
104 // Update the timing offset ;
b7571f8d
PB
105 if (update_offset) {
106 if (state->timing_offset_comp_done == 0) {
107 usleep(200000);
1da177e4
LT
108 state->timing_offset_comp_done = 1;
109 }
b7571f8d 110 tim_offset = dib3000mc_read_word(state, 416);
1da177e4 111 if ((tim_offset & 0x2000) == 0x2000)
b7571f8d
PB
112 tim_offset |= 0xC000; // PB: This only works if tim_offset is s16 - weird
113
114 if (nfft == 0)
115 tim_offset = tim_offset << 2; // PB: Do not store the offset for different things in one variable
1da177e4
LT
116 state->timing_offset += tim_offset;
117 }
1da177e4 118 tim_offset = state->timing_offset;
b7571f8d 119
1da177e4
LT
120 if (tim_offset < 0) {
121 tim_sgn = 1;
122 tim_offset = -tim_offset;
123 } else
124 tim_sgn = 0;
125
b7571f8d
PB
126 comp1 = tim_offset * timf_lsb;
127 comp2 = tim_offset * timf_msb;
1da177e4
LT
128 comp = ((comp1 >> 16) + comp2) >> 7;
129
130 if (tim_sgn == 0)
b7571f8d 131 comp = timf_msb * (1<<16) + timf_lsb + comp;
1da177e4 132 else
b7571f8d
PB
133 comp = timf_msb * (1<<16) + timf_lsb - comp;
134
135 timf_msb = (comp>>16)&0xFF ;
136 timf_lsb = comp&0xFFFF;
137*/
138 u32 timf = 1384402 * (BW_INDEX_TO_KHZ(bw) / 1000);
1da177e4 139
b7571f8d
PB
140 dib3000mc_write_word(state, 23, timf >> 16);
141 dib3000mc_write_word(state, 24, timf & 0xffff);
1da177e4 142
1da177e4
LT
143 return 0;
144}
145
b7571f8d 146static int dib3000mc_setup_pwm3_state(struct dib3000mc_state *state)
1da177e4 147{
b7571f8d
PB
148 if (state->cfg->pwm3_inversion) {
149 dib3000mc_write_word(state, 51, (2 << 14) | (0 << 10) | (7 << 6) | (2 << 2) | (2 << 0));
150 dib3000mc_write_word(state, 52, (0 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (2 << 0));
1da177e4 151 } else {
b7571f8d
PB
152 dib3000mc_write_word(state, 51, (2 << 14) | (4 << 10) | (7 << 6) | (2 << 2) | (2 << 0));
153 dib3000mc_write_word(state, 52, (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0));
1da177e4 154 }
b7571f8d
PB
155
156 if (state->cfg->use_pwm3)
157 dib3000mc_write_word(state, 245, (1 << 3) | (1 << 0));
158 else
159 dib3000mc_write_word(state, 245, 0);
160
161 dib3000mc_write_word(state, 1040, 0x3);
1da177e4
LT
162 return 0;
163}
164
b7571f8d 165static int dib3000mc_set_output_mode(struct dib3000mc_state *state, int mode)
1da177e4 166{
b7571f8d
PB
167 int ret = 0;
168 u16 fifo_threshold = 1792;
169 u16 outreg = 0;
170 u16 outmode = 0;
171 u16 elecout = 1;
172 u16 smo_reg = (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (1 << 1) | 0 ; //smo_mode = 1
173
174 dprintk("-I- Setting output mode for demod %p to %d\n",
175 &state->demod, mode);
176
177 switch (mode) {
178 case OUTMODE_HIGH_Z: // disable
179 elecout = 0;
180 break;
181 case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock
182 outmode = 0;
183 break;
184 case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock
185 outmode = 1;
186 break;
187 case OUTMODE_MPEG2_SERIAL: // STBs with serial input
188 outmode = 2;
189 break;
190 case OUTMODE_MPEG2_FIFO: // e.g. USB feeding
191 elecout = 3;
192 /*ADDR @ 206 :
193 P_smo_error_discard [1;6:6] = 0
194 P_smo_rs_discard [1;5:5] = 0
195 P_smo_pid_parse [1;4:4] = 0
196 P_smo_fifo_flush [1;3:3] = 0
197 P_smo_mode [2;2:1] = 11
198 P_smo_ovf_prot [1;0:0] = 0
199 */
200 smo_reg = (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) |(3 << 1) | 0;
201 fifo_threshold = 512;
202 outmode = 5;
203 break;
204 case OUTMODE_DIVERSITY:
205 outmode = 4;
206 elecout = 1;
1da177e4
LT
207 break;
208 default:
b7571f8d
PB
209 dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod);
210 outmode = 0;
1da177e4
LT
211 break;
212 }
b7571f8d
PB
213
214 if ((state->cfg->output_mpeg2_in_188_bytes))
215 smo_reg |= (1 << 5) ; //P_smo_rs_discard [1;5:5] = 1
216
217 outreg = dib3000mc_read_word(state, 244) & 0x07FF;
218 outreg |= (outmode << 11);
219 ret |= dib3000mc_write_word(state, 244, outreg);
220 ret |= dib3000mc_write_word(state, 206, smo_reg); /*smo_ mode*/
221 ret |= dib3000mc_write_word(state, 207, fifo_threshold); /* synchronous fread */
222 ret |= dib3000mc_write_word(state, 1040, elecout); /* P_out_cfg */
223 return ret;
1da177e4
LT
224}
225
b7571f8d 226static int dib3000mc_set_bandwidth(struct dvb_frontend *demod, u8 bw)
1da177e4 227{
b7571f8d
PB
228 struct dib3000mc_state *state = demod->demodulator_priv;
229 u16 bw_cfg[6] = { 0 };
230 u16 imp_bw_cfg[3] = { 0 };
231 u16 reg;
1da177e4 232
b7571f8d
PB
233/* settings here are for 27.7MHz */
234 switch (bw) {
235 case BANDWIDTH_8_MHZ:
236 bw_cfg[0] = 0x0019; bw_cfg[1] = 0x5c30; bw_cfg[2] = 0x0054; bw_cfg[3] = 0x88a0; bw_cfg[4] = 0x01a6; bw_cfg[5] = 0xab20;
237 imp_bw_cfg[0] = 0x04db; imp_bw_cfg[1] = 0x00db; imp_bw_cfg[2] = 0x00b7;
238 break;
1da177e4 239
b7571f8d
PB
240 case BANDWIDTH_7_MHZ:
241 bw_cfg[0] = 0x001c; bw_cfg[1] = 0xfba5; bw_cfg[2] = 0x0060; bw_cfg[3] = 0x9c25; bw_cfg[4] = 0x01e3; bw_cfg[5] = 0x0cb7;
242 imp_bw_cfg[0] = 0x04c0; imp_bw_cfg[1] = 0x00c0; imp_bw_cfg[2] = 0x00a0;
243 break;
1da177e4 244
b7571f8d
PB
245 case BANDWIDTH_6_MHZ:
246 bw_cfg[0] = 0x0021; bw_cfg[1] = 0xd040; bw_cfg[2] = 0x0070; bw_cfg[3] = 0xb62b; bw_cfg[4] = 0x0233; bw_cfg[5] = 0x8ed5;
247 imp_bw_cfg[0] = 0x04a5; imp_bw_cfg[1] = 0x00a5; imp_bw_cfg[2] = 0x0089;
1da177e4 248 break;
b7571f8d
PB
249
250 case 255 /* BANDWIDTH_5_MHZ */:
251 bw_cfg[0] = 0x0028; bw_cfg[1] = 0x9380; bw_cfg[2] = 0x0087; bw_cfg[3] = 0x4100; bw_cfg[4] = 0x02a4; bw_cfg[5] = 0x4500;
252 imp_bw_cfg[0] = 0x0489; imp_bw_cfg[1] = 0x0089; imp_bw_cfg[2] = 0x0072;
1da177e4 253 break;
b7571f8d
PB
254
255 default: return -EINVAL;
1da177e4
LT
256 }
257
b7571f8d
PB
258 for (reg = 6; reg < 12; reg++)
259 dib3000mc_write_word(state, reg, bw_cfg[reg - 6]);
260 dib3000mc_write_word(state, 12, 0x0000);
261 dib3000mc_write_word(state, 13, 0x03e8);
262 dib3000mc_write_word(state, 14, 0x0000);
263 dib3000mc_write_word(state, 15, 0x03f2);
264 dib3000mc_write_word(state, 16, 0x0001);
265 dib3000mc_write_word(state, 17, 0xb0d0);
266 // P_sec_len
267 dib3000mc_write_word(state, 18, 0x0393);
268 dib3000mc_write_word(state, 19, 0x8700);
1da177e4 269
b7571f8d
PB
270 for (reg = 55; reg < 58; reg++)
271 dib3000mc_write_word(state, reg, imp_bw_cfg[reg - 55]);
1da177e4 272
b7571f8d
PB
273 // Timing configuration
274 dib3000mc_set_timing(state, 0, bw, 0);
1da177e4 275
b7571f8d
PB
276 return 0;
277}
1da177e4 278
b7571f8d 279static u16 impulse_noise_val[29] =
1da177e4 280
b7571f8d
PB
281{
282 0x38, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c, 0x3ffe, 0x7f3,
283 0x2d94, 0x76, 0x53d, 0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3, 0x3feb, 0x7d2,
284 0x365e, 0x76, 0x48c, 0x3ffe, 0x5b3, 0x3feb, 0x76, 0x0000, 0xd
285};
1da177e4 286
b7571f8d
PB
287static void dib3000mc_set_impulse_noise(struct dib3000mc_state *state, u8 mode, s16 nfft)
288{
289 u16 i;
290 for (i = 58; i < 87; i++)
291 dib3000mc_write_word(state, i, impulse_noise_val[i-58]);
292
293 if (nfft == 1) {
294 dib3000mc_write_word(state, 58, 0x3b);
295 dib3000mc_write_word(state, 84, 0x00);
296 dib3000mc_write_word(state, 85, 0x8200);
1da177e4
LT
297 }
298
b7571f8d
PB
299 dib3000mc_write_word(state, 34, 0x1294);
300 dib3000mc_write_word(state, 35, 0x1ff8);
301 if (mode == 1)
302 dib3000mc_write_word(state, 55, dib3000mc_read_word(state, 55) | (1 << 10));
303}
304
305static int dib3000mc_init(struct dvb_frontend *demod)
306{
307 struct dib3000mc_state *state = demod->demodulator_priv;
308 struct dibx000_agc_config *agc = state->cfg->agc;
309
310 // Restart Configuration
311 dib3000mc_write_word(state, 1027, 0x8000);
312 dib3000mc_write_word(state, 1027, 0x0000);
313
314 // power up the demod + mobility configuration
315 dib3000mc_write_word(state, 140, 0x0000);
316 dib3000mc_write_word(state, 1031, 0);
317
318 if (state->cfg->mobile_mode) {
319 dib3000mc_write_word(state, 139, 0x0000);
320 dib3000mc_write_word(state, 141, 0x0000);
321 dib3000mc_write_word(state, 175, 0x0002);
322 dib3000mc_write_word(state, 1032, 0x0000);
1da177e4 323 } else {
b7571f8d
PB
324 dib3000mc_write_word(state, 139, 0x0001);
325 dib3000mc_write_word(state, 141, 0x0000);
326 dib3000mc_write_word(state, 175, 0x0000);
327 dib3000mc_write_word(state, 1032, 0x012C);
1da177e4 328 }
b7571f8d 329 dib3000mc_write_word(state, 1033, 0);
1da177e4 330
b7571f8d
PB
331 // P_clk_cfg
332 dib3000mc_write_word(state, 1037, 12592);
1da177e4 333
b7571f8d 334 // other configurations
1da177e4 335
b7571f8d
PB
336 // P_ctrl_sfreq
337 dib3000mc_write_word(state, 33, (5 << 0));
338 dib3000mc_write_word(state, 88, (1 << 10) | (0x10 << 0));
1da177e4 339
b7571f8d
PB
340 // Phase noise control
341 // P_fft_phacor_inh, P_fft_phacor_cpe, P_fft_powrange
342 dib3000mc_write_word(state, 99, (1 << 9) | (0x20 << 0));
1da177e4 343
b7571f8d
PB
344 if (state->cfg->phase_noise_mode == 0)
345 dib3000mc_write_word(state, 111, 0x00);
346 else
347 dib3000mc_write_word(state, 111, 0x02);
348
349 // P_agc_global
350 dib3000mc_write_word(state, 50, 0x8000);
351
352 // agc setup misc
353 dib3000mc_setup_pwm3_state(state);
354
355 // P_agc_counter_lock
356 dib3000mc_write_word(state, 53, 0x87);
357 // P_agc_counter_unlock
358 dib3000mc_write_word(state, 54, 0x87);
359
360 /* agc */
361 dib3000mc_write_word(state, 36, state->cfg->max_time);
362 dib3000mc_write_word(state, 37, agc->setup);
363 dib3000mc_write_word(state, 38, state->cfg->pwm3_value);
364 dib3000mc_write_word(state, 39, state->cfg->ln_adc_level);
365
366 // set_agc_loop_Bw
367 dib3000mc_write_word(state, 40, 0x0179);
368 dib3000mc_write_word(state, 41, 0x03f0);
369
370 dib3000mc_write_word(state, 42, agc->agc1_max);
371 dib3000mc_write_word(state, 43, agc->agc1_min);
372 dib3000mc_write_word(state, 44, agc->agc2_max);
373 dib3000mc_write_word(state, 45, agc->agc2_min);
374 dib3000mc_write_word(state, 46, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
375 dib3000mc_write_word(state, 47, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
376 dib3000mc_write_word(state, 48, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
377 dib3000mc_write_word(state, 49, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
378
379// Begin: TimeOut registers
380 // P_pha3_thres
381 dib3000mc_write_word(state, 110, 3277);
382 // P_timf_alpha = 6, P_corm_alpha = 6, P_corm_thres = 0x80
383 dib3000mc_write_word(state, 26, 0x6680);
384 // lock_mask0
385 dib3000mc_write_word(state, 1, 4);
386 // lock_mask1
387 dib3000mc_write_word(state, 2, 4);
388 // lock_mask2
389 dib3000mc_write_word(state, 3, 0x1000);
390 // P_search_maxtrial=1
391 dib3000mc_write_word(state, 5, 1);
392
393 dib3000mc_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ);
394
395 // div_lock_mask
396 dib3000mc_write_word(state, 4, 0x814);
397
398 dib3000mc_write_word(state, 21, (1 << 9) | 0x164);
399 dib3000mc_write_word(state, 22, 0x463d);
400
401 // Spurious rm cfg
402 // P_cspu_regul, P_cspu_win_cut
403 dib3000mc_write_word(state, 120, 0x200f);
404 // P_adp_selec_monit
405 dib3000mc_write_word(state, 134, 0);
406
407 // Fec cfg
408 dib3000mc_write_word(state, 195, 0x10);
409
410 // diversity register: P_dvsy_sync_wait..
411 dib3000mc_write_word(state, 180, 0x2FF0);
412
413 // Impulse noise configuration
414 dib3000mc_set_impulse_noise(state, 0, 1);
415
416 // output mode set-up
417 dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
418
419 /* close the i2c-gate */
420 dib3000mc_write_word(state, 769, (1 << 7) );
1da177e4 421
b7571f8d
PB
422 return 0;
423}
1da177e4 424
b7571f8d
PB
425static int dib3000mc_sleep(struct dvb_frontend *demod)
426{
427 struct dib3000mc_state *state = demod->demodulator_priv;
1da177e4 428
b7571f8d
PB
429 dib3000mc_write_word(state, 1037, dib3000mc_read_word(state, 1037) | 0x0003);
430 dib3000mc_write_word(state, 1031, 0xFFFF);
431 dib3000mc_write_word(state, 1032, 0xFFFF);
432 dib3000mc_write_word(state, 1033, 0xFFF4); // **** Bin2
1da177e4 433
b7571f8d
PB
434 return 0;
435}
1da177e4 436
b7571f8d
PB
437static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam)
438{
439 u16 cfg[4] = { 0 },reg;
440 switch (qam) {
441 case 0:
442 cfg[0] = 0x099a; cfg[1] = 0x7fae; cfg[2] = 0x0333; cfg[3] = 0x7ff0;
443 break;
444 case 1:
445 cfg[0] = 0x023d; cfg[1] = 0x7fdf; cfg[2] = 0x00a4; cfg[3] = 0x7ff0;
446 break;
447 case 2:
448 cfg[0] = 0x0148; cfg[1] = 0x7ff0; cfg[2] = 0x00a4; cfg[3] = 0x7ff8;
449 break;
1da177e4 450 }
b7571f8d
PB
451 for (reg = 129; reg < 133; reg++)
452 dib3000mc_write_word(state, reg, cfg[reg - 129]);
1da177e4
LT
453}
454
b7571f8d 455static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dibx000_ofdm_channel *chan, u16 seq)
1da177e4 456{
b7571f8d 457 u16 tmp;
1da177e4 458
b7571f8d 459 dib3000mc_set_timing(state, chan->nfft, chan->Bw, 0);
1da177e4 460
b7571f8d
PB
461// if (boost)
462// dib3000mc_write_word(state, 100, (11 << 6) + 6);
463// else
464 dib3000mc_write_word(state, 100, (16 << 6) + 9);
1da177e4 465
b7571f8d
PB
466 dib3000mc_write_word(state, 1027, 0x0800);
467 dib3000mc_write_word(state, 1027, 0x0000);
1da177e4 468
b7571f8d
PB
469 //Default cfg isi offset adp
470 dib3000mc_write_word(state, 26, 0x6680);
471 dib3000mc_write_word(state, 29, 0x1273);
472 dib3000mc_write_word(state, 33, 5);
473 dib3000mc_set_adp_cfg(state, 1);
474 dib3000mc_write_word(state, 133, 15564);
1da177e4 475
b7571f8d
PB
476 dib3000mc_write_word(state, 12 , 0x0);
477 dib3000mc_write_word(state, 13 , 0x3e8);
478 dib3000mc_write_word(state, 14 , 0x0);
479 dib3000mc_write_word(state, 15 , 0x3f2);
1da177e4 480
b7571f8d
PB
481 dib3000mc_write_word(state, 93,0);
482 dib3000mc_write_word(state, 94,0);
483 dib3000mc_write_word(state, 95,0);
484 dib3000mc_write_word(state, 96,0);
485 dib3000mc_write_word(state, 97,0);
486 dib3000mc_write_word(state, 98,0);
1da177e4 487
b7571f8d 488 dib3000mc_set_impulse_noise(state, 0, chan->nfft);
e4d6c1f7 489
b7571f8d
PB
490 tmp = ((chan->nfft & 0x1) << 7) | (chan->guard << 5) | (chan->nqam << 3) | chan->vit_alpha;
491 dib3000mc_write_word(state, 0, tmp);
e4d6c1f7 492
b7571f8d 493 dib3000mc_write_word(state, 5, seq);
1da177e4 494
b7571f8d
PB
495 tmp = (chan->vit_hrch << 4) | (chan->vit_select_hp);
496 if (!chan->vit_hrch || (chan->vit_hrch && chan->vit_select_hp))
497 tmp |= chan->vit_code_rate_hp << 1;
498 else
499 tmp |= chan->vit_code_rate_lp << 1;
500 dib3000mc_write_word(state, 181, tmp);
1da177e4 501
b7571f8d
PB
502 // diversity synchro delay
503 tmp = dib3000mc_read_word(state, 180) & 0x000f;
504 tmp |= ((chan->nfft == 0) ? 64 : 256) * ((1 << (chan->guard)) * 3 / 2) << 4; // add 50% SFN margin
505 dib3000mc_write_word(state, 180, tmp);
1da177e4 506
b7571f8d
PB
507 // restart demod
508 tmp = dib3000mc_read_word(state, 0);
509 dib3000mc_write_word(state, 0, tmp | (1 << 9));
510 dib3000mc_write_word(state, 0, tmp);
1da177e4 511
b7571f8d 512 msleep(30);
1da177e4 513
b7571f8d
PB
514 dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, chan->nfft);
515}
1da177e4 516
b7571f8d
PB
517static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *chan)
518{
519 struct dib3000mc_state *state = demod->demodulator_priv;
520 u16 reg;
521// u32 val;
522 struct dibx000_ofdm_channel fchan;
1da177e4 523
b7571f8d
PB
524 INIT_OFDM_CHANNEL(&fchan);
525 fchan = *chan;
1da177e4 526
1da177e4 527
b7571f8d
PB
528 /* a channel for autosearch */
529 reg = 0;
530 if (chan->nfft == -1 && chan->guard == -1) reg = 7;
531 if (chan->nfft == -1 && chan->guard != -1) reg = 2;
532 if (chan->nfft != -1 && chan->guard == -1) reg = 3;
1da177e4 533
b7571f8d
PB
534 fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2;
535 fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2;
536 fchan.vit_hrch = 0; fchan.vit_select_hp = 1;
1da177e4 537
b7571f8d 538 dib3000mc_set_channel_cfg(state, &fchan, reg);
1da177e4 539
b7571f8d
PB
540 reg = dib3000mc_read_word(state, 0);
541 dib3000mc_write_word(state, 0, reg | (1 << 8));
542 dib3000mc_write_word(state, 0, reg);
1da177e4 543
b7571f8d
PB
544 return 0;
545}
1da177e4 546
b7571f8d
PB
547static int dib3000mc_autosearch_is_irq(struct dvb_frontend *demod)
548{
549 struct dib3000mc_state *state = demod->demodulator_priv;
550 u16 irq_pending = dib3000mc_read_word(state, 511);
1da177e4 551
b7571f8d
PB
552 if (irq_pending & 0x1) // failed
553 return 1;
1da177e4 554
b7571f8d
PB
555 if (irq_pending & 0x2) // succeeded
556 return 2;
a16bf5d5 557
b7571f8d 558 return 0; // still pending
1da177e4 559}
b7571f8d
PB
560
561static int dib3000mc_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
1da177e4 562{
b7571f8d 563 struct dib3000mc_state *state = demod->demodulator_priv;
1da177e4 564
b7571f8d
PB
565 // ** configure demod **
566 dib3000mc_set_channel_cfg(state, ch, 0);
567
568 // activates isi
569 dib3000mc_write_word(state, 29, 0x1073);
1da177e4 570
b7571f8d
PB
571 dib3000mc_set_adp_cfg(state, (u8)ch->nqam);
572
573 if (ch->nfft == 1) {
574 dib3000mc_write_word(state, 26, 38528);
575 dib3000mc_write_word(state, 33, 8);
576 } else {
577 dib3000mc_write_word(state, 26, 30336);
578 dib3000mc_write_word(state, 33, 6);
579 }
580
581 // if (lock)
582 // dib3000mc_set_timing(state, ch->nfft, ch->Bw, 1);
1da177e4
LT
583
584 return 0;
585}
586
b7571f8d 587static int dib3000mc_demod_output_mode(struct dvb_frontend *demod, int mode)
1da177e4 588{
b7571f8d
PB
589 struct dib3000mc_state *state = demod->demodulator_priv;
590 return dib3000mc_set_output_mode(state, mode);
1da177e4
LT
591}
592
b7571f8d 593static int dib3000mc_i2c_enumeration(struct dvb_frontend *demod[], int no_of_demods, u8 default_addr)
1da177e4 594{
b7571f8d
PB
595 struct dib3000mc_state *st;
596 int k,ret=0;
597 u8 new_addr;
598
599 static u8 DIB3000MC_I2C_ADDRESS[] = {20,22,24,26};
600
601 for (k = no_of_demods-1; k >= 0; k--) {
602 st = demod[k]->demodulator_priv;
603
604 /* designated i2c address */
605 new_addr = DIB3000MC_I2C_ADDRESS[k];
606
607 st->i2c_addr = new_addr;
608 if (dib3000mc_identify(st) != 0) {
609 st->i2c_addr = default_addr;
610 if (dib3000mc_identify(st) != 0) {
611 dprintk("-E- DiB3000P/MC #%d: not identified\n", k);
612 return -EINVAL;
613 }
614 }
615
616 /* turn on div_out */
617 dib3000mc_demod_output_mode(demod[k], OUTMODE_MPEG2_PAR_CONT_CLK);
618
619 // set new i2c address and force divstr (Bit 1) to value 0 (Bit 0)
620 ret |= dib3000mc_write_word(st, 1024, (new_addr << 3) | 0x1);
621 st->i2c_addr = new_addr;
622 }
1da177e4 623
b7571f8d
PB
624 for (k = 0; k < no_of_demods; k++) {
625 st = demod[k]->demodulator_priv;
626
627 ret |= dib3000mc_write_word(st, 1024, st->i2c_addr << 3);
628
629 /* turn off data output */
630 dib3000mc_demod_output_mode(demod[k],OUTMODE_HIGH_Z);
631 dib3000mc_write_word(st, 769, (1 << 7) );
632
633 }
1da177e4
LT
634 return 0;
635}
636
b7571f8d 637struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating)
1da177e4 638{
b7571f8d
PB
639 struct dib3000mc_state *st = demod->demodulator_priv;
640 return dibx000_get_i2c_adapter(&st->i2c_master, DIBX000_I2C_INTERFACE_TUNER, gating);
1da177e4
LT
641}
642
b7571f8d
PB
643EXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master);
644
645static int dib3000mc_get_frontend(struct dvb_frontend* fe,
646 struct dvb_frontend_parameters *fep)
1da177e4 647{
b7571f8d
PB
648 struct dib3000mc_state *state = fe->demodulator_priv;
649 u16 tps = dib3000mc_read_word(state,458);
1da177e4 650
b7571f8d
PB
651 fep->inversion = INVERSION_AUTO;
652
653 fep->u.ofdm.bandwidth = state->current_bandwidth;
654
655 switch ((tps >> 8) & 0x1) {
656 case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
657 case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
658 }
659
660 switch (tps & 0x3) {
661 case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
662 case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
663 case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
664 case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
665 }
666
667 switch ((tps >> 13) & 0x3) {
668 case 0: fep->u.ofdm.constellation = QPSK; break;
669 case 1: fep->u.ofdm.constellation = QAM_16; break;
670 case 2:
671 default: fep->u.ofdm.constellation = QAM_64; break;
672 }
673
674 /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
675 /* (tps >> 12) & 0x1 == hrch is used, (tps >> 9) & 0x7 == alpha */
676
677 fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
678 switch ((tps >> 5) & 0x7) {
679 case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
680 case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
681 case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
682 case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
683 case 7:
684 default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
685
686 }
687
688 switch ((tps >> 2) & 0x7) {
689 case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
690 case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
691 case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
692 case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
693 case 7:
694 default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
695 }
1da177e4 696
1da177e4
LT
697 return 0;
698}
699
b7571f8d
PB
700static int dib3000mc_set_frontend(struct dvb_frontend* fe,
701 struct dvb_frontend_parameters *fep)
1da177e4 702{
b7571f8d
PB
703 struct dib3000mc_state *state = fe->demodulator_priv;
704 struct dibx000_ofdm_channel ch;
1da177e4 705
b7571f8d
PB
706 INIT_OFDM_CHANNEL(&ch);
707 FEP2DIB(fep,&ch);
708
b7571f8d
PB
709 state->current_bandwidth = fep->u.ofdm.bandwidth;
710 dib3000mc_set_bandwidth(fe, fep->u.ofdm.bandwidth);
711
712 if (fe->ops.tuner_ops.set_params) {
713 fe->ops.tuner_ops.set_params(fe, fep);
714 msleep(100);
715 }
716
717 if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
718 fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
719 fep->u.ofdm.constellation == QAM_AUTO ||
720 fep->u.ofdm.code_rate_HP == FEC_AUTO) {
721 int i = 100, found;
722
723 dib3000mc_autosearch_start(fe, &ch);
724 do {
725 msleep(1);
726 found = dib3000mc_autosearch_is_irq(fe);
727 } while (found == 0 && i--);
728
729 dprintk("autosearch returns: %d\n",found);
730 if (found == 0 || found == 1)
731 return 0; // no channel found
732
733 dib3000mc_get_frontend(fe, fep);
734 FEP2DIB(fep,&ch);
735 }
736
737 /* make this a config parameter */
738 dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO);
739
740 return dib3000mc_tune(fe, &ch);
1da177e4
LT
741}
742
b7571f8d 743static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat)
1da177e4 744{
b7571f8d
PB
745 struct dib3000mc_state *state = fe->demodulator_priv;
746 u16 lock = dib3000mc_read_word(state, 509);
747
748 *stat = 0;
749
750 if (lock & 0x8000)
751 *stat |= FE_HAS_SIGNAL;
752 if (lock & 0x3000)
753 *stat |= FE_HAS_CARRIER;
754 if (lock & 0x0100)
755 *stat |= FE_HAS_VITERBI;
756 if (lock & 0x0010)
757 *stat |= FE_HAS_SYNC;
758 if (lock & 0x0008)
759 *stat |= FE_HAS_LOCK;
760
1da177e4
LT
761 return 0;
762}
763
b7571f8d 764static int dib3000mc_read_ber(struct dvb_frontend *fe, u32 *ber)
1da177e4 765{
b7571f8d
PB
766 struct dib3000mc_state *state = fe->demodulator_priv;
767 *ber = (dib3000mc_read_word(state, 500) << 16) | dib3000mc_read_word(state, 501);
768 return 0;
1da177e4
LT
769}
770
b7571f8d 771static int dib3000mc_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
1da177e4 772{
b7571f8d
PB
773 struct dib3000mc_state *state = fe->demodulator_priv;
774 *unc = dib3000mc_read_word(state, 508);
775 return 0;
1da177e4
LT
776}
777
b7571f8d 778static int dib3000mc_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
1da177e4 779{
b7571f8d
PB
780 struct dib3000mc_state *state = fe->demodulator_priv;
781 u16 val = dib3000mc_read_word(state, 392);
782 *strength = 65535 - val;
783 return 0;
1da177e4
LT
784}
785
b7571f8d 786static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr)
1da177e4 787{
b7571f8d 788 *snr = 0x0000;
1da177e4
LT
789 return 0;
790}
791
b7571f8d 792static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
1da177e4 793{
b7571f8d 794 tune->min_delay_ms = 1000;
1da177e4
LT
795 return 0;
796}
797
b7571f8d 798static void dib3000mc_release(struct dvb_frontend *fe)
1da177e4 799{
b7571f8d
PB
800 struct dib3000mc_state *state = fe->demodulator_priv;
801 dibx000_exit_i2c_master(&state->i2c_master);
802 kfree(state);
1da177e4
LT
803}
804
b7571f8d 805int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff)
1da177e4 806{
b7571f8d
PB
807 struct dib3000mc_state *state = fe->demodulator_priv;
808 dib3000mc_write_word(state, 212 + index, onoff ? (1 << 13) | pid : 0);
1da177e4
LT
809 return 0;
810}
b7571f8d 811EXPORT_SYMBOL(dib3000mc_pid_control);
1da177e4 812
b7571f8d 813int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff)
1da177e4 814{
b7571f8d
PB
815 struct dib3000mc_state *state = fe->demodulator_priv;
816 u16 tmp = dib3000mc_read_word(state, 206) & ~(1 << 4);
817 tmp |= (onoff << 4);
818 return dib3000mc_write_word(state, 206, tmp);
1da177e4 819}
b7571f8d 820EXPORT_SYMBOL(dib3000mc_pid_parse);
1da177e4 821
b7571f8d 822void dib3000mc_set_config(struct dvb_frontend *fe, struct dib3000mc_config *cfg)
e4d6c1f7 823{
b7571f8d
PB
824 struct dib3000mc_state *state = fe->demodulator_priv;
825 state->cfg = cfg;
e4d6c1f7 826}
b7571f8d 827EXPORT_SYMBOL(dib3000mc_set_config);
1da177e4
LT
828
829static struct dvb_frontend_ops dib3000mc_ops;
830
b7571f8d 831int dib3000mc_attach(struct i2c_adapter *i2c_adap, int no_of_demods, u8 default_addr, u8 do_i2c_enum, struct dib3000mc_config cfg[], struct dvb_frontend *demod[])
1da177e4 832{
b7571f8d
PB
833 struct dib3000mc_state *st;
834 int k, num=0;
1da177e4 835
b7571f8d
PB
836 if (no_of_demods < 1)
837 return -EINVAL;
1da177e4 838
b7571f8d
PB
839 for (k = 0; k < no_of_demods; k++) {
840 st = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
841 if (st == NULL)
842 goto error;
1da177e4 843
b7571f8d 844 num++;
1da177e4 845
b7571f8d
PB
846 st->cfg = &cfg[k];
847 // st->gpio_val = cfg[k].gpio_val;
848 // st->gpio_dir = cfg[k].gpio_dir;
849 st->i2c_adap = i2c_adap;
1da177e4 850
b7571f8d
PB
851 demod[k] = &st->demod;
852 demod[k]->demodulator_priv = st;
853 memcpy(&st->demod.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
1da177e4 854
b7571f8d
PB
855// INIT_COMPONENT_REGISTER_ACCESS(&st->register_access, 12, 16, dib7000p_register_read, dib7000p_register_write, st);
856// demod[k]->register_access = &st->register_access;
857 }
1da177e4 858
b7571f8d
PB
859 if (do_i2c_enum) {
860 if (dib3000mc_i2c_enumeration(demod,no_of_demods,default_addr) != 0)
861 goto error;
862 } else {
863 st = demod[0]->demodulator_priv;
864 st->i2c_addr = default_addr;
865 if (dib3000mc_identify(st) != 0)
866 goto error;
867 }
1da177e4 868
b7571f8d
PB
869 for (k = 0; k < num; k++) {
870 st = demod[k]->demodulator_priv;
871 dibx000_init_i2c_master(&st->i2c_master, DIB3000MC, st->i2c_adap, st->i2c_addr);
872 }
1da177e4 873
b7571f8d 874 return 0;
1da177e4
LT
875
876error:
4e66c97c 877 for (k = 0; k < num; k++) {
b7571f8d 878 kfree(demod[k]->demodulator_priv);
4e66c97c
PB
879 demod[k] = NULL;
880 }
b7571f8d 881 return -EINVAL;
1da177e4 882}
b7571f8d 883
e4d6c1f7 884EXPORT_SYMBOL(dib3000mc_attach);
1da177e4
LT
885
886static struct dvb_frontend_ops dib3000mc_ops = {
1da177e4 887 .info = {
b7571f8d
PB
888 .name = "DiBcom 3000MC/P",
889 .type = FE_OFDM,
890 .frequency_min = 44250000,
891 .frequency_max = 867250000,
892 .frequency_stepsize = 62500,
1da177e4 893 .caps = FE_CAN_INVERSION_AUTO |
b7571f8d
PB
894 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
895 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
896 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
897 FE_CAN_TRANSMISSION_MODE_AUTO |
898 FE_CAN_GUARD_INTERVAL_AUTO |
899 FE_CAN_RECOVER |
900 FE_CAN_HIERARCHY_AUTO,
1da177e4
LT
901 },
902
b7571f8d 903 .release = dib3000mc_release,
1da177e4 904
b7571f8d
PB
905 .init = dib3000mc_init,
906 .sleep = dib3000mc_sleep,
1da177e4 907
b7571f8d
PB
908 .set_frontend = dib3000mc_set_frontend,
909 .get_tune_settings = dib3000mc_fe_get_tune_settings,
910 .get_frontend = dib3000mc_get_frontend,
1da177e4 911
b7571f8d
PB
912 .read_status = dib3000mc_read_status,
913 .read_ber = dib3000mc_read_ber,
1da177e4 914 .read_signal_strength = dib3000mc_read_signal_strength,
b7571f8d
PB
915 .read_snr = dib3000mc_read_snr,
916 .read_ucblocks = dib3000mc_read_unc_blocks,
1da177e4
LT
917};
918
b7571f8d
PB
919MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
920MODULE_DESCRIPTION("Driver for the DiBcom 3000MC/P COFDM demodulator");
1da177e4 921MODULE_LICENSE("GPL");