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