diff options
author | Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> | 2012-04-22 12:11:26 (GMT) |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-20 15:45:39 (GMT) |
commit | ceb9e30e9f4a892997a61f1f5a30bc5b561c9e67 (patch) | |
tree | e11eaabf3ac03008cceab8f1abf2732349c9ba64 /drivers/media | |
parent | 1e73eea781bc302ba7f35da89d627bd355a7814a (diff) | |
download | linux-ceb9e30e9f4a892997a61f1f5a30bc5b561c9e67.tar.xz |
[media] smiapp: Quirk for sensors that only do 8-bit reads
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>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/smiapp/smiapp-quirk.h | 1 | ||||
-rw-r--r-- | drivers/media/video/smiapp/smiapp-regs.c | 73 | ||||
-rw-r--r-- | drivers/media/video/smiapp/smiapp-regs.h | 1 |
3 files changed, 66 insertions, 9 deletions
diff --git a/drivers/media/video/smiapp/smiapp-quirk.h b/drivers/media/video/smiapp/smiapp-quirk.h index 7a1b3a0..de82cdf 100644 --- a/drivers/media/video/smiapp/smiapp-quirk.h +++ b/drivers/media/video/smiapp/smiapp-quirk.h @@ -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; diff --git a/drivers/media/video/smiapp/smiapp-regs.c b/drivers/media/video/smiapp/smiapp-regs.c index e5e5f43..9c430647 100644 --- a/drivers/media/video/smiapp/smiapp-regs.c +++ b/drivers/media/video/smiapp/smiapp-regs.c @@ -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. diff --git a/drivers/media/video/smiapp/smiapp-regs.h b/drivers/media/video/smiapp/smiapp-regs.h index 1edfd20..7f9013b 100644 --- a/drivers/media/video/smiapp/smiapp-regs.h +++ b/drivers/media/video/smiapp/smiapp-regs.h @@ -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 |