summaryrefslogtreecommitdiff
path: root/drivers/media/i2c/ccs/ccs-reg-access.c
diff options
context:
space:
mode:
authorSakari Ailus <sakari.ailus@linux.intel.com>2020-06-24 15:39:05 +0200
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>2020-12-03 12:27:31 +0100
commitfe652254e243a58daf50aa0ddb938885ae2ba565 (patch)
treed86582b4f11dcbcd5ae15cea3a2d890fb1f32dd8 /drivers/media/i2c/ccs/ccs-reg-access.c
parent5017f8b4e0ed9ec39c04ac85de6ce49603f5f02b (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.c23
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;
}