aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarod Wilson <jarod@redhat.com>2011-01-14 14:25:21 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-01-19 09:52:20 -0500
commit324b04ba5da7918a2409f8113e46843bfbd89e67 (patch)
treeba998b90b4de1f7a825357fff03fc123a4884cc8
parent706c57d802394e2fe720ebc929234a678f94e716 (diff)
[media] hdpvr: enable IR part
A number of things going on here, but the end result is that the IR part on the hdpvr gets enabled, and can be used with ir-kbd-i2c and/or lirc_zilog. First up, there are some conditional build fixes that come into play whether i2c is built-in or modular. Second, we're swapping out i2c_new_probed_device() for i2c_new_device(), as in my testing, probing always fails, but we *know* that all hdpvr devices have a z8 chip at 0x70 and 0x71. Third, we're poking at an i2c address directly without a client, and writing some magic bits to actually turn on this IR part (this could use some improvement in the future). Fourth, some of the i2c_adapter storage has been reworked, as the existing implementation used to lead to an oops following i2c changes c. 2.6.31. Earlier editions of this patch have been floating around the 'net for a while, including being patched into Fedora kernels, and they *do* work. This specific version isn't yet tested, beyond loading ir-kbd-i2c and confirming that it does bind to the RX address of the hdpvr. [mchehab@redhat.com: I2C_CLASS_TV_ANALOG is not defined. Fix compilation bug] Signed-off-by: Jarod Wilson <jarod@redhat.com> Acked-by: Andy Walls <awalls@md.metrocast.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/hdpvr/Makefile4
-rw-r--r--drivers/media/video/hdpvr/hdpvr-core.c10
-rw-r--r--drivers/media/video/hdpvr/hdpvr-i2c.c119
-rw-r--r--drivers/media/video/hdpvr/hdpvr-video.c7
-rw-r--r--drivers/media/video/hdpvr/hdpvr.h2
5 files changed, 65 insertions, 77 deletions
diff --git a/drivers/media/video/hdpvr/Makefile b/drivers/media/video/hdpvr/Makefile
index e0230fcb2e3..3baa9f613ca 100644
--- a/drivers/media/video/hdpvr/Makefile
+++ b/drivers/media/video/hdpvr/Makefile
@@ -1,6 +1,4 @@
1hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-video.o 1hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-video.o hdpvr-i2c.o
2
3hdpvr-$(CONFIG_I2C) += hdpvr-i2c.o
4 2
5obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o 3obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o
6 4
diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c
index f7d1ee55185..a6572e5ae36 100644
--- a/drivers/media/video/hdpvr/hdpvr-core.c
+++ b/drivers/media/video/hdpvr/hdpvr-core.c
@@ -378,19 +378,17 @@ static int hdpvr_probe(struct usb_interface *interface,
378 goto error; 378 goto error;
379 } 379 }
380 380
381#ifdef CONFIG_I2C 381#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
382 /* until i2c is working properly */ 382 retval = hdpvr_register_i2c_adapter(dev);
383 retval = 0; /* hdpvr_register_i2c_adapter(dev); */
384 if (retval < 0) { 383 if (retval < 0) {
385 v4l2_err(&dev->v4l2_dev, "registering i2c adapter failed\n"); 384 v4l2_err(&dev->v4l2_dev, "registering i2c adapter failed\n");
386 goto error; 385 goto error;
387 } 386 }
388 387
389 /* until i2c is working properly */ 388 retval = hdpvr_register_i2c_ir(dev);
390 retval = 0; /* hdpvr_register_i2c_ir(dev); */
391 if (retval < 0) 389 if (retval < 0)
392 v4l2_err(&dev->v4l2_dev, "registering i2c IR devices failed\n"); 390 v4l2_err(&dev->v4l2_dev, "registering i2c IR devices failed\n");
393#endif /* CONFIG_I2C */ 391#endif
394 392
395 /* let the user know what node this device is now attached to */ 393 /* let the user know what node this device is now attached to */
396 v4l2_info(&dev->v4l2_dev, "device now attached to %s\n", 394 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 24966aa02a7..45b88cf60d6 100644
--- a/drivers/media/video/hdpvr/hdpvr-i2c.c
+++ b/drivers/media/video/hdpvr/hdpvr-i2c.c
@@ -13,6 +13,8 @@
13 * 13 *
14 */ 14 */
15 15
16#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
17
16#include <linux/i2c.h> 18#include <linux/i2c.h>
17#include <linux/slab.h> 19#include <linux/slab.h>
18 20
@@ -28,55 +30,31 @@
28#define Z8F0811_IR_TX_I2C_ADDR 0x70 30#define Z8F0811_IR_TX_I2C_ADDR 0x70
29#define Z8F0811_IR_RX_I2C_ADDR 0x71 31#define Z8F0811_IR_RX_I2C_ADDR 0x71
30 32
31static const u8 ir_i2c_addrs[] = {
32 Z8F0811_IR_TX_I2C_ADDR,
33 Z8F0811_IR_RX_I2C_ADDR,
34};
35 33
36static const char * const ir_devicenames[] = { 34static struct i2c_board_info hdpvr_i2c_board_info = {
37 "ir_tx_z8f0811_hdpvr", 35 I2C_BOARD_INFO("ir_tx_z8f0811_hdpvr", Z8F0811_IR_TX_I2C_ADDR),
38 "ir_rx_z8f0811_hdpvr", 36 I2C_BOARD_INFO("ir_rx_z8f0811_hdpvr", Z8F0811_IR_RX_I2C_ADDR),
39}; 37};
40 38
41static int hdpvr_new_i2c_ir(struct hdpvr_device *dev, struct i2c_adapter *adap, 39int hdpvr_register_i2c_ir(struct hdpvr_device *dev)
42 const char *type, u8 addr)
43{ 40{
44 struct i2c_board_info info; 41 struct i2c_client *c;
45 struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data; 42 struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data;
46 unsigned short addr_list[2] = { addr, I2C_CLIENT_END };
47
48 memset(&info, 0, sizeof(struct i2c_board_info));
49 strlcpy(info.type, type, I2C_NAME_SIZE);
50 43
51 /* Our default information for ir-kbd-i2c.c to use */ 44 /* Our default information for ir-kbd-i2c.c to use */
52 switch (addr) { 45 init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW;
53 case Z8F0811_IR_RX_I2C_ADDR: 46 init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
54 init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; 47 init_data->type = RC_TYPE_RC5;
55 init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; 48 init_data->name = "HD PVR";
56 init_data->type = RC_TYPE_RC5; 49 hdpvr_i2c_board_info.platform_data = init_data;
57 init_data->name = "HD PVR";
58 info.platform_data = init_data;
59 break;
60 }
61
62 return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ?
63 -1 : 0;
64}
65 50
66int hdpvr_register_i2c_ir(struct hdpvr_device *dev) 51 c = i2c_new_device(&dev->i2c_adapter, &hdpvr_i2c_board_info);
67{
68 int i;
69 int ret = 0;
70 52
71 for (i = 0; i < ARRAY_SIZE(ir_i2c_addrs); i++) 53 return (c == NULL) ? -ENODEV : 0;
72 ret += hdpvr_new_i2c_ir(dev, dev->i2c_adapter,
73 ir_devicenames[i], ir_i2c_addrs[i]);
74
75 return ret;
76} 54}
77 55
78static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr, 56static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus,
79 char *data, int len) 57 unsigned char addr, char *data, int len)
80{ 58{
81 int ret; 59 int ret;
82 char *buf = kmalloc(len, GFP_KERNEL); 60 char *buf = kmalloc(len, GFP_KERNEL);
@@ -86,7 +64,7 @@ static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr,
86 ret = usb_control_msg(dev->udev, 64 ret = usb_control_msg(dev->udev,
87 usb_rcvctrlpipe(dev->udev, 0), 65 usb_rcvctrlpipe(dev->udev, 0),
88 REQTYPE_I2C_READ, CTRL_READ_REQUEST, 66 REQTYPE_I2C_READ, CTRL_READ_REQUEST,
89 0x100|addr, 0, buf, len, 1000); 67 (bus << 8) | addr, 0, buf, len, 1000);
90 68
91 if (ret == len) { 69 if (ret == len) {
92 memcpy(data, buf, len); 70 memcpy(data, buf, len);
@@ -99,8 +77,8 @@ static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr,
99 return ret; 77 return ret;
100} 78}
101 79
102static int hdpvr_i2c_write(struct hdpvr_device *dev, unsigned char addr, 80static int hdpvr_i2c_write(struct hdpvr_device *dev, int bus,
103 char *data, int len) 81 unsigned char addr, char *data, int len)
104{ 82{
105 int ret; 83 int ret;
106 char *buf = kmalloc(len, GFP_KERNEL); 84 char *buf = kmalloc(len, GFP_KERNEL);
@@ -111,7 +89,7 @@ static int hdpvr_i2c_write(struct hdpvr_device *dev, unsigned char addr,
111 ret = usb_control_msg(dev->udev, 89 ret = usb_control_msg(dev->udev,
112 usb_sndctrlpipe(dev->udev, 0), 90 usb_sndctrlpipe(dev->udev, 0),
113 REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST, 91 REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
114 0x100|addr, 0, buf, len, 1000); 92 (bus << 8) | addr, 0, buf, len, 1000);
115 93
116 if (ret < 0) 94 if (ret < 0)
117 goto error; 95 goto error;
@@ -121,7 +99,7 @@ static int hdpvr_i2c_write(struct hdpvr_device *dev, unsigned char addr,
121 REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST, 99 REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST,
122 0, 0, buf, 2, 1000); 100 0, 0, buf, 2, 1000);
123 101
124 if (ret == 2) 102 if ((ret == 2) && (buf[1] == (len - 1)))
125 ret = 0; 103 ret = 0;
126 else if (ret >= 0) 104 else if (ret >= 0)
127 ret = -EIO; 105 ret = -EIO;
@@ -146,10 +124,10 @@ static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs,
146 addr = msgs[i].addr << 1; 124 addr = msgs[i].addr << 1;
147 125
148 if (msgs[i].flags & I2C_M_RD) 126 if (msgs[i].flags & I2C_M_RD)
149 retval = hdpvr_i2c_read(dev, addr, msgs[i].buf, 127 retval = hdpvr_i2c_read(dev, 1, addr, msgs[i].buf,
150 msgs[i].len); 128 msgs[i].len);
151 else 129 else
152 retval = hdpvr_i2c_write(dev, addr, msgs[i].buf, 130 retval = hdpvr_i2c_write(dev, 1, addr, msgs[i].buf,
153 msgs[i].len); 131 msgs[i].len);
154 } 132 }
155 133
@@ -168,30 +146,47 @@ static struct i2c_algorithm hdpvr_algo = {
168 .functionality = hdpvr_functionality, 146 .functionality = hdpvr_functionality,
169}; 147};
170 148
149static struct i2c_adapter hdpvr_i2c_adapter_template = {
150 .name = "Hauppage HD PVR I2C",
151 .owner = THIS_MODULE,
152 .algo = &hdpvr_algo,
153};
154
155static int hdpvr_activate_ir(struct hdpvr_device *dev)
156{
157 char buffer[8];
158
159 mutex_lock(&dev->i2c_mutex);
160
161 hdpvr_i2c_read(dev, 0, 0x54, buffer, 1);
162
163 buffer[0] = 0;
164 buffer[1] = 0x8;
165 hdpvr_i2c_write(dev, 1, 0x54, buffer, 2);
166
167 buffer[1] = 0x18;
168 hdpvr_i2c_write(dev, 1, 0x54, buffer, 2);
169
170 mutex_unlock(&dev->i2c_mutex);
171
172 return 0;
173}
174
171int hdpvr_register_i2c_adapter(struct hdpvr_device *dev) 175int hdpvr_register_i2c_adapter(struct hdpvr_device *dev)
172{ 176{
173 struct i2c_adapter *i2c_adap;
174 int retval = -ENOMEM; 177 int retval = -ENOMEM;
175 178
176 i2c_adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); 179 hdpvr_activate_ir(dev);
177 if (i2c_adap == NULL)
178 goto error;
179 180
180 strlcpy(i2c_adap->name, "Hauppauge HD PVR I2C", 181 memcpy(&dev->i2c_adapter, &hdpvr_i2c_adapter_template,
181 sizeof(i2c_adap->name)); 182 sizeof(struct i2c_adapter));
182 i2c_adap->algo = &hdpvr_algo; 183 dev->i2c_adapter.dev.parent = &dev->udev->dev;
183 i2c_adap->owner = THIS_MODULE;
184 i2c_adap->dev.parent = &dev->udev->dev;
185 184
186 i2c_set_adapdata(i2c_adap, dev); 185 i2c_set_adapdata(&dev->i2c_adapter, dev);
187 186
188 retval = i2c_add_adapter(i2c_adap); 187 retval = i2c_add_adapter(&dev->i2c_adapter);
189 188
190 if (!retval)
191 dev->i2c_adapter = i2c_adap;
192 else
193 kfree(i2c_adap);
194
195error:
196 return retval; 189 return retval;
197} 190}
191
192#endif
diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c
index d38fe1043e4..514aea76eaa 100644
--- a/drivers/media/video/hdpvr/hdpvr-video.c
+++ b/drivers/media/video/hdpvr/hdpvr-video.c
@@ -1220,12 +1220,9 @@ static void hdpvr_device_release(struct video_device *vdev)
1220 v4l2_device_unregister(&dev->v4l2_dev); 1220 v4l2_device_unregister(&dev->v4l2_dev);
1221 1221
1222 /* deregister I2C adapter */ 1222 /* deregister I2C adapter */
1223#ifdef CONFIG_I2C 1223#if defined(CONFIG_I2C) || (CONFIG_I2C_MODULE)
1224 mutex_lock(&dev->i2c_mutex); 1224 mutex_lock(&dev->i2c_mutex);
1225 if (dev->i2c_adapter) 1225 i2c_del_adapter(&dev->i2c_adapter);
1226 i2c_del_adapter(dev->i2c_adapter);
1227 kfree(dev->i2c_adapter);
1228 dev->i2c_adapter = NULL;
1229 mutex_unlock(&dev->i2c_mutex); 1226 mutex_unlock(&dev->i2c_mutex);
1230#endif /* CONFIG_I2C */ 1227#endif /* CONFIG_I2C */
1231 1228
diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h
index 37f1e4c7675..29f74269400 100644
--- a/drivers/media/video/hdpvr/hdpvr.h
+++ b/drivers/media/video/hdpvr/hdpvr.h
@@ -106,7 +106,7 @@ struct hdpvr_device {
106 struct work_struct worker; 106 struct work_struct worker;
107 107
108 /* I2C adapter */ 108 /* I2C adapter */
109 struct i2c_adapter *i2c_adapter; 109 struct i2c_adapter i2c_adapter;
110 /* I2C lock */ 110 /* I2C lock */
111 struct mutex i2c_mutex; 111 struct mutex i2c_mutex;
112 112