The code to make it work already is in the DVB-T tree, somebody "just" needs to glue the TDA10046 frontend to the existing VP7045 backend code, Steward has started this work but I don´t know if he has progressed further than the attached diff.
The firmware needs to be extracted from the windows driver, I have the information needed for that, but hopefully we will be allowed to redistribute the firmware instead.
I think Chris has both the new and the old stick, so he would be a perfect tester.
That is about all I know.
/Henrik
diff -r 443f5b4e2365 linux/drivers/media/dvb/dvb-usb/Makefile --- a/linux/drivers/media/dvb/dvb-usb/Makefile Sun Sep 3 16:33:10 2006 +++ b/linux/drivers/media/dvb/dvb-usb/Makefile Thu Sep 7 03:11:12 2006 @@ -1,7 +1,7 @@ dvb-usb-objs = dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o dvb-usb-i2c.o dvb-usb-dvb.o dvb-usb-remote.o obj-$(CONFIG_DVB_USB) += dvb-usb.o -dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o +dvb-usb-vp7045-objs = vp7045.o obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o diff -r 443f5b4e2365 linux/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c Sun Sep 3 16:33:10 2006 +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c Thu Sep 7 03:11:12 2006 @@ -52,27 +52,30 @@ ret = usb_cypress_writemem(udev,hx.addr,hx.data,hx.len); if (ret != hx.len) { - err("error while transferring firmware " - "(transferred size: %d, block size: %d)", + printk("error while transferring firmware " + "(transferred size: %d, block size: %d)\n", ret,hx.len); ret = -EINVAL; break; } } if (ret < 0) { - err("firmware download failed at %d with %d",pos,ret); + printk("firmware download failed at %d with %d\n",pos,ret); return ret; } if (ret == 0) { /* restart the CPU */ reset = 0; + printk("restarting cpu\n"); if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) { - err("could not restart the USB controller CPU."); + printk("could not restart the USB controller CPU.\n"); ret = -EINVAL; } - } else + } else { + printk("returning eio\n"); ret = -EIO; + } return ret; } @@ -110,7 +113,7 @@ ret = -EINVAL; break; } - + printk("done, releasing firmware\n"); release_firmware(fw); return ret; } diff -r 443f5b4e2365 linux/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c Sun Sep 3 16:33:10 2006 +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c Thu Sep 7 03:11:12 2006 @@ -12,10 +12,13 @@ int ret = 0; if (!(d->props.caps & DVB_USB_IS_AN_I2C_ADAPTER)) + { + printk("no cap\n"); return 0; + } if (d->props.i2c_algo == NULL) { - err("no i2c algorithm specified"); + printk("no i2c algorithm specified\n"); return -EINVAL; } @@ -31,7 +34,7 @@ i2c_set_adapdata(&d->i2c_adap, d); if ((ret = i2c_add_adapter(&d->i2c_adap)) < 0) - err("could not add i2c adapter"); + printk("could not add i2c adapter\n"); d->state |= DVB_USB_STATE_I2C; diff -r 443f5b4e2365 linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c Sun Sep 3 16:33:10 2006 +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c Thu Sep 7 03:11:12 2006 @@ -69,11 +69,16 @@ if (d->props.power_ctrl) d->props.power_ctrl(d,1); - if ((ret = dvb_usb_urb_init(d)) || - (ret = dvb_usb_dvb_init(d)) || - (ret = dvb_usb_i2c_init(d)) || - (ret = dvb_usb_fe_init(d))) { + ret = dvb_usb_urb_init(d); + err("init urb %d", ret); + ret |= dvb_usb_dvb_init(d); + err("init dvb %d", ret); + ret |= dvb_usb_i2c_init(d); + err("init i2c %d", ret); + ret |= dvb_usb_fe_init(d); + if(ret) { dvb_usb_exit(d); + err("failed initing. urb, dvb, i2c, fe %d", ret); return ret; } diff -r 443f5b4e2365 linux/drivers/media/dvb/dvb-usb/dvb-usb.h --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h Sun Sep 3 16:33:10 2006 +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h Thu Sep 7 03:11:12 2006 @@ -327,6 +327,9 @@ struct module *owner; void *priv; + + u8 last_result[32]; // hack + u8 c; /* transaction counter, wraps around... */ }; extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_properties *, struct module *, struct dvb_usb_device **); diff -r 443f5b4e2365 linux/drivers/media/dvb/dvb-usb/vp7045.c --- a/linux/drivers/media/dvb/dvb-usb/vp7045.c Sun Sep 3 16:33:10 2006 +++ b/linux/drivers/media/dvb/dvb-usb/vp7045.c Thu Sep 7 03:11:12 2006 @@ -13,6 +13,7 @@ * see Documentation/dvb/README.dvb-usb for more information */ #include "vp7045.h" +#include "tda1004x.h" /* debug */ int dvb_usb_vp7045_debug; @@ -168,6 +169,22 @@ { return vp7045_read_eeprom(d,mac, 6, MAC_0_ADDR); } +/* +static int philips_tdm1316l_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) +{ + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + + return request_firmware(fw, name, &ttusb->dev->dev); +}*/ + +static struct tda1004x_config philips_tdm1316l_config = { + + .demod_address = 0x31, + .invert = 1, + .invert_oclk = 0, + .request_firmware = NULL, //philips_tdm1316l_request_firmware, +}; + static int vp7045_frontend_attach(struct dvb_usb_device *d) { @@ -175,21 +192,38 @@ vp7045_usb_op(d,VENDOR_STRING_READ,NULL,0,buf,20,0); buf[10] = '\0'; - deb_info("firmware says: %s ",buf); + printk("firmware says: %s\n",buf); vp7045_usb_op(d,PRODUCT_STRING_READ,NULL,0,buf,20,0); buf[10] = '\0'; - deb_info("%s ",buf); + printk("%s\n",buf); vp7045_usb_op(d,FW_VERSION_READ,NULL,0,buf,20,0); buf[10] = '\0'; - deb_info("v%s\n",buf); - + printk("v%s\n",buf); + +/* u8 obuf[3] = { 0x00, 0x7f,0x01 },tuner; + +vp7045_usb_op(d,TUNER_REG_READ,obuf,3,&tuner,1,30);*/ + u32 tuner = vp7045_read_reg(d,0x7F); + switch(tuner) + { + case 0x14: + printk("VP7045 Tuner is MT353\n"); + break; + case 0x13: + printk("VP7045 Tuner is MT352\n"); + default: + printk("UNKNOWN TUNER 0x%x!!!!\n",tuner); + } /* Dump the EEPROM */ /* vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */ - d->fe = vp7045_fe_attach(d); - +// d->fe = vp7045_fe_attach(d); + + printk("The i2c_adap: %p\n", d->i2c_adap); + d->fe = tda10046_attach(&philips_tdm1316l_config, &d->i2c_adap); + // d->fe = tda10046_attach(); return 0; } @@ -210,8 +244,174 @@ }; MODULE_DEVICE_TABLE(usb, vp7045_usb_table); +#define DEBUG 0 +static int ttusb_cmd(struct dvb_usb_device *d, + const u8 * data, int len, int needresult) +{ + int actual_len; + int err; +#if DEBUG >= 3 + int i; + + printk(">"); + for (i = 0; i < len; ++i) + printk(" %02x", data[i]); + printk("\n"); +#endif + + if (mutex_lock_interruptible(&d->usb_mutex) < 0) + return -EAGAIN; + + err = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev, + d->props.generic_bulk_ctrl_endpoint), + (u8 *) data, len, &actual_len, 1000); + if (err != 0) { + printk("%s: usb_bulk_msg(send) failed, err == %i!\n", + __FUNCTION__, err); + mutex_unlock(&d->usb_mutex); + return err; + } + if (actual_len != len) { + printk("%s: only wrote %d of %d bytes\n", __FUNCTION__, + actual_len, len); + mutex_unlock(&d->usb_mutex); + return -1; + } + + err = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev, + d->props.generic_bulk_ctrl_endpoint), + d->last_result, 32, &actual_len, 1000); + + if (err != 0) { + printk("%s: failed, receive error %d\n", __FUNCTION__, + err); + mutex_unlock(&d->usb_mutex); + return err; + } +#if DEBUG >= 3 + actual_len = d->last_result[3] + 4; + printk("<"); + for (i = 0; i < actual_len; ++i) + printk(" %02x", d->last_result[i]); + printk("\n"); +#endif + if (!needresult) + mutex_unlock(&d->usb_mutex); + return 0; +} + +static int ttusb_result(struct dvb_usb_device *d, u8 * data, int len) +{ + memcpy(data, d->last_result, len); + mutex_unlock(&d->usb_mutex); + return 0; +} + +static int ttusb_i2c_msg(struct dvb_usb_device *d, + u8 addr, u8 * snd_buf, u8 snd_len, u8 * rcv_buf, + u8 rcv_len) +{ + u8 b[0x28]; + u8 id = ++d->c; + int i, err; + + if (snd_len > 0x28 - 7 || rcv_len > 0x20 - 7) + return -EINVAL; + + b[0] = 0xaa; + b[1] = id; + b[2] = 0x31; + b[3] = snd_len + 3; + b[4] = addr << 1; + b[5] = snd_len; + b[6] = rcv_len; + + for (i = 0; i < snd_len; i++) + b[7 + i] = snd_buf[i]; + + err = ttusb_cmd(d, b, snd_len + 7, 1); + + if (err) + return -EREMOTEIO; + + err = ttusb_result(d, b, 0x20); + + /* check if the i2c transaction was successful */ + if ((snd_len != b[5]) || (rcv_len != b[6])) return -EREMOTEIO; + + if (rcv_len > 0) { + + if (err || b[0] != 0x55 || b[1] != id) { + printk + ("%s: usb_bulk_msg(recv) failed, err == %i, id == %02x, b == ", + __FUNCTION__, err, id); + return -EREMOTEIO; + } + + for (i = 0; i < rcv_len; i++) + rcv_buf[i] = b[7 + i]; + } + + return rcv_len; +} + +static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adapter); + int i = 0; + int inc; + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + while (i < num) { + u8 addr, snd_len, rcv_len, *snd_buf, *rcv_buf; + int err; + + if (num > i + 1 && (msg[i + 1].flags & I2C_M_RD)) { + addr = msg[i].addr; + snd_buf = msg[i].buf; + snd_len = msg[i].len; + rcv_buf = msg[i + 1].buf; + rcv_len = msg[i + 1].len; + inc = 2; + } else { + addr = msg[i].addr; + snd_buf = msg[i].buf; + snd_len = msg[i].len; + rcv_buf = NULL; + rcv_len = 0; + inc = 1; + } + + err = ttusb_i2c_msg(d, addr, + snd_buf, snd_len, rcv_buf, rcv_len); + + if (err < rcv_len) { + printk("%s: i == %i\n", __FUNCTION__, i); + break; + } + + i += inc; + } + + mutex_unlock(&d->i2c_mutex); + return i; +} + +static u32 functionality(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm ttusb_dec_algo = { + .master_xfer = master_xfer, + .functionality = functionality, +}; + + static struct dvb_usb_properties vp7045_properties = { - .caps = 0, + .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = CYPRESS_FX2, .firmware = "dvb-usb-vp7045-01.fw", @@ -220,6 +420,9 @@ .frontend_attach = vp7045_frontend_attach, .read_mac_address = vp7045_read_mac_addr, + .i2c_algo = &ttusb_dec_algo, + + .no_reconnect = 1, .rc_interval = 400, .rc_key_map = vp7045_rc_keys, .rc_key_map_size = ARRAY_SIZE(vp7045_rc_keys),
Attachment:
dvb-usb-vp7045-01.fw
Description: Binary data
_______________________________________________ linux-dvb mailing list linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb