2 * dvb-dibusb-fe-i2c.c is part of the driver for mobile USB Budget DVB-T devices
3 * based on reference design made by DiBcom (http://www.dibcom.fr/)
5 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
7 * see dvb-dibusb-core.c for more copyright details.
9 * This file contains functions for attaching, initializing of an appropriate
10 * demodulator/frontend. I2C-stuff is also located here.
13 #include "dvb-dibusb.h"
15 #include <linux/usb.h>
17 static int dibusb_i2c_msg(struct usb_dibusb
*dib
, u8 addr
,
18 u8
*wbuf
, u16 wlen
, u8
*rbuf
, u16 rlen
)
20 u8 sndbuf
[wlen
+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */
22 int wo
= (rbuf
== NULL
|| rlen
== 0),
23 len
= 2 + wlen
+ (wo
? 0 : 2);
25 sndbuf
[0] = wo
? DIBUSB_REQ_I2C_WRITE
: DIBUSB_REQ_I2C_READ
;
26 sndbuf
[1] = (addr
<< 1) | (wo
? 0 : 1);
28 memcpy(&sndbuf
[2],wbuf
,wlen
);
31 sndbuf
[wlen
+2] = (rlen
>> 8) & 0xff;
32 sndbuf
[wlen
+3] = rlen
& 0xff;
35 return dibusb_readwrite_usb(dib
,sndbuf
,len
,rbuf
,rlen
);
39 * I2C master xfer function
41 static int dibusb_i2c_xfer(struct i2c_adapter
*adap
,struct i2c_msg
*msg
,int num
)
43 struct usb_dibusb
*dib
= i2c_get_adapdata(adap
);
46 if (down_interruptible(&dib
->i2c_sem
) < 0)
50 warn("more than 2 i2c messages at a time is not handled yet. TODO.");
52 for (i
= 0; i
< num
; i
++) {
53 /* write/read request */
54 if (i
+1 < num
&& (msg
[i
+1].flags
& I2C_M_RD
)) {
55 if (dibusb_i2c_msg(dib
, msg
[i
].addr
, msg
[i
].buf
,msg
[i
].len
,
56 msg
[i
+1].buf
,msg
[i
+1].len
) < 0)
60 if (dibusb_i2c_msg(dib
, msg
[i
].addr
, msg
[i
].buf
,msg
[i
].len
,NULL
,0) < 0)
68 static u32
dibusb_i2c_func(struct i2c_adapter
*adapter
)
73 static struct i2c_algorithm dibusb_algo
= {
74 .name
= "DiBcom USB i2c algorithm",
76 .master_xfer
= dibusb_i2c_xfer
,
77 .functionality
= dibusb_i2c_func
,
80 static int dibusb_general_demod_init(struct dvb_frontend
*fe
);
81 static u8
dibusb_general_pll_addr(struct dvb_frontend
*fe
);
82 static int dibusb_general_pll_init(struct dvb_frontend
*fe
, u8 pll_buf
[5]);
83 static int dibusb_general_pll_set(struct dvb_frontend
*fe
,
84 struct dvb_frontend_parameters
* params
, u8 pll_buf
[5]);
86 static struct mt352_config mt352_hanftek_umt_010_config
= {
87 .demod_address
= 0x1e,
88 .demod_init
= dibusb_general_demod_init
,
89 .pll_set
= dibusb_general_pll_set
,
92 static int dibusb_tuner_quirk(struct usb_dibusb
*dib
)
94 switch (dib
->dibdev
->dev_cl
->id
) {
95 case DIBUSB1_1
: /* some these device have the ENV77H11D5 and some the THOMSON CABLE */
96 case DIBUSB1_1_AN2235
: { /* actually its this device, but in warm state they are indistinguishable */
97 struct dibusb_tuner
*t
;
98 u8 b
[2] = { 0,0 } ,b2
[1];
99 struct i2c_msg msg
[2] = {
100 { .flags
= 0, .buf
= b
, .len
= 2 },
101 { .flags
= I2C_M_RD
, .buf
= b2
, .len
= 1},
104 t
= &dibusb_tuner
[DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5
];
106 msg
[0].addr
= msg
[1].addr
= t
->pll_addr
;
108 if (dib
->xfer_ops
.tuner_pass_ctrl
!= NULL
)
109 dib
->xfer_ops
.tuner_pass_ctrl(dib
->fe
,1,t
->pll_addr
);
110 dibusb_i2c_xfer(&dib
->i2c_adap
,msg
,2);
111 if (dib
->xfer_ops
.tuner_pass_ctrl
!= NULL
)
112 dib
->xfer_ops
.tuner_pass_ctrl(dib
->fe
,0,t
->pll_addr
);
115 info("this device has the Thomson Cable onboard. Which is default.");
118 info("this device has the Panasonic ENV77H11D5 onboard.");
128 int dibusb_fe_init(struct usb_dibusb
* dib
)
130 struct dib3000_config demod_cfg
;
133 if (dib
->init_state
& DIBUSB_STATE_I2C
) {
134 for (i
= 0; i
< sizeof(dib
->dibdev
->dev_cl
->demod
->i2c_addrs
) / sizeof(unsigned char) &&
135 dib
->dibdev
->dev_cl
->demod
->i2c_addrs
[i
] != 0; i
++) {
137 demod_cfg
.demod_address
= dib
->dibdev
->dev_cl
->demod
->i2c_addrs
[i
];
138 demod_cfg
.pll_addr
= dibusb_general_pll_addr
;
139 demod_cfg
.pll_set
= dibusb_general_pll_set
;
140 demod_cfg
.pll_init
= dibusb_general_pll_init
;
142 deb_info("demod id: %d %d\n",dib
->dibdev
->dev_cl
->demod
->id
,DTT200U_FE
);
144 switch (dib
->dibdev
->dev_cl
->demod
->id
) {
145 case DIBUSB_DIB3000MB
:
146 dib
->fe
= dib3000mb_attach(&demod_cfg
,&dib
->i2c_adap
,&dib
->xfer_ops
);
148 case DIBUSB_DIB3000MC
:
149 dib
->fe
= dib3000mc_attach(&demod_cfg
,&dib
->i2c_adap
,&dib
->xfer_ops
);
152 mt352_hanftek_umt_010_config
.demod_address
= dib
->dibdev
->dev_cl
->demod
->i2c_addrs
[i
];
153 dib
->fe
= mt352_attach(&mt352_hanftek_umt_010_config
, &dib
->i2c_adap
);
156 dib
->fe
= dtt200u_fe_attach(dib
,&dib
->xfer_ops
);
159 if (dib
->fe
!= NULL
) {
160 info("found demodulator at i2c address 0x%x",dib
->dibdev
->dev_cl
->demod
->i2c_addrs
[i
]);
164 /* if a frontend was found */
165 if (dib
->fe
!= NULL
) {
166 if (dib
->fe
->ops
->sleep
!= NULL
)
167 dib
->fe_sleep
= dib
->fe
->ops
->sleep
;
168 dib
->fe
->ops
->sleep
= dibusb_hw_sleep
;
170 if (dib
->fe
->ops
->init
!= NULL
)
171 dib
->fe_init
= dib
->fe
->ops
->init
;
172 dib
->fe
->ops
->init
= dibusb_hw_wakeup
;
174 /* setting the default tuner */
175 dib
->tuner
= dib
->dibdev
->dev_cl
->tuner
;
177 /* check which tuner is mounted on this device, in case this is unsure */
178 dibusb_tuner_quirk(dib
);
181 if (dib
->fe
== NULL
) {
182 err("A frontend driver was not found for device '%s'.",
186 if (dvb_register_frontend(&dib
->adapter
, dib
->fe
)) {
187 err("Frontend registration failed.");
188 if (dib
->fe
->ops
->release
)
189 dib
->fe
->ops
->release(dib
->fe
);
198 int dibusb_fe_exit(struct usb_dibusb
*dib
)
201 dvb_unregister_frontend(dib
->fe
);
205 int dibusb_i2c_init(struct usb_dibusb
*dib
)
209 dib
->adapter
.priv
= dib
;
211 strncpy(dib
->i2c_adap
.name
,dib
->dibdev
->name
,I2C_NAME_SIZE
);
212 #ifdef I2C_ADAP_CLASS_TV_DIGITAL
213 dib
->i2c_adap
.class = I2C_ADAP_CLASS_TV_DIGITAL
,
215 dib
->i2c_adap
.class = I2C_CLASS_TV_DIGITAL
,
217 dib
->i2c_adap
.algo
= &dibusb_algo
;
218 dib
->i2c_adap
.algo_data
= NULL
;
219 dib
->i2c_adap
.id
= I2C_ALGO_BIT
;
221 i2c_set_adapdata(&dib
->i2c_adap
, dib
);
223 if ((ret
= i2c_add_adapter(&dib
->i2c_adap
)) < 0)
224 err("could not add i2c adapter");
226 dib
->init_state
|= DIBUSB_STATE_I2C
;
231 int dibusb_i2c_exit(struct usb_dibusb
*dib
)
233 if (dib
->init_state
& DIBUSB_STATE_I2C
)
234 i2c_del_adapter(&dib
->i2c_adap
);
235 dib
->init_state
&= ~DIBUSB_STATE_I2C
;
240 /* pll stuff, maybe removed soon (thx to Gerd/Andrew in advance) */
241 static int thomson_cable_eu_pll_set(struct dvb_frontend_parameters
*fep
, u8 pllbuf
[4])
243 u32 tfreq
= (fep
->frequency
+ 36125000) / 62500;
246 if (fep
->frequency
> 403250000)
247 vu
= 1, p2
= 1, p1
= 0, p0
= 1;
248 else if (fep
->frequency
> 115750000)
249 vu
= 0, p2
= 1, p1
= 1, p0
= 0;
250 else if (fep
->frequency
> 44250000)
251 vu
= 0, p2
= 0, p1
= 1, p0
= 1;
255 pllbuf
[0] = (tfreq
>> 8) & 0x7f;
256 pllbuf
[1] = tfreq
& 0xff;
258 pllbuf
[3] = (vu
<< 7) | (p2
<< 2) | (p1
<< 1) | p0
;
262 static int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend_parameters
*fep
, u8 pllbuf
[4])
264 u32 freq_khz
= fep
->frequency
/ 1000;
265 u32 tfreq
= ((freq_khz
+ 36125)*6 + 500) / 1000;
266 u8 TA
, T210
, R210
, ctrl1
, cp210
, p4321
;
267 if (freq_khz
> 858000) {
268 err("frequency cannot be larger than 858 MHz.");
272 // contol data 1 : 1 | T/A=1 | T2,T1,T0 = 0,0,0 | R2,R1,R0 = 0,1,0
276 ctrl1
= (1 << 7) | (TA
<< 6) | (T210
<< 3) | R210
;
278 // ******** CHARGE PUMP CONFIG vs RF FREQUENCIES *****************
279 if (freq_khz
< 470000)
280 cp210
= 2; // VHF Low and High band ch E12 to E4 to E12
281 else if (freq_khz
< 526000)
282 cp210
= 4; // UHF band Ch E21 to E27
283 else // if (freq < 862000000)
284 cp210
= 5; // UHF band ch E28 to E69
286 //********************* BW select *******************************
287 if (freq_khz
< 153000)
288 p4321
= 1; // BW selected for VHF low
289 else if (freq_khz
< 470000)
290 p4321
= 2; // BW selected for VHF high E5 to E12
291 else // if (freq < 862000000)
292 p4321
= 4; // BW selection for UHF E21 to E69
294 pllbuf
[0] = (tfreq
>> 8) & 0xff;
295 pllbuf
[1] = (tfreq
>> 0) & 0xff;
296 pllbuf
[2] = 0xff & ctrl1
;
297 pllbuf
[3] = (cp210
<< 5) | (p4321
);
304 * Address Byte 1 1 0 0 0 MA1 MA0 R/~W=0
306 * Program divider byte 1 0 n14 n13 n12 n11 n10 n9 n8
307 * Program divider byte 2 n7 n6 n5 n4 n3 n2 n1 n0
309 * Control byte 1 1 T/A=1 T2 T1 T0 R2 R1 R0
310 * 1 T/A=0 0 0 ATC AL2 AL1 AL0
312 * Control byte 2 CP2 CP1 CP0 BS5 BS4 BS3 BS2 BS1
314 * MA0/1 = programmable address bits
315 * R/~W = read/write bit (0 for writing)
316 * N14-0 = programmable LO frequency
318 * T/A = test AGC bit (0 = next 6 bits AGC setting,
319 * 1 = next 6 bits test and reference divider ratio settings)
321 * R2-0 = reference divider ratio and programmable frequency step
322 * ATC = AGC current setting and time constant
323 * ATC = 0: AGC current = 220nA, AGC time constant = 2s
324 * ATC = 1: AGC current = 9uA, AGC time constant = 50ms
325 * AL2-0 = AGC take-over point bits
326 * CP2-0 = charge pump current
327 * BS5-1 = PMOS ports control bits;
328 * BSn = 0 corresponding port is off, high-impedance state (at power-on)
329 * BSn = 1 corresponding port is on
331 static int panasonic_cofdm_env77h11d5_tda6650_init(struct dvb_frontend
*fe
, u8 pllbuf
[4])
340 static int panasonic_cofdm_env77h11d5_tda6650_set (struct dvb_frontend_parameters
*fep
,u8 pllbuf
[4])
342 int tuner_frequency
= 0;
345 // determine charge pump
346 tuner_frequency
= fep
->frequency
+ 36166000;
347 if (tuner_frequency
< 87000000)
349 else if (tuner_frequency
< 130000000)
351 else if (tuner_frequency
< 160000000)
353 else if (tuner_frequency
< 200000000)
355 else if (tuner_frequency
< 290000000)
357 else if (tuner_frequency
< 420000000)
359 else if (tuner_frequency
< 480000000)
361 else if (tuner_frequency
< 620000000)
363 else if (tuner_frequency
< 830000000)
365 else if (tuner_frequency
< 895000000)
371 if (fep
->frequency
< 49000000)
373 else if (fep
->frequency
< 161000000)
375 else if (fep
->frequency
< 444000000)
377 else if (fep
->frequency
< 861000000)
383 switch (fep
->u
.ofdm
.bandwidth
) {
384 case BANDWIDTH_6_MHZ
:
385 case BANDWIDTH_7_MHZ
:
388 case BANDWIDTH_8_MHZ
:
396 // ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
397 tuner_frequency
= (((fep
->frequency
/ 1000) * 6) + 217496) / 1000;
399 // setup tuner buffer
400 pllbuf
[0] = (tuner_frequency
>> 8) & 0x7f;
401 pllbuf
[1] = tuner_frequency
& 0xff;
403 pllbuf
[3] = (cp
<< 5) | (filter
<< 3) | band
;
409 * Address Byte 1 1 0 0 0 MA1 MA0 R/~W=0
411 * Program divider byte 1 0 n14 n13 n12 n11 n10 n9 n8
412 * Program divider byte 2 n7 n6 n5 n4 n3 n2 n1 n0
414 * Control byte 1 CP T2 T1 T0 RSA RSB OS
416 * Band Switch byte X X X P4 P3 P2 P1 P0
418 * Auxiliary byte ATC AL2 AL1 AL0 0 0 0 0
420 * Address: MA1 MA0 Address
422 * 0 1 c2 (always valid)
426 static int lg_tdtp_e102p_tua6034(struct dvb_frontend_parameters
* fep
, u8 pllbuf
[4])
431 #define TUNER_MUL 62500
433 div
= (fep
->frequency
+ 36125000 + TUNER_MUL
/ 2) / TUNER_MUL
;
434 // div = ((fep->frequency/1000 + 36166) * 6) / 1000;
436 if (fep
->frequency
< 174500000)
437 p210
= 1; // not supported by the tdtp_e102p
438 else if (fep
->frequency
< 230000000) // VHF
443 if (fep
->u
.ofdm
.bandwidth
== BANDWIDTH_7_MHZ
)
448 pllbuf
[0] = (div
>> 8) & 0x7f;
449 pllbuf
[1] = div
& 0xff;
452 pllbuf
[3] = (p3
<< 3) | p210
;
457 static int lg_tdtp_e102p_mt352_demod_init(struct dvb_frontend
*fe
)
459 static u8 mt352_clock_config
[] = { 0x89, 0xb8, 0x2d };
460 static u8 mt352_reset
[] = { 0x50, 0x80 };
461 static u8 mt352_mclk_ratio
[] = { 0x8b, 0x00 };
462 static u8 mt352_adc_ctl_1_cfg
[] = { 0x8E, 0x40 };
463 static u8 mt352_agc_cfg
[] = { 0x67, 0x10, 0xa0 };
465 static u8 mt352_sec_agc_cfg1
[] = { 0x6a, 0xff };
466 static u8 mt352_sec_agc_cfg2
[] = { 0x6d, 0xff };
467 static u8 mt352_sec_agc_cfg3
[] = { 0x70, 0x40 };
468 static u8 mt352_sec_agc_cfg4
[] = { 0x7b, 0x03 };
469 static u8 mt352_sec_agc_cfg5
[] = { 0x7d, 0x0f };
471 static u8 mt352_acq_ctl
[] = { 0x53, 0x50 };
472 static u8 mt352_input_freq_1
[] = { 0x56, 0x31, 0x06 };
474 mt352_write(fe
, mt352_clock_config
, sizeof(mt352_clock_config
));
476 mt352_write(fe
, mt352_reset
, sizeof(mt352_reset
));
477 mt352_write(fe
, mt352_mclk_ratio
, sizeof(mt352_mclk_ratio
));
479 mt352_write(fe
, mt352_adc_ctl_1_cfg
, sizeof(mt352_adc_ctl_1_cfg
));
480 mt352_write(fe
, mt352_agc_cfg
, sizeof(mt352_agc_cfg
));
482 mt352_write(fe
, mt352_sec_agc_cfg1
, sizeof(mt352_sec_agc_cfg1
));
483 mt352_write(fe
, mt352_sec_agc_cfg2
, sizeof(mt352_sec_agc_cfg2
));
484 mt352_write(fe
, mt352_sec_agc_cfg3
, sizeof(mt352_sec_agc_cfg3
));
485 mt352_write(fe
, mt352_sec_agc_cfg4
, sizeof(mt352_sec_agc_cfg4
));
486 mt352_write(fe
, mt352_sec_agc_cfg5
, sizeof(mt352_sec_agc_cfg5
));
488 mt352_write(fe
, mt352_acq_ctl
, sizeof(mt352_acq_ctl
));
489 mt352_write(fe
, mt352_input_freq_1
, sizeof(mt352_input_freq_1
));
494 static int dibusb_general_demod_init(struct dvb_frontend
*fe
)
496 struct usb_dibusb
* dib
= (struct usb_dibusb
*) fe
->dvb
->priv
;
497 switch (dib
->dibdev
->dev_cl
->id
) {
499 return lg_tdtp_e102p_mt352_demod_init(fe
);
500 default: /* other device classes do not have device specific demod inits */
506 static u8
dibusb_general_pll_addr(struct dvb_frontend
*fe
)
508 struct usb_dibusb
* dib
= (struct usb_dibusb
*) fe
->dvb
->priv
;
509 return dib
->tuner
->pll_addr
;
512 static int dibusb_pll_i2c_helper(struct usb_dibusb
*dib
, u8 pll_buf
[5], u8 buf
[4])
514 if (pll_buf
== NULL
) {
515 struct i2c_msg msg
= {
516 .addr
= dib
->tuner
->pll_addr
,
521 if (i2c_transfer (&dib
->i2c_adap
, &msg
, 1) != 1)
525 pll_buf
[0] = dib
->tuner
->pll_addr
<< 1;
526 memcpy(&pll_buf
[1],buf
,4);
532 static int dibusb_general_pll_init(struct dvb_frontend
*fe
,
535 struct usb_dibusb
* dib
= (struct usb_dibusb
*) fe
->dvb
->priv
;
538 switch (dib
->tuner
->id
) {
539 case DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5
:
540 ret
= panasonic_cofdm_env77h11d5_tda6650_init(fe
,buf
);
549 return dibusb_pll_i2c_helper(dib
,pll_buf
,buf
);
552 static int dibusb_general_pll_set(struct dvb_frontend
*fe
,
553 struct dvb_frontend_parameters
*fep
, u8 pll_buf
[5])
555 struct usb_dibusb
* dib
= (struct usb_dibusb
*) fe
->dvb
->priv
;
559 switch (dib
->tuner
->id
) {
560 case DIBUSB_TUNER_CABLE_THOMSON
:
561 ret
= thomson_cable_eu_pll_set(fep
, buf
);
563 case DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5
:
564 ret
= panasonic_cofdm_env57h1xd5_pll_set(fep
, buf
);
566 case DIBUSB_TUNER_CABLE_LG_TDTP_E102P
:
567 ret
= lg_tdtp_e102p_tua6034(fep
, buf
);
569 case DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5
:
570 ret
= panasonic_cofdm_env77h11d5_tda6650_set(fep
,buf
);
573 warn("no pll programming routine found for tuner %d.\n",dib
->tuner
->id
);
581 return dibusb_pll_i2c_helper(dib
,pll_buf
,buf
);