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
60 static struct dvb_frontend_info tdlb7_info = {
63 .frequency_min = 470000000,
64 .frequency_max = 860000000,
65 .frequency_stepsize = 166666,
66 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
67 FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 |
68 FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
69 FE_CAN_QPSK | FE_CAN_QAM_16 |
70 FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
71 FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER
75 static int sp8870_writereg (struct dvb_i2c_bus *i2c, u16 reg, u16 data)
77 u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff };
78 struct i2c_msg msg = { .addr = 0x71, .flags = 0, .buf = buf, .len = 4 };
81 if ((err = i2c->xfer (i2c, &msg, 1)) != 1) {
82 dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
90 static u16 sp8870_readreg (struct dvb_i2c_bus *i2c, u16 reg)
93 u8 b0 [] = { reg >> 8 , reg & 0xff };
95 struct i2c_msg msg [] = { { .addr = 0x71, .flags = 0, .buf = b0, .len = 2 },
96 { .addr = 0x71, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
98 ret = i2c->xfer (i2c, msg, 2);
101 dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
105 return (b1[0] << 8 | b1[1]);
109 static int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4])
112 struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = 4 };
114 ret = i2c->xfer (i2c, &msg, 1);
117 printk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret);
119 return (ret != 1) ? -1 : 0;
123 static void sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq)
125 u32 div = (freq + 36200000) / 166666;
129 if (freq <= 782000000)
134 buf[0] = (div >> 8) & 0x7f;
139 /* open i2c gate for PLL message transmission... */
140 sp8870_writereg(i2c, 0x206, 0x001);
141 sp5659_write (i2c, buf);
142 sp8870_writereg(i2c, 0x206, 0x000);
146 static int sp8870_read_firmware_file (const char *fn, char **fp)
152 fd = sys_open(fn, 0, 0);
154 printk("%s: unable to open '%s'.\n", __FUNCTION__, fn);
158 filesize = sys_lseek(fd, 0L, 2);
159 if (filesize <= 0 || filesize < SP8870_FIRMWARE_OFFSET + SP8870_FIRMWARE_SIZE) {
160 printk("%s: firmware filesize to small '%s'\n", __FUNCTION__, fn);
165 *fp= dp = vmalloc(SP8870_FIRMWARE_SIZE);
167 printk("%s: out of memory loading '%s'.\n", __FUNCTION__, fn);
172 sys_lseek(fd, SP8870_FIRMWARE_OFFSET, 0);
173 if (sys_read(fd, dp, SP8870_FIRMWARE_SIZE) != SP8870_FIRMWARE_SIZE) {
174 printk("%s: failed to read '%s'.\n",__FUNCTION__, fn);
187 static int sp8870_firmware_upload (struct dvb_i2c_bus *i2c)
195 mm_segment_t fs = get_fs();
197 dprintk ("%s: ...\n", __FUNCTION__);
199 // system controller stop
200 sp8870_writereg(i2c,0x0F00,0x0000);
202 // instruction RAM register hiword
203 sp8870_writereg(i2c, 0x8F08, ((SP8870_FIRMWARE_SIZE / 2) & 0xFFFF));
205 // instruction RAM MWR
206 sp8870_writereg(i2c, 0x8F0A, ((SP8870_FIRMWARE_SIZE / 2) >> 16));
208 // reading firmware file to buffer
210 err = sp8870_read_firmware_file(firmware_file, (char**) &fw_buf);
213 printk("%s: reading firmware file failed!\n", __FUNCTION__);
217 // do firmware upload
219 while (fw_pos < SP8870_FIRMWARE_SIZE){
220 tx_len = (fw_pos <= SP8870_FIRMWARE_SIZE - 252) ? 252 : SP8870_FIRMWARE_SIZE - fw_pos;
221 // write register 0xCF0A
224 memcpy(&tx_buf[2], fw_buf + fw_pos, tx_len);
228 msg.len = tx_len + 2;
229 if ((err = i2c->xfer (i2c, &msg, 1)) != 1) {
230 printk("%s: firmware upload failed!\n", __FUNCTION__);
231 printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
240 dprintk ("%s: done!\n", __FUNCTION__);
245 static void sp8870_microcontroller_stop (struct dvb_i2c_bus *i2c)
247 sp8870_writereg(i2c, 0x0F08, 0x000);
248 sp8870_writereg(i2c, 0x0F09, 0x000);
250 // microcontroller STOP
251 sp8870_writereg(i2c, 0x0F00, 0x000);
255 static void sp8870_microcontroller_start (struct dvb_i2c_bus *i2c)
257 sp8870_writereg(i2c, 0x0F08, 0x000);
258 sp8870_writereg(i2c, 0x0F09, 0x000);
260 // microcontroller START
261 sp8870_writereg(i2c, 0x0F00, 0x001);
262 // not documented but if we don't read 0x0D01 out here
263 // we don't get a correct data valid signal
264 sp8870_readreg(i2c, 0x0D01);
268 static int sp8870_init (struct dvb_i2c_bus *i2c)
270 dprintk ("%s\n", __FUNCTION__);
272 /* enable TS output and interface pins */
273 sp8870_writereg(i2c, 0xc18, 0x00d);
275 // system controller stop
276 sp8870_microcontroller_stop(i2c);
279 sp8870_writereg(i2c,0x0301,0x0003);
281 // Reed Solomon parity bytes passed to output
282 sp8870_writereg(i2c,0x0C13,0x0001);
284 // MPEG clock is suppressed if no valid data
285 sp8870_writereg(i2c,0x0C14,0x0001);
287 /* bit 0x010: enable data valid signal */
288 sp8870_writereg(i2c, 0x0D00, 0x010);
289 sp8870_writereg(i2c, 0x0D01, 0x000);
295 static int sp8870_read_status (struct dvb_i2c_bus *i2c, fe_status_t * fe_status)
302 status = sp8870_readreg (i2c, 0x0200);
306 signal = sp8870_readreg (i2c, 0x0303);
311 *fe_status |= FE_HAS_SIGNAL;
313 *fe_status |= FE_HAS_SYNC;
315 *fe_status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_VITERBI;
321 static int sp8870_read_ber (struct dvb_i2c_bus *i2c, u32 * ber)
328 ret = sp8870_readreg(i2c, 0xC08);
334 ret = sp8870_readreg(i2c, 0xC07);
349 static int sp8870_read_signal_strength (struct dvb_i2c_bus *i2c, u16 * signal)
356 ret = sp8870_readreg (i2c, 0x306);
362 ret = sp8870_readreg (i2c, 0x303);
369 *signal = 0xFFFF - tmp;
375 static int sp8870_read_snr(struct dvb_i2c_bus *i2c, u32* snr)
382 static int sp8870_read_uncorrected_blocks (struct dvb_i2c_bus *i2c, u32* ublocks)
388 ret = sp8870_readreg(i2c, 0xC0C);
401 static int sp8870_read_data_valid_signal(struct dvb_i2c_bus *i2c)
403 return (sp8870_readreg(i2c, 0x0D02) > 0);
408 int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
410 int known_parameters = 1;
414 switch (p->u.ofdm.constellation) {
418 *reg0xc05 |= (1 << 10);
421 *reg0xc05 |= (2 << 10);
424 known_parameters = 0;
430 switch (p->u.ofdm.hierarchy_information) {
434 *reg0xc05 |= (1 << 7);
437 *reg0xc05 |= (2 << 7);
440 *reg0xc05 |= (3 << 7);
443 known_parameters = 0;
449 switch (p->u.ofdm.code_rate_HP) {
453 *reg0xc05 |= (1 << 3);
456 *reg0xc05 |= (2 << 3);
459 *reg0xc05 |= (3 << 3);
462 *reg0xc05 |= (4 << 3);
465 known_parameters = 0;
471 if (known_parameters)
472 *reg0xc05 |= (2 << 1); /* use specified parameters */
474 *reg0xc05 |= (1 << 1); /* enable autoprobing */
480 static int sp8870_set_frontend_parameters (struct dvb_i2c_bus *i2c,
481 struct dvb_frontend_parameters *p)
486 if ((err = configure_reg0xc05(p, ®0xc05)))
489 // system controller stop
490 sp8870_microcontroller_stop(i2c);
492 // set tuner parameters
493 sp5659_set_tv_freq (i2c, p->frequency);
495 // sample rate correction bit [23..17]
496 sp8870_writereg(i2c,0x0319,0x000A);
498 // sample rate correction bit [16..0]
499 sp8870_writereg(i2c,0x031A,0x0AAB);
501 // integer carrier offset
502 sp8870_writereg(i2c,0x0309,0x0400);
504 // fractional carrier offset
505 sp8870_writereg(i2c,0x030A,0x0000);
507 // filter for 6/7/8 Mhz channel
508 if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
509 sp8870_writereg(i2c,0x0311,0x0002);
510 else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
511 sp8870_writereg(i2c,0x0311,0x0001);
513 sp8870_writereg(i2c,0x0311,0x0000);
515 // scan order: 2k first = 0x0000, 8k first = 0x0001
516 if (p->u.ofdm.transmission_mode == TRANSMISSION_MODE_2K)
517 sp8870_writereg(i2c,0x0338,0x0000);
519 sp8870_writereg(i2c,0x0338,0x0001);
521 sp8870_writereg(i2c, 0xc05, reg0xc05);
523 // read status reg in order to clear pending irqs
524 sp8870_readreg(i2c, 0x200);
526 // system controller start
527 sp8870_microcontroller_start(i2c);
533 // number of trials to recover from lockup
535 // maximum checks for data valid signal
536 #define MAXCHECKS 100
538 // only for debugging: counter for detected lockups
539 static int lockups = 0;
540 // only for debugging: counter for channel switches
541 static int switches = 0;
543 static int sp8870_set_frontend (struct dvb_i2c_bus *i2c, struct dvb_frontend_parameters *p)
546 The firmware of the sp8870 sometimes locks up after setting frontend parameters.
547 We try to detect this by checking the data valid signal.
548 If it is not set after MAXCHECKS we try to recover the lockup by setting
549 the frontend parameters again.
557 dprintk("%s: frequency = %i\n", __FUNCTION__, p->frequency);
559 for (trials = 1; trials <= MAXTRIALS; trials++) {
561 if ((err = sp8870_set_frontend_parameters(i2c, p)))
564 for (check_count = 0; check_count < MAXCHECKS; check_count++) {
565 // valid = ((sp8870_readreg(i2c, 0x0200) & 4) == 0);
566 valid = sp8870_read_data_valid_signal(i2c);
568 dprintk("%s: delay = %i usec\n",
569 __FUNCTION__, check_count * 10);
579 printk("%s: firmware crash!!!!!!\n", __FUNCTION__);
586 printk("%s: firmware lockup!!!\n", __FUNCTION__);
587 printk("%s: recovered after %i trial(s))\n", __FUNCTION__, trials - 1);
592 printk("%s: switches = %i lockups = %i\n", __FUNCTION__, switches, lockups);
599 static int sp8870_sleep(struct dvb_i2c_bus *i2c)
601 // tristate TS output and disable interface pins
602 return sp8870_writereg(i2c, 0xC18, 0x000);
606 static int sp8870_wake_up(struct dvb_i2c_bus *i2c)
608 // enable TS output and interface pins
609 return sp8870_writereg(i2c, 0xC18, 0x00D);
613 static int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
615 struct dvb_i2c_bus *i2c = fe->i2c;
619 memcpy (arg, &tdlb7_info, sizeof(struct dvb_frontend_info));
623 return sp8870_read_status(i2c, (fe_status_t *) arg);
626 return sp8870_read_ber(i2c, (u32 *) arg);
628 case FE_READ_SIGNAL_STRENGTH:
629 return sp8870_read_signal_strength(i2c, (u16 *) arg);
631 case FE_READ_SNR: // not supported by hardware?
632 return sp8870_read_snr(i2c, (u32 *) arg);
634 case FE_READ_UNCORRECTED_BLOCKS:
635 return sp8870_read_uncorrected_blocks(i2c, (u32 *) arg);
637 case FE_SET_FRONTEND:
638 return sp8870_set_frontend(i2c, (struct dvb_frontend_parameters*) arg);
640 case FE_GET_FRONTEND: // FIXME: read known values back from Hardware...
644 return sp8870_sleep(i2c);
648 if (fe->data == NULL) { // first time initialisation...
649 fe->data = (void*) ~0;
654 case FE_GET_TUNE_SETTINGS:
656 struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg;
657 fesettings->min_delay_ms = 150;
658 fesettings->step_size = 166667;
659 fesettings->max_drift = 166667*2;
671 static int tdlb7_attach (struct dvb_i2c_bus *i2c, void **data)
673 u8 b0 [] = { 0x02 , 0x00 };
675 struct i2c_msg msg [] = { { .addr = 0x71, .flags = 0, .buf = b0, .len = 2 },
676 { .addr = 0x71, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
678 dprintk ("%s\n", __FUNCTION__);
680 if (i2c->xfer (i2c, msg, 2) != 2)
683 sp8870_firmware_upload(i2c);
685 return dvb_register_frontend (tdlb7_ioctl, i2c, NULL, &tdlb7_info);
689 static void tdlb7_detach (struct dvb_i2c_bus *i2c, void *data)
691 dprintk ("%s\n", __FUNCTION__);
693 dvb_unregister_frontend (tdlb7_ioctl, i2c);
697 static int __init init_tdlb7 (void)
699 dprintk ("%s\n", __FUNCTION__);
701 return dvb_register_i2c_device (THIS_MODULE, tdlb7_attach, tdlb7_detach);
705 static void __exit exit_tdlb7 (void)
707 dprintk ("%s\n", __FUNCTION__);
709 dvb_unregister_i2c_device (tdlb7_attach);
713 module_init(init_tdlb7);
714 module_exit(exit_tdlb7);
717 MODULE_PARM(debug,"i");
718 MODULE_PARM_DESC(debug, "enable verbose debug messages");
720 MODULE_PARM(firmware_file,"s");
721 MODULE_PARM_DESC(firmware_file, "where to find the firmware file");
723 MODULE_DESCRIPTION("TDLB7 DVB-T Frontend");
724 MODULE_AUTHOR("Juergen Peitz");
725 MODULE_LICENSE("GPL");