@@ -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)
@@ -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) \
{ \
@@ -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;
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(-)