• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/src/linux/linux-2.6/drivers/media/dvb/frontends/
1/*
2 * Driver for DiBcom DiB3000MC/P-demodulator.
3 *
4 * Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/)
5 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
6 *
7 * This code is partially based on the previous dib3000mc.c .
8 *
9 * This program is free software; you can redistribute it and/or
10 *	modify it under the terms of the GNU General Public License as
11 *	published by the Free Software Foundation, version 2.
12 */
13
14#include <linux/kernel.h>
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
25static int debug;
26module_param(debug, int, 0644);
27MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
28
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	u32 timf;
41
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
74
75static int dib3000mc_identify(struct dib3000mc_state *state)
76{
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	}
82
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;
87	}
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{
97	u32 timf;
98
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
103	} else
104		timf = state->timf;
105
106	timf *= (BW_INDEX_TO_KHZ(bw) / 1000);
107
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	}
120
121	dprintk("timf: %d\n", timf);
122
123	dib3000mc_write_word(state, 23, timf >> 16);
124	dib3000mc_write_word(state, 24, timf & 0xffff);
125
126	return 0;
127}
128
129static int dib3000mc_setup_pwm_state(struct dib3000mc_state *state)
130{
131	u16 reg_51, reg_52 = state->cfg->agc->setup & 0xfefb;
132    if (state->cfg->pwm3_inversion) {
133		reg_51 =  (2 << 14) | (0 << 10) | (7 << 6) | (2 << 2) | (2 << 0);
134		reg_52 |= (1 << 2);
135	} else {
136		reg_51 = (2 << 14) | (4 << 10) | (7 << 6) | (2 << 2) | (2 << 0);
137		reg_52 |= (1 << 8);
138	}
139	dib3000mc_write_word(state, 51, reg_51);
140	dib3000mc_write_word(state, 52, reg_52);
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);
148	return 0;
149}
150
151static int dib3000mc_set_output_mode(struct dib3000mc_state *state, int mode)
152{
153	int    ret = 0;
154	u16 fifo_threshold = 1792;
155	u16 outreg = 0;
156	u16 outmode = 0;
157	u16 elecout = 1;
158	u16 smo_reg = dib3000mc_read_word(state, 206) & 0x0010; /* keep the pid_parse bit */
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			*/
186			smo_reg |= 3 << 1;
187			fifo_threshold = 512;
188			outmode = 5;
189			break;
190		case OUTMODE_DIVERSITY:
191			outmode = 4;
192			elecout = 1;
193			break;
194		default:
195			dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod);
196			outmode = 0;
197			break;
198	}
199
200	if ((state->cfg->output_mpeg2_in_188_bytes))
201		smo_reg |= (1 << 5); // P_smo_rs_discard     [1;5:5] = 1
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;
210}
211
212static int dib3000mc_set_bandwidth(struct dvb_frontend *demod, u8 bw)
213{
214	struct dib3000mc_state *state = demod->demodulator_priv;
215	u16 bw_cfg[6] = { 0 };
216	u16 imp_bw_cfg[3] = { 0 };
217	u16 reg;
218
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;
225
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;
230
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;
234			break;
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;
239			break;
240
241		default: return -EINVAL;
242	}
243
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);
255
256	for (reg = 55; reg < 58; reg++)
257		dib3000mc_write_word(state, reg, imp_bw_cfg[reg - 55]);
258
259	// Timing configuration
260	dib3000mc_set_timing(state, 0, bw, 0);
261
262	return 0;
263}
264
265static u16 impulse_noise_val[29] =
266
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};
272
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);
283	}
284
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);
309	} else {
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);
314	}
315	dib3000mc_write_word(state, 1033, 0x0000);
316
317	// P_clk_cfg
318	dib3000mc_write_word(state, 1037, 0x3130);
319
320	// other configurations
321
322	// P_ctrl_sfreq
323	dib3000mc_write_word(state, 33, (5 << 0));
324	dib3000mc_write_word(state, 88, (1 << 10) | (0x10 << 0));
325
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));
329
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
339	dib3000mc_setup_pwm_state(state);
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);
348	dib3000mc_write_word(state, 37, (state->cfg->agc_command1 << 13) | (state->cfg->agc_command2 << 12) | (0x1d << 0));
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) );
407
408	return 0;
409}
410
411static int dib3000mc_sleep(struct dvb_frontend *demod)
412{
413	struct dib3000mc_state *state = demod->demodulator_priv;
414
415	dib3000mc_write_word(state, 1031, 0xFFFF);
416	dib3000mc_write_word(state, 1032, 0xFFFF);
417	dib3000mc_write_word(state, 1033, 0xFFF0);
418
419    return 0;
420}
421
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;
435	}
436	for (reg = 129; reg < 133; reg++)
437		dib3000mc_write_word(state, reg, cfg[reg - 129]);
438}
439
440static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dibx000_ofdm_channel *chan, u16 seq)
441{
442	u16 tmp;
443
444	dib3000mc_set_timing(state, chan->nfft, chan->Bw, 0);
445
446//	if (boost)
447//		dib3000mc_write_word(state, 100, (11 << 6) + 6);
448//	else
449		dib3000mc_write_word(state, 100, (16 << 6) + 9);
450
451	dib3000mc_write_word(state, 1027, 0x0800);
452	dib3000mc_write_word(state, 1027, 0x0000);
453
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);
460
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);
465
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);
472
473	dib3000mc_set_impulse_noise(state, 0, chan->nfft);
474
475	tmp = ((chan->nfft & 0x1) << 7) | (chan->guard << 5) | (chan->nqam << 3) | chan->vit_alpha;
476	dib3000mc_write_word(state, 0, tmp);
477
478	dib3000mc_write_word(state, 5, (1 << 8) | ((seq & 0xf) << 4));
479
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);
486
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);
491
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);
496
497	msleep(30);
498
499	dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, chan->nfft);
500}
501
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;
508
509	INIT_OFDM_CHANNEL(&fchan);
510	fchan = *chan;
511
512
513	/* a channel for autosearch */
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;
517
518	dib3000mc_set_channel_cfg(state, &fchan, 11);
519
520	reg = dib3000mc_read_word(state, 0);
521	dib3000mc_write_word(state, 0, reg | (1 << 8));
522	dib3000mc_read_word(state, 511);
523	dib3000mc_write_word(state, 0, reg);
524
525	return 0;
526}
527
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);
532
533	if (irq_pending & 0x1) // failed
534		return 1;
535
536	if (irq_pending & 0x2) // succeeded
537		return 2;
538
539	return 0; // still pending
540}
541
542static int dib3000mc_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
543{
544	struct dib3000mc_state *state = demod->demodulator_priv;
545
546	// ** configure demod **
547	dib3000mc_set_channel_cfg(state, ch, 0);
548
549	// activates isi
550	dib3000mc_write_word(state, 29, 0x1073);
551
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
562	if (dib3000mc_read_word(state, 509) & 0x80)
563		dib3000mc_set_timing(state, ch->nfft, ch->Bw, 1);
564
565	return 0;
566}
567
568struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating)
569{
570	struct dib3000mc_state *st = demod->demodulator_priv;
571	return dibx000_get_i2c_adapter(&st->i2c_master, DIBX000_I2C_INTERFACE_TUNER, gating);
572}
573
574EXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master);
575
576static int dib3000mc_get_frontend(struct dvb_frontend* fe,
577				struct dvb_frontend_parameters *fep)
578{
579	struct dib3000mc_state *state = fe->demodulator_priv;
580	u16 tps = dib3000mc_read_word(state,458);
581
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	}
627
628	return 0;
629}
630
631static int dib3000mc_set_frontend(struct dvb_frontend* fe,
632				struct dvb_frontend_parameters *fep)
633{
634	struct dib3000mc_state *state = fe->demodulator_priv;
635	struct dibx000_ofdm_channel ch;
636
637	INIT_OFDM_CHANNEL(&ch);
638	FEP2DIB(fep,&ch);
639
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);
672}
673
674static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat)
675{
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
692	return 0;
693}
694
695static int dib3000mc_read_ber(struct dvb_frontend *fe, u32 *ber)
696{
697	struct dib3000mc_state *state = fe->demodulator_priv;
698	*ber = (dib3000mc_read_word(state, 500) << 16) | dib3000mc_read_word(state, 501);
699	return 0;
700}
701
702static int dib3000mc_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
703{
704	struct dib3000mc_state *state = fe->demodulator_priv;
705	*unc = dib3000mc_read_word(state, 508);
706	return 0;
707}
708
709static int dib3000mc_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
710{
711	struct dib3000mc_state *state = fe->demodulator_priv;
712	u16 val = dib3000mc_read_word(state, 392);
713	*strength = 65535 - val;
714	return 0;
715}
716
717static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr)
718{
719	*snr = 0x0000;
720	return 0;
721}
722
723static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
724{
725	tune->min_delay_ms = 1000;
726	return 0;
727}
728
729static void dib3000mc_release(struct dvb_frontend *fe)
730{
731	struct dib3000mc_state *state = fe->demodulator_priv;
732	dibx000_exit_i2c_master(&state->i2c_master);
733	kfree(state);
734}
735
736int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff)
737{
738	struct dib3000mc_state *state = fe->demodulator_priv;
739	dib3000mc_write_word(state, 212 + index,  onoff ? (1 << 13) | pid : 0);
740	return 0;
741}
742EXPORT_SYMBOL(dib3000mc_pid_control);
743
744int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff)
745{
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);
750}
751EXPORT_SYMBOL(dib3000mc_pid_parse);
752
753void dib3000mc_set_config(struct dvb_frontend *fe, struct dib3000mc_config *cfg)
754{
755	struct dib3000mc_state *state = fe->demodulator_priv;
756	state->cfg = cfg;
757}
758EXPORT_SYMBOL(dib3000mc_set_config);
759
760int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib3000mc_config cfg[])
761{
762	struct dib3000mc_state st = { .i2c_adap = i2c };
763	int k;
764	u8 new_addr;
765
766	static u8 DIB3000MC_I2C_ADDRESS[] = {20,22,24,26};
767
768	for (k = no_of_demods-1; k >= 0; k--) {
769		st.cfg = &cfg[k];
770
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		}
781
782		dib3000mc_set_output_mode(&st, OUTMODE_MPEG2_PAR_CONT_CLK);
783
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;
787	}
788
789	for (k = 0; k < no_of_demods; k++) {
790		st.cfg = &cfg[k];
791		st.i2c_addr = DIB3000MC_I2C_ADDRESS[k];
792
793		dib3000mc_write_word(&st, 1024, st.i2c_addr << 3);
794
795		/* turn off data output */
796		dib3000mc_set_output_mode(&st, OUTMODE_HIGH_Z);
797	}
798	return 0;
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;
814	st->i2c_addr = i2c_addr;
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
825	dib3000mc_write_word(st, 1037, 0x3130);
826
827	return demod;
828
829error:
830	kfree(st);
831	return NULL;
832}
833EXPORT_SYMBOL(dib3000mc_attach);
834
835static struct dvb_frontend_ops dib3000mc_ops = {
836	.info = {
837		.name = "DiBcom 3000MC/P",
838		.type = FE_OFDM,
839		.frequency_min      = 44250000,
840		.frequency_max      = 867250000,
841		.frequency_stepsize = 62500,
842		.caps = FE_CAN_INVERSION_AUTO |
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,
850	},
851
852	.release              = dib3000mc_release,
853
854	.init                 = dib3000mc_init,
855	.sleep                = dib3000mc_sleep,
856
857	.set_frontend         = dib3000mc_set_frontend,
858	.get_tune_settings    = dib3000mc_fe_get_tune_settings,
859	.get_frontend         = dib3000mc_get_frontend,
860
861	.read_status          = dib3000mc_read_status,
862	.read_ber             = dib3000mc_read_ber,
863	.read_signal_strength = dib3000mc_read_signal_strength,
864	.read_snr             = dib3000mc_read_snr,
865	.read_ucblocks        = dib3000mc_read_unc_blocks,
866};
867
868MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
869MODULE_DESCRIPTION("Driver for the DiBcom 3000MC/P COFDM demodulator");
870MODULE_LICENSE("GPL");
871