diff mbox

[17/17] smiapp: Add register diversion quirk

Message ID 1397071509-2071-18-git-send-email-sakari.ailus@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Sakari Ailus April 9, 2014, 7:25 p.m. UTC
Add a quirk for diverting registers for on some sensors, even the standard
registers are not where they can be expected to be found. Add a quirk to
to help using such sensors.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/smiapp/smiapp-quirk.c |  8 ++++++++
 drivers/media/i2c/smiapp/smiapp-quirk.h |  4 ++++
 drivers/media/i2c/smiapp/smiapp-regs.c  | 14 +++++++++++---
 3 files changed, 23 insertions(+), 3 deletions(-)
diff mbox

Patch

diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.c b/drivers/media/i2c/smiapp/smiapp-quirk.c
index 580132d..9d86217 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.c
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.c
@@ -107,6 +107,14 @@  bool smiapp_quirk_reg(struct smiapp_sensor *sensor,
 	return false;
 }
 
+u32 smiapp_quirk_reg_divert(struct smiapp_sensor *sensor, u32 reg, u32 *val)
+{
+	if (sensor->minfo.quirk && sensor->minfo.quirk->reg_divert)
+		return sensor->minfo.quirk->reg_divert(sensor, reg, val);
+	else
+		return reg;
+}
+
 static int jt8ew9_limits(struct smiapp_sensor *sensor)
 {
 	if (sensor->minfo.revision_number_major < 0x03)
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.h b/drivers/media/i2c/smiapp/smiapp-quirk.h
index 15ef0af6..295931c 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.h
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.h
@@ -35,6 +35,8 @@  struct smiapp_sensor;
  * @post_poweron: Called always after the sensor has been fully powered on.
  * @pre_streamon: Called just before streaming is enabled.
  * @post_streamon: Called right after stopping streaming.
+ * @reg_divert: reg is diverted to point to the location of the actual
+ *		register. For sensors that loosely conform to SMIA.
  */
 struct smiapp_quirk {
 	int (*limits)(struct smiapp_sensor *sensor);
@@ -42,6 +44,7 @@  struct smiapp_quirk {
 	int (*pre_streamon)(struct smiapp_sensor *sensor);
 	int (*post_streamoff)(struct smiapp_sensor *sensor);
 	unsigned long (*pll_flags)(struct smiapp_sensor *sensor);
+	u32 (*reg_divert)(struct smiapp_sensor *sensor, u32 reg, u32 *val);
 	const struct smia_reg *regs;
 	unsigned long flags;
 };
@@ -57,6 +60,7 @@  void smiapp_replace_limit(struct smiapp_sensor *sensor,
 			  u32 limit, u64 val);
 bool smiapp_quirk_reg(struct smiapp_sensor *sensor,
 		      u32 reg, u32 *val);
+u32 smiapp_quirk_reg_divert(struct smiapp_sensor *sensor, u32 reg, u32 *val);
 
 #define SMIAPP_MK_QUIRK_REG(_reg, _val) \
 	{				\
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.c b/drivers/media/i2c/smiapp/smiapp-regs.c
index e88a59a..57ebd51 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.c
+++ b/drivers/media/i2c/smiapp/smiapp-regs.c
@@ -165,7 +165,7 @@  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);
+	u8 len = reg >> 16;
 	int rval;
 
 	if (len != SMIA_REG_8BIT && len != SMIA_REG_16BIT
@@ -175,6 +175,9 @@  static int __smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val,
 	if (smiapp_quirk_reg(sensor, reg, val))
 		goto found_quirk;
 
+	reg = smiapp_quirk_reg_divert(sensor, reg, val);
+	len = reg >> 16;
+
 	if (len == SMIA_REG_8BIT && !only8)
 		rval = ____smiapp_read(sensor, (u16)reg, len, val);
 	else
@@ -213,8 +216,8 @@  int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val)
 	unsigned char data[6];
 	unsigned int retries;
 	unsigned int flags = reg >> 24;
-	unsigned int len = (u8)(reg >> 16);
-	u16 offset = reg;
+	u8 len = reg >> 16;
+	u16 offset;
 	int r;
 
 	if ((len != SMIA_REG_8BIT && len != SMIA_REG_16BIT &&
@@ -228,6 +231,11 @@  int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val)
 		return 0;
 	}
 
+	reg = smiapp_quirk_reg_divert(sensor, reg, &val);
+	offset = reg;
+	flags = reg >> 24;
+	len = reg >> 16;
+
 	msg.addr = client->addr;
 	msg.flags = 0; /* Write */
 	msg.len = 2 + len;