summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/ir-kbd-i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/video/ir-kbd-i2c.c')
-rw-r--r--linux/drivers/media/video/ir-kbd-i2c.c197
1 files changed, 168 insertions, 29 deletions
diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c
index a99aea49a..a1e8fb561 100644
--- a/linux/drivers/media/video/ir-kbd-i2c.c
+++ b/linux/drivers/media/video/ir-kbd-i2c.c
@@ -47,9 +47,9 @@
#include <linux/i2c-id.h>
#include <linux/workqueue.h>
+#include "compat.h"
#include <media/ir-common.h>
#include <media/ir-kbd-i2c.h>
-#include "compat.h"
/* ----------------------------------------------------------------------- */
/* insmod parameters */
@@ -75,7 +75,11 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
int start, range, toggle, dev, code, ircode;
/* poll IR chip */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
if (size != i2c_master_recv(&ir->c,buf,size))
+#else
+ if (size != i2c_master_recv(ir->c, buf, size))
+#endif
return -EIO;
/* split rc5 data block ... */
@@ -123,12 +127,12 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
return 1;
}
-static inline int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
return get_key_haup_common (ir, ir_key, ir_raw, 3, 0);
}
-static inline int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
return get_key_haup_common (ir, ir_key, ir_raw, 6, 3);
}
@@ -138,7 +142,11 @@ static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
unsigned char b;
/* poll IR chip */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
if (1 != i2c_master_recv(&ir->c,&b,1)) {
+#else
+ if (1 != i2c_master_recv(ir->c, &b, 1)) {
+#endif
dprintk(1,"read error\n");
return -EIO;
}
@@ -152,7 +160,11 @@ static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
unsigned char b;
/* poll IR chip */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
if (1 != i2c_master_recv(&ir->c,&b,1)) {
+#else
+ if (1 != i2c_master_recv(ir->c, &b, 1)) {
+#endif
dprintk(1,"read error\n");
return -EIO;
}
@@ -172,7 +184,11 @@ static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
unsigned char buf[4];
/* poll IR chip */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
if (4 != i2c_master_recv(&ir->c,buf,4)) {
+#else
+ if (4 != i2c_master_recv(ir->c, buf, 4)) {
+#endif
dprintk(1,"read error\n");
return -EIO;
}
@@ -196,7 +212,11 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
unsigned char b;
/* poll IR chip */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
if (1 != i2c_master_recv(&ir->c,&b,1)) {
+#else
+ if (1 != i2c_master_recv(ir->c, &b, 1)) {
+#endif
dprintk(1,"read error\n");
return -EIO;
}
@@ -223,12 +243,24 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
u32 *ir_key, u32 *ir_raw)
{
unsigned char subaddr, key, keygroup;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
struct i2c_msg msg[] = { { .addr = ir->c.addr, .flags = 0,
+#else
+ struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0,
+#endif
.buf = &subaddr, .len = 1},
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
{ .addr = ir->c.addr, .flags = I2C_M_RD,
+#else
+ { .addr = ir->c->addr, .flags = I2C_M_RD,
+#endif
.buf = &key, .len = 1} };
subaddr = 0x0d;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
+#else
+ if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
+#endif
dprintk(1, "read error\n");
return -EIO;
}
@@ -238,7 +270,11 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
subaddr = 0x0b;
msg[1].buf = &keygroup;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
+#else
+ if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
+#endif
dprintk(1, "read error\n");
return -EIO;
}
@@ -280,12 +316,6 @@ static void ir_key_poll(struct IR_i2c *ir)
}
}
-static void ir_timer(unsigned long data)
-{
- struct IR_i2c *ir = (struct IR_i2c*)data;
- schedule_work(&ir->work);
-}
-
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
static void ir_work(void *data)
#else
@@ -295,23 +325,28 @@ static void ir_work(struct work_struct *work)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
struct IR_i2c *ir = data;
#else
- struct IR_i2c *ir = container_of(work, struct IR_i2c, work);
+ struct IR_i2c *ir = container_of(work, struct IR_i2c, work.work);
#endif
int polling_interval = 100;
/* MSI TV@nywhere Plus requires more frequent polling
otherwise it will miss some keypresses */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
if (ir->c.adapter->id == I2C_HW_SAA7134 && ir->c.addr == 0x30)
+#else
+ if (ir->c->adapter->id == I2C_HW_SAA7134 && ir->c->addr == 0x30)
+#endif
polling_interval = 50;
ir_key_poll(ir);
- mod_timer(&ir->timer, jiffies + msecs_to_jiffies(polling_interval));
+ schedule_delayed_work(&ir->work, msecs_to_jiffies(polling_interval));
}
/* ----------------------------------------------------------------------- */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
static int ir_attach(struct i2c_adapter *adap, int addr,
- unsigned short flags, int kind);
+ unsigned short flags, int kind);
static int ir_detach(struct i2c_client *client);
static int ir_probe(struct i2c_adapter *adap);
@@ -324,20 +359,27 @@ static struct i2c_driver driver = {
.detach_client = ir_detach,
};
-static struct i2c_client client_template =
+static struct i2c_client client =
{
.name = "unset",
.driver = &driver
-};
+ };
static int ir_attach(struct i2c_adapter *adap, int addr,
unsigned short flags, int kind)
+#else
+static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
+#endif
{
IR_KEYTAB_TYPE *ir_codes = NULL;
- char *name;
+ const char *name = NULL;
int ir_type;
struct IR_i2c *ir;
struct input_dev *input_dev;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+ struct i2c_adapter *adap = client->adapter;
+ unsigned short addr = client->addr;
+#endif
int err;
ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL);
@@ -347,13 +389,18 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
goto err_out_free;
}
- ir->c = client_template;
+ ir->c = client;
ir->input = input_dev;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
ir->c.adapter = adap;
ir->c.addr = addr;
+ snprintf(ir->c.name, sizeof(ir->c.name), "ir-kbd");
i2c_set_clientdata(&ir->c, ir);
+#else
+ i2c_set_clientdata(client, ir);
+#endif
switch(addr) {
case 0x64:
@@ -395,9 +442,11 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
case 0x47:
case 0x71:
case 0x2d:
- if (adap->id == I2C_HW_B_CX2388x) {
+ if (adap->id == I2C_HW_B_CX2388x ||
+ adap->id == I2C_HW_B_CX2341X) {
/* Handled by cx88-input */
- name = "CX2388x remote";
+ name = adap->id == I2C_HW_B_CX2341X ? "CX2341x remote"
+ : "CX2388x remote";
ir_type = IR_TYPE_RC5;
ir->get_key = get_key_haup_xvr;
if (hauppauge == 1) {
@@ -418,16 +467,69 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
ir_codes = ir_codes_avermedia_cardbus;
break;
default:
- /* shouldn't happen */
- printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr);
+ dprintk(1, DEVNAME ": Unsupported i2c address 0x%02x\n", addr);
err = -ENODEV;
goto err_out_free;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+ /* Let the caller override settings */
+ if (client->dev.platform_data) {
+ const struct IR_i2c_init_data *init_data =
+ client->dev.platform_data;
+
+ ir_codes = init_data->ir_codes;
+ name = init_data->name;
+ if (init_data->type)
+ ir_type = init_data->type;
+
+ switch (init_data->internal_get_key_func) {
+ case IR_KBD_GET_KEY_CUSTOM:
+ /* The bridge driver provided us its own function */
+ ir->get_key = init_data->get_key;
+ break;
+ case IR_KBD_GET_KEY_PIXELVIEW:
+ ir->get_key = get_key_pixelview;
+ break;
+ case IR_KBD_GET_KEY_PV951:
+ ir->get_key = get_key_pv951;
+ break;
+ case IR_KBD_GET_KEY_HAUP:
+ ir->get_key = get_key_haup;
+ break;
+ case IR_KBD_GET_KEY_KNC1:
+ ir->get_key = get_key_knc1;
+ break;
+ case IR_KBD_GET_KEY_FUSIONHDTV:
+ ir->get_key = get_key_fusionhdtv;
+ break;
+ case IR_KBD_GET_KEY_HAUP_XVR:
+ ir->get_key = get_key_haup_xvr;
+ break;
+ case IR_KBD_GET_KEY_AVERMEDIA_CARDBUS:
+ ir->get_key = get_key_avermedia_cardbus;
+ break;
+ }
+ }
+
+ /* Make sure we are all setup before going on */
+ if (!name || !ir->get_key || !ir_codes) {
+ dprintk(1, DEVNAME ": Unsupported device at address 0x%02x\n",
+ addr);
+ err = -ENODEV;
+ goto err_out_free;
+ }
+#endif
+
/* Sets name */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name);
+#else
+ snprintf(ir->name, sizeof(ir->name), "i2c IR (%s)", name);
+#endif
ir->ir_codes = ir_codes;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
/* register i2c device
* At device register, IR codes may be changed to be
* board dependent.
@@ -443,61 +545,80 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
}
/* Phys addr can only be set after attaching (for ir->c.dev) */
+#endif
snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0",
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
dev_name(&ir->c.adapter->dev),
dev_name(&ir->c.dev));
+#else
+ dev_name(&adap->dev),
+ dev_name(&client->dev));
+#endif
/* init + register input device */
ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes);
input_dev->id.bustype = BUS_I2C;
- input_dev->name = ir->c.name;
+ input_dev->name = ir->name;
input_dev->phys = ir->phys;
err = input_register_device(ir->input);
if (err)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
goto err_out_detach;
+#else
+ goto err_out_free;
+#endif
printk(DEVNAME ": %s detected at %s [%s]\n",
ir->input->name, ir->input->phys, adap->name);
/* start polling via eventd */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
- INIT_WORK(&ir->work, ir_work, ir);
+ INIT_DELAYED_WORK(&ir->work, ir_work, ir);
#else
- INIT_WORK(&ir->work, ir_work);
+ INIT_DELAYED_WORK(&ir->work, ir_work);
#endif
- init_timer(&ir->timer);
- ir->timer.function = ir_timer;
- ir->timer.data = (unsigned long)ir;
- schedule_work(&ir->work);
+ schedule_delayed_work(&ir->work, 0);
return 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
err_out_detach:
i2c_detach_client(&ir->c);
+#endif
err_out_free:
input_free_device(input_dev);
kfree(ir);
return err;
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
static int ir_detach(struct i2c_client *client)
+#else
+static int ir_remove(struct i2c_client *client)
+#endif
{
struct IR_i2c *ir = i2c_get_clientdata(client);
/* kill outstanding polls */
- del_timer_sync(&ir->timer);
- flush_scheduled_work();
+ cancel_delayed_work_sync(&ir->work);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
/* unregister devices */
+#else
+ /* unregister device */
+#endif
input_unregister_device(ir->input);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
i2c_detach_client(&ir->c);
+#endif
/* free memory */
kfree(ir);
return 0;
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
static int ir_probe(struct i2c_adapter *adap)
{
@@ -603,6 +724,24 @@ static int ir_probe(struct i2c_adapter *adap)
return 0;
}
+#else
+static const struct i2c_device_id ir_kbd_id[] = {
+ /* Generic entry for any IR receiver */
+ { "ir_video", 0 },
+ /* IR device specific entries should be added here */
+ { "ir_rx_z8f0811_haup", 0 },
+ { }
+};
+
+static struct i2c_driver driver = {
+ .driver = {
+ .name = "ir-kbd-i2c",
+ },
+ .probe = ir_probe,
+ .remove = ir_remove,
+ .id_table = ir_kbd_id,
+};
+#endif
/* ----------------------------------------------------------------------- */