Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ceb9e30e authored by Sakari Ailus's avatar Sakari Ailus Committed by Mauro Carvalho Chehab
Browse files

[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: default avatarSakari Ailus <sakari.ailus@maxwell.research.nokia.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 1e73eea7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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;
+64 −9
Original line number Diff line number Diff line
@@ -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 @@ int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val)
	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.
+1 −0
Original line number Diff line number Diff line
@@ -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