| diff --git a/drivers/media/video/hdpvr/Makefile b/drivers/media/video/hdpvr/Makefile |
| index e0230fc..3baa9f6 100644 |
| |
| |
| @@ -1,6 +1,4 @@ |
| -hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-video.o |
| - |
| -hdpvr-$(CONFIG_I2C) += hdpvr-i2c.o |
| +hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-video.o hdpvr-i2c.o |
| |
| obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o |
| |
| diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c |
| index 830d47b..70cfdc8 100644 |
| |
| |
| @@ -364,14 +364,13 @@ static int hdpvr_probe(struct usb_interface *interface, |
| goto error; |
| } |
| |
| -#ifdef CONFIG_I2C |
| - /* until i2c is working properly */ |
| - retval = 0; /* hdpvr_register_i2c_adapter(dev); */ |
| +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
| + retval = hdpvr_register_i2c_adapter(dev); |
| if (retval < 0) { |
| v4l2_err(&dev->v4l2_dev, "registering i2c adapter failed\n"); |
| goto error; |
| } |
| -#endif /* CONFIG_I2C */ |
| +#endif |
| |
| /* let the user know what node this device is now attached to */ |
| v4l2_info(&dev->v4l2_dev, "device now attached to %s\n", |
| diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c |
| index 463b81b..60cdc06 100644 |
| |
| |
| @@ -10,6 +10,8 @@ |
| * |
| */ |
| |
| +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
| + |
| #include <linux/i2c.h> |
| #include <linux/slab.h> |
| |
| @@ -22,8 +24,11 @@ |
| #define REQTYPE_I2C_WRITE 0xb0 |
| #define REQTYPE_I2C_WRITE_STATT 0xd0 |
| |
| -static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr, |
| - char *data, int len) |
| +#define HDPVR_HW_Z8F0811_IR_TX_I2C_ADDR 0x70 |
| +#define HDPVR_HW_Z8F0811_IR_RX_I2C_ADDR 0x71 |
| + |
| +static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus, |
| + unsigned char addr, char *data, int len) |
| { |
| int ret; |
| char *buf = kmalloc(len, GFP_KERNEL); |
| @@ -33,7 +38,7 @@ static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr, |
| ret = usb_control_msg(dev->udev, |
| usb_rcvctrlpipe(dev->udev, 0), |
| REQTYPE_I2C_READ, CTRL_READ_REQUEST, |
| - 0x100|addr, 0, buf, len, 1000); |
| + (bus << 8) | addr, 0, buf, len, 1000); |
| |
| if (ret == len) { |
| memcpy(data, buf, len); |
| @@ -46,8 +51,8 @@ static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr, |
| return ret; |
| } |
| |
| -static int hdpvr_i2c_write(struct hdpvr_device *dev, unsigned char addr, |
| - char *data, int len) |
| +static int hdpvr_i2c_write(struct hdpvr_device *dev, int bus, |
| + unsigned char addr, char *data, int len) |
| { |
| int ret; |
| char *buf = kmalloc(len, GFP_KERNEL); |
| @@ -58,7 +63,7 @@ static int hdpvr_i2c_write(struct hdpvr_device *dev, unsigned char addr, |
| ret = usb_control_msg(dev->udev, |
| usb_sndctrlpipe(dev->udev, 0), |
| REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST, |
| - 0x100|addr, 0, buf, len, 1000); |
| + (bus << 8) | addr, 0, buf, len, 1000); |
| |
| if (ret < 0) |
| goto error; |
| @@ -68,7 +73,7 @@ static int hdpvr_i2c_write(struct hdpvr_device *dev, unsigned char addr, |
| 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; |
| @@ -93,10 +98,10 @@ static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs, |
| addr = msgs[i].addr << 1; |
| |
| if (msgs[i].flags & I2C_M_RD) |
| - retval = hdpvr_i2c_read(dev, addr, msgs[i].buf, |
| + retval = hdpvr_i2c_read(dev, 1, addr, msgs[i].buf, |
| msgs[i].len); |
| else |
| - retval = hdpvr_i2c_write(dev, addr, msgs[i].buf, |
| + retval = hdpvr_i2c_write(dev, 1, addr, msgs[i].buf, |
| msgs[i].len); |
| } |
| |
| @@ -115,30 +120,58 @@ static struct i2c_algorithm hdpvr_algo = { |
| .functionality = hdpvr_functionality, |
| }; |
| |
| +static struct i2c_adapter hdpvr_i2c_adapter_template = { |
| + .name = "Hauppage HD PVR I2C", |
| + .owner = THIS_MODULE, |
| + .id = I2C_HW_B_HDPVR, |
| + .algo = &hdpvr_algo, |
| +}; |
| + |
| +static struct i2c_board_info hdpvr_i2c_board_info = { |
| + I2C_BOARD_INFO("ir_tx_z8f0811_haup", HDPVR_HW_Z8F0811_IR_TX_I2C_ADDR), |
| + I2C_BOARD_INFO("ir_rx_z8f0811_haup", HDPVR_HW_Z8F0811_IR_RX_I2C_ADDR), |
| +}; |
| + |
| +static int hdpvr_activate_ir(struct hdpvr_device *dev) |
| +{ |
| + char buffer[8]; |
| + |
| + mutex_lock(&dev->i2c_mutex); |
| + |
| + hdpvr_i2c_read(dev, 0, 0x54, buffer, 1); |
| + |
| + buffer[0] = 0; |
| + buffer[1] = 0x8; |
| + hdpvr_i2c_write(dev, 1, 0x54, buffer, 2); |
| + |
| + buffer[1] = 0x18; |
| + hdpvr_i2c_write(dev, 1, 0x54, buffer, 2); |
| + |
| + mutex_unlock(&dev->i2c_mutex); |
| + |
| + return 0; |
| +} |
| + |
| int hdpvr_register_i2c_adapter(struct hdpvr_device *dev) |
| { |
| - struct i2c_adapter *i2c_adap; |
| int retval = -ENOMEM; |
| |
| - i2c_adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); |
| - if (i2c_adap == NULL) |
| - goto error; |
| + hdpvr_activate_ir(dev); |
| |
| - strlcpy(i2c_adap->name, "Hauppauge HD PVR I2C", |
| - sizeof(i2c_adap->name)); |
| - i2c_adap->algo = &hdpvr_algo; |
| - i2c_adap->owner = THIS_MODULE; |
| - i2c_adap->dev.parent = &dev->udev->dev; |
| + memcpy(&dev->i2c_adapter, &hdpvr_i2c_adapter_template, |
| + sizeof(struct i2c_adapter)); |
| + dev->i2c_adapter.dev.parent = &dev->udev->dev; |
| |
| - i2c_set_adapdata(i2c_adap, dev); |
| + i2c_set_adapdata(&dev->i2c_adapter, dev); |
| |
| - retval = i2c_add_adapter(i2c_adap); |
| + retval = i2c_add_adapter(&dev->i2c_adapter); |
| + if (retval) |
| + goto error; |
| |
| - if (!retval) |
| - dev->i2c_adapter = i2c_adap; |
| - else |
| - kfree(i2c_adap); |
| + i2c_new_device(&dev->i2c_adapter, &hdpvr_i2c_board_info); |
| |
| error: |
| return retval; |
| } |
| + |
| +#endif |
| diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c |
| index c338f3f..26fd9bf 100644 |
| |
| |
| @@ -1221,12 +1221,9 @@ static void hdpvr_device_release(struct video_device *vdev) |
| v4l2_device_unregister(&dev->v4l2_dev); |
| |
| /* deregister I2C adapter */ |
| -#ifdef CONFIG_I2C |
| +#if defined(CONFIG_I2C) || (CONFIG_I2C_MODULE) |
| mutex_lock(&dev->i2c_mutex); |
| - if (dev->i2c_adapter) |
| - i2c_del_adapter(dev->i2c_adapter); |
| - kfree(dev->i2c_adapter); |
| - dev->i2c_adapter = NULL; |
| + i2c_del_adapter(&dev->i2c_adapter); |
| mutex_unlock(&dev->i2c_mutex); |
| #endif /* CONFIG_I2C */ |
| |
| diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h |
| index b0f046d..2107055 100644 |
| |
| |
| @@ -102,7 +102,7 @@ struct hdpvr_device { |
| struct work_struct worker; |
| |
| /* I2C adapter */ |
| - struct i2c_adapter *i2c_adapter; |
| + struct i2c_adapter i2c_adapter; |
| /* I2C lock */ |
| struct mutex i2c_mutex; |
| |
| diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h |
| index 4bef5c5..4385341 100644 |
| |
| |
| @@ -33,5 +33,6 @@ |
| |
| /* --- Bit algorithm adapters */ |
| #define I2C_HW_B_CX2388x 0x01001b /* connexant 2388x based tv cards */ |
| +#define I2C_HW_B_HDPVR 0x010025 /* Hauppauge HD PVR */ |
| |
| #endif /* LINUX_I2C_ID_H */ |