Hi, 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),
dvb-usb-vp7045-01.fw
Description: Binary data
_______________________________________________ linux-dvb mailing list [email protected] http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb
