diff -r 9875eaae8c41 linux/drivers/media/video/hdpvr/hdpvr-core.c --- a/linux/drivers/media/video/hdpvr/hdpvr-core.c Sat Dec 27 00:28:56 2008 +0100 +++ b/linux/drivers/media/video/hdpvr/hdpvr-core.c Mon Jan 19 13:09:23 2009 -0500 @@ -171,6 +171,7 @@ print_buf); } #endif + hdpvr_err("firmware version 0x%x", buf[1]); if (buf[1] == HDPVR_FIRMWARE_VERSION) { dev->flags &= ~HDPVR_FLAG_AC3_CAP; } else if (buf[1] == HDPVR_FIRMWARE_VERSION_AC3) { @@ -373,7 +374,7 @@ goto error; } -#if 0 /* until i2c is working properly */ +#if 1 /* until i2c is working properly */ retval = hdpvr_register_i2c_adapter(dev); if (retval < 0) { hdpvr_err("registering videodev failed"); diff -r 9875eaae8c41 linux/drivers/media/video/hdpvr/hdpvr-i2c.c --- a/linux/drivers/media/video/hdpvr/hdpvr-i2c.c Sat Dec 27 00:28:56 2008 +0100 +++ b/linux/drivers/media/video/hdpvr/hdpvr-i2c.c Mon Jan 19 13:09:23 2009 -0500 @@ -22,7 +22,7 @@ #define REQTYPE_I2C_WRITE_STATT 0xd0 static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr, - char *data, int len) + char *data, int len, int hassub, int subaddress) { int ret; char *buf = kmalloc(len, GFP_KERNEL); @@ -32,7 +32,7 @@ ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), REQTYPE_I2C_READ, CTRL_READ_REQUEST, - 0x100|addr, 0, buf, len, 1000); + (hassub ? 0x100 : 0) | addr, (hassub ? subaddress : 0), buf, len, 1000); if (ret == len) { memcpy(data, buf, len); @@ -67,7 +67,7 @@ REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST, 0, 0, buf, 2, 1000); - if (ret == 2) + if (ret == 2 && buf[1]==(len-1)) ret = 0; else if (ret >= 0) ret = -EIO; @@ -81,26 +81,68 @@ int num) { struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter); - int retval = 0, i, addr; + int retval = 0, addr; if (num <= 0) - return 0; + { + retval = -EINVAL; + goto done; + } + + // Prevent access other than IR chip for now + if (msgs[0].addr != 0x70 && msgs[0].addr != 0x71) { + retval = -EIO; + goto done; + } mutex_lock(&dev->i2c_mutex); - for (i = 0; i < num && !retval; i++) { - addr = msgs[i].addr << 1; - - if (msgs[i].flags & I2C_M_RD) - retval = hdpvr_i2c_read(dev, addr, msgs[i].buf, - msgs[i].len); + if (num == 1) { + if (msgs[0].flags & I2C_M_RD) { + // probe + if (!msgs[0].len) { + goto doneunlock; + } + else + { + // simple read + addr = msgs[0].addr << 1; + retval = hdpvr_i2c_read(dev, addr, msgs[0].buf, + msgs[0].len, 0, 0); + } + } else - retval = hdpvr_i2c_write(dev, addr, msgs[i].buf, - msgs[i].len); + { + // simple write + addr = msgs[0].addr << 1; + retval = hdpvr_i2c_write(dev, addr, msgs[0].buf, + msgs[0].len); + } } - + else + { + // We only support subaddress + read case + if (msgs[0].addr != msgs[1].addr) + { + retval = -ENOTSUPP; + goto doneunlock; + } + if ((!((msgs[0].flags & I2C_M_RD))) && + (msgs[1].flags & I2C_M_RD) && + (msgs[0].len==1)) { + // simple read with subaddress + addr = msgs[0].addr << 1; + retval = hdpvr_i2c_read(dev, addr, msgs[1].buf, + msgs[1].len, 1, msgs[0].buf[0]); + } else { + retval = -ENOTSUPP; + goto doneunlock; + } + } +doneunlock: mutex_unlock(&dev->i2c_mutex); +done: return retval ? retval : num; } @@ -140,6 +182,34 @@ else kfree(i2c_adap); + // This is most likely used to reset something, without it IR doesn't work + { + char reseti2c[2]={0,0}; + + retval = hdpvr_i2c_read(dev, 0x2A*2, &reseti2c[1], + 1, 0, 0); + if(retval!=0) + { + hdpvr_err("Couldn't read from I2C 0x2A for unknown reset"); + goto error; + } + reseti2c[1]&=~0x10; + hdpvr_i2c_write(dev, 0x2A*2, + &reseti2c[0], 2); + if(retval!=0) + { + hdpvr_err("Couldn't write to I2C 0x2A for unknown reset"); + goto error; + } + reseti2c[1]|=0x10; + hdpvr_i2c_write(dev, 0x2A*2, + &reseti2c[0], 2); + if(retval!=0) + { + hdpvr_err("Couldn't write to I2C 0x2A for unknown reset"); + goto error; + } + } error: return retval; }