4 * Atmel DVB-C Frontend Driver (at76c651/dat7021)
6 * Copyright (C) 2001 fnbrd <fnbrd@gmx.de>
7 * & 2002 Andreas Oberritter <obi@linuxtv.org>
8 * & 2003 Wolfram Joost <dbox2@frokaschwei.de>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * 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/init.h>
27 #include <linux/module.h>
28 #include <linux/kernel.h>
29 #include <linux/string.h>
30 #include <linux/slab.h>
32 #if defined(__powerpc__)
33 #include <asm/bitops.h>
36 #include "dvb_frontend.h"
38 #include "dvb_functions.h"
41 static u8 at76c651_qam;
42 static u8 at76c651_revision;
44 #define dprintk if (debug) printk
49 * Input Frequency Range (RF): 48.25 MHz to 863.25 MHz
51 * Level Input (Range for Digital Signals): -61 dBm to -41 dBm
52 * Output Frequency (IF): 36 MHz
54 * (see http://www.atmel.com/atmel/acrobat/doc1320.pdf)
57 static struct dvb_frontend_info at76c651_info = {
59 .name = "Atmel AT76C651(B) with DAT7021",
61 .frequency_min = 48250000,
62 .frequency_max = 863250000,
63 .frequency_stepsize = 62500,
64 /*.frequency_tolerance = */ /* FIXME: 12% of SR */
65 .symbol_rate_min = 0, /* FIXME */
66 .symbol_rate_max = 9360000, /* FIXME */
67 .symbol_rate_tolerance = 4000,
69 .caps = FE_CAN_INVERSION_AUTO |
70 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
71 FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
72 FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
73 FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 |
74 FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER
77 #if ! defined(__powerpc__)
78 static __inline__ int __ilog2(unsigned long x)
85 for (i = 0; x != 0; i++)
92 static int at76c651_writereg(struct dvb_i2c_bus *i2c, u8 reg, u8 data)
96 u8 buf[] = { reg, data };
97 struct i2c_msg msg = { .addr = 0x1a >> 1, .flags = 0, .buf = buf, .len = 2 };
99 ret = i2c->xfer(i2c, &msg, 1);
102 dprintk("%s: writereg error "
103 "(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
104 __FUNCTION__, reg, data, ret);
108 return (ret != 1) ? -EREMOTEIO : 0;
112 static u8 at76c651_readreg(struct dvb_i2c_bus *i2c, u8 reg)
118 struct i2c_msg msg[] = { {.addr = 0x1a >> 1, .flags = 0, .buf = b0, .len = 1},
119 {.addr = 0x1a >> 1, .flags = I2C_M_RD, .buf = b1, .len = 1} };
121 ret = i2c->xfer(i2c, msg, 2);
124 dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
130 static int at76c651_reset(struct dvb_i2c_bus *i2c)
133 return at76c651_writereg(i2c, 0x07, 0x01);
137 static int at76c651_disable_interrupts(struct dvb_i2c_bus *i2c)
140 return at76c651_writereg(i2c, 0x0b, 0x00);
144 static int at76c651_set_auto_config(struct dvb_i2c_bus *i2c)
151 at76c651_writereg(i2c, 0x06, 0x01);
154 * Performance optimizations, should be done after autoconfig
157 at76c651_writereg(i2c, 0x10, 0x06);
158 at76c651_writereg(i2c, 0x11, ((at76c651_qam == 5) || (at76c651_qam == 7)) ? 0x12 : 0x10);
159 at76c651_writereg(i2c, 0x15, 0x28);
160 at76c651_writereg(i2c, 0x20, 0x09);
161 at76c651_writereg(i2c, 0x24, ((at76c651_qam == 5) || (at76c651_qam == 7)) ? 0xC0 : 0x90);
162 at76c651_writereg(i2c, 0x30, 0x90);
163 if (at76c651_qam == 5)
164 at76c651_writereg(i2c, 0x35, 0x2A);
167 * Initialize A/D-converter
170 if (at76c651_revision == 0x11) {
171 at76c651_writereg(i2c, 0x2E, 0x38);
172 at76c651_writereg(i2c, 0x2F, 0x13);
175 at76c651_disable_interrupts(i2c);
187 static int at76c651_set_bbfreq(struct dvb_i2c_bus *i2c)
190 at76c651_writereg(i2c, 0x04, 0x3f);
191 at76c651_writereg(i2c, 0x05, 0xee);
197 static int at76c651_switch_tuner_i2c(struct dvb_i2c_bus *i2c, u8 enable)
201 return at76c651_writereg(i2c, 0x0c, 0xc2 | 0x01);
203 return at76c651_writereg(i2c, 0x0c, 0xc2);
207 static int dat7021_write(struct dvb_i2c_bus *i2c, u32 tw)
212 { .addr = 0xc2 >> 1, .flags = 0, .buf = (u8 *) & tw, .len = sizeof (tw) };
214 #ifdef __LITTLE_ENDIAN
215 tw = __cpu_to_be32(tw);
218 at76c651_switch_tuner_i2c(i2c, 1);
220 ret = i2c->xfer(i2c, &msg, 1);
222 at76c651_switch_tuner_i2c(i2c, 0);
233 static int dat7021_set_tv_freq(struct dvb_i2c_bus *i2c, u32 freq)
240 if ((freq < 48250) || (freq > 863250))
244 * formula: dw=0x17e28e06+(freq-346000UL)/8000UL*0x800000
245 * or: dw=0x4E28E06+(freq-42000) / 125 * 0x20000
248 dw = (freq - 42000) * 4096;
257 return dat7021_write(i2c, dw);
261 static int at76c651_set_symbolrate(struct dvb_i2c_bus *i2c, u32 symbolrate)
267 if (symbolrate > 9360000)
272 * exponent = 10 + floor ( log2 ( symbolrate / FREF ) )
273 * mantissa = ( symbolrate / FREF) * ( 1 << ( 30 - exponent ) )
276 exponent = __ilog2((symbolrate << 4) / 903125);
277 mantissa = ((symbolrate / 3125) * (1 << (24 - exponent))) / 289;
279 at76c651_writereg(i2c, 0x00, mantissa >> 13);
280 at76c651_writereg(i2c, 0x01, mantissa >> 5);
281 at76c651_writereg(i2c, 0x02, (mantissa << 3) | exponent);
287 static int at76c651_set_qam(struct dvb_i2c_bus *i2c, fe_modulation_t qam)
322 return at76c651_writereg(i2c, 0x03, at76c651_qam);
326 static int at76c651_set_inversion(struct dvb_i2c_bus *i2c,
327 fe_spectral_inversion_t inversion)
330 u8 feciqinv = at76c651_readreg(i2c, 0x60);
350 return at76c651_writereg(i2c, 0x60, feciqinv);
354 static int at76c651_set_parameters(struct dvb_i2c_bus *i2c,
355 struct dvb_frontend_parameters *p)
358 dat7021_set_tv_freq(i2c, p->frequency);
359 at76c651_set_symbolrate(i2c, p->u.qam.symbol_rate);
360 at76c651_set_inversion(i2c, p->inversion);
361 at76c651_set_auto_config(i2c);
368 static int at76c651_set_defaults(struct dvb_i2c_bus *i2c)
371 at76c651_set_symbolrate(i2c, 6900000);
372 at76c651_set_qam(i2c, QAM_64);
373 at76c651_set_bbfreq(i2c);
374 at76c651_set_auto_config(i2c);
380 static int at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
386 memcpy(arg, &at76c651_info, sizeof (struct dvb_frontend_info));
392 fe_status_t *status = (fe_status_t *) arg;
396 * Bits: FEC, CAR, EQU, TIM, AGC2, AGC1, ADC, PLL (PLL=0)
398 sync = at76c651_readreg(fe->i2c, 0x80);
402 if (sync & (0x04 | 0x10)) /* AGC1 || TIM */
403 *status |= FE_HAS_SIGNAL;
405 if (sync & 0x10) /* TIM */
406 *status |= FE_HAS_CARRIER;
408 if (sync & 0x80) /* FEC */
409 *status |= FE_HAS_VITERBI;
411 if (sync & 0x40) /* CAR */
412 *status |= FE_HAS_SYNC;
414 if ((sync & 0xF0) == 0xF0) /* TIM && EQU && CAR && FEC */
415 *status |= FE_HAS_LOCK;
423 u32 *ber = (u32 *) arg;
425 *ber = (at76c651_readreg(fe->i2c, 0x81) & 0x0F) << 16;
426 *ber |= at76c651_readreg(fe->i2c, 0x82) << 8;
427 *ber |= at76c651_readreg(fe->i2c, 0x83);
433 case FE_READ_SIGNAL_STRENGTH:
435 u8 gain = ~at76c651_readreg(fe->i2c, 0x91);
437 *(u16 *) arg = (gain << 8) | gain;
444 ((at76c651_readreg(fe->i2c, 0x8F) << 8) |
445 at76c651_readreg(fe->i2c, 0x90));
448 case FE_READ_UNCORRECTED_BLOCKS:
449 *(u32 *) arg = at76c651_readreg(fe->i2c, 0x82);
452 case FE_SET_FRONTEND:
453 return at76c651_set_parameters(fe->i2c, arg);
455 case FE_GET_FRONTEND:
462 return at76c651_set_defaults(fe->i2c);
464 case FE_GET_TUNE_SETTINGS:
466 struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg;
467 fesettings->min_delay_ms = 50;
468 fesettings->step_size = 0;
469 fesettings->max_drift = 0;
481 static int at76c651_attach(struct dvb_i2c_bus *i2c, void **data)
483 if ( (at76c651_readreg(i2c, 0x0E) != 0x65) ||
484 ( ( (at76c651_revision = at76c651_readreg(i2c, 0x0F)) & 0xFE) != 0x10) )
486 dprintk("no AT76C651(B) found\n");
490 if (at76c651_revision == 0x10)
492 dprintk("AT76C651A found\n");
493 strcpy(at76c651_info.name,"Atmel AT76C651A with DAT7021");
497 strcpy(at76c651_info.name,"Atmel AT76C651B with DAT7021");
498 dprintk("AT76C651B found\n");
501 at76c651_set_defaults(i2c);
503 return dvb_register_frontend(at76c651_ioctl, i2c, NULL, &at76c651_info);
507 static void at76c651_detach(struct dvb_i2c_bus *i2c, void *data)
510 dvb_unregister_frontend(at76c651_ioctl, i2c);
514 static int __init at76c651_init(void)
517 return dvb_register_i2c_device(THIS_MODULE, at76c651_attach,
522 static void __exit at76c651_exit(void)
525 dvb_unregister_i2c_device(at76c651_attach);
529 module_init(at76c651_init);
530 module_exit(at76c651_exit);
532 MODULE_DESCRIPTION("at76c651/dat7021 dvb-c frontend driver");
533 MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
534 MODULE_LICENSE("GPL");
535 MODULE_PARM(debug, "i");