aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/i2c/smiapp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/i2c/smiapp')
-rw-r--r--drivers/media/i2c/smiapp/smiapp-core.c57
-rw-r--r--drivers/media/i2c/smiapp/smiapp-quirk.c55
-rw-r--r--drivers/media/i2c/smiapp/smiapp-quirk.h24
-rw-r--r--drivers/media/i2c/smiapp/smiapp-reg-defs.h8
-rw-r--r--drivers/media/i2c/smiapp/smiapp-regs.c89
-rw-r--r--drivers/media/i2c/smiapp/smiapp-regs.h19
6 files changed, 127 insertions, 125 deletions
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 8741cae9c9f2..06fb03291d59 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -606,7 +606,7 @@ static int smiapp_get_limits(struct smiapp_sensor *sensor, int const *limit,
if (rval)
return rval;
sensor->limits[limit[i]] = val;
- dev_dbg(&client->dev, "0x%8.8x \"%s\" = %d, 0x%x\n",
+ dev_dbg(&client->dev, "0x%8.8x \"%s\" = %u, 0x%x\n",
smiapp_reg_limits[limit[i]].addr,
smiapp_reg_limits[limit[i]].what, val, val);
}
@@ -741,8 +741,8 @@ static int smiapp_get_mbus_formats(struct smiapp_sensor *sensor)
if (rval)
return rval;
- dev_dbg(&client->dev, "bpp %d, compressed %d\n",
- fmt >> 8, (u8)fmt);
+ dev_dbg(&client->dev, "%u: bpp %u, compressed %u\n",
+ i, fmt >> 8, (u8)fmt);
for (j = 0; j < ARRAY_SIZE(smiapp_csi_data_formats); j++) {
const struct smiapp_csi_data_format *f =
@@ -1128,7 +1128,7 @@ static int smiapp_power_on(struct smiapp_sensor *sensor)
}
usleep_range(1000, 1000);
- if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
+ if (gpio_is_valid(sensor->platform_data->xshutdown))
gpio_set_value(sensor->platform_data->xshutdown, 1);
sleep = SMIAPP_RESET_DELAY(sensor->platform_data->ext_clk);
@@ -1238,7 +1238,7 @@ static int smiapp_power_on(struct smiapp_sensor *sensor)
return 0;
out_cci_addr_fail:
- if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
+ if (gpio_is_valid(sensor->platform_data->xshutdown))
gpio_set_value(sensor->platform_data->xshutdown, 0);
if (sensor->platform_data->set_xclk)
sensor->platform_data->set_xclk(&sensor->src->sd, 0);
@@ -1264,7 +1264,7 @@ static void smiapp_power_off(struct smiapp_sensor *sensor)
SMIAPP_REG_U8_SOFTWARE_RESET,
SMIAPP_SOFTWARE_RESET);
- if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
+ if (gpio_is_valid(sensor->platform_data->xshutdown))
gpio_set_value(sensor->platform_data->xshutdown, 0);
if (sensor->platform_data->set_xclk)
sensor->platform_data->set_xclk(&sensor->src->sd, 0);
@@ -1766,7 +1766,7 @@ static void smiapp_set_compose_binner(struct v4l2_subdev *subdev,
struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
unsigned int i;
unsigned int binh = 1, binv = 1;
- unsigned int best = scaling_goodness(
+ int best = scaling_goodness(
subdev,
crops[SMIAPP_PAD_SINK]->width, sel->r.width,
crops[SMIAPP_PAD_SINK]->height, sel->r.height, sel->flags);
@@ -2355,17 +2355,17 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
unsigned int i;
int rval;
- sensor->vana = devm_regulator_get(&client->dev, "VANA");
+ sensor->vana = devm_regulator_get(&client->dev, "vana");
if (IS_ERR(sensor->vana)) {
dev_err(&client->dev, "could not get regulator for vana\n");
- return -ENODEV;
+ return PTR_ERR(sensor->vana);
}
if (!sensor->platform_data->set_xclk) {
sensor->ext_clk = devm_clk_get(&client->dev, "ext_clk");
if (IS_ERR(sensor->ext_clk)) {
dev_err(&client->dev, "could not get clock\n");
- return -ENODEV;
+ return PTR_ERR(sensor->ext_clk);
}
rval = clk_set_rate(sensor->ext_clk,
@@ -2374,18 +2374,19 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
dev_err(&client->dev,
"unable to set clock freq to %u\n",
sensor->platform_data->ext_clk);
- return -ENODEV;
+ return rval;
}
}
- if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) {
- if (devm_gpio_request_one(&client->dev,
- sensor->platform_data->xshutdown, 0,
- "SMIA++ xshutdown") != 0) {
+ if (gpio_is_valid(sensor->platform_data->xshutdown)) {
+ rval = devm_gpio_request_one(
+ &client->dev, sensor->platform_data->xshutdown, 0,
+ "SMIA++ xshutdown");
+ if (rval < 0) {
dev_err(&client->dev,
"unable to acquire reset gpio %d\n",
sensor->platform_data->xshutdown);
- return -ENODEV;
+ return rval;
}
}
@@ -2423,6 +2424,12 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
sensor->hvflip_inv_mask = SMIAPP_IMAGE_ORIENTATION_HFLIP |
SMIAPP_IMAGE_ORIENTATION_VFLIP;
+ rval = smiapp_call_quirk(sensor, limits);
+ if (rval) {
+ dev_err(&client->dev, "limits quirks failed\n");
+ goto out_power_off;
+ }
+
rval = smiapp_get_mbus_formats(sensor);
if (rval) {
rval = -ENODEV;
@@ -2483,12 +2490,6 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
}
}
- rval = smiapp_call_quirk(sensor, limits);
- if (rval) {
- dev_err(&client->dev, "limits quirks failed\n");
- goto out_nvm_release;
- }
-
/* We consider this as profile 0 sensor if any of these are zero. */
if (!sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV] ||
!sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV] ||
@@ -2543,8 +2544,9 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
}
snprintf(this->sd.name,
- sizeof(this->sd.name), "%s %s",
- sensor->minfo.name, _this->name);
+ sizeof(this->sd.name), "%s %d-%4.4x %s",
+ sensor->minfo.name, i2c_adapter_id(client->adapter),
+ client->addr, _this->name);
this->sink_fmt.width =
sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
@@ -2616,12 +2618,11 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2;
pll->csi2.lanes = sensor->platform_data->lanes;
pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
+ pll->flags = smiapp_call_quirk(sensor, pll_flags);
+
/* Profile 0 sensors have no separate OP clock branch. */
if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
- if (smiapp_needs_quirk(sensor,
- SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE))
- pll->flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE;
pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
rval = smiapp_update_mode(sensor);
@@ -2830,7 +2831,7 @@ static int smiapp_remove(struct i2c_client *client)
unsigned int i;
if (sensor->power_count) {
- if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
+ if (gpio_is_valid(sensor->platform_data->xshutdown))
gpio_set_value(sensor->platform_data->xshutdown, 0);
if (sensor->platform_data->set_xclk)
sensor->platform_data->set_xclk(&sensor->src->sd, 0);
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.c b/drivers/media/i2c/smiapp/smiapp-quirk.c
index bb8c506e0e3d..e0bee8752122 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.c
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.c
@@ -28,7 +28,7 @@
static int smiapp_write_8(struct smiapp_sensor *sensor, u16 reg, u8 val)
{
- return smiapp_write(sensor, (SMIA_REG_8BIT << 16) | reg, val);
+ return smiapp_write(sensor, SMIAPP_REG_MK_U8(reg), val);
}
static int smiapp_write_8s(struct smiapp_sensor *sensor,
@@ -61,52 +61,6 @@ void smiapp_replace_limit(struct smiapp_sensor *sensor,
sensor->limits[limit] = val;
}
-bool smiapp_quirk_reg(struct smiapp_sensor *sensor,
- u32 reg, u32 *val)
-{
- struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
- const struct smia_reg *sreg;
-
- if (!sensor->minfo.quirk)
- return false;
-
- sreg = sensor->minfo.quirk->regs;
-
- if (!sreg)
- return false;
-
- while (sreg->type) {
- u16 type = reg >> 16;
- u16 reg16 = reg;
-
- if (sreg->type != type || sreg->reg != reg16) {
- sreg++;
- continue;
- }
-
- switch ((u8)type) {
- case SMIA_REG_8BIT:
- dev_dbg(&client->dev, "quirk: 0x%8.8x: 0x%2.2x\n",
- reg, sreg->val);
- break;
- case SMIA_REG_16BIT:
- dev_dbg(&client->dev, "quirk: 0x%8.8x: 0x%4.4x\n",
- reg, sreg->val);
- break;
- case SMIA_REG_32BIT:
- dev_dbg(&client->dev, "quirk: 0x%8.8x: 0x%8.8x\n",
- reg, sreg->val);
- break;
- }
-
- *val = sreg->val;
-
- return true;
- }
-
- return false;
-}
-
static int jt8ew9_limits(struct smiapp_sensor *sensor)
{
if (sensor->minfo.revision_number_major < 0x03)
@@ -266,12 +220,17 @@ static int jt8ev1_post_streamoff(struct smiapp_sensor *sensor)
return smiapp_write_8(sensor, 0x3328, 0x80);
}
+static unsigned long jt8ev1_pll_flags(struct smiapp_sensor *sensor)
+{
+ return SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE;
+}
+
const struct smiapp_quirk smiapp_jt8ev1_quirk = {
.limits = jt8ev1_limits,
.post_poweron = jt8ev1_post_poweron,
.pre_streamon = jt8ev1_pre_streamon,
.post_streamoff = jt8ev1_post_streamoff,
- .flags = SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE,
+ .pll_flags = jt8ev1_pll_flags,
};
static int tcm8500md_limits(struct smiapp_sensor *sensor)
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.h b/drivers/media/i2c/smiapp/smiapp-quirk.h
index 504a6d80ced5..46e9ea8bfa08 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.h
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.h
@@ -35,19 +35,30 @@ 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_access: Register access quirk. The quirk may divert the access
+ * to another register, or no register at all.
+ *
+ * @write: Is this read (false) or write (true) access?
+ * @reg: Pointer to the register to access
+ * @value: Register value, set by the caller on write, or
+ * by the quirk on read
+ *
+ * @return: 0 on success, -ENOIOCTLCMD if no register
+ * access may be done by the caller (default read
+ * value is zero), else negative error code on error
*/
struct smiapp_quirk {
int (*limits)(struct smiapp_sensor *sensor);
int (*post_poweron)(struct smiapp_sensor *sensor);
int (*pre_streamon)(struct smiapp_sensor *sensor);
int (*post_streamoff)(struct smiapp_sensor *sensor);
- const struct smia_reg *regs;
+ unsigned long (*pll_flags)(struct smiapp_sensor *sensor);
+ int (*reg_access)(struct smiapp_sensor *sensor, bool write, u32 *reg,
+ u32 *val);
unsigned long flags;
};
-/* 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)
+#define SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY (1 << 0)
struct smiapp_reg_8 {
u16 reg;
@@ -56,12 +67,9 @@ struct smiapp_reg_8 {
void smiapp_replace_limit(struct smiapp_sensor *sensor,
u32 limit, u32 val);
-bool smiapp_quirk_reg(struct smiapp_sensor *sensor,
- u32 reg, u32 *val);
-#define SMIAPP_MK_QUIRK_REG(_reg, _val) \
+#define SMIAPP_MK_QUIRK_REG_8(_reg, _val) \
{ \
- .type = (_reg >> 16), \
.reg = (u16)_reg, \
.val = _val, \
}
diff --git a/drivers/media/i2c/smiapp/smiapp-reg-defs.h b/drivers/media/i2c/smiapp/smiapp-reg-defs.h
index 3aa0ca948d87..c488ef028074 100644
--- a/drivers/media/i2c/smiapp/smiapp-reg-defs.h
+++ b/drivers/media/i2c/smiapp/smiapp-reg-defs.h
@@ -21,11 +21,11 @@
* 02110-1301 USA
*
*/
-#define SMIAPP_REG_MK_U8(r) ((SMIA_REG_8BIT << 16) | (r))
-#define SMIAPP_REG_MK_U16(r) ((SMIA_REG_16BIT << 16) | (r))
-#define SMIAPP_REG_MK_U32(r) ((SMIA_REG_32BIT << 16) | (r))
+#define SMIAPP_REG_MK_U8(r) ((SMIAPP_REG_8BIT << 16) | (r))
+#define SMIAPP_REG_MK_U16(r) ((SMIAPP_REG_16BIT << 16) | (r))
+#define SMIAPP_REG_MK_U32(r) ((SMIAPP_REG_32BIT << 16) | (r))
-#define SMIAPP_REG_MK_F32(r) (SMIA_REG_FLAG_FLOAT | (SMIA_REG_32BIT << 16) | (r))
+#define SMIAPP_REG_MK_F32(r) (SMIAPP_REG_FLAG_FLOAT | (SMIAPP_REG_32BIT << 16) | (r))
#define SMIAPP_REG_U16_MODEL_ID SMIAPP_REG_MK_U16(0x0000)
#define SMIAPP_REG_U8_REVISION_NUMBER_MAJOR SMIAPP_REG_MK_U8(0x0002)
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.c b/drivers/media/i2c/smiapp/smiapp-regs.c
index 4fac32cfcb3f..a2098007fb70 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.c
+++ b/drivers/media/i2c/smiapp/smiapp-regs.c
@@ -114,14 +114,14 @@ static int ____smiapp_read(struct smiapp_sensor *sensor, u16 reg,
*val = 0;
/* high byte comes first */
switch (len) {
- case SMIA_REG_32BIT:
+ case SMIAPP_REG_32BIT:
*val = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) +
data[3];
break;
- case SMIA_REG_16BIT:
+ case SMIAPP_REG_16BIT:
*val = (data[0] << 8) + data[1];
break;
- case SMIA_REG_8BIT:
+ case SMIAPP_REG_8BIT:
*val = data[0];
break;
default:
@@ -165,31 +165,28 @@ 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 = SMIAPP_REG_WIDTH(reg);
int rval;
- if (len != SMIA_REG_8BIT && len != SMIA_REG_16BIT
- && len != SMIA_REG_32BIT)
+ if (len != SMIAPP_REG_8BIT && len != SMIAPP_REG_16BIT
+ && len != SMIAPP_REG_32BIT)
return -EINVAL;
- if (smiapp_quirk_reg(sensor, reg, val))
- goto found_quirk;
-
- if (len == SMIA_REG_8BIT && !only8)
- rval = ____smiapp_read(sensor, (u16)reg, len, val);
+ if (len == SMIAPP_REG_8BIT || !only8)
+ rval = ____smiapp_read(sensor, SMIAPP_REG_ADDR(reg), len, val);
else
- rval = ____smiapp_read_8only(sensor, (u16)reg, len, val);
+ rval = ____smiapp_read_8only(sensor, SMIAPP_REG_ADDR(reg), len,
+ val);
if (rval < 0)
return rval;
-found_quirk:
- if (reg & SMIA_REG_FLAG_FLOAT)
+ if (reg & SMIAPP_REG_FLAG_FLOAT)
*val = float_to_u32_mul_1000000(client, *val);
return 0;
}
-int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val)
+int smiapp_read_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 *val)
{
return __smiapp_read(
sensor, reg, val,
@@ -197,28 +194,47 @@ int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val)
SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY));
}
+int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val)
+{
+ int rval;
+
+ *val = 0;
+ rval = smiapp_call_quirk(sensor, reg_access, false, &reg, val);
+ if (rval == -ENOIOCTLCMD)
+ return 0;
+ if (rval < 0)
+ return rval;
+
+ return smiapp_read_no_quirk(sensor, reg, val);
+}
+
int smiapp_read_8only(struct smiapp_sensor *sensor, u32 reg, u32 *val)
{
+ int rval;
+
+ *val = 0;
+ rval = smiapp_call_quirk(sensor, reg_access, false, &reg, val);
+ if (rval == -ENOIOCTLCMD)
+ return 0;
+ if (rval < 0)
+ return rval;
+
return __smiapp_read(sensor, reg, val, true);
}
-/*
- * Write to a 8/16-bit register.
- * Returns zero if successful, or non-zero otherwise.
- */
-int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val)
+int smiapp_write_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 val)
{
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
struct i2c_msg msg;
unsigned char data[6];
unsigned int retries;
- unsigned int flags = reg >> 24;
- unsigned int len = (u8)(reg >> 16);
- u16 offset = reg;
+ u8 flags = SMIAPP_REG_FLAGS(reg);
+ u8 len = SMIAPP_REG_WIDTH(reg);
+ u16 offset = SMIAPP_REG_ADDR(reg);
int r;
- if ((len != SMIA_REG_8BIT && len != SMIA_REG_16BIT &&
- len != SMIA_REG_32BIT) || flags)
+ if ((len != SMIAPP_REG_8BIT && len != SMIAPP_REG_16BIT &&
+ len != SMIAPP_REG_32BIT) || flags)
return -EINVAL;
msg.addr = client->addr;
@@ -231,14 +247,14 @@ int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val)
data[1] = (u8) (reg & 0xff);
switch (len) {
- case SMIA_REG_8BIT:
+ case SMIAPP_REG_8BIT:
data[2] = val;
break;
- case SMIA_REG_16BIT:
+ case SMIAPP_REG_16BIT:
data[2] = val >> 8;
data[3] = val;
break;
- case SMIA_REG_32BIT:
+ case SMIAPP_REG_32BIT:
data[2] = val >> 24;
data[3] = val >> 16;
data[4] = val >> 8;
@@ -271,3 +287,20 @@ int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val)
return r;
}
+
+/*
+ * Write to a 8/16-bit register.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val)
+{
+ int rval;
+
+ rval = smiapp_call_quirk(sensor, reg_access, true, &reg, &val);
+ if (rval == -ENOIOCTLCMD)
+ return 0;
+ if (rval < 0)
+ return rval;
+
+ return smiapp_write_no_quirk(sensor, reg, val);
+}
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.h b/drivers/media/i2c/smiapp/smiapp-regs.h
index eefc6c84d5fe..35521125a2cc 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.h
+++ b/drivers/media/i2c/smiapp/smiapp-regs.h
@@ -28,22 +28,23 @@
#include <linux/i2c.h>
#include <linux/types.h>
+#define SMIAPP_REG_ADDR(reg) ((u16)reg)
+#define SMIAPP_REG_WIDTH(reg) ((u8)(reg >> 16))
+#define SMIAPP_REG_FLAGS(reg) ((u8)(reg >> 24))
+
/* Use upper 8 bits of the type field for flags */
-#define SMIA_REG_FLAG_FLOAT (1 << 24)
+#define SMIAPP_REG_FLAG_FLOAT (1 << 24)
-#define SMIA_REG_8BIT 1
-#define SMIA_REG_16BIT 2
-#define SMIA_REG_32BIT 4
-struct smia_reg {
- u16 type;
- u16 reg; /* 16-bit offset */
- u32 val; /* 8/16/32-bit value */
-};
+#define SMIAPP_REG_8BIT 1
+#define SMIAPP_REG_16BIT 2
+#define SMIAPP_REG_32BIT 4
struct smiapp_sensor;
+int smiapp_read_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 *val);
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_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 val);
int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val);
#endif