]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/media/video/ir-kbd-i2c.c
V4L/DVB (10632): Added support for AVerMedia Cardbus Hybrid remote control
[mv-sheeva.git] / drivers / media / video / ir-kbd-i2c.c
index efe849981ab7c3766bb61efe78e437ebc1bb6ff1..2ee49b7ddcf02f868fe35b92d7aa30e8f5a10af6 100644 (file)
@@ -16,6 +16,8 @@
  *      Henry Wong <henry@stuffedcow.net>
  *      Mark Schultz <n9xmj@yahoo.com>
  *      Brian Rogers <brian_rogers@comcast.net>
+ * modified for AVerMedia Cardbus by
+ *      Oldrich Jedlicka <oldium.pro@seznam.cz>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -216,6 +218,46 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        return 1;
 }
 
+static int get_key_avermedia_cardbus(struct IR_i2c *ir,
+                                    u32 *ir_key, u32 *ir_raw)
+{
+       unsigned char subaddr, key, keygroup;
+       struct i2c_msg msg[] = { { .addr = ir->c.addr, .flags = 0,
+                                  .buf = &subaddr, .len = 1},
+                                { .addr = ir->c.addr, .flags = I2C_M_RD,
+                                 .buf = &key, .len = 1} };
+       subaddr = 0x0d;
+       if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
+               dprintk(1, "read error\n");
+               return -EIO;
+       }
+
+       if (key == 0xff)
+               return 0;
+
+       subaddr = 0x0b;
+       msg[1].buf = &keygroup;
+       if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
+               dprintk(1, "read error\n");
+               return -EIO;
+       }
+
+       if (keygroup == 0xff)
+               return 0;
+
+       dprintk(1, "read key 0x%02x/0x%02x\n", key, keygroup);
+       if (keygroup < 2 || keygroup > 3) {
+               /* Only a warning */
+               dprintk(1, "warning: invalid key group 0x%02x for key 0x%02x\n",
+                                                               keygroup, key);
+       }
+       key |= (keygroup & 1) << 6;
+
+       *ir_key = key;
+       *ir_raw = key;
+       return 1;
+}
+
 /* ----------------------------------------------------------------------- */
 
 static void ir_key_poll(struct IR_i2c *ir)
@@ -360,6 +402,12 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
                        ir_type     = IR_TYPE_OTHER;
                }
                break;
+       case 0x40:
+               name        = "AVerMedia Cardbus remote";
+               ir->get_key = get_key_avermedia_cardbus;
+               ir_type     = IR_TYPE_OTHER;
+               ir_codes    = ir_codes_avermedia_cardbus;
+               break;
        default:
                /* shouldn't happen */
                printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr);
@@ -385,10 +433,10 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
                goto err_out_detach;
        }
 
-       /* Phys addr can only be set after attaching (for ir->c.dev.bus_id) */
+       /* Phys addr can only be set after attaching (for ir->c.dev) */
        snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0",
-                ir->c.adapter->dev.bus_id,
-                ir->c.dev.bus_id);
+                dev_name(&ir->c.adapter->dev),
+                dev_name(&ir->c.dev));
 
        /* init + register input device */
        ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes);
@@ -524,6 +572,22 @@ static int ir_probe(struct i2c_adapter *adap)
                        ir_attach(adap, msg.addr, 0, 0);
        }
 
+       /* Special case for AVerMedia Cardbus remote */
+       if (adap->id == I2C_HW_SAA7134) {
+               unsigned char subaddr, data;
+               struct i2c_msg msg[] = { { .addr = 0x40, .flags = 0,
+                                          .buf = &subaddr, .len = 1},
+                                        { .addr = 0x40, .flags = I2C_M_RD,
+                                          .buf = &data, .len = 1} };
+               subaddr = 0x0d;
+               rc = i2c_transfer(adap, msg, 2);
+               dprintk(1, "probe 0x%02x/0x%02x @ %s: %s\n",
+                       msg[0].addr, subaddr, adap->name,
+                       (2 == rc) ? "yes" : "no");
+               if (2 == rc)
+                       ir_attach(adap, msg[0].addr, 0, 0);
+       }
+
        return 0;
 }