2 Driver for VES1893 and VES1993 QPSK Frontends
4 Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
5 Copyright (C) 2001 Ronny Strutz <3des@tuxbox.org>
6 Copyright (C) 2002 Dennis Noermann <dennis.noermann@noernet.de>
7 Copyright (C) 2002-2003 Andreas Oberritter <obi@tuxbox.org>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/string.h>
30 #include <linux/slab.h>
32 #include "dvb_frontend.h"
35 #define dprintk if (debug) printk
37 static int board_type
= 0;
38 #define BOARD_SIEMENS_PCI 0
39 #define BOARD_NOKIA_DBOX2 1
40 #define BOARD_SAGEM_DBOX2 2
42 static int demod_type
= 0;
43 #define DEMOD_VES1893 0
44 #define DEMOD_VES1993 1
46 static struct dvb_frontend_info ves1x93_info
= {
49 .frequency_min
= 950000,
50 .frequency_max
= 2150000,
51 .frequency_stepsize
= 250, /* kHz for QPSK frontends */
52 .frequency_tolerance
= 29500,
53 .symbol_rate_min
= 1000000,
54 .symbol_rate_max
= 45000000,
55 /* .symbol_rate_tolerance = ???,*/
56 .notifier_delay
= 50, /* 1/20 s */
57 .caps
= FE_CAN_INVERSION_AUTO
|
58 FE_CAN_FEC_1_2
| FE_CAN_FEC_2_3
| FE_CAN_FEC_3_4
|
59 FE_CAN_FEC_5_6
| FE_CAN_FEC_7_8
| FE_CAN_FEC_AUTO
|
65 * nokia dbox2 (ves1893) and sagem dbox2 (ves1993)
66 * need bit AGCR[PWMS] set to 1
69 static u8 init_1893_tab
[] = {
70 0x01, 0xa4, 0x35, 0x81, 0x2a, 0x0d, 0x55, 0xc4,
71 0x09, 0x69, 0x00, 0x86, 0x4c, 0x28, 0x7f, 0x00,
72 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x80, 0x00, 0x31, 0xb0, 0x14, 0x00, 0xdc, 0x00,
74 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x55, 0x00, 0x00, 0x7f, 0x00
80 static u8 init_1993_tab
[] = {
81 0x00, 0x9c, 0x35, 0x80, 0x6a, 0x09, 0x72, 0x8c,
82 0x09, 0x6b, 0x00, 0x00, 0x4c, 0x08, 0x00, 0x00,
83 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 0x80, 0x40, 0x21, 0xb0, 0x00, 0x00, 0x00, 0x10,
85 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
87 0x00, 0x55, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
88 0x00, 0x00, 0x0e, 0x80, 0x00
92 static u8
* init_1x93_tab
;
95 static u8 init_1893_wtab
[] =
97 1,1,1,1,1,1,1,1, 1,1,0,0,1,1,0,0,
98 0,1,0,0,0,0,0,0, 1,0,1,1,0,0,0,1,
99 1,1,1,0,0,0,0,0, 0,0,1,1,0,0,0,0,
104 static u8 init_1993_wtab
[] =
106 1,1,1,1,1,1,1,1, 1,1,0,0,1,1,0,0,
107 0,1,0,0,0,0,0,0, 1,1,1,1,0,0,0,1,
108 1,1,1,0,0,0,0,0, 0,0,1,1,0,0,0,0,
109 1,1,1,0,1,1,1,1, 1,1,1,1,1
113 static int ves1x93_writereg (struct dvb_i2c_bus
*i2c
, u8 reg
, u8 data
)
115 u8 buf
[] = { 0x00, reg
, data
};
116 struct i2c_msg msg
= { .addr
= 0x08, .flags
= 0, .buf
= buf
, .len
= 3 };
119 if ((err
= i2c
->xfer (i2c
, &msg
, 1)) != 1) {
120 dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__
, err
, reg
, data
);
128 static u8
ves1x93_readreg (struct dvb_i2c_bus
*i2c
, u8 reg
)
131 u8 b0
[] = { 0x00, reg
};
133 struct i2c_msg msg
[] = { { .addr
= 0x08, .flags
= 0, .buf
= b0
, .len
= 2 },
134 { .addr
= 0x08, .flags
= I2C_M_RD
, .buf
= b1
, .len
= 1 } };
136 ret
= i2c
->xfer (i2c
, msg
, 2);
139 dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__
, ret
);
145 static int tuner_write (struct dvb_i2c_bus
*i2c
, u8
*data
, u8 len
)
148 struct i2c_msg msg
= { .addr
= 0x61, .flags
= 0, .buf
= data
, .len
= len
};
150 ves1x93_writereg(i2c
, 0x00, 0x11);
151 ret
= i2c
->xfer (i2c
, &msg
, 1);
152 ves1x93_writereg(i2c
, 0x00, 0x01);
155 printk("%s: i/o error (ret == %i)\n", __FUNCTION__
, ret
);
157 return (ret
!= 1) ? -1 : 0;
163 * set up the downconverter frequency divisor for a
164 * reference clock comparision frequency of 125 kHz.
166 static int sp5659_set_tv_freq (struct dvb_i2c_bus
*i2c
, u32 freq
, u8 pwr
)
168 u32 div
= (freq
+ 479500) / 125;
169 u8 buf
[4] = { (div
>> 8) & 0x7f, div
& 0xff, 0x95, (pwr
<< 5) | 0x30 };
171 return tuner_write (i2c
, buf
, sizeof(buf
));
175 static int tsa5059_set_tv_freq (struct dvb_i2c_bus
*i2c
, u32 freq
)
182 buf
[0] = (freq
>> 8) & 0x7F;
183 buf
[1] = freq
& 0xFF;
185 ret
= tuner_write(i2c
, buf
, sizeof(buf
));
191 static int tuner_set_tv_freq (struct dvb_i2c_bus
*i2c
, u32 freq
, u8 pwr
)
193 if ((demod_type
== DEMOD_VES1893
) && (board_type
== BOARD_SIEMENS_PCI
))
194 return sp5659_set_tv_freq (i2c
, freq
, pwr
);
195 else if (demod_type
== DEMOD_VES1993
)
196 return tsa5059_set_tv_freq (i2c
, freq
);
202 static int ves1x93_init (struct dvb_i2c_bus
*i2c
)
208 dprintk("%s: init chip\n", __FUNCTION__
);
210 switch (demod_type
) {
212 init_1x93_tab
= init_1893_tab
;
213 init_1x93_wtab
= init_1893_wtab
;
214 size
= sizeof(init_1893_tab
);
215 if (board_type
== BOARD_NOKIA_DBOX2
)
216 init_1x93_tab
[0x05] |= 0x20; /* invert PWM */
220 init_1x93_tab
= init_1993_tab
;
221 init_1x93_wtab
= init_1993_wtab
;
222 size
= sizeof(init_1993_tab
);
223 if (board_type
== BOARD_SAGEM_DBOX2
)
224 init_1x93_tab
[0x05] |= 0x20; /* invert PWM */
231 for (i
= 0; i
< size
; i
++)
232 if (init_1x93_wtab
[i
])
233 ves1x93_writereg (i2c
, i
, init_1x93_tab
[i
]);
235 if (demod_type
== DEMOD_VES1993
) {
236 if (board_type
== BOARD_NOKIA_DBOX2
)
237 tuner_write(i2c
, "\x06\x5c\x83\x60", 4);
238 else if (board_type
== BOARD_SAGEM_DBOX2
)
239 tuner_write(i2c
, "\x25\x70\x92\x40", 4);
246 static int ves1x93_clr_bit (struct dvb_i2c_bus
*i2c
)
248 ves1x93_writereg (i2c
, 0, init_1x93_tab
[0] & 0xfe);
249 ves1x93_writereg (i2c
, 0, init_1x93_tab
[0]);
250 ves1x93_writereg (i2c
, 3, 0x00);
251 return ves1x93_writereg (i2c
, 3, init_1x93_tab
[3]);
255 static int ves1x93_set_inversion (struct dvb_i2c_bus
*i2c
, fe_spectral_inversion_t inversion
)
260 * inversion on/off are interchanged because i and q seem to
261 * be swapped on the hardware
278 /* needs to be saved for FE_GET_FRONTEND */
279 init_1x93_tab
[0x0c] = (init_1x93_tab
[0x0c] & 0x3f) | val
;
281 return ves1x93_writereg (i2c
, 0x0c, init_1x93_tab
[0x0c]);
285 static int ves1x93_set_fec (struct dvb_i2c_bus
*i2c
, fe_code_rate_t fec
)
288 return ves1x93_writereg (i2c
, 0x0d, 0x08);
289 else if (fec
< FEC_1_2
|| fec
> FEC_8_9
)
292 return ves1x93_writereg (i2c
, 0x0d, fec
- FEC_1_2
);
296 static fe_code_rate_t
ves1x93_get_fec (struct dvb_i2c_bus
*i2c
)
298 return FEC_1_2
+ ((ves1x93_readreg (i2c
, 0x0d) >> 4) & 0x7);
302 static int ves1x93_set_symbolrate (struct dvb_i2c_bus
*i2c
, u32 srate
)
306 u8 ADCONF
, FCONF
, FNR
;
311 dprintk("%s: srate == %d\n", __FUNCTION__
, (unsigned int) srate
);
313 switch (board_type
) {
314 case BOARD_SIEMENS_PCI
:
317 case BOARD_NOKIA_DBOX2
:
318 if (demod_type
== DEMOD_VES1893
)
320 else if (demod_type
== DEMOD_VES1993
)
325 case BOARD_SAGEM_DBOX2
:
338 #define MUL (1UL<<26)
340 FIN
= (XIN
+ 6000) >> 4;
345 tmp
= (tmp
% FIN
) << 8;
346 ratio
= (ratio
<< 8) + tmp
/ FIN
;
348 tmp
= (tmp
% FIN
) << 8;
349 ratio
= (ratio
<< 8) + tmp
/ FIN
;
353 if (ratio
< MUL
/3) FNR
= 0;
354 if (ratio
< (MUL
*11)/50) FNR
= 1;
355 if (ratio
< MUL
/6) FNR
= 2;
356 if (ratio
< MUL
/9) FNR
= 3;
357 if (ratio
< MUL
/12) FNR
= 4;
358 if (ratio
< (MUL
*11)/200) FNR
= 5;
359 if (ratio
< MUL
/24) FNR
= 6;
360 if (ratio
< (MUL
*27)/1000) FNR
= 7;
361 if (ratio
< MUL
/48) FNR
= 8;
362 if (ratio
< (MUL
*137)/10000) FNR
= 9;
370 FCONF
= 0x88 | (FNR
>> 1) | ((FNR
& 0x01) << 5);
371 /*FCONF = 0x80 | ((FNR & 0x01) << 5) | (((FNR > 1) & 0x03) << 3) | ((FNR >> 1) & 0x07);*/
374 BDR
= (( (ratio
<< (FNR
>> 1)) >> 4) + 1) >> 1;
375 BDRI
= ( ((FIN
<< 8) / ((srate
<< (FNR
>> 1)) >> 2)) + 1) >> 1;
377 dprintk("FNR= %d\n", FNR
);
378 dprintk("ratio= %08x\n", (unsigned int) ratio
);
379 dprintk("BDR= %08x\n", (unsigned int) BDR
);
380 dprintk("BDRI= %02x\n", (unsigned int) BDRI
);
385 ves1x93_writereg (i2c
, 0x06, 0xff & BDR
);
386 ves1x93_writereg (i2c
, 0x07, 0xff & (BDR
>> 8));
387 ves1x93_writereg (i2c
, 0x08, 0x0f & (BDR
>> 16));
389 ves1x93_writereg (i2c
, 0x09, BDRI
);
390 ves1x93_writereg (i2c
, 0x20, ADCONF
);
391 ves1x93_writereg (i2c
, 0x21, FCONF
);
394 ves1x93_writereg (i2c
, 0x05, init_1x93_tab
[0x05] | 0x80);
396 ves1x93_writereg (i2c
, 0x05, init_1x93_tab
[0x05] & 0x7f);
398 ves1x93_writereg (i2c
, 0x00, 0x00);
399 ves1x93_writereg (i2c
, 0x00, 0x01);
401 /* ves1993 hates this, will lose lock */
402 if (demod_type
!= DEMOD_VES1993
)
403 ves1x93_clr_bit (i2c
);
409 static int ves1x93_set_voltage (struct dvb_i2c_bus
*i2c
, fe_sec_voltage_t voltage
)
413 return ves1x93_writereg (i2c
, 0x1f, 0x20);
415 return ves1x93_writereg (i2c
, 0x1f, 0x30);
416 case SEC_VOLTAGE_OFF
:
417 return ves1x93_writereg (i2c
, 0x1f, 0x00);
424 static int ves1x93_ioctl (struct dvb_frontend
*fe
, unsigned int cmd
, void *arg
)
426 struct dvb_i2c_bus
*i2c
= fe
->i2c
;
430 memcpy (arg
, &ves1x93_info
, sizeof(struct dvb_frontend_info
));
435 fe_status_t
*status
= arg
;
436 u8 sync
= ves1x93_readreg (i2c
, 0x0e);
441 *status
|= FE_HAS_SIGNAL
;
444 *status
|= FE_HAS_CARRIER
;
447 *status
|= FE_HAS_VITERBI
;
450 *status
|= FE_HAS_SYNC
;
452 if ((sync
& 0x1f) == 0x1f)
453 *status
|= FE_HAS_LOCK
;
460 u32
*ber
= (u32
*) arg
;
462 *ber
= ves1x93_readreg (i2c
, 0x15);
463 *ber
|= (ves1x93_readreg (i2c
, 0x16) << 8);
464 *ber
|= ((ves1x93_readreg (i2c
, 0x17) & 0x0F) << 16);
469 case FE_READ_SIGNAL_STRENGTH
:
471 u8 signal
= ~ves1x93_readreg (i2c
, 0x0b);
472 *((u16
*) arg
) = (signal
<< 8) | signal
;
478 u8 snr
= ~ves1x93_readreg (i2c
, 0x1c);
479 *(u16
*) arg
= (snr
<< 8) | snr
;
483 case FE_READ_UNCORRECTED_BLOCKS
:
485 *(u32
*) arg
= ves1x93_readreg (i2c
, 0x18) & 0x7f;
487 if (*(u32
*) arg
== 0x7f)
488 *(u32
*) arg
= 0xffffffff; /* counter overflow... */
490 ves1x93_writereg (i2c
, 0x18, 0x00); /* reset the counter */
491 ves1x93_writereg (i2c
, 0x18, 0x80); /* dto. */
495 case FE_SET_FRONTEND
:
497 struct dvb_frontend_parameters
*p
= arg
;
499 tuner_set_tv_freq (i2c
, p
->frequency
, 0);
500 ves1x93_set_inversion (i2c
, p
->inversion
);
501 ves1x93_set_fec (i2c
, p
->u
.qpsk
.fec_inner
);
502 ves1x93_set_symbolrate (i2c
, p
->u
.qpsk
.symbol_rate
);
506 case FE_GET_FRONTEND
:
508 struct dvb_frontend_parameters
*p
= arg
;
511 afc
= ((int)((char)(ves1x93_readreg (i2c
, 0x0a) << 1)))/2;
512 afc
= (afc
* (int)(p
->u
.qpsk
.symbol_rate
/1000/8))/16;
517 * inversion indicator is only valid
518 * if auto inversion was used
520 if (!(init_1x93_tab
[0x0c] & 0x80))
521 p
->inversion
= (ves1x93_readreg (i2c
, 0x0f) & 2) ?
522 INVERSION_OFF
: INVERSION_ON
;
523 p
->u
.qpsk
.fec_inner
= ves1x93_get_fec (i2c
);
524 /* XXX FIXME: timing offset !! */
529 if (board_type
== BOARD_SIEMENS_PCI
)
530 ves1x93_writereg (i2c
, 0x1f, 0x00); /* LNB power off */
531 return ves1x93_writereg (i2c
, 0x00, 0x08);
534 return ves1x93_init (i2c
);
537 return ves1x93_clr_bit (i2c
);
540 return -EOPNOTSUPP
; /* the ves1893 can generate the 22k */
541 /* let's implement this when we have */
542 /* a box that uses the 22K_0 pin... */
545 return ves1x93_set_voltage (i2c
, (fe_sec_voltage_t
) arg
);
555 static int ves1x93_attach (struct dvb_i2c_bus
*i2c
, void **data
)
557 u8 identity
= ves1x93_readreg(i2c
, 0x1e);
560 case 0xdc: /* VES1893A rev1 */
561 case 0xdd: /* VES1893A rev2 */
562 demod_type
= DEMOD_VES1893
;
563 ves1x93_info
.name
[4] = '8';
565 case 0xde: /* VES1993 */
566 demod_type
= DEMOD_VES1993
;
567 ves1x93_info
.name
[4] = '9';
570 dprintk("VES1x93 not found (identity %02x)\n", identity
);
574 return dvb_register_frontend (ves1x93_ioctl
, i2c
, NULL
, &ves1x93_info
);
578 static void ves1x93_detach (struct dvb_i2c_bus
*i2c
, void *data
)
580 dvb_unregister_frontend (ves1x93_ioctl
, i2c
);
584 static int __init
init_ves1x93 (void)
586 switch (board_type
) {
587 case BOARD_NOKIA_DBOX2
:
588 dprintk("%s: NOKIA_DBOX2\n", __FILE__
);
590 case BOARD_SAGEM_DBOX2
:
591 dprintk("%s: SAGEM_DBOX2\n", __FILE__
);
593 case BOARD_SIEMENS_PCI
:
594 dprintk("%s: SIEMENS_PCI\n", __FILE__
);
600 return dvb_register_i2c_device (THIS_MODULE
, ves1x93_attach
, ves1x93_detach
);
604 static void __exit
exit_ves1x93 (void)
606 dvb_unregister_i2c_device (ves1x93_attach
);
610 module_init(init_ves1x93
);
611 module_exit(exit_ves1x93
);
614 MODULE_DESCRIPTION("VES1x93 DVB-S Frontend");
615 MODULE_AUTHOR("Ralph Metzler");
616 MODULE_LICENSE("GPL");
617 MODULE_PARM(debug
,"i");
618 MODULE_PARM(board_type
,"i");