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'.
31 #include <linux/module.h>
32 #include <linux/init.h>
33 #include <linux/vmalloc.h>
35 #include <linux/unistd.h>
36 #include <linux/delay.h>
37 #include <linux/syscalls.h>
39 #include "dvb_frontend.h"
40 #include "dvb_functions.h"
42 #ifndef CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION
43 #define CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION "/usr/lib/DVB/driver/frontends/Sc_main.mc"
46 static char * firmware_file = CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION;
49 #define dprintk if (debug) printk
51 /* firmware size for sp8870 */
52 #define SP8870_FIRMWARE_SIZE 16382
54 /* starting point for firmware in file 'Sc_main.mc' */
55 #define SP8870_FIRMWARE_OFFSET 0x0A
57 static struct dvb_frontend_info tdlb7_info = {
60 .frequency_min = 470000000,
61 .frequency_max = 860000000,
62 .frequency_stepsize = 166666,
63 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
64 FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 |
65 FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
66 FE_CAN_QPSK | FE_CAN_QAM_16 |
67 FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
68 FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER
72 static int sp8870_writereg (struct dvb_i2c_bus *i2c, u16 reg, u16 data)
74 u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff };
75 struct i2c_msg msg = { .addr = 0x71, .flags = 0, .buf = buf, .len = 4 };
78 if ((err = i2c->xfer (i2c, &msg, 1)) != 1) {
79 dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
87 static u16 sp8870_readreg (struct dvb_i2c_bus *i2c, u16 reg)
90 u8 b0 [] = { reg >> 8 , reg & 0xff };
92 struct i2c_msg msg [] = { { .addr = 0x71, .flags = 0, .buf = b0, .len = 2 },
93 { .addr = 0x71, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
95 ret = i2c->xfer (i2c, msg, 2);
98 dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
102 return (b1[0] << 8 | b1[1]);
106 static int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4])
109 struct i2c_msg msg = { .addr = 0x60, .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;
120 static void sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq)
122 u32 div = (freq + 36200000) / 166666;
126 if (freq <= 782000000)
131 buf[0] = (div >> 8) & 0x7f;
136 /* open i2c gate for PLL message transmission... */
137 sp8870_writereg(i2c, 0x206, 0x001);
138 sp5659_write (i2c, buf);
139 sp8870_writereg(i2c, 0x206, 0x000);
143 static int sp8870_read_firmware_file (const char *fn, char **fp)
149 fd = sys_open(fn, 0, 0);
151 printk("%s: unable to open '%s'.\n", __FUNCTION__, fn);
155 filesize = sys_lseek(fd, 0L, 2);
156 if (filesize <= 0 || filesize < SP8870_FIRMWARE_OFFSET + SP8870_FIRMWARE_SIZE) {
157 printk("%s: firmware filesize to small '%s'\n", __FUNCTION__, fn);
162 *fp= dp = vmalloc(SP8870_FIRMWARE_SIZE);
164 printk("%s: out of memory loading '%s'.\n", __FUNCTION__, fn);
169 sys_lseek(fd, SP8870_FIRMWARE_OFFSET, 0);
170 if (sys_read(fd, dp, SP8870_FIRMWARE_SIZE) != SP8870_FIRMWARE_SIZE) {
171 printk("%s: failed to read '%s'.\n",__FUNCTION__, fn);
184 static int sp8870_firmware_upload (struct dvb_i2c_bus *i2c)
192 mm_segment_t fs = get_fs();
194 dprintk ("%s: ...\n", __FUNCTION__);
196 // system controller stop
197 sp8870_writereg(i2c,0x0F00,0x0000);
199 // instruction RAM register hiword
200 sp8870_writereg(i2c, 0x8F08, ((SP8870_FIRMWARE_SIZE / 2) & 0xFFFF));
202 // instruction RAM MWR
203 sp8870_writereg(i2c, 0x8F0A, ((SP8870_FIRMWARE_SIZE / 2) >> 16));
205 // reading firmware file to buffer
207 err = sp8870_read_firmware_file(firmware_file, (char**) &fw_buf);
210 printk("%s: reading firmware file failed!\n", __FUNCTION__);
214 // do firmware upload
216 while (fw_pos < SP8870_FIRMWARE_SIZE){
217 tx_len = (fw_pos <= SP8870_FIRMWARE_SIZE - 252) ? 252 : SP8870_FIRMWARE_SIZE - fw_pos;
218 // write register 0xCF0A
221 memcpy(&tx_buf[2], fw_buf + fw_pos, tx_len);
225 msg.len = tx_len + 2;
226 if ((err = i2c->xfer (i2c, &msg, 1)) != 1) {
227 printk("%s: firmware upload failed!\n", __FUNCTION__);
228 printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
237 dprintk ("%s: done!\n", __FUNCTION__);
242 static void sp8870_microcontroller_stop (struct dvb_i2c_bus *i2c)
244 sp8870_writereg(i2c, 0x0F08, 0x000);
245 sp8870_writereg(i2c, 0x0F09, 0x000);
247 // microcontroller STOP
248 sp8870_writereg(i2c, 0x0F00, 0x000);
252 static void sp8870_microcontroller_start (struct dvb_i2c_bus *i2c)
254 sp8870_writereg(i2c, 0x0F08, 0x000);
255 sp8870_writereg(i2c, 0x0F09, 0x000);
257 // microcontroller START
258 sp8870_writereg(i2c, 0x0F00, 0x001);
259 // not documented but if we don't read 0x0D01 out here
260 // we don't get a correct data valid signal
261 sp8870_readreg(i2c, 0x0D01);
265 static int sp8870_init (struct dvb_i2c_bus *i2c)
267 dprintk ("%s\n", __FUNCTION__);
269 /* enable TS output and interface pins */
270 sp8870_writereg(i2c, 0xc18, 0x00d);
272 // system controller stop
273 sp8870_microcontroller_stop(i2c);
276 sp8870_writereg(i2c,0x0301,0x0003);
278 // Reed Solomon parity bytes passed to output
279 sp8870_writereg(i2c,0x0C13,0x0001);
281 // MPEG clock is suppressed if no valid data
282 sp8870_writereg(i2c,0x0C14,0x0001);
284 /* bit 0x010: enable data valid signal */
285 sp8870_writereg(i2c, 0x0D00, 0x010);
286 sp8870_writereg(i2c, 0x0D01, 0x000);
292 static int sp8870_read_status (struct dvb_i2c_bus *i2c, fe_status_t * fe_status)
299 status = sp8870_readreg (i2c, 0x0200);
303 signal = sp8870_readreg (i2c, 0x0303);
308 *fe_status |= FE_HAS_SIGNAL;
310 *fe_status |= FE_HAS_SYNC;
312 *fe_status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_VITERBI;
318 static int sp8870_read_ber (struct dvb_i2c_bus *i2c, u32 * ber)
325 ret = sp8870_readreg(i2c, 0xC08);
331 ret = sp8870_readreg(i2c, 0xC07);
346 static int sp8870_read_signal_strength (struct dvb_i2c_bus *i2c, u16 * signal)
353 ret = sp8870_readreg (i2c, 0x306);
359 ret = sp8870_readreg (i2c, 0x303);
366 *signal = 0xFFFF - tmp;
372 static int sp8870_read_snr(struct dvb_i2c_bus *i2c, u32* snr)
379 static int sp8870_read_uncorrected_blocks (struct dvb_i2c_bus *i2c, u32* ublocks)
385 ret = sp8870_readreg(i2c, 0xC0C);
398 static int sp8870_read_data_valid_signal(struct dvb_i2c_bus *i2c)
400 return (sp8870_readreg(i2c, 0x0D02) > 0);
405 int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
407 int known_parameters = 1;
411 switch (p->u.ofdm.constellation) {
415 *reg0xc05 |= (1 << 10);
418 *reg0xc05 |= (2 << 10);
421 known_parameters = 0;
427 switch (p->u.ofdm.hierarchy_information) {
431 *reg0xc05 |= (1 << 7);
434 *reg0xc05 |= (2 << 7);
437 *reg0xc05 |= (3 << 7);
440 known_parameters = 0;
446 switch (p->u.ofdm.code_rate_HP) {
450 *reg0xc05 |= (1 << 3);
453 *reg0xc05 |= (2 << 3);
456 *reg0xc05 |= (3 << 3);
459 *reg0xc05 |= (4 << 3);
462 known_parameters = 0;
468 if (known_parameters)
469 *reg0xc05 |= (2 << 1); /* use specified parameters */
471 *reg0xc05 |= (1 << 1); /* enable autoprobing */
477 static int sp8870_set_frontend_parameters (struct dvb_i2c_bus *i2c,
478 struct dvb_frontend_parameters *p)
483 if ((err = configure_reg0xc05(p, ®0xc05)))
486 // system controller stop
487 sp8870_microcontroller_stop(i2c);
489 // set tuner parameters
490 sp5659_set_tv_freq (i2c, p->frequency);
492 // sample rate correction bit [23..17]
493 sp8870_writereg(i2c,0x0319,0x000A);
495 // sample rate correction bit [16..0]
496 sp8870_writereg(i2c,0x031A,0x0AAB);
498 // integer carrier offset
499 sp8870_writereg(i2c,0x0309,0x0400);
501 // fractional carrier offset
502 sp8870_writereg(i2c,0x030A,0x0000);
504 // filter for 6/7/8 Mhz channel
505 if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
506 sp8870_writereg(i2c,0x0311,0x0002);
507 else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
508 sp8870_writereg(i2c,0x0311,0x0001);
510 sp8870_writereg(i2c,0x0311,0x0000);
512 // scan order: 2k first = 0x0000, 8k first = 0x0001
513 if (p->u.ofdm.transmission_mode == TRANSMISSION_MODE_2K)
514 sp8870_writereg(i2c,0x0338,0x0000);
516 sp8870_writereg(i2c,0x0338,0x0001);
518 sp8870_writereg(i2c, 0xc05, reg0xc05);
520 // read status reg in order to clear pending irqs
521 sp8870_readreg(i2c, 0x200);
523 // system controller start
524 sp8870_microcontroller_start(i2c);
530 // number of trials to recover from lockup
532 // maximum checks for data valid signal
533 #define MAXCHECKS 100
535 // only for debugging: counter for detected lockups
536 static int lockups = 0;
537 // only for debugging: counter for channel switches
538 static int switches = 0;
540 static int sp8870_set_frontend (struct dvb_i2c_bus *i2c, struct dvb_frontend_parameters *p)
543 The firmware of the sp8870 sometimes locks up after setting frontend parameters.
544 We try to detect this by checking the data valid signal.
545 If it is not set after MAXCHECKS we try to recover the lockup by setting
546 the frontend parameters again.
554 dprintk("%s: frequency = %i\n", __FUNCTION__, p->frequency);
556 for (trials = 1; trials <= MAXTRIALS; trials++) {
558 if ((err = sp8870_set_frontend_parameters(i2c, p)))
561 for (check_count = 0; check_count < MAXCHECKS; check_count++) {
562 // valid = ((sp8870_readreg(i2c, 0x0200) & 4) == 0);
563 valid = sp8870_read_data_valid_signal(i2c);
565 dprintk("%s: delay = %i usec\n",
566 __FUNCTION__, check_count * 10);
576 printk("%s: firmware crash!!!!!!\n", __FUNCTION__);
583 printk("%s: firmware lockup!!!\n", __FUNCTION__);
584 printk("%s: recovered after %i trial(s))\n", __FUNCTION__, trials - 1);
589 printk("%s: switches = %i lockups = %i\n", __FUNCTION__, switches, lockups);
596 static int sp8870_sleep(struct dvb_i2c_bus *i2c)
598 // tristate TS output and disable interface pins
599 return sp8870_writereg(i2c, 0xC18, 0x000);
603 static int sp8870_wake_up(struct dvb_i2c_bus *i2c)
605 // enable TS output and interface pins
606 return sp8870_writereg(i2c, 0xC18, 0x00D);
610 static int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
612 struct dvb_i2c_bus *i2c = fe->i2c;
616 memcpy (arg, &tdlb7_info, sizeof(struct dvb_frontend_info));
620 return sp8870_read_status(i2c, (fe_status_t *) arg);
623 return sp8870_read_ber(i2c, (u32 *) arg);
625 case FE_READ_SIGNAL_STRENGTH:
626 return sp8870_read_signal_strength(i2c, (u16 *) arg);
628 case FE_READ_SNR: // not supported by hardware?
629 return sp8870_read_snr(i2c, (u32 *) arg);
631 case FE_READ_UNCORRECTED_BLOCKS:
632 return sp8870_read_uncorrected_blocks(i2c, (u32 *) arg);
634 case FE_SET_FRONTEND:
635 return sp8870_set_frontend(i2c, (struct dvb_frontend_parameters*) arg);
637 case FE_GET_FRONTEND: // FIXME: read known values back from Hardware...
641 return sp8870_sleep(i2c);
645 if (fe->data == NULL) { // first time initialisation...
646 fe->data = (void*) ~0;
651 case FE_GET_TUNE_SETTINGS:
653 struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg;
654 fesettings->min_delay_ms = 150;
655 fesettings->step_size = 166667;
656 fesettings->max_drift = 166667*2;
668 static int tdlb7_attach (struct dvb_i2c_bus *i2c, void **data)
670 u8 b0 [] = { 0x02 , 0x00 };
672 struct i2c_msg msg [] = { { .addr = 0x71, .flags = 0, .buf = b0, .len = 2 },
673 { .addr = 0x71, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
675 dprintk ("%s\n", __FUNCTION__);
677 if (i2c->xfer (i2c, msg, 2) != 2)
680 sp8870_firmware_upload(i2c);
682 return dvb_register_frontend (tdlb7_ioctl, i2c, NULL, &tdlb7_info);
686 static void tdlb7_detach (struct dvb_i2c_bus *i2c, void *data)
688 dprintk ("%s\n", __FUNCTION__);
690 dvb_unregister_frontend (tdlb7_ioctl, i2c);
694 static int __init init_tdlb7 (void)
696 dprintk ("%s\n", __FUNCTION__);
698 return dvb_register_i2c_device (THIS_MODULE, tdlb7_attach, tdlb7_detach);
702 static void __exit exit_tdlb7 (void)
704 dprintk ("%s\n", __FUNCTION__);
706 dvb_unregister_i2c_device (tdlb7_attach);
710 module_init(init_tdlb7);
711 module_exit(exit_tdlb7);
714 MODULE_PARM(debug,"i");
715 MODULE_PARM_DESC(debug, "enable verbose debug messages");
717 MODULE_PARM(firmware_file,"s");
718 MODULE_PARM_DESC(firmware_file, "where to find the firmware file");
720 MODULE_DESCRIPTION("TDLB7 DVB-T Frontend");
721 MODULE_AUTHOR("Juergen Peitz");
722 MODULE_LICENSE("GPL");