diff options
author | Sakari Ailus <sakari.ailus@linux.intel.com> | 2020-06-24 15:39:05 +0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 2020-12-03 12:27:31 +0100 |
commit | fe652254e243a58daf50aa0ddb938885ae2ba565 (patch) | |
tree | d86582b4f11dcbcd5ae15cea3a2d890fb1f32dd8 /drivers/media/i2c/ccs/ccs-reg-access.c | |
parent | 5017f8b4e0ed9ec39c04ac85de6ce49603f5f02b (diff) |
media: ccs: Read ireal numbers correctly
Some limit values are available in q16.q16 format, referred to as 32-bit
unsigned ireal in CCS. Read these correctly.
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Diffstat (limited to 'drivers/media/i2c/ccs/ccs-reg-access.c')
-rw-r--r-- | drivers/media/i2c/ccs/ccs-reg-access.c | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/media/i2c/ccs/ccs-reg-access.c b/drivers/media/i2c/ccs/ccs-reg-access.c index fe6112cba6be..91ccbca11577 100644 --- a/drivers/media/i2c/ccs/ccs-reg-access.c +++ b/drivers/media/i2c/ccs/ccs-reg-access.c @@ -15,6 +15,7 @@ #include <linux/i2c.h> #include "ccs.h" +#include "ccs-limits.h" static uint32_t float_to_u32_mul_1000000(struct i2c_client *client, uint32_t phloat) @@ -143,12 +144,30 @@ unsigned int ccs_reg_width(u32 reg) return sizeof(uint8_t); } +static u32 ireal32_to_u32_mul_1000000(struct i2c_client *client, u32 val) +{ + if (val >> 10 > U32_MAX / 15625) { + dev_warn(&client->dev, "value %u overflows!\n", val); + return U32_MAX; + } + + return ((val >> 10) * 15625) + + (val & GENMASK(9, 0)) * 15625 / 1024; +} + u32 ccs_reg_conv(struct ccs_sensor *sensor, u32 reg, u32 val) { struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - if (reg & CCS_FL_FLOAT_IREAL) - val = float_to_u32_mul_1000000(client, val); + if (reg & CCS_FL_FLOAT_IREAL) { + if (CCS_LIM(sensor, CLOCK_CAPA_TYPE_CAPABILITY) & + CCS_CLOCK_CAPA_TYPE_CAPABILITY_IREAL) + val = ireal32_to_u32_mul_1000000(client, val); + else + val = float_to_u32_mul_1000000(client, val); + } else if (reg & CCS_FL_IREAL) { + val = ireal32_to_u32_mul_1000000(client, val); + } return val; } |