2 Driver for Alps BSRV2 QPSK Frontend
4 Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include <linux/kernel.h>
24 #include <linux/module.h>
25 #include <linux/init.h>
26 #include <linux/string.h>
27 #include <linux/slab.h>
29 #include "dvb_frontend.h"
32 #define dprintk if (debug) printk
35 static struct dvb_frontend_info bsrv2_info
= {
38 .frequency_min
= 950000,
39 .frequency_max
= 2150000,
40 .frequency_stepsize
= 250, /* kHz for QPSK frontends */
41 .frequency_tolerance
= 29500,
42 .symbol_rate_min
= 1000000,
43 .symbol_rate_max
= 45000000,
44 /* . symbol_rate_tolerance = ???,*/
45 .notifier_delay
= 50, /* 1/20 s */
46 .caps
= FE_CAN_INVERSION_AUTO
|
47 FE_CAN_FEC_1_2
| FE_CAN_FEC_2_3
| FE_CAN_FEC_3_4
|
48 FE_CAN_FEC_5_6
| FE_CAN_FEC_7_8
| FE_CAN_FEC_AUTO
|
54 static u8 init_1893_tab
[] = {
55 0x01, 0xA4, 0x35, 0x81, 0x2A, 0x0d, 0x55, 0xC4,
56 0x09, 0x69, 0x00, 0x86, 0x4c, 0x28, 0x7F, 0x00,
57 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x80, 0x00, 0x31, 0xb0, 0x14, 0x00, 0xDC, 0x00,
59 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x55, 0x00, 0x00, 0x7f, 0x00
65 static u8 init_1893_wtab
[] =
67 1,1,1,1,1,1,1,1, 1,1,0,0,1,1,0,0,
68 0,1,0,0,0,0,0,0, 1,0,1,1,0,0,0,1,
69 1,1,1,0,0,0,0,0, 0,0,1,1,0,0,0,0,
74 static int ves1893_writereg (struct dvb_i2c_bus
*i2c
, u8 reg
, u8 data
)
76 u8 buf
[] = { 0x00, reg
, data
};
77 struct i2c_msg msg
= { .addr
= 0x08, .flags
= 0, .buf
= buf
, .len
= 3 };
80 if ((err
= i2c
->xfer (i2c
, &msg
, 1)) != 1) {
81 dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__
, err
, reg
, data
);
89 static u8
ves1893_readreg (struct dvb_i2c_bus
*i2c
, u8 reg
)
92 u8 b0
[] = { 0x00, reg
};
94 struct i2c_msg msg
[] = { { .addr
= 0x08, .flags
= 0, .buf
= b0
, .len
= 2 },
95 { .addr
= 0x08, .flags
= I2C_M_RD
, .buf
= b1
, .len
= 1 } };
97 ret
= i2c
->xfer (i2c
, msg
, 2);
100 dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__
, ret
);
106 static int sp5659_write (struct dvb_i2c_bus
*i2c
, u8 data
[4])
109 struct i2c_msg msg
= { .addr
= 0x61, .flags
= 0, .buf
= data
, .len
= 4 };
111 ret
= i2c
->xfer (i2c
, &msg
, 1);
114 printk("%s: i/o error (ret == %i)\n", __FUNCTION__
, ret
);
116 return (ret
!= 1) ? -1 : 0;
122 * set up the downconverter frequency divisor for a
123 * reference clock comparision frequency of 125 kHz.
125 static int sp5659_set_tv_freq (struct dvb_i2c_bus
*i2c
, u32 freq
, u8 pwr
)
127 u32 div
= (freq
+ 479500) / 125;
128 u8 buf
[4] = { (div
>> 8) & 0x7f, div
& 0xff, 0x95, (pwr
<< 5) | 0x30 };
130 return sp5659_write (i2c
, buf
);
134 static int ves1893_init (struct dvb_i2c_bus
*i2c
)
138 dprintk("%s: init chip\n", __FUNCTION__
);
141 if (init_1893_wtab
[i
])
142 ves1893_writereg (i2c
, i
, init_1893_tab
[i
]);
148 static int ves1893_clr_bit (struct dvb_i2c_bus
*i2c
)
150 ves1893_writereg (i2c
, 0, init_1893_tab
[0] & 0xfe);
151 ves1893_writereg (i2c
, 0, init_1893_tab
[0]);
152 ves1893_writereg (i2c
, 3, 0x00);
153 return ves1893_writereg (i2c
, 3, init_1893_tab
[3]);
157 static int ves1893_set_inversion (struct dvb_i2c_bus
*i2c
, fe_spectral_inversion_t inversion
)
162 * inversion on/off are interchanged because i and q seem to
163 * be swapped on the hardware
180 /* needs to be saved for FE_GET_FRONTEND */
181 init_1893_tab
[0x0c] = (init_1893_tab
[0x0c] & 0x3f) | val
;
183 return ves1893_writereg (i2c
, 0x0c, init_1893_tab
[0x0c]);
187 static int ves1893_set_fec (struct dvb_i2c_bus
*i2c
, fe_code_rate_t fec
)
190 return ves1893_writereg (i2c
, 0x0d, 0x08);
191 else if (fec
< FEC_1_2
|| fec
> FEC_8_9
)
194 return ves1893_writereg (i2c
, 0x0d, fec
- FEC_1_2
);
198 static fe_code_rate_t
ves1893_get_fec (struct dvb_i2c_bus
*i2c
)
200 return FEC_1_2
+ ((ves1893_readreg (i2c
, 0x0d) >> 4) & 0x7);
204 static int ves1893_set_symbolrate (struct dvb_i2c_bus
*i2c
, u32 srate
)
208 u8 ADCONF
, FCONF
, FNR
;
212 dprintk("%s: srate == %ud\n", __FUNCTION__
, (unsigned int) srate
);
214 if (srate
> 90100000UL/2)
215 srate
= 90100000UL/2;
220 #define MUL (1UL<<26)
221 #define FIN (90106000UL>>4)
226 tmp
= (tmp
% FIN
) << 8;
227 ratio
= (ratio
<< 8) + tmp
/ FIN
;
229 tmp
= (tmp
% FIN
) << 8;
230 ratio
= (ratio
<< 8) + tmp
/ FIN
;
234 if (ratio
< MUL
/3) FNR
= 0;
235 if (ratio
< (MUL
*11)/50) FNR
= 1;
236 if (ratio
< MUL
/6) FNR
= 2;
237 if (ratio
< MUL
/9) FNR
= 3;
238 if (ratio
< MUL
/12) FNR
= 4;
239 if (ratio
< (MUL
*11)/200) FNR
= 5;
240 if (ratio
< MUL
/24) FNR
= 6;
241 if (ratio
< (MUL
*27)/1000) FNR
= 7;
242 if (ratio
< MUL
/48) FNR
= 8;
243 if (ratio
< (MUL
*137)/10000) FNR
= 9;
251 FCONF
= 0x88 | (FNR
>> 1) | ((FNR
& 0x01) << 5);
254 BDR
= (( (ratio
<< (FNR
>> 1)) >> 4) + 1) >> 1;
255 BDRI
= ( ((FIN
<< 8) / ((srate
<< (FNR
>> 1)) >> 2)) + 1) >> 1;
257 dprintk("FNR= %d\n", FNR
);
258 dprintk("ratio= %08x\n", (unsigned int) ratio
);
259 dprintk("BDR= %08x\n", (unsigned int) BDR
);
260 dprintk("BDRI= %02x\n", (unsigned int) BDRI
);
265 ves1893_writereg (i2c
, 0x06, 0xff & BDR
);
266 ves1893_writereg (i2c
, 0x07, 0xff & (BDR
>> 8));
267 ves1893_writereg (i2c
, 0x08, 0x0f & (BDR
>> 16));
269 ves1893_writereg (i2c
, 0x09, BDRI
);
270 ves1893_writereg (i2c
, 0x20, ADCONF
);
271 ves1893_writereg (i2c
, 0x21, FCONF
);
274 ves1893_writereg (i2c
, 0x05, init_1893_tab
[0x05] | 0x80);
276 ves1893_writereg (i2c
, 0x05, init_1893_tab
[0x05] & 0x7f);
278 ves1893_writereg (i2c
, 0x00, 0x00);
279 ves1893_writereg (i2c
, 0x00, 0x01);
281 ves1893_clr_bit (i2c
);
287 static int ves1893_set_voltage (struct dvb_i2c_bus
*i2c
, fe_sec_voltage_t voltage
)
291 return ves1893_writereg (i2c
, 0x1f, 0x20);
293 return ves1893_writereg (i2c
, 0x1f, 0x30);
294 case SEC_VOLTAGE_OFF
:
295 return ves1893_writereg (i2c
, 0x1f, 0x00);
302 static int bsrv2_ioctl (struct dvb_frontend
*fe
, unsigned int cmd
, void *arg
)
304 struct dvb_i2c_bus
*i2c
= fe
->i2c
;
308 memcpy (arg
, &bsrv2_info
, sizeof(struct dvb_frontend_info
));
313 fe_status_t
*status
= arg
;
314 u8 sync
= ves1893_readreg (i2c
, 0x0e);
319 *status
|= FE_HAS_SIGNAL
;
322 *status
|= FE_HAS_CARRIER
;
325 *status
|= FE_HAS_VITERBI
;
328 *status
|= FE_HAS_SYNC
;
330 if ((sync
& 0x1f) == 0x1f)
331 *status
|= FE_HAS_LOCK
;
338 u32
*ber
= (u32
*) arg
;
340 *ber
= ves1893_readreg (i2c
, 0x15);
341 *ber
|= (ves1893_readreg (i2c
, 0x16) << 8);
342 *ber
|= ((ves1893_readreg (i2c
, 0x17) & 0x0f) << 16);
347 case FE_READ_SIGNAL_STRENGTH
:
349 u8 signal
= ~ves1893_readreg (i2c
, 0x0b);
350 *((u16
*) arg
) = (signal
<< 8) | signal
;
356 u8 snr
= ~ves1893_readreg (i2c
, 0x1c);
357 *(u16
*) arg
= (snr
<< 8) | snr
;
361 case FE_READ_UNCORRECTED_BLOCKS
:
363 *(u32
*) arg
= ves1893_readreg (i2c
, 0x18) & 0x7f;
365 if (*(u32
*) arg
== 0x7f)
366 *(u32
*) arg
= 0xffffffff; /* counter overflow... */
368 ves1893_writereg (i2c
, 0x18, 0x00); /* reset the counter */
369 ves1893_writereg (i2c
, 0x18, 0x80); /* dto. */
373 case FE_SET_FRONTEND
:
375 struct dvb_frontend_parameters
*p
= arg
;
377 sp5659_set_tv_freq (i2c
, p
->frequency
, 0);
378 ves1893_set_inversion (i2c
, p
->inversion
);
379 ves1893_set_fec (i2c
, p
->u
.qpsk
.fec_inner
);
380 // sp5659_set_tv_freq (i2c, p->frequency, 0);
381 ves1893_set_symbolrate (i2c
, p
->u
.qpsk
.symbol_rate
);
385 case FE_GET_FRONTEND
:
387 struct dvb_frontend_parameters
*p
= arg
;
390 afc
= ((int)((char)(ves1893_readreg (i2c
, 0x0a) << 1)))/2;
391 afc
= (afc
* (int)(p
->u
.qpsk
.symbol_rate
/1000/8))/16;
396 * inversion indicator is only valid
397 * if auto inversion was used
399 if (!(init_1893_tab
[0x0c] & 0x80))
400 p
->inversion
= (ves1893_readreg (i2c
, 0x0f) & 2) ?
401 INVERSION_OFF
: INVERSION_ON
;
402 p
->u
.qpsk
.fec_inner
= ves1893_get_fec (i2c
);
403 /* XXX FIXME: timing offset !! */
408 ves1893_writereg (i2c
, 0x1f, 0x00); /* LNB power off */
409 return ves1893_writereg (i2c
, 0x00, 0x08);
412 return ves1893_init (i2c
);
415 return ves1893_clr_bit (i2c
);
418 return -EOPNOTSUPP
; /* the ves1893 can generate the 22k */
419 /* let's implement this when we have */
420 /* a box that uses the 22K_0 pin... */
422 return ves1893_set_voltage (i2c
, (fe_sec_voltage_t
) arg
);
432 static int bsrv2_attach (struct dvb_i2c_bus
*i2c
)
434 if ((ves1893_readreg (i2c
, 0x1e) & 0xf0) != 0xd0)
437 dvb_register_frontend (bsrv2_ioctl
, i2c
, NULL
, &bsrv2_info
);
443 static void bsrv2_detach (struct dvb_i2c_bus
*i2c
)
445 dvb_unregister_frontend (bsrv2_ioctl
, i2c
);
449 static int __init
init_bsrv2 (void)
451 return dvb_register_i2c_device (THIS_MODULE
, bsrv2_attach
, bsrv2_detach
);
455 static void __exit
exit_bsrv2 (void)
457 dvb_unregister_i2c_device (bsrv2_attach
);
461 module_init(init_bsrv2
);
462 module_exit(exit_bsrv2
);
465 MODULE_DESCRIPTION("BSRV2 DVB-S Frontend");
466 MODULE_AUTHOR("Ralph Metzler");
467 MODULE_LICENSE("GPL");
468 MODULE_PARM(debug
,"i");