diff options
author | Holger Waechtler <devnull@localhost> | 2003-11-20 03:54:10 +0000 |
---|---|---|
committer | Holger Waechtler <devnull@localhost> | 2003-11-20 03:54:10 +0000 |
commit | 16df2e090a7bbd03359880991777c52fed1874c9 (patch) | |
tree | f54633609c50aad85b8c704de64b71a68a0e0475 | |
parent | 03efc557ef5c42cb4e6259997665e6ccc4b29ead (diff) | |
download | mediapointer-dvb-s2-16df2e090a7bbd03359880991777c52fed1874c9.tar.gz mediapointer-dvb-s2-16df2e090a7bbd03359880991777c52fed1874c9.tar.bz2 |
firmware loader implementation contributed by Martin Stubbs
-rw-r--r-- | linux/drivers/media/dvb/frontends/Kconfig | 16 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/sp887x.c | 100 |
2 files changed, 106 insertions, 10 deletions
diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index dd20a8aab..e9dc80540 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -155,3 +155,19 @@ config DVB_TDA1004X_FIRMWARE_FILE wget http://www.technotrend.de/new/215/TTweb_215a_budget_20_05_2003.zip unzip -j TTweb_215a_budget_20_05_2003.zip Software/Oem/PCI/App/ttlcdacc.dll mv ttlcdacc.dll /etc/dvb/tda1004x.bin + +config DVB_SP887X_FIRMWARE_FILE + string "Full pathname of sp887x firmware file" + depends on DVB_SP887X + default "/etc/dvb/sc_main.mc" + help + This driver needs a copy of the Avermedia firmware. The version tested + is part of the Avermedia DVB-T 1.3.26.3 Application. This can be downloaded + from the Avermedia web site. + If the software is installed in Windows the file will be in the + /Program Files/AVerTV DVB-T/ directory and is called sc_main.mc. + Alternatively it can "extracted" from the install cab files but this will have + to be done in windows as I don't know of a linux version of extract.exe. + Copy this file to /etc/dvb/sc_main.mc. With this version of the file the first + 10 bytes are discarded and the next 0x4000 loaded. This may change in future + versions.
\ No newline at end of file diff --git a/linux/drivers/media/dvb/frontends/sp887x.c b/linux/drivers/media/dvb/frontends/sp887x.c index a19281995..b25c3ff2f 100644 --- a/linux/drivers/media/dvb/frontends/sp887x.c +++ b/linux/drivers/media/dvb/frontends/sp887x.c @@ -1,11 +1,39 @@ +/* + Driver for the Microtune 7202D Frontend +*/ + +/* + This driver needs a copy of the Avermedia firmware. The version tested + is part of the Avermedia DVB-T 1.3.26.3 Application. If the software is + installed in Windows the file will be in the /Program Files/AVerTV DVB-T/ + directory and is called sc_main.mc. Alternatively it can "extracted" from + the install cab files. Copy this file to /etc/dvb/sc_main.mc. + With this version of the file the first 10 bytes are discarded and the + next 0x4000 loaded. This may change in future versions. + */ +#define __KERNEL_SYSCALLS__ +#include <linux/kernel.h> +#include <linux/vmalloc.h> #include <linux/module.h> #include <linux/init.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/fs.h> +#include <linux/unistd.h> +#include <linux/fcntl.h> +#include <linux/errno.h> #include <linux/i2c.h> + #include "dvb_frontend.h" #include "dvb_functions.h" +#ifndef DVB_SP887X_FIRMWARE_FILE +#define DVB_SP887X_FIRMWARE_FILE "/etc/dvb/sc_main.mc" +#endif + +static char *sp887x_firmware = DVB_SP887X_FIRMWARE_FILE; #if 0 #define dprintk(x...) printk(x) @@ -39,7 +67,7 @@ struct dvb_frontend_info sp887x_info = { FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_RECOVER }; - +static int errno; static int i2c_writebytes (struct dvb_frontend *fe, u8 addr, u8 *buf, u8 len) @@ -75,7 +103,7 @@ int sp887x_writereg (struct dvb_frontend *fe, u16 reg, u16 data) /** * in case of soft reset we ignore ACK errors... */ - if (!(reg == 0xf1a && data == 0x000 && + if (!(reg == 0xf1a && data == 0x000 && (ret == -EREMOTEIO || ret == -EFAULT))) { printk("%s: writereg error " @@ -112,8 +140,9 @@ u16 sp887x_readreg (struct dvb_frontend *fe, u16 reg) static void sp887x_microcontroller_stop (struct dvb_frontend *fe) { + dprintk("%s\n", __FUNCTION__); sp887x_writereg(fe, 0xf08, 0x000); - sp887x_writereg(fe, 0xf09, 0x000); + sp887x_writereg(fe, 0xf09, 0x000); /* microcontroller STOP */ sp887x_writereg(fe, 0xf00, 0x000); @@ -123,8 +152,9 @@ void sp887x_microcontroller_stop (struct dvb_frontend *fe) static void sp887x_microcontroller_start (struct dvb_frontend *fe) { + dprintk("%s\n", __FUNCTION__); sp887x_writereg(fe, 0xf08, 0x000); - sp887x_writereg(fe, 0xf09, 0x000); + sp887x_writereg(fe, 0xf09, 0x000); /* microcontroller START */ sp887x_writereg(fe, 0xf00, 0x001); @@ -135,6 +165,7 @@ static void sp887x_setup_agc (struct dvb_frontend *fe) { /* setup AGC parameters */ + dprintk("%s\n", __FUNCTION__); sp887x_writereg(fe, 0x33c, 0x054); sp887x_writereg(fe, 0x33b, 0x04c); sp887x_writereg(fe, 0x328, 0x000); @@ -152,8 +183,6 @@ void sp887x_setup_agc (struct dvb_frontend *fe) } -#include "sp887x_firm.h" - #define BLOCKSIZE 30 /** @@ -163,13 +192,61 @@ static int sp887x_initial_setup (struct dvb_frontend *fe) { u8 buf [BLOCKSIZE+2]; + unsigned char *firmware = NULL; int i; + int fd; + int filesize; + int fw_size; + + dprintk("%s\n", __FUNCTION__); /* soft reset */ sp887x_writereg(fe, 0xf1a, 0x000); sp887x_microcontroller_stop (fe); + mm_segment_t fs = get_fs(); + + // Load the firmware + set_fs(get_ds()); + fd = open(sp887x_firmware, 0, 0); + if (fd < 0) { + printk(KERN_WARNING "%s: Unable to open firmware %s\n", __FUNCTION__, + sp887x_firmware); + return -EIO; + } + filesize = lseek(fd, 0L, 2); + if (filesize <= 0) { + printk(KERN_WARNING "%s: Firmware %s is empty\n", __FUNCTION__, + sp887x_firmware); + sys_close(fd); + return -EIO; + } + + fw_size = 0x4000; + + // allocate buffer for it + firmware = vmalloc(fw_size); + if (firmware == NULL) { + printk(KERN_WARNING "%s: Out of memory loading firmware\n", + __FUNCTION__); + sys_close(fd); + return -EIO; + } + + // read it! + // read the first 16384 bytes from the file + // ignore the first 10 bytes + lseek(fd, 10, 0); + if (read(fd, firmware, fw_size) != fw_size) { + printk(KERN_WARNING "%s: Failed to read firmware\n", __FUNCTION__); + vfree(firmware); + sys_close(fd); + return -EIO; + } + sys_close(fd); + set_fs(fs); + printk ("%s: firmware upload... ", __FUNCTION__); /* setup write pointer to -1 (end of memory) */ @@ -179,12 +256,12 @@ int sp887x_initial_setup (struct dvb_frontend *fe) /* dummy write (wrap around to start of memory) */ sp887x_writereg(fe, 0x8f0a, 0x0000); - for (i=0; i<sizeof(sp887x_firm); i+=BLOCKSIZE) { + for (i=0; i<fw_size; i+=BLOCKSIZE) { int c = BLOCKSIZE; int err; - if (i+c > sizeof(sp887x_firm)) - c = sizeof(sp887x_firm) - i; + if (i+c > fw_size) + c = fw_size - i; /* bit 0x8000 in address is set to enable 13bit mode */ /* bit 0x4000 enables multibyte read/write transfers */ @@ -192,15 +269,18 @@ int sp887x_initial_setup (struct dvb_frontend *fe) buf[0] = 0xcf; buf[1] = 0x0a; - memcpy(&buf[2], &sp887x_firm[i], c); + memcpy(&buf[2], firmware + i, c); if ((err = i2c_writebytes (fe, 0x70, buf, c+2)) < 0) { printk ("failed.\n"); printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err); + vfree(firmware); return err; } } + vfree(firmware); + /* don't write RS bytes between packets */ sp887x_writereg(fe, 0xc13, 0x001); |