V4L/DVB (11844): ir-kbd-i2c: Switch to the new-style device binding model
authorJean Delvare <khali@linux-fr.org>
Wed, 13 May 2009 19:48:50 +0000 (16:48 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 16 Jun 2009 21:21:11 +0000 (18:21 -0300)
Let card drivers probe for IR receiver devices and instantiate them if
found. Ultimately it would be better if we could stop probing
completely, but I suspect this won't be possible for all card types.

There's certainly room for cleanups. For example, some drivers are
sharing I2C adapter IDs, so they also had to share the list of I2C
addresses being probed for an IR receiver. Now that each driver
explicitly says which addresses should be probed, maybe some addresses
can be dropped from some drivers.

Also, the special cases in saa7134-i2c should probably be handled on a
per-board basis. This would be more efficient and less risky than always
probing extra addresses on all boards. I'll give it a try later.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
16 files changed:
drivers/media/video/bt8xx/bttv-i2c.c
drivers/media/video/cx231xx/cx231xx-cards.c
drivers/media/video/cx231xx/cx231xx-i2c.c
drivers/media/video/cx231xx/cx231xx.h
drivers/media/video/cx23885/cx23885-i2c.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/em28xx/em28xx-i2c.c
drivers/media/video/em28xx/em28xx-input.c
drivers/media/video/em28xx/em28xx.h
drivers/media/video/ir-kbd-i2c.c
drivers/media/video/ivtv/ivtv-i2c.c
drivers/media/video/saa7134/saa7134-i2c.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/saa7134/saa7134.h
include/media/ir-kbd-i2c.h

index a99d92fac3dc4e7731cfa9b2349886ac926b6d6c..ebd1ee9dc871d222f6f918b8670aa407037e9777 100644 (file)
@@ -389,6 +389,27 @@ int __devinit init_bttv_i2c(struct bttv *btv)
        }
        if (0 == btv->i2c_rc && i2c_scan)
                do_i2c_scan(btv->c.v4l2_dev.name, &btv->i2c_client);
+
+       /* Instantiate the IR receiver device, if present */
+       if (0 == btv->i2c_rc) {
+               struct i2c_board_info info;
+               /* The external IR receiver is at i2c address 0x34 (0x35 for
+                  reads).  Future Hauppauge cards will have an internal
+                  receiver at 0x30 (0x31 for reads).  In theory, both can be
+                  fitted, and Hauppauge suggest an external overrides an
+                  internal.
+
+                  That's why we probe 0x1a (~0x34) first. CB
+               */
+               const unsigned short addr_list[] = {
+                       0x1a, 0x18, 0x4b, 0x64, 0x30,
+                       I2C_CLIENT_END
+               };
+
+               memset(&info, 0, sizeof(struct i2c_board_info));
+               strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+               i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list);
+       }
        return btv->i2c_rc;
 }
 
index c8a32b1b53812654f3442939d2e14b7571087a28..734f6eaefd9bf40ac7652b39ace0c6eec3738650 100644 (file)
@@ -281,13 +281,16 @@ static void cx231xx_config_tuner(struct cx231xx *dev)
 }
 
 /* ----------------------------------------------------------------------- */
-void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir)
+void cx231xx_register_i2c_ir(struct cx231xx *dev)
 {
-       if (disable_ir) {
-               ir->get_key = NULL;
+       if (disable_ir)
                return;
-       }
 
+       /* REVISIT: instantiate IR device */
+}
+
+void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir)
+{
        /* detect & configure */
        switch (dev->model) {
 
index b4a03d813e00d7b9c3001bc52233bb48e0556c87..ac4099a49da095851f08345972185bbfeef5fe55 100644 (file)
@@ -537,6 +537,9 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus)
        if (0 == bus->i2c_rc) {
                if (i2c_scan)
                        cx231xx_do_i2c_scan(dev, &bus->i2c_client);
+
+               /* Instantiate the IR receiver device, if present */
+               cx231xx_register_i2c_ir(dev);
        } else
                cx231xx_warn("%s: i2c bus %d register FAILED\n",
                             dev->name, bus->nr);
index aa4a23ef491a3341e2851cc6429a25345f9fbbc6..8c300f60fdff2a097638d0db5a2b0d4d405bc5ef 100644 (file)
@@ -738,6 +738,7 @@ extern void cx231xx_card_setup(struct cx231xx *dev);
 extern struct cx231xx_board cx231xx_boards[];
 extern struct usb_device_id cx231xx_id_table[];
 extern const unsigned int cx231xx_bcount;
+void cx231xx_register_i2c_ir(struct cx231xx *dev);
 void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir);
 int cx231xx_tuner_callback(void *ptr, int component, int command, int arg);
 
index 3421bd12056a95ee58a4604ca380354f4ccb444c..384dec34134fe56ef6298909fa6a633a0c9bec4b 100644 (file)
@@ -357,6 +357,18 @@ int cx23885_i2c_register(struct cx23885_i2c *bus)
                printk(KERN_WARNING "%s: i2c bus %d register FAILED\n",
                        dev->name, bus->nr);
 
+       /* Instantiate the IR receiver device, if present */
+       if (0 == bus->i2c_rc) {
+               struct i2c_board_info info;
+               const unsigned short addr_list[] = {
+                       0x6b, I2C_CLIENT_END
+               };
+
+               memset(&info, 0, sizeof(struct i2c_board_info));
+               strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+               i2c_new_probed_device(&bus->i2c_adap, &info, addr_list);
+       }
+
        return bus->i2c_rc;
 }
 
index 996b4ed5a4fc8ae414cd18abc1a6d1cdb44ef092..ee1ca39db06ad684758dc4da0bfa8b35aa8e1f56 100644 (file)
@@ -180,6 +180,19 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
                        do_i2c_scan(core->name,&core->i2c_client);
        } else
                printk("%s: i2c register FAILED\n", core->name);
+
+       /* Instantiate the IR receiver device, if present */
+       if (0 == core->i2c_rc) {
+               struct i2c_board_info info;
+               const unsigned short addr_list[] = {
+                       0x18, 0x6b, 0x71,
+                       I2C_CLIENT_END
+               };
+
+               memset(&info, 0, sizeof(struct i2c_board_info));
+               strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+               i2c_new_probed_device(&core->i2c_adap, &info, addr_list);
+       }
        return core->i2c_rc;
 }
 
index b2aed29e2d745e062971c66b53031ba9feb2b4c7..edba71115a9402ccebbafeaa37d59dd6be204ece 100644 (file)
@@ -1912,13 +1912,23 @@ static int em28xx_hint_board(struct em28xx *dev)
 }
 
 /* ----------------------------------------------------------------------- */
-void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir)
+void em28xx_register_i2c_ir(struct em28xx *dev)
 {
-       if (disable_ir) {
-               ir->get_key = NULL;
-               return ;
-       }
+       struct i2c_board_info info;
+       const unsigned short addr_list[] = {
+                0x30, 0x47, I2C_CLIENT_END
+       };
+
+       if (disable_ir)
+               return;
 
+       memset(&info, 0, sizeof(struct i2c_board_info));
+       strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+       i2c_new_probed_device(&dev->i2c_adap, &info, addr_list);
+}
+
+void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir)
+{
        /* detect & configure */
        switch (dev->model) {
        case (EM2800_BOARD_UNKNOWN):
index f0bf1d960c759a081652ade96e3573d6326a6113..d90294cbb70d8d8e0fcd11daf6b3aa719d527321 100644 (file)
@@ -575,6 +575,9 @@ int em28xx_i2c_register(struct em28xx *dev)
        if (i2c_scan)
                em28xx_do_i2c_scan(dev);
 
+       /* Instantiate the IR receiver device, if present */
+       em28xx_register_i2c_ir(dev);
+
        return 0;
 }
 
index 7450ba7dee83bbbb9708ee6e0e23df953ff20d48..7a0fe3816e3db6613d051c528ac8a25347ea8d97 100644 (file)
@@ -85,7 +85,7 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        unsigned char b;
 
        /* poll IR chip */
-       if (1 != i2c_master_recv(&ir->c, &b, 1)) {
+       if (1 != i2c_master_recv(ir->c, &b, 1)) {
                i2cdprintk("read error\n");
                return -EIO;
        }
@@ -114,7 +114,7 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        unsigned char code;
 
        /* poll IR chip */
-       if (2 != i2c_master_recv(&ir->c, buf, 2))
+       if (2 != i2c_master_recv(ir->c, buf, 2))
                return -EIO;
 
        /* Does eliminate repeated parity code */
@@ -147,7 +147,7 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
 
        /* poll IR chip */
 
-       if (3 != i2c_master_recv(&ir->c, buf, 3)) {
+       if (3 != i2c_master_recv(ir->c, buf, 3)) {
                i2cdprintk("read error\n");
                return -EIO;
        }
index 58c0ef4a2dcedc782ea4ea493bc6d2adcf51ffd8..9c632541df10fcac6fa3e83b84ad8350abed07e8 100644 (file)
@@ -643,6 +643,7 @@ extern void em28xx_card_setup(struct em28xx *dev);
 extern struct em28xx_board em28xx_boards[];
 extern struct usb_device_id em28xx_id_table[];
 extern const unsigned int em28xx_bcount;
+void em28xx_register_i2c_ir(struct em28xx *dev);
 void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir);
 int em28xx_tuner_callback(void *ptr, int component, int command, int arg);
 void em28xx_release_resources(struct em28xx *dev);
index ba341e6fb2dae5153cf5fb96e79b74c2a8d035f8..cb833a63041cf0a004f08a138307e1c59a6d28fb 100644 (file)
@@ -74,7 +74,7 @@ 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 (size != i2c_master_recv(&ir->c,buf,size))
+       if (size != i2c_master_recv(ir->c, buf, size))
                return -EIO;
 
        /* split rc5 data block ... */
@@ -137,7 +137,7 @@ static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        unsigned char b;
 
        /* poll IR chip */
-       if (1 != i2c_master_recv(&ir->c,&b,1)) {
+       if (1 != i2c_master_recv(ir->c, &b, 1)) {
                dprintk(1,"read error\n");
                return -EIO;
        }
@@ -151,7 +151,7 @@ static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        unsigned char b;
 
        /* poll IR chip */
-       if (1 != i2c_master_recv(&ir->c,&b,1)) {
+       if (1 != i2c_master_recv(ir->c, &b, 1)) {
                dprintk(1,"read error\n");
                return -EIO;
        }
@@ -171,7 +171,7 @@ static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        unsigned char buf[4];
 
        /* poll IR chip */
-       if (4 != i2c_master_recv(&ir->c,buf,4)) {
+       if (4 != i2c_master_recv(ir->c, buf, 4)) {
                dprintk(1,"read error\n");
                return -EIO;
        }
@@ -195,7 +195,7 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        unsigned char b;
 
        /* poll IR chip */
-       if (1 != i2c_master_recv(&ir->c,&b,1)) {
+       if (1 != i2c_master_recv(ir->c, &b, 1)) {
                dprintk(1,"read error\n");
                return -EIO;
        }
@@ -222,12 +222,12 @@ 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,
+       struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0,
                                   .buf = &subaddr, .len = 1},
-                                { .addr = ir->c.addr, .flags = I2C_M_RD,
+                                { .addr = ir->c->addr, .flags = I2C_M_RD,
                                  .buf = &key, .len = 1} };
        subaddr = 0x0d;
-       if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
+       if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
                dprintk(1, "read error\n");
                return -EIO;
        }
@@ -237,7 +237,7 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
 
        subaddr = 0x0b;
        msg[1].buf = &keygroup;
-       if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
+       if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
                dprintk(1, "read error\n");
                return -EIO;
        }
@@ -286,7 +286,7 @@ static void ir_work(struct work_struct *work)
 
        /* MSI TV@nywhere Plus requires more frequent polling
           otherwise it will miss some keypresses */
-       if (ir->c.adapter->id == I2C_HW_SAA7134 && ir->c.addr == 0x30)
+       if (ir->c->adapter->id == I2C_HW_SAA7134 && ir->c->addr == 0x30)
                polling_interval = 50;
 
        ir_key_poll(ir);
@@ -295,34 +295,15 @@ static void ir_work(struct work_struct *work)
 
 /* ----------------------------------------------------------------------- */
 
-static int ir_attach(struct i2c_adapter *adap, int addr,
-                     unsigned short flags, int kind);
-static int ir_detach(struct i2c_client *client);
-static int ir_probe(struct i2c_adapter *adap);
-
-static struct i2c_driver driver = {
-       .driver = {
-               .name   = "ir-kbd-i2c",
-       },
-       .id             = I2C_DRIVERID_INFRARED,
-       .attach_adapter = ir_probe,
-       .detach_client  = ir_detach,
-};
-
-static struct i2c_client client_template =
-{
-       .name = "unset",
-       .driver = &driver
-};
-
-static int ir_attach(struct i2c_adapter *adap, int addr,
-                    unsigned short flags, int kind)
+static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
        IR_KEYTAB_TYPE *ir_codes = NULL;
        char *name;
        int ir_type;
        struct IR_i2c *ir;
        struct input_dev *input_dev;
+       struct i2c_adapter *adap = client->adapter;
+       unsigned short addr = client->addr;
        int err;
 
        ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL);
@@ -332,14 +313,9 @@ 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;
-
-       ir->c.adapter = adap;
-       ir->c.addr    = addr;
-       snprintf(ir->c.name, sizeof(ir->c.name), "ir-kbd");
-
-       i2c_set_clientdata(&ir->c, ir);
+       i2c_set_clientdata(client, ir);
 
        switch(addr) {
        case 0x64:
@@ -414,24 +390,9 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
        snprintf(ir->name, sizeof(ir->name), "i2c IR (%s)", name);
        ir->ir_codes = ir_codes;
 
-       /* register i2c device
-        * At device register, IR codes may be changed to be
-        * board dependent.
-        */
-       err = i2c_attach_client(&ir->c);
-       if (err)
-               goto err_out_free;
-
-       /* If IR not supported or disabled, unregisters driver */
-       if (ir->get_key == NULL) {
-               err = -ENODEV;
-               goto err_out_detach;
-       }
-
-       /* Phys addr can only be set after attaching (for ir->c.dev) */
        snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0",
-                dev_name(&ir->c.adapter->dev),
-                dev_name(&ir->c.dev));
+                dev_name(&adap->dev),
+                dev_name(&client->dev));
 
        /* init + register input device */
        ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes);
@@ -441,7 +402,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
 
        err = input_register_device(ir->input);
        if (err)
-               goto err_out_detach;
+               goto err_out_free;
 
        printk(DEVNAME ": %s detected at %s [%s]\n",
               ir->input->name, ir->input->phys, adap->name);
@@ -452,135 +413,42 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
 
        return 0;
 
- err_out_detach:
-       i2c_detach_client(&ir->c);
  err_out_free:
        input_free_device(input_dev);
        kfree(ir);
        return err;
 }
 
-static int ir_detach(struct i2c_client *client)
+static int ir_remove(struct i2c_client *client)
 {
        struct IR_i2c *ir = i2c_get_clientdata(client);
 
        /* kill outstanding polls */
        cancel_delayed_work_sync(&ir->work);
 
-       /* unregister devices */
+       /* unregister device */
        input_unregister_device(ir->input);
-       i2c_detach_client(&ir->c);
 
        /* free memory */
        kfree(ir);
        return 0;
 }
 
-static int ir_probe(struct i2c_adapter *adap)
-{
-
-       /* The external IR receiver is at i2c address 0x34 (0x35 for
-          reads).  Future Hauppauge cards will have an internal
-          receiver at 0x30 (0x31 for reads).  In theory, both can be
-          fitted, and Hauppauge suggest an external overrides an
-          internal.
-
-          That's why we probe 0x1a (~0x34) first. CB
-       */
-
-       static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1};
-       static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, 0x2d, -1 };
-       static const int probe_em28XX[] = { 0x30, 0x47, -1 };
-       static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 };
-       static const int probe_cx23885[] = { 0x6b, -1 };
-       const int *probe;
-       struct i2c_msg msg = {
-               .flags = I2C_M_RD,
-               .len = 0,
-               .buf = NULL,
-       };
-       int i, rc;
-
-       switch (adap->id) {
-       case I2C_HW_B_BT848:
-               probe = probe_bttv;
-               break;
-       case I2C_HW_B_CX2341X:
-               probe = probe_bttv;
-               break;
-       case I2C_HW_SAA7134:
-               probe = probe_saa7134;
-               break;
-       case I2C_HW_B_EM28XX:
-               probe = probe_em28XX;
-               break;
-       case I2C_HW_B_CX2388x:
-               probe = probe_cx88;
-               break;
-       case I2C_HW_B_CX23885:
-               probe = probe_cx23885;
-               break;
-       default:
-               return 0;
-       }
-
-       for (i = 0; -1 != probe[i]; i++) {
-               msg.addr = probe[i];
-               rc = i2c_transfer(adap, &msg, 1);
-               dprintk(1,"probe 0x%02x @ %s: %s\n",
-                       probe[i], adap->name,
-                       (1 == rc) ? "yes" : "no");
-               if (1 == rc) {
-                       ir_attach(adap, probe[i], 0, 0);
-                       return 0;
-               }
-       }
-
-       /* Special case for MSI TV@nywhere Plus remote */
-       if (adap->id == I2C_HW_SAA7134) {
-               u8 temp;
-
-               /* MSI TV@nywhere Plus controller doesn't seem to
-                  respond to probes unless we read something from
-                  an existing device. Weird... */
-
-               msg.addr = 0x50;
-               rc = i2c_transfer(adap, &msg, 1);
-                       dprintk(1, "probe 0x%02x @ %s: %s\n",
-                       msg.addr, adap->name,
-                       (1 == rc) ? "yes" : "no");
-
-               /* Now do the probe. The controller does not respond
-                  to 0-byte reads, so we use a 1-byte read instead. */
-               msg.addr = 0x30;
-               msg.len = 1;
-               msg.buf = &temp;
-               rc = i2c_transfer(adap, &msg, 1);
-               dprintk(1, "probe 0x%02x @ %s: %s\n",
-                       msg.addr, adap->name,
-                       (1 == rc) ? "yes" : "no");
-               if (1 == rc)
-                       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);
-       }
+static const struct i2c_device_id ir_kbd_id[] = {
+       /* Generic entry for any IR receiver */
+       { "ir_video", 0 },
+       /* IR device specific entries could be added here */
+       { }
+};
 
-       return 0;
-}
+static struct i2c_driver driver = {
+       .driver = {
+               .name   = "ir-kbd-i2c",
+       },
+       .probe          = ir_probe,
+       .remove         = ir_remove,
+       .id_table       = ir_kbd_id,
+};
 
 /* ----------------------------------------------------------------------- */
 
index 9e3d32b8004c0e571b2b92e3db4363bab2f7b1fd..0ecde9ca05c1cee0e3f019f490e388a5c591dde4 100644 (file)
@@ -579,9 +579,11 @@ static struct i2c_client ivtv_i2c_client_template = {
        .name = "ivtv internal",
 };
 
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter + instantiate IR receiver */
 int init_ivtv_i2c(struct ivtv *itv)
 {
+       int retval;
+
        IVTV_DEBUG_I2C("i2c init\n");
 
        /* Sanity checks for the I2C hardware arrays. They must be the
@@ -619,9 +621,32 @@ int init_ivtv_i2c(struct ivtv *itv)
        ivtv_setsda(itv, 1);
 
        if (itv->options.newi2c > 0)
-               return i2c_add_adapter(&itv->i2c_adap);
+               retval = i2c_add_adapter(&itv->i2c_adap);
        else
-               return i2c_bit_add_bus(&itv->i2c_adap);
+               retval = i2c_bit_add_bus(&itv->i2c_adap);
+
+       /* Instantiate the IR receiver device, if present */
+       if (retval == 0) {
+               struct i2c_board_info info;
+               /* The external IR receiver is at i2c address 0x34 (0x35 for
+                  reads).  Future Hauppauge cards will have an internal
+                  receiver at 0x30 (0x31 for reads).  In theory, both can be
+                  fitted, and Hauppauge suggest an external overrides an
+                  internal.
+
+                  That's why we probe 0x1a (~0x34) first. CB
+               */
+               const unsigned short addr_list[] = {
+                       0x1a, 0x18, 0x64, 0x30,
+                       I2C_CLIENT_END
+               };
+
+               memset(&info, 0, sizeof(struct i2c_board_info));
+               strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+               i2c_new_probed_device(&itv->i2c_adap, &info, addr_list);
+       }
+
+       return retval;
 }
 
 void exit_ivtv_i2c(struct ivtv *itv)
index f3e285aa2fb4ee66ea8a8e8365f0995816b9fd53..a96f75985cbab16341a73bf5d48bef74da58ad79 100644 (file)
@@ -433,6 +433,9 @@ int saa7134_i2c_register(struct saa7134_dev *dev)
        saa7134_i2c_eeprom(dev,dev->eedata,sizeof(dev->eedata));
        if (i2c_scan)
                do_i2c_scan(dev->name,&dev->i2c_client);
+
+       /* Instantiate the IR receiver device, if present */
+       saa7134_probe_i2c_ir(dev);
        return 0;
 }
 
index 6cd693d3b8ed5dd9dcab0afeee007f7b8b2a5697..4144ca9cc7e00f432151839ab47d97744e95be56 100644 (file)
@@ -134,10 +134,10 @@ static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
        int gpio;
 
        /* <dev> is needed to access GPIO. Used by the saa_readl macro. */
-       struct saa7134_dev *dev = ir->c.adapter->algo_data;
+       struct saa7134_dev *dev = ir->c->adapter->algo_data;
        if (dev == NULL) {
                dprintk("get_key_msi_tvanywhere_plus: "
-                       "gir->c.adapter->algo_data is NULL!\n");
+                       "gir->c->adapter->algo_data is NULL!\n");
                return -EIO;
        }
 
@@ -156,7 +156,7 @@ static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
 
        /* GPIO says there is a button press. Get it. */
 
-       if (1 != i2c_master_recv(&ir->c, &b, 1)) {
+       if (1 != i2c_master_recv(ir->c, &b, 1)) {
                i2cdprintk("read error\n");
                return -EIO;
        }
@@ -179,7 +179,7 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        unsigned char b;
 
        /* poll IR chip */
-       if (1 != i2c_master_recv(&ir->c,&b,1)) {
+       if (1 != i2c_master_recv(ir->c, &b, 1)) {
                i2cdprintk("read error\n");
                return -EIO;
        }
@@ -202,7 +202,7 @@ static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        unsigned char buf[5], cod4, code3, code4;
 
        /* poll IR chip */
-       if (5 != i2c_master_recv(&ir->c,buf,5))
+       if (5 != i2c_master_recv(ir->c, buf, 5))
                return -EIO;
 
        cod4    = buf[4];
@@ -224,7 +224,7 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        unsigned char data[12];
        u32 gpio;
 
-       struct saa7134_dev *dev = ir->c.adapter->algo_data;
+       struct saa7134_dev *dev = ir->c->adapter->algo_data;
 
        /* rising SAA7134_GPIO_GPRESCAN reads the status */
        saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
@@ -235,9 +235,9 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        if (0x400000 & ~gpio)
                return 0; /* No button press */
 
-       ir->c.addr = 0x5a >> 1;
+       ir->c->addr = 0x5a >> 1;
 
-       if (12 != i2c_master_recv(&ir->c, data, 12)) {
+       if (12 != i2c_master_recv(ir->c, data, 12)) {
                i2cdprintk("read error\n");
                return -EIO;
        }
@@ -267,7 +267,7 @@ static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
        unsigned int start = 0,parity = 0,code = 0;
 
        /* poll IR chip */
-       if (4 != i2c_master_recv(&ir->c, b, 4)) {
+       if (4 != i2c_master_recv(ir->c, b, 4)) {
                i2cdprintk("read error\n");
                return -EIO;
        }
@@ -682,14 +682,76 @@ void saa7134_input_fini(struct saa7134_dev *dev)
        dev->remote = NULL;
 }
 
-void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
+void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
 {
+       struct i2c_board_info info;
+       const unsigned short addr_list[] = {
+               0x7a, 0x47, 0x71, 0x2d,
+               I2C_CLIENT_END
+       };
+
+       const unsigned short addr_list_msi[] = {
+               0x30, I2C_CLIENT_END
+       };
+       struct i2c_msg msg_msi = {
+               .addr = 0x50,
+               .flags = I2C_M_RD,
+               .len = 0,
+               .buf = NULL,
+       };
+
+       unsigned char subaddr, data;
+       struct i2c_msg msg_avermedia[] = { {
+               .addr = 0x40,
+               .flags = 0,
+               .len = 1,
+               .buf = &subaddr,
+       }, {
+               .addr = 0x40,
+               .flags = I2C_M_RD,
+               .len = 1,
+               .buf = &data,
+       } };
+
+       struct i2c_client *client;
+       int rc;
+
        if (disable_ir) {
-               dprintk("Found supported i2c remote, but IR has been disabled\n");
-               ir->get_key=NULL;
+               dprintk("IR has been disabled, not probing for i2c remote\n");
                return;
        }
 
+       memset(&info, 0, sizeof(struct i2c_board_info));
+       strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+       client = i2c_new_probed_device(&dev->i2c_adap, &info, addr_list);
+       if (client)
+               return;
+
+       /* MSI TV@nywhere Plus controller doesn't seem to
+          respond to probes unless we read something from
+          an existing device. Weird... */
+       rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1);
+       dprintk(KERN_DEBUG "probe 0x%02x @ %s: %s\n",
+               msg_msi.addr, dev->i2c_adap.name,
+               (1 == rc) ? "yes" : "no");
+       client = i2c_new_probed_device(&dev->i2c_adap, &info, addr_list_msi);
+       if (client)
+               return;
+
+       /* Special case for AVerMedia Cardbus remote */
+       subaddr = 0x0d;
+       rc = i2c_transfer(&dev->i2c_adap, msg_avermedia, 2);
+       dprintk(KERN_DEBUG "probe 0x%02x/0x%02x @ %s: %s\n",
+               msg_avermedia[0].addr, subaddr, dev->i2c_adap.name,
+               (2 == rc) ? "yes" : "no");
+       if (2 == rc) {
+               info.addr = msg_avermedia[0].addr;
+               i2c_new_device(&dev->i2c_adap, &info);
+       }
+}
+
+void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
+{
        switch (dev->board) {
        case SAA7134_BOARD_PINNACLE_PCTV_110i:
        case SAA7134_BOARD_PINNACLE_PCTV_310i:
index 8229ab2132238497e39484aedfd0f8fb5e52ede9..116534ec33ebca7c31179ee55e3b2c0682c4bd0b 100644 (file)
@@ -799,6 +799,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status);
 int  saa7134_input_init1(struct saa7134_dev *dev);
 void saa7134_input_fini(struct saa7134_dev *dev);
 void saa7134_input_irq(struct saa7134_dev *dev);
+void saa7134_probe_i2c_ir(struct saa7134_dev *dev);
 void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir);
 void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir);
 void saa7134_ir_stop(struct saa7134_dev *dev);
index 6a9719c8e903fbc333539ad4d1b9bf57e168439c..94a77b15a30a1e88be166e99ece0e03d14ba6909 100644 (file)
@@ -7,7 +7,7 @@ struct IR_i2c;
 
 struct IR_i2c {
        IR_KEYTAB_TYPE         *ir_codes;
-       struct i2c_client      c;
+       struct i2c_client      *c;
        struct input_dev       *input;
        struct ir_input_state  ir;