Tested with device "Terratec Cinergy 200 USB".

Signed-off-by: Frank Schäfer <fschaefer....@googlemail.com>
---
 drivers/media/usb/em28xx/em28xx-cards.c |    9 +-
 drivers/media/usb/em28xx/em28xx-i2c.c   |    1 +
 drivers/media/usb/em28xx/em28xx-input.c |  142 +++++++++++++++++--------------
 3 Dateien geändert, 83 Zeilen hinzugefügt(+), 69 Zeilen entfernt(-)

diff --git a/drivers/media/usb/em28xx/em28xx-cards.c 
b/drivers/media/usb/em28xx/em28xx-cards.c
index 40c3e45..3b226b1 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -488,6 +488,7 @@ struct em28xx_board em28xx_boards[] = {
                .name         = "Terratec Cinergy 250 USB",
                .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
                .has_ir_i2c   = 1,
+               .ir_codes     = RC_MAP_EM_TERRATEC,
                .tda9887_conf = TDA9887_PRESENT,
                .decoder      = EM28XX_SAA711X,
                .input        = { {
@@ -508,6 +509,7 @@ struct em28xx_board em28xx_boards[] = {
                .name         = "Pinnacle PCTV USB 2",
                .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
                .has_ir_i2c   = 1,
+               .ir_codes     = RC_MAP_PINNACLE_GREY,
                .tda9887_conf = TDA9887_PRESENT,
                .decoder      = EM28XX_SAA711X,
                .input        = { {
@@ -533,6 +535,7 @@ struct em28xx_board em28xx_boards[] = {
                .decoder      = EM28XX_TVP5150,
                .has_msp34xx  = 1,
                .has_ir_i2c   = 1,
+               .ir_codes     = RC_MAP_HAUPPAUGE,
                .input        = { {
                        .type     = EM28XX_VMUX_TELEVISION,
                        .vmux     = TVP5150_COMPOSITE0,
@@ -629,6 +632,7 @@ struct em28xx_board em28xx_boards[] = {
                .valid        = EM28XX_BOARD_NOT_VALIDATED,
                .tuner_type   = TUNER_PHILIPS_FM1216ME_MK3,
                .has_ir_i2c   = 1,
+               .ir_codes     = RC_MAP_WINFAST_USBII_DELUXE,
                .tvaudio_addr = 0x58,
                .tda9887_conf = TDA9887_PRESENT |
                                TDA9887_PORT2_ACTIVE |
@@ -1222,6 +1226,7 @@ struct em28xx_board em28xx_boards[] = {
                .name         = "Terratec Cinergy 200 USB",
                .is_em2800    = 1,
                .has_ir_i2c   = 1,
+               .ir_codes     = RC_MAP_EM_TERRATEC,
                .tuner_type   = TUNER_LG_TALN,
                .tda9887_conf = TDA9887_PRESENT,
                .decoder      = EM28XX_SAA711X,
@@ -2912,7 +2917,7 @@ static void request_module_async(struct work_struct *work)
 
        if (dev->board.has_dvb)
                request_module("em28xx-dvb");
-       if (dev->board.ir_codes && !disable_ir)
+       if ((dev->board.ir_codes || dev->board.has_ir_i2c) && !disable_ir)
                request_module("em28xx-rc");
 #endif /* CONFIG_MODULES */
 }
@@ -2935,8 +2940,6 @@ static void flush_request_modules(struct em28xx *dev)
 */
 void em28xx_release_resources(struct em28xx *dev)
 {
-       /*FIXME: I2C IR should be disconnected */
-
        em28xx_release_analog_resources(dev);
 
        em28xx_i2c_unregister(dev);
diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c 
b/drivers/media/usb/em28xx/em28xx-i2c.c
index 44533e4..39c5a3e 100644
--- a/drivers/media/usb/em28xx/em28xx-i2c.c
+++ b/drivers/media/usb/em28xx/em28xx-i2c.c
@@ -470,6 +470,7 @@ static struct i2c_client em28xx_client_template = {
 static char *i2c_devs[128] = {
        [0x4a >> 1] = "saa7113h",
        [0x52 >> 1] = "drxk",
+       [0x3e >> 1] = "remote IR sensor",
        [0x60 >> 1] = "remote IR sensor",
        [0x8e >> 1] = "remote IR sensor",
        [0x86 >> 1] = "tda9887",
diff --git a/drivers/media/usb/em28xx/em28xx-input.c 
b/drivers/media/usb/em28xx/em28xx-input.c
index 3598221..631e252 100644
--- a/drivers/media/usb/em28xx/em28xx-input.c
+++ b/drivers/media/usb/em28xx/em28xx-input.c
@@ -5,6 +5,7 @@
                      Markus Rechberger <mrechber...@gmail.com>
                      Mauro Carvalho Chehab <mche...@infradead.org>
                      Sascha Sommer <saschasom...@freenet.de>
+   Copyright (C) 2012 Frank Schäfer <fschaefer....@googlemail.com>
 
   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
@@ -34,6 +35,8 @@
 #define EM28XX_SBUTTON_QUERY_INTERVAL 500
 #define EM28XX_R0C_USBSUSP_SNAPSHOT 0x20
 
+#define EM28XX_RC_QUERY_INTERVAL 100
+
 static unsigned int ir_debug;
 module_param(ir_debug, int, 0644);
 MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
@@ -67,13 +70,14 @@ struct em28xx_IR {
        char name[32];
        char phys[32];
 
-       /* poll external decoder */
        int polling;
        struct delayed_work work;
        unsigned int full_code:1;
        unsigned int last_readcount;
        u64 rc_type;
 
+       struct i2c_client *i2c_dev; /* external i2c IR receiver/decoder */
+
        int  (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *);
 };
 
@@ -452,7 +456,7 @@ static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, 
u64 *rc_type)
        }
 }
 
-static void em28xx_register_i2c_ir(struct em28xx *dev)
+static int em28xx_register_i2c_ir(struct em28xx *dev, struct rc_dev *rc_dev)
 {
        /* Leadtek winfast tv USBII deluxe can find a non working IR-device */
        /* at address 0x18, so if that address is needed for another board in */
@@ -470,30 +474,46 @@ static void em28xx_register_i2c_ir(struct em28xx *dev)
        switch (dev->model) {
        case EM2800_BOARD_TERRATEC_CINERGY_200:
        case EM2820_BOARD_TERRATEC_CINERGY_250:
-               dev->init_data.ir_codes = RC_MAP_EM_TERRATEC;
-               dev->init_data.get_key = em28xx_get_key_terratec;
                dev->init_data.name = "i2c IR (EM28XX Terratec)";
+               dev->init_data.type = RC_BIT_OTHER;
+               dev->init_data.get_key = em28xx_get_key_terratec;
                break;
        case EM2820_BOARD_PINNACLE_USB_2:
-               dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY;
-               dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey;
                dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)";
+               dev->init_data.type = RC_BIT_OTHER;
+               dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey;
                break;
        case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
-               dev->init_data.ir_codes = RC_MAP_HAUPPAUGE;
-               dev->init_data.get_key = em28xx_get_key_em_haup;
                dev->init_data.name = "i2c IR (EM2840 Hauppauge)";
+               dev->init_data.type = RC_BIT_RC5;
+               dev->init_data.get_key = em28xx_get_key_em_haup;
                break;
        case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE:
-               dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE;
-               dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe;
                dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)";
+               dev->init_data.type = RC_BIT_OTHER;
+               dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe;
                break;
        }
 
-       if (dev->init_data.name)
+       if (dev->init_data.name && dev->board.ir_codes) {
+               dev->init_data.ir_codes = dev->board.ir_codes;
+               dev->init_data.polling_interval = EM28XX_RC_QUERY_INTERVAL;
+               dev->init_data.rc_dev = rc_dev;
                info.platform_data = &dev->init_data;
-       i2c_new_probed_device(&dev->i2c_adap, &info, addr_list, NULL);
+       } else {
+               em28xx_warn("Unknown i2c remote control device.\n");
+               em28xx_warn("If the remote control doesn't work properly, 
please contact <linux-media@vger.kernel.org>\n");
+       }
+
+       dev->ir->i2c_dev = i2c_new_probed_device(&dev->i2c_adap, &info, 
addr_list, NULL);
+       if (NULL == dev->ir->i2c_dev)
+               return -ENODEV;
+
+#if defined(CONFIG_MODULES) && defined(MODULE)
+       request_module("ir-kbd-i2c");
+#endif
+
+       return 0;
 }
 
 /**********************************************************
@@ -590,7 +610,7 @@ static int em28xx_ir_init(struct em28xx *dev)
        int err = -ENOMEM;
        u64 rc_type;
 
-       if (dev->board.ir_codes == NULL) {
+       if (dev->board.ir_codes == NULL && !dev->board.has_ir_i2c) {
                /* No remote control support */
                em28xx_warn("Remote control support is not available for "
                                "this card.\n");
@@ -607,68 +627,56 @@ static int em28xx_ir_init(struct em28xx *dev)
        dev->ir = ir;
        ir->rc = rc;
 
-       /*
-        * em2874 supports more protocols. For now, let's just announce
-        * the two protocols that were already tested
-        */
-       rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
-       rc->priv = ir;
-       rc->change_protocol = em28xx_ir_change_protocol;
-       rc->open = em28xx_ir_start;
-       rc->close = em28xx_ir_stop;
-
-       switch (dev->chip_id) {
-       case CHIP_ID_EM2860:
-       case CHIP_ID_EM2883:
-               rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
-               break;
-       case CHIP_ID_EM2884:
-       case CHIP_ID_EM2874:
-       case CHIP_ID_EM28174:
-               rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC | RC_BIT_RC6_0;
-               break;
-       default:
-               err = -ENODEV;
-               goto error;
-       }
-
-       /* By default, keep protocol field untouched */
-       rc_type = RC_BIT_UNKNOWN;
-       err = em28xx_ir_change_protocol(rc, &rc_type);
-       if (err)
-               goto error;
-
-       /* This is how often we ask the chip for IR information */
-       ir->polling = 100; /* ms */
-
-       /* init input device */
-       snprintf(ir->name, sizeof(ir->name), "em28xx IR (%s)",
-                                               dev->name);
-
+       snprintf(ir->name, sizeof(ir->name), "em28xx IR (%s)", dev->name);
        usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
        strlcat(ir->phys, "/input0", sizeof(ir->phys));
+       ir->polling = EM28XX_RC_QUERY_INTERVAL;
 
-       rc->input_name = ir->name;
-       rc->input_phys = ir->phys;
-       rc->input_id.bustype = BUS_USB;
        rc->input_id.version = 1;
        rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
        rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
        rc->dev.parent = &dev->udev->dev;
-       rc->map_name = dev->board.ir_codes;
        rc->driver_name = MODULE_NAME;
 
-       /* all done */
-       err = rc_register_device(rc);
-       if (err)
-               goto error;
-
-       em28xx_register_i2c_ir(dev);
+       if (dev->board.has_ir_i2c) {
+               err = em28xx_register_i2c_ir(dev, rc);
+               if (err < 0)
+                       goto error;
+       } else {
+               switch (dev->chip_id) {
+               case CHIP_ID_EM2860:
+               case CHIP_ID_EM2883:
+                       rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
+                       break;
+               case CHIP_ID_EM2884:
+               case CHIP_ID_EM2874:
+               case CHIP_ID_EM28174:
+                       rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC | 
RC_BIT_RC6_0;
+                       break;
+               default:
+                       err = -ENODEV;
+                       goto error;
+               }
+               rc->priv = ir;
+               rc->change_protocol = em28xx_ir_change_protocol;
+               rc->open = em28xx_ir_start;
+               rc->close = em28xx_ir_stop;
+               rc->input_name = ir->name;
+               rc->input_phys = ir->phys;
+               rc->input_id.bustype = BUS_USB;
+               rc->map_name = dev->board.ir_codes;
+
+               /* By default, keep protocol field untouched */
+               rc_type = RC_BIT_UNKNOWN;
+               err = em28xx_ir_change_protocol(rc, &rc_type);
+               if (err)
+                       goto error;
+
+               err = rc_register_device(rc);
+               if (err < 0)
+                       goto error;
+       }
 
-#if defined(CONFIG_MODULES) && defined(MODULE)
-       if (dev->board.has_ir_i2c)
-               request_module("ir-kbd-i2c");
-#endif
        if (dev->board.has_snapshot_button)
                em28xx_register_snapshot_button(dev);
 
@@ -691,7 +699,9 @@ static int em28xx_ir_fini(struct em28xx *dev)
        if (!ir)
                return 0;
 
-       if (ir->rc)
+       if (ir->i2c_dev)
+               i2c_unregister_device(ir->i2c_dev);
+       else if (ir->rc)
                rc_unregister_device(ir->rc);
 
        /* done */
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to