[media] smiapp: Quirk for sensors that only do 8-bit reads
authorSakari Ailus <sakari.ailus@maxwell.research.nokia.com>
Sun, 22 Apr 2012 12:11:26 +0000 (09:11 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sun, 20 May 2012 15:45:39 +0000 (12:45 -0300)
Some sensors implement only 8-bit read functionality and fail on wider
reads. Add a quirk flag for such sensors.

Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/smiapp/smiapp-quirk.h
drivers/media/video/smiapp/smiapp-regs.c
drivers/media/video/smiapp/smiapp-regs.h

index 7a1b3a02a7bd0290e02e076787a994add683ef91..de82cdf43a89b1edf5c6649248b62f637c4a2bbe 100644 (file)
@@ -46,6 +46,7 @@ struct smiapp_quirk {
 
 /* op pix clock is for all lanes in total normally */
 #define SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE                        (1 << 0)
+#define SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY                       (1 << 1)
 
 struct smiapp_reg_8 {
        u16 reg;
index e5e5f4356dd2de6ba1b1c88b765d78fdb8384e56..9c430647b0476b4d8b53b1e3adb21baf5371b31a 100644 (file)
@@ -78,19 +78,15 @@ static uint32_t float_to_u32_mul_1000000(struct i2c_client *client,
  * Read a 8/16/32-bit i2c register.  The value is returned in 'val'.
  * Returns zero if successful, or non-zero otherwise.
  */
-int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val)
+static int ____smiapp_read(struct smiapp_sensor *sensor, u16 reg,
+                          u16 len, u32 *val)
 {
        struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
        struct i2c_msg msg;
        unsigned char data[4];
-       unsigned int len = (u8)(reg >> 16);
        u16 offset = reg;
        int r;
 
-       if (len != SMIA_REG_8BIT && len != SMIA_REG_16BIT
-           && len != SMIA_REG_32BIT)
-               return -EINVAL;
-
        msg.addr = client->addr;
        msg.flags = 0;
        msg.len = 2;
@@ -132,9 +128,6 @@ int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val)
                BUG();
        }
 
-       if (reg & SMIA_REG_FLAG_FLOAT)
-               *val = float_to_u32_mul_1000000(client, *val);
-
        return 0;
 
 err:
@@ -143,6 +136,68 @@ err:
        return r;
 }
 
+/* Read a register using 8-bit access only. */
+static int ____smiapp_read_8only(struct smiapp_sensor *sensor, u16 reg,
+                                u16 len, u32 *val)
+{
+       unsigned int i;
+       int rval;
+
+       *val = 0;
+
+       for (i = 0; i < len; i++) {
+               u32 val8;
+
+               rval = ____smiapp_read(sensor, reg + i, 1, &val8);
+               if (rval < 0)
+                       return rval;
+               *val |= val8 << ((len - i - 1) << 3);
+       }
+
+       return 0;
+}
+
+/*
+ * Read a 8/16/32-bit i2c register.  The value is returned in 'val'.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int __smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val,
+                        bool only8)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+       unsigned int len = (u8)(reg >> 16);
+       int rval;
+
+       if (len != SMIA_REG_8BIT && len != SMIA_REG_16BIT
+           && len != SMIA_REG_32BIT)
+               return -EINVAL;
+
+       if (len == SMIA_REG_8BIT && !only8)
+               rval = ____smiapp_read(sensor, (u16)reg, len, val);
+       else
+               rval = ____smiapp_read_8only(sensor, (u16)reg, len, val);
+       if (rval < 0)
+               return rval;
+
+       if (reg & SMIA_REG_FLAG_FLOAT)
+               *val = float_to_u32_mul_1000000(client, *val);
+
+       return 0;
+}
+
+int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val)
+{
+       return __smiapp_read(
+               sensor, reg, val,
+               smiapp_needs_quirk(sensor,
+                                  SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY));
+}
+
+int smiapp_read_8only(struct smiapp_sensor *sensor, u32 reg, u32 *val)
+{
+       return __smiapp_read(sensor, reg, val, true);
+}
+
 /*
  * Write to a 8/16-bit register.
  * Returns zero if successful, or non-zero otherwise.
index 1edfd206fb767a053a7ffd492b69ac767515c931..7f9013b47971586155ccce3fe8c26e88e7805cc7 100644 (file)
@@ -43,6 +43,7 @@ struct smia_reg {
 struct smiapp_sensor;
 
 int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val);
+int smiapp_read_8only(struct smiapp_sensor *sensor, u32 reg, u32 *val);
 int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val);
 
 #endif