2 Driver for Alps TDLB7 Frontend
4 Copyright (C) 1999 Juergen Peitz
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.
25 This driver needs a copy of the firmware file 'Sc_main.mc' from the Haupauge
26 windows driver in the '/usr/lib/DVB/driver/frontends' directory.
27 You can also pass the complete file name with the module parameter 'firmware_file'.
32 #define __KERNEL_SYSCALLS__
33 #include <linux/module.h>
34 #include <linux/init.h>
35 #include <linux/vmalloc.h>
37 #include <linux/unistd.h>
38 #include <linux/delay.h>
39 #include <linux/syscalls.h>
41 #include "dvb_frontend.h"
42 #include "dvb_functions.h"
44 #ifndef CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION
45 #define CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION "/usr/lib/DVB/driver/frontends/Sc_main.mc"
48 static char * firmware_file = CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION;
51 #define dprintk if (debug) printk
53 /* firmware size for sp8870 */
54 #define SP8870_FIRMWARE_SIZE 16382
56 /* starting point for firmware in file 'Sc_main.mc' */
57 #define SP8870_FIRMWARE_OFFSET 0x0A
62 static struct dvb_frontend_info tdlb7_info = {
65 .frequency_min = 470000000,
66 .frequency_max = 860000000,
67 .frequency_stepsize = 166666,
68 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
69 FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 |
70 FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
71 FE_CAN_QPSK | FE_CAN_QAM_16 |
72 FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
73 FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER
77 static int sp8870_writereg (struct dvb_i2c_bus *i2c, u16 reg, u16 data)
79 u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff };
80 struct i2c_msg msg = { .addr = 0x71, .flags = 0, .buf = buf, .len = 4 };
83 if ((err = i2c->xfer (i2c, &msg, 1)) != 1) {
84 dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
92 static u16 sp8870_readreg (struct dvb_i2c_bus *i2c, u16 reg)
95 u8 b0 [] = { reg >> 8 , reg & 0xff };
97 struct i2c_msg msg [] = { { .addr = 0x71, .flags = 0, .buf = b0, .len = 2 },
98 { .addr = 0x71, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
100 ret = i2c->xfer (i2c, msg, 2);
103 dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
107 return (b1[0] << 8 | b1[1]);
111 static int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4])
114 struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = 4 };
116 ret = i2c->xfer (i2c, &msg, 1);
119 printk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret);
121 return (ret != 1) ? -1 : 0;
125 static void sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq)
127 u32 div = (freq + 36200000) / 166666;
131 if (freq <= 782000000)
136 buf[0] = (div >> 8) & 0x7f;
141 /* open i2c gate for PLL message transmission... */
142 sp8870_writereg(i2c, 0x206, 0x001);
143 sp5659_write (i2c, buf);
144 sp8870_writereg(i2c, 0x206, 0x000);
148 static int sp8870_read_firmware_file (const char *fn, char **fp)
156 printk("%s: unable to open '%s'.\n", __FUNCTION__, fn);
160 filesize = lseek(fd, 0L, 2);
161 if (filesize <= 0 || filesize < SP8870_FIRMWARE_OFFSET + SP8870_FIRMWARE_SIZE) {
162 printk("%s: firmware filesize to small '%s'\n", __FUNCTION__, fn);
167 *fp= dp = vmalloc(SP8870_FIRMWARE_SIZE);
169 printk("%s: out of memory loading '%s'.\n", __FUNCTION__, fn);
174 lseek(fd, SP8870_FIRMWARE_OFFSET, 0);
175 if (read(fd, dp, SP8870_FIRMWARE_SIZE) != SP8870_FIRMWARE_SIZE) {
176 printk("%s: failed to read '%s'.\n",__FUNCTION__, fn);
189 static int sp8870_firmware_upload (struct dvb_i2c_bus *i2c)
197 mm_segment_t fs = get_fs();
199 dprintk ("%s: ...\n", __FUNCTION__);
201 // system controller stop
202 sp8870_writereg(i2c,0x0F00,0x0000);
204 // instruction RAM register hiword
205 sp8870_writereg(i2c, 0x8F08, ((SP8870_FIRMWARE_SIZE / 2) & 0xFFFF));
207 // instruction RAM MWR
208 sp8870_writereg(i2c, 0x8F0A, ((SP8870_FIRMWARE_SIZE / 2) >> 16));
210 // reading firmware file to buffer
212 err = sp8870_read_firmware_file(firmware_file, (char**) &fw_buf);
215 printk("%s: reading firmware file failed!\n", __FUNCTION__);
219 // do firmware upload
221 while (fw_pos < SP8870_FIRMWARE_SIZE){
222 tx_len = (fw_pos <= SP8870_FIRMWARE_SIZE - 252) ? 252 : SP8870_FIRMWARE_SIZE - fw_pos;
223 // write register 0xCF0A
226 memcpy(&tx_buf[2], fw_buf + fw_pos, tx_len);
230 msg.len = tx_len + 2;
231 if ((err = i2c->xfer (i2c, &msg, 1)) != 1) {
232 printk("%s: firmware upload failed!\n", __FUNCTION__);
233 printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
242 dprintk ("%s: done!\n", __FUNCTION__);
247 static void sp8870_microcontroller_stop (struct dvb_i2c_bus *i2c)
249 sp8870_writereg(i2c, 0x0F08, 0x000);
250 sp8870_writereg(i2c, 0x0F09, 0x000);
252 // microcontroller STOP
253 sp8870_writereg(i2c, 0x0F00, 0x000);
257 static void sp8870_microcontroller_start (struct dvb_i2c_bus *i2c)
259 sp8870_writereg(i2c, 0x0F08, 0x000);
260 sp8870_writereg(i2c, 0x0F09, 0x000);
262 // microcontroller START
263 sp8870_writereg(i2c, 0x0F00, 0x001);
264 // not documented but if we don't read 0x0D01 out here
265 // we don't get a correct data valid signal
266 sp8870_readreg(i2c, 0x0D01);
270 static int sp8870_init (struct dvb_i2c_bus *i2c)
272 dprintk ("%s\n", __FUNCTION__);
274 /* enable TS output and interface pins */
275 sp8870_writereg(i2c, 0xc18, 0x00d);
277 // system controller stop
278 sp8870_microcontroller_stop(i2c);
281 sp8870_writereg(i2c,0x0301,0x0003);
283 // Reed Solomon parity bytes passed to output
284 sp8870_writereg(i2c,0x0C13,0x0001);
286 // MPEG clock is suppressed if no valid data
287 sp8870_writereg(i2c,0x0C14,0x0001);
289 /* bit 0x010: enable data valid signal */
290 sp8870_writereg(i2c, 0x0D00, 0x010);
291 sp8870_writereg(i2c, 0x0D01, 0x000);
297 static int sp8870_read_status (struct dvb_i2c_bus *i2c, fe_status_t * fe_status)
304 status = sp8870_readreg (i2c, 0x0200);
308 signal = sp8870_readreg (i2c, 0x0303);
313 *fe_status |= FE_HAS_SIGNAL;
315 *fe_status |= FE_HAS_SYNC;
317 *fe_status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_VITERBI;
323 static int sp8870_read_ber (struct dvb_i2c_bus *i2c, u32 * ber)
330 ret = sp8870_readreg(i2c, 0xC08);
336 ret = sp8870_readreg(i2c, 0xC07);
351 static int sp8870_read_signal_strength (struct dvb_i2c_bus *i2c, u16 * signal)
358 ret = sp8870_readreg (i2c, 0x306);
364 ret = sp8870_readreg (i2c, 0x303);
371 *signal = 0xFFFF - tmp;
377 static int sp8870_read_snr(struct dvb_i2c_bus *i2c, u32* snr)
384 static int sp8870_read_uncorrected_blocks (struct dvb_i2c_bus *i2c, u32* ublocks)
390 ret = sp8870_readreg(i2c, 0xC0C);
403 static int sp8870_read_data_valid_signal(struct dvb_i2c_bus *i2c)
405 return (sp8870_readreg(i2c, 0x0D02) > 0);
410 int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
412 int known_parameters = 1;
416 switch (p->u.ofdm.constellation) {
420 *reg0xc05 |= (1 << 10);
423 *reg0xc05 |= (2 << 10);
426 known_parameters = 0;
432 switch (p->u.ofdm.hierarchy_information) {
436 *reg0xc05 |= (1 << 7);
439 *reg0xc05 |= (2 << 7);
442 *reg0xc05 |= (3 << 7);
445 known_parameters = 0;
451 switch (p->u.ofdm.code_rate_HP) {
455 *reg0xc05 |= (1 << 3);
458 *reg0xc05 |= (2 << 3);
461 *reg0xc05 |= (3 << 3);
464 *reg0xc05 |= (4 << 3);
467 known_parameters = 0;
473 if (known_parameters)
474 *reg0xc05 |= (2 << 1); /* use specified parameters */
476 *reg0xc05 |= (1 << 1); /* enable autoprobing */
482 static int sp8870_set_frontend_parameters (struct dvb_i2c_bus *i2c,
483 struct dvb_frontend_parameters *p)
488 if ((err = configure_reg0xc05(p, ®0xc05)))
491 // system controller stop
492 sp8870_microcontroller_stop(i2c);
494 // set tuner parameters
495 sp5659_set_tv_freq (i2c, p->frequency);
497 // sample rate correction bit [23..17]
498 sp8870_writereg(i2c,0x0319,0x000A);
500 // sample rate correction bit [16..0]
501 sp8870_writereg(i2c,0x031A,0x0AAB);
503 // integer carrier offset
504 sp8870_writereg(i2c,0x0309,0x0400);
506 // fractional carrier offset
507 sp8870_writereg(i2c,0x030A,0x0000);
509 // filter for 6/7/8 Mhz channel
510 if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
511 sp8870_writereg(i2c,0x0311,0x0002);
512 else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
513 sp8870_writereg(i2c,0x0311,0x0001);
515 sp8870_writereg(i2c,0x0311,0x0000);
517 // scan order: 2k first = 0x0000, 8k first = 0x0001
518 if (p->u.ofdm.transmission_mode == TRANSMISSION_MODE_2K)
519 sp8870_writereg(i2c,0x0338,0x0000);
521 sp8870_writereg(i2c,0x0338,0x0001);
523 sp8870_writereg(i2c, 0xc05, reg0xc05);
525 // read status reg in order to clear pending irqs
526 sp8870_readreg(i2c, 0x200);
528 // system controller start
529 sp8870_microcontroller_start(i2c);
535 // number of trials to recover from lockup
537 // maximum checks for data valid signal
538 #define MAXCHECKS 100
540 // only for debugging: counter for detected lockups
541 static int lockups = 0;
542 // only for debugging: counter for channel switches
543 static int switches = 0;
545 static int sp8870_set_frontend (struct dvb_i2c_bus *i2c, struct dvb_frontend_parameters *p)
548 The firmware of the sp8870 sometimes locks up after setting frontend parameters.
549 We try to detect this by checking the data valid signal.
550 If it is not set after MAXCHECKS we try to recover the lockup by setting
551 the frontend parameters again.
559 dprintk("%s: frequency = %i\n", __FUNCTION__, p->frequency);
561 for (trials = 1; trials <= MAXTRIALS; trials++) {
563 if ((err = sp8870_set_frontend_parameters(i2c, p)))
566 for (check_count = 0; check_count < MAXCHECKS; check_count++) {
567 // valid = ((sp8870_readreg(i2c, 0x0200) & 4) == 0);
568 valid = sp8870_read_data_valid_signal(i2c);
570 dprintk("%s: delay = %i usec\n",
571 __FUNCTION__, check_count * 10);
581 printk("%s: firmware crash!!!!!!\n", __FUNCTION__);
588 printk("%s: firmware lockup!!!\n", __FUNCTION__);
589 printk("%s: recovered after %i trial(s))\n", __FUNCTION__, trials - 1);
594 printk("%s: switches = %i lockups = %i\n", __FUNCTION__, switches, lockups);
601 static int sp8870_sleep(struct dvb_i2c_bus *i2c)
603 // tristate TS output and disable interface pins
604 return sp8870_writereg(i2c, 0xC18, 0x000);
608 static int sp8870_wake_up(struct dvb_i2c_bus *i2c)
610 // enable TS output and interface pins
611 return sp8870_writereg(i2c, 0xC18, 0x00D);
615 static int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
617 struct dvb_i2c_bus *i2c = fe->i2c;
621 memcpy (arg, &tdlb7_info, sizeof(struct dvb_frontend_info));
625 return sp8870_read_status(i2c, (fe_status_t *) arg);
628 return sp8870_read_ber(i2c, (u32 *) arg);
630 case FE_READ_SIGNAL_STRENGTH:
631 return sp8870_read_signal_strength(i2c, (u16 *) arg);
633 case FE_READ_SNR: // not supported by hardware?
634 return sp8870_read_snr(i2c, (u32 *) arg);
636 case FE_READ_UNCORRECTED_BLOCKS:
637 return sp8870_read_uncorrected_blocks(i2c, (u32 *) arg);
639 case FE_SET_FRONTEND:
640 return sp8870_set_frontend(i2c, (struct dvb_frontend_parameters*) arg);
642 case FE_GET_FRONTEND: // FIXME: read known values back from Hardware...
646 return sp8870_sleep(i2c);
650 if (fe->data == NULL) { // first time initialisation...
651 fe->data = (void*) ~0;
656 case FE_GET_TUNE_SETTINGS:
658 struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg;
659 fesettings->min_delay_ms = 150;
660 fesettings->step_size = 166667;
661 fesettings->max_drift = 166667*2;
673 static int tdlb7_attach (struct dvb_i2c_bus *i2c, void **data)
675 u8 b0 [] = { 0x02 , 0x00 };
677 struct i2c_msg msg [] = { { .addr = 0x71, .flags = 0, .buf = b0, .len = 2 },
678 { .addr = 0x71, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
680 dprintk ("%s\n", __FUNCTION__);
682 if (i2c->xfer (i2c, msg, 2) != 2)
685 sp8870_firmware_upload(i2c);
687 return dvb_register_frontend (tdlb7_ioctl, i2c, NULL, &tdlb7_info);
691 static void tdlb7_detach (struct dvb_i2c_bus *i2c, void *data)
693 dprintk ("%s\n", __FUNCTION__);
695 dvb_unregister_frontend (tdlb7_ioctl, i2c);
699 static int __init init_tdlb7 (void)
701 dprintk ("%s\n", __FUNCTION__);
703 return dvb_register_i2c_device (THIS_MODULE, tdlb7_attach, tdlb7_detach);
707 static void __exit exit_tdlb7 (void)
709 dprintk ("%s\n", __FUNCTION__);
711 dvb_unregister_i2c_device (tdlb7_attach);
715 module_init(init_tdlb7);
716 module_exit(exit_tdlb7);
719 MODULE_PARM(debug,"i");
720 MODULE_PARM_DESC(debug, "enable verbose debug messages");
722 MODULE_PARM(firmware_file,"s");
723 MODULE_PARM_DESC(firmware_file, "where to find the firmware file");
725 MODULE_DESCRIPTION("TDLB7 DVB-T Frontend");
726 MODULE_AUTHOR("Juergen Peitz");
727 MODULE_LICENSE("GPL");