V4L/DVB (11844): ir-kbd-i2c: Switch to the new-style device binding model
[safe/jmp/linux-2.6] / drivers / media / video / ivtv / ivtv-i2c.c
index 1735341..0ecde9c 100644 (file)
@@ -62,8 +62,7 @@
 #include "ivtv-driver.h"
 #include "ivtv-cards.h"
 #include "ivtv-gpio.h"
-
-#include <media/ir-kbd-i2c.h>
+#include "ivtv-i2c.h"
 
 /* i2c implementation for cx23415/6 chip, ivtv project.
  * Author: Kevin Thayer (nufan_wfk at yahoo.com)
 #define IVTV_REG_I2C_GETSCL_OFFSET 0x7008
 #define IVTV_REG_I2C_GETSDA_OFFSET 0x700c
 
-#ifndef I2C_ADAP_CLASS_TV_ANALOG
-#define I2C_ADAP_CLASS_TV_ANALOG I2C_CLASS_TV_ANALOG
-#endif /* I2C_ADAP_CLASS_TV_ANALOG */
-
 #define IVTV_CS53L32A_I2C_ADDR         0x11
+#define IVTV_M52790_I2C_ADDR           0x48
 #define IVTV_CX25840_I2C_ADDR          0x44
 #define IVTV_SAA7115_I2C_ADDR          0x21
 #define IVTV_SAA7127_I2C_ADDR          0x44
 #define IVTV_TEA5767_I2C_ADDR          0x60
 #define IVTV_UPD64031A_I2C_ADDR        0x12
 #define IVTV_UPD64083_I2C_ADDR                 0x5c
-#define IVTV_TDA985X_I2C_ADDR          0x5b
+#define IVTV_VP27SMPX_I2C_ADDR         0x5b
+#define IVTV_M52790_I2C_ADDR           0x48
 
 /* This array should match the IVTV_HW_ defines */
-static const u8 hw_driverids[] = {
-       I2C_DRIVERID_CX25840,
-       I2C_DRIVERID_SAA711X,
-       I2C_DRIVERID_SAA7127,
-       I2C_DRIVERID_MSP3400,
-       I2C_DRIVERID_TUNER,
-       I2C_DRIVERID_WM8775,
-       I2C_DRIVERID_CS53L32A,
-       I2C_DRIVERID_TVEEPROM,
-       I2C_DRIVERID_SAA711X,
-       I2C_DRIVERID_TVAUDIO,
-       I2C_DRIVERID_UPD64031A,
-       I2C_DRIVERID_UPD64083,
-       I2C_DRIVERID_SAA717X,
-       I2C_DRIVERID_WM8739,
+static const u8 hw_addrs[] = {
+       IVTV_CX25840_I2C_ADDR,
+       IVTV_SAA7115_I2C_ADDR,
+       IVTV_SAA7127_I2C_ADDR,
+       IVTV_MSP3400_I2C_ADDR,
+       0,
+       IVTV_WM8775_I2C_ADDR,
+       IVTV_CS53L32A_I2C_ADDR,
+       0,
+       IVTV_SAA7115_I2C_ADDR,
+       IVTV_UPD64031A_I2C_ADDR,
+       IVTV_UPD64083_I2C_ADDR,
+       IVTV_SAA717x_I2C_ADDR,
+       IVTV_WM8739_I2C_ADDR,
+       IVTV_VP27SMPX_I2C_ADDR,
+       IVTV_M52790_I2C_ADDR,
        0               /* IVTV_HW_GPIO dummy driver ID */
 };
 
 /* This array should match the IVTV_HW_ defines */
-static const char * const hw_drivernames[] = {
-       "cx2584x",
+static const char *hw_modules[] = {
+       "cx25840",
        "saa7115",
        "saa7127",
        "msp3400",
        "tuner",
        "wm8775",
        "cs53l32a",
+       NULL,
+       "saa7115",
+       "upd64031a",
+       "upd64083",
+       "saa717x",
+       "wm8739",
+       "vp27smpx",
+       "m52790",
+       NULL
+};
+
+/* This array should match the IVTV_HW_ defines */
+static const char * const hw_devicenames[] = {
+       "cx25840",
+       "saa7115",
+       "saa7127_auto", /* saa7127 or saa7129 */
+       "msp3400",
+       "tuner",
+       "wm8775",
+       "cs53l32a",
        "tveeprom",
        "saa7114",
-       "tvaudio",
        "upd64031a",
        "upd64083",
        "saa717x",
        "wm8739",
+       "vp27smpx",
+       "m52790",
        "gpio",
 };
 
-static int attach_inform(struct i2c_client *client)
-{
-       struct ivtv *itv = (struct ivtv *)i2c_get_adapdata(client->adapter);
-       int i;
-
-       IVTV_DEBUG_I2C("i2c client attach\n");
-       for (i = 0; i < I2C_CLIENTS_MAX; i++) {
-               if (itv->i2c_clients[i] == NULL) {
-                       itv->i2c_clients[i] = client;
-                       break;
-               }
+int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
+{
+       struct v4l2_subdev *sd;
+       struct i2c_adapter *adap = &itv->i2c_adap;
+       const char *mod = hw_modules[idx];
+       const char *type = hw_devicenames[idx];
+       u32 hw = 1 << idx;
+
+       if (idx >= ARRAY_SIZE(hw_addrs))
+               return -1;
+       if (hw == IVTV_HW_TUNER) {
+               /* special tuner handling */
+               sd = v4l2_i2c_new_probed_subdev(&itv->v4l2_dev,
+                               adap, mod, type,
+                               itv->card_i2c->radio);
+               if (sd)
+                       sd->grp_id = 1 << idx;
+               sd = v4l2_i2c_new_probed_subdev(&itv->v4l2_dev,
+                               adap, mod, type,
+                               itv->card_i2c->demod);
+               if (sd)
+                       sd->grp_id = 1 << idx;
+               sd = v4l2_i2c_new_probed_subdev(&itv->v4l2_dev,
+                               adap, mod, type,
+                               itv->card_i2c->tv);
+               if (sd)
+                       sd->grp_id = 1 << idx;
+               return sd ? 0 : -1;
        }
-       if (i == I2C_CLIENTS_MAX) {
-               IVTV_ERR("insufficient room for new I2C client!\n");
+       if (!hw_addrs[idx])
+               return -1;
+       if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) {
+               sd = v4l2_i2c_new_probed_subdev_addr(&itv->v4l2_dev,
+                               adap, mod, type, hw_addrs[idx]);
+       } else {
+               sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
+                               adap, mod, type, hw_addrs[idx]);
        }
-       return 0;
+       if (sd)
+               sd->grp_id = 1 << idx;
+       return sd ? 0 : -1;
 }
 
-static int detach_inform(struct i2c_client *client)
+struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw)
 {
-       int i;
-       struct ivtv *itv = (struct ivtv *)i2c_get_adapdata(client->adapter);
+       struct v4l2_subdev *result = NULL;
+       struct v4l2_subdev *sd;
 
-       IVTV_DEBUG_I2C("i2c client detach\n");
-       for (i = 0; i < I2C_CLIENTS_MAX; i++) {
-               if (itv->i2c_clients[i] == client) {
-                       itv->i2c_clients[i] = NULL;
+       spin_lock(&itv->v4l2_dev.lock);
+       v4l2_device_for_each_subdev(sd, &itv->v4l2_dev) {
+               if (sd->grp_id == hw) {
+                       result = sd;
                        break;
                }
        }
-       IVTV_DEBUG_I2C("i2c detach [client=%s,%s]\n",
-                  client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed");
-
-       return 0;
+       spin_unlock(&itv->v4l2_dev.lock);
+       return result;
 }
 
 /* Set the serial clock line to the desired state */
@@ -235,7 +277,7 @@ static int ivtv_ack(struct ivtv *itv)
        int ret = 0;
 
        if (ivtv_getscl(itv) == 1) {
-               IVTV_DEBUG_I2C("SCL was high starting an ack\n");
+               IVTV_DEBUG_HI_I2C("SCL was high starting an ack\n");
                ivtv_setscl(itv, 0);
                if (!ivtv_waitscl(itv, 0)) {
                        IVTV_DEBUG_I2C("Could not set SCL low starting an ack\n");
@@ -262,7 +304,7 @@ static int ivtv_sendbyte(struct ivtv *itv, unsigned char byte)
 {
        int i, bit;
 
-       IVTV_DEBUG_I2C("write %x\n",byte);
+       IVTV_DEBUG_HI_I2C("write %x\n",byte);
        for (i = 0; i < 8; ++i, byte<<=1) {
                ivtv_setscl(itv, 0);
                if (!ivtv_waitscl(itv, 0)) {
@@ -317,7 +359,7 @@ static int ivtv_readbyte(struct ivtv *itv, unsigned char *byte, int nack)
        ivtv_scldelay(itv);
        ivtv_setscl(itv, 0);
        ivtv_scldelay(itv);
-       IVTV_DEBUG_I2C("read %x\n",*byte);
+       IVTV_DEBUG_HI_I2C("read %x\n",*byte);
        return 0;
 }
 
@@ -329,7 +371,7 @@ static int ivtv_start(struct ivtv *itv)
 
        sda = ivtv_getsda(itv);
        if (sda != 1) {
-               IVTV_DEBUG_I2C("SDA was low at start\n");
+               IVTV_DEBUG_HI_I2C("SDA was low at start\n");
                ivtv_setsda(itv, 1);
                if (!ivtv_waitsda(itv, 1)) {
                        IVTV_DEBUG_I2C("SDA stuck low\n");
@@ -354,7 +396,7 @@ static int ivtv_stop(struct ivtv *itv)
        int i;
 
        if (ivtv_getscl(itv) != 0) {
-               IVTV_DEBUG_I2C("SCL not low when stopping\n");
+               IVTV_DEBUG_HI_I2C("SCL not low when stopping\n");
                ivtv_setscl(itv, 0);
                if (!ivtv_waitscl(itv, 0)) {
                        IVTV_DEBUG_I2C("SCL could not be set low\n");
@@ -433,7 +475,8 @@ static int ivtv_read(struct ivtv *itv, unsigned char addr, unsigned char *data,
    intervening stop condition */
 static int ivtv_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
 {
-       struct ivtv *itv = i2c_get_adapdata(i2c_adap);
+       struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap);
+       struct ivtv *itv = to_ivtv(v4l2_dev);
        int retval;
        int i;
 
@@ -469,12 +512,7 @@ static struct i2c_adapter ivtv_i2c_adap_hw_template = {
        .id = I2C_HW_B_CX2341X,
        .algo = &ivtv_algo,
        .algo_data = NULL,                      /* filled from template */
-       .client_register = attach_inform,
-       .client_unregister = detach_inform,
        .owner = THIS_MODULE,
-#ifdef I2C_ADAP_CLASS_TV_ANALOG
-       .class = I2C_ADAP_CLASS_TV_ANALOG,
-#endif
 };
 
 static void ivtv_setscl_old(void *data, int state)
@@ -522,195 +560,41 @@ static int ivtv_getsda_old(void *data)
 /* template for i2c-bit-algo */
 static struct i2c_adapter ivtv_i2c_adap_template = {
        .name = "ivtv i2c driver",
-       .id = I2C_HW_B_CX2341X,         /* algo-bit is OR'd with this */
+       .id = I2C_HW_B_CX2341X,
        .algo = NULL,                   /* set by i2c-algo-bit */
        .algo_data = NULL,              /* filled from template */
-       .client_register = attach_inform,
-       .client_unregister = detach_inform,
        .owner = THIS_MODULE,
-#ifdef I2C_ADAP_CLASS_TV_ANALOG
-       .class = I2C_ADAP_CLASS_TV_ANALOG,
-#endif
 };
 
-static struct i2c_algo_bit_data ivtv_i2c_algo_template = {
-       NULL,                   /* ?? */
-       ivtv_setsda_old,        /* setsda function */
-       ivtv_setscl_old,        /* " */
-       ivtv_getsda_old,        /* " */
-       ivtv_getscl_old,        /* " */
-       10,                     /* udelay */
-       200                     /* timeout */
+static const struct i2c_algo_bit_data ivtv_i2c_algo_template = {
+       .setsda         = ivtv_setsda_old,
+       .setscl         = ivtv_setscl_old,
+       .getsda         = ivtv_getsda_old,
+       .getscl         = ivtv_getscl_old,
+       .udelay         = 10,
+       .timeout        = 200,
 };
 
 static struct i2c_client ivtv_i2c_client_template = {
-       .name = "ivtv internal use only",
+       .name = "ivtv internal",
 };
 
-int ivtv_call_i2c_client(struct ivtv *itv, int addr, unsigned int cmd, void *arg)
+/* init + register i2c adapter + instantiate IR receiver */
+int init_ivtv_i2c(struct ivtv *itv)
 {
-       struct i2c_client *client;
        int retval;
-       int i;
-
-       IVTV_DEBUG_I2C("call_i2c_client addr=%02x\n", addr);
-       for (i = 0; i < I2C_CLIENTS_MAX; i++) {
-               client = itv->i2c_clients[i];
-               if (client == NULL) {
-                       continue;
-               }
-               if (client->driver->command == NULL) {
-                       continue;
-               }
-               if (addr == client->addr) {
-                       retval = client->driver->command(client, cmd, arg);
-                       return retval;
-               }
-       }
-       IVTV_ERR("i2c addr 0x%02x not found for command 0x%x!\n", addr, cmd);
-       return -ENODEV;
-}
-
-/* Find the i2c device based on the driver ID and return
-   its i2c address or -ENODEV if no matching device was found. */
-int ivtv_i2c_id_addr(struct ivtv *itv, u32 id)
-{
-       struct i2c_client *client;
-       int retval = -ENODEV;
-       int i;
-
-       for (i = 0; i < I2C_CLIENTS_MAX; i++) {
-               client = itv->i2c_clients[i];
-               if (client == NULL)
-                       continue;
-               if (id == client->driver->id) {
-                       retval = client->addr;
-                       break;
-               }
-       }
-       return retval;
-}
-
-/* Find the i2c device name matching the DRIVERID */
-static const char *ivtv_i2c_id_name(u32 id)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
-               if (hw_driverids[i] == id)
-                       return hw_drivernames[i];
-       return "unknown device";
-}
-
-/* Find the i2c device name matching the IVTV_HW_ flag */
-static const char *ivtv_i2c_hw_name(u32 hw)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
-               if (1 << i == hw)
-                       return hw_drivernames[i];
-       return "unknown device";
-}
-
-/* Find the i2c device matching the IVTV_HW_ flag and return
-   its i2c address or -ENODEV if no matching device was found. */
-int ivtv_i2c_hw_addr(struct ivtv *itv, u32 hw)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
-               if (1 << i == hw)
-                       return ivtv_i2c_id_addr(itv, hw_driverids[i]);
-       return -ENODEV;
-}
-
-/* Calls i2c device based on IVTV_HW_ flag. If hw == 0, then do nothing.
-   If hw == IVTV_HW_GPIO then call the gpio handler. */
-int ivtv_i2c_hw(struct ivtv *itv, u32 hw, unsigned int cmd, void *arg)
-{
-       int addr;
-
-       if (hw == IVTV_HW_GPIO)
-               return ivtv_gpio(itv, cmd, arg);
-       if (hw == 0)
-               return 0;
-
-       addr = ivtv_i2c_hw_addr(itv, hw);
-       if (addr < 0) {
-               IVTV_ERR("i2c hardware 0x%08x (%s) not found for command 0x%x!\n",
-                              hw, ivtv_i2c_hw_name(hw), cmd);
-               return addr;
-       }
-       return ivtv_call_i2c_client(itv, addr, cmd, arg);
-}
-
-/* Calls i2c device based on I2C driver ID. */
-int ivtv_i2c_id(struct ivtv *itv, u32 id, unsigned int cmd, void *arg)
-{
-       int addr;
-
-       addr = ivtv_i2c_id_addr(itv, id);
-       if (addr < 0) {
-               IVTV_ERR("i2c ID 0x%08x (%s) not found for command 0x%x!\n",
-                               id, ivtv_i2c_id_name(id), cmd);
-               return addr;
-       }
-       return ivtv_call_i2c_client(itv, addr, cmd, arg);
-}
-
-int ivtv_cx25840(struct ivtv *itv, unsigned int cmd, void *arg)
-{
-       return ivtv_call_i2c_client(itv, IVTV_CX25840_I2C_ADDR, cmd, arg);
-}
-
-int ivtv_saa7115(struct ivtv *itv, unsigned int cmd, void *arg)
-{
-       return ivtv_call_i2c_client(itv, IVTV_SAA7115_I2C_ADDR, cmd, arg);
-}
 
-int ivtv_saa7127(struct ivtv *itv, unsigned int cmd, void *arg)
-{
-       return ivtv_call_i2c_client(itv, IVTV_SAA7127_I2C_ADDR, cmd, arg);
-}
-
-int ivtv_saa717x(struct ivtv *itv, unsigned int cmd, void *arg)
-{
-       return ivtv_call_i2c_client(itv, IVTV_SAA717x_I2C_ADDR, cmd, arg);
-}
-
-int ivtv_msp34xx(struct ivtv *itv, unsigned int cmd, void *arg)
-{
-       return ivtv_call_i2c_client(itv, IVTV_MSP3400_I2C_ADDR, cmd, arg);
-}
-
-int ivtv_upd64031a(struct ivtv *itv, unsigned int cmd, void *arg)
-{
-       return ivtv_call_i2c_client(itv, IVTV_UPD64031A_I2C_ADDR, cmd, arg);
-}
-
-int ivtv_upd64083(struct ivtv *itv, unsigned int cmd, void *arg)
-{
-       return ivtv_call_i2c_client(itv, IVTV_UPD64083_I2C_ADDR, cmd, arg);
-}
-
-/* broadcast cmd for all I2C clients and for the gpio subsystem */
-void ivtv_call_i2c_clients(struct ivtv *itv, unsigned int cmd, void *arg)
-{
-       if (itv->i2c_adap.algo == NULL) {
-               IVTV_ERR("adapter is not set");
-               return;
-       }
-       i2c_clients_command(&itv->i2c_adap, cmd, arg);
-       if (itv->hw_flags & IVTV_HW_GPIO)
-               ivtv_gpio(itv, cmd, arg);
-}
-
-/* init + register i2c algo-bit adapter */
-int __devinit init_ivtv_i2c(struct ivtv *itv)
-{
        IVTV_DEBUG_I2C("i2c init\n");
 
+       /* Sanity checks for the I2C hardware arrays. They must be the
+        * same size and GPIO must be the last entry.
+        */
+       if (ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs) ||
+           ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_modules) ||
+           IVTV_HW_GPIO != (1 << (ARRAY_SIZE(hw_addrs) - 1))) {
+               IVTV_ERR("Mismatched I2C hardware arrays\n");
+               return -ENODEV;
+       }
        if (itv->options.newi2c > 0) {
                memcpy(&itv->i2c_adap, &ivtv_i2c_adap_hw_template,
                       sizeof(struct i2c_adapter));
@@ -719,30 +603,53 @@ int __devinit init_ivtv_i2c(struct ivtv *itv)
                       sizeof(struct i2c_adapter));
                memcpy(&itv->i2c_algo, &ivtv_i2c_algo_template,
                       sizeof(struct i2c_algo_bit_data));
-               itv->i2c_algo.data = itv;
-               itv->i2c_adap.algo_data = &itv->i2c_algo;
        }
+       itv->i2c_algo.data = itv;
+       itv->i2c_adap.algo_data = &itv->i2c_algo;
 
        sprintf(itv->i2c_adap.name + strlen(itv->i2c_adap.name), " #%d",
-               itv->num);
-       i2c_set_adapdata(&itv->i2c_adap, itv);
+               itv->instance);
+       i2c_set_adapdata(&itv->i2c_adap, &itv->v4l2_dev);
 
        memcpy(&itv->i2c_client, &ivtv_i2c_client_template,
               sizeof(struct i2c_client));
        itv->i2c_client.adapter = &itv->i2c_adap;
-       itv->i2c_adap.dev.parent = &itv->dev->dev;
+       itv->i2c_adap.dev.parent = &itv->pdev->dev;
 
        IVTV_DEBUG_I2C("setting scl and sda to 1\n");
        ivtv_setscl(itv, 1);
        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 __devexit exit_ivtv_i2c(struct ivtv *itv)
+void exit_ivtv_i2c(struct ivtv *itv)
 {
        IVTV_DEBUG_I2C("i2c exit\n");