1b24cc2a1SSakari Ailus // SPDX-License-Identifier: GPL-2.0-only
2b24cc2a1SSakari Ailus /*
3b24cc2a1SSakari Ailus * drivers/media/i2c/ccs/ccs-reg-access.c
4b24cc2a1SSakari Ailus *
5b24cc2a1SSakari Ailus * Generic driver for MIPI CCS/SMIA/SMIA++ compliant camera sensors
6b24cc2a1SSakari Ailus *
7b24cc2a1SSakari Ailus * Copyright (C) 2020 Intel Corporation
8b24cc2a1SSakari Ailus * Copyright (C) 2011--2012 Nokia Corporation
97389d01cSSakari Ailus * Contact: Sakari Ailus <sakari.ailus@linux.intel.com>
10b24cc2a1SSakari Ailus */
11b24cc2a1SSakari Ailus
12*5f60d5f6SAl Viro #include <linux/unaligned.h>
13b24cc2a1SSakari Ailus
14b24cc2a1SSakari Ailus #include <linux/delay.h>
15b24cc2a1SSakari Ailus #include <linux/i2c.h>
16b24cc2a1SSakari Ailus
17b24cc2a1SSakari Ailus #include "ccs.h"
18fe652254SSakari Ailus #include "ccs-limits.h"
19b24cc2a1SSakari Ailus
float_to_u32_mul_1000000(struct i2c_client * client,u32 phloat)20dffbdf37SSakari Ailus static u32 float_to_u32_mul_1000000(struct i2c_client *client, u32 phloat)
21b24cc2a1SSakari Ailus {
22dffbdf37SSakari Ailus s32 exp;
23dffbdf37SSakari Ailus u64 man;
24b24cc2a1SSakari Ailus
25b24cc2a1SSakari Ailus if (phloat >= 0x80000000) {
26b24cc2a1SSakari Ailus dev_err(&client->dev, "this is a negative number\n");
27b24cc2a1SSakari Ailus return 0;
28b24cc2a1SSakari Ailus }
29b24cc2a1SSakari Ailus
30b24cc2a1SSakari Ailus if (phloat == 0x7f800000)
31b24cc2a1SSakari Ailus return ~0; /* Inf. */
32b24cc2a1SSakari Ailus
33b24cc2a1SSakari Ailus if ((phloat & 0x7f800000) == 0x7f800000) {
34b24cc2a1SSakari Ailus dev_err(&client->dev, "NaN or other special number\n");
35b24cc2a1SSakari Ailus return 0;
36b24cc2a1SSakari Ailus }
37b24cc2a1SSakari Ailus
38b24cc2a1SSakari Ailus /* Valid cases begin here */
39b24cc2a1SSakari Ailus if (phloat == 0)
40b24cc2a1SSakari Ailus return 0; /* Valid zero */
41b24cc2a1SSakari Ailus
42b24cc2a1SSakari Ailus if (phloat > 0x4f800000)
43b24cc2a1SSakari Ailus return ~0; /* larger than 4294967295 */
44b24cc2a1SSakari Ailus
45b24cc2a1SSakari Ailus /*
46b24cc2a1SSakari Ailus * Unbias exponent (note how phloat is now guaranteed to
47b24cc2a1SSakari Ailus * have 0 in the high bit)
48b24cc2a1SSakari Ailus */
49b24cc2a1SSakari Ailus exp = ((int32_t)phloat >> 23) - 127;
50b24cc2a1SSakari Ailus
51b24cc2a1SSakari Ailus /* Extract mantissa, add missing '1' bit and it's in MHz */
52b24cc2a1SSakari Ailus man = ((phloat & 0x7fffff) | 0x800000) * 1000000ULL;
53b24cc2a1SSakari Ailus
54b24cc2a1SSakari Ailus if (exp < 0)
55b24cc2a1SSakari Ailus man >>= -exp;
56b24cc2a1SSakari Ailus else
57b24cc2a1SSakari Ailus man <<= exp;
58b24cc2a1SSakari Ailus
59b24cc2a1SSakari Ailus man >>= 23; /* Remove mantissa bias */
60b24cc2a1SSakari Ailus
61b24cc2a1SSakari Ailus return man & 0xffffffff;
62b24cc2a1SSakari Ailus }
63b24cc2a1SSakari Ailus
64b24cc2a1SSakari Ailus
ireal32_to_u32_mul_1000000(struct i2c_client * client,u32 val)65fe652254SSakari Ailus static u32 ireal32_to_u32_mul_1000000(struct i2c_client *client, u32 val)
66fe652254SSakari Ailus {
67fe652254SSakari Ailus if (val >> 10 > U32_MAX / 15625) {
68fe652254SSakari Ailus dev_warn(&client->dev, "value %u overflows!\n", val);
69fe652254SSakari Ailus return U32_MAX;
70fe652254SSakari Ailus }
71fe652254SSakari Ailus
72fe652254SSakari Ailus return ((val >> 10) * 15625) +
73fe652254SSakari Ailus (val & GENMASK(9, 0)) * 15625 / 1024;
74fe652254SSakari Ailus }
75fe652254SSakari Ailus
ccs_reg_conv(struct ccs_sensor * sensor,u32 reg,u32 val)767d2f8ddaSSakari Ailus u32 ccs_reg_conv(struct ccs_sensor *sensor, u32 reg, u32 val)
777d2f8ddaSSakari Ailus {
787d2f8ddaSSakari Ailus struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
797d2f8ddaSSakari Ailus
80fe652254SSakari Ailus if (reg & CCS_FL_FLOAT_IREAL) {
81fe652254SSakari Ailus if (CCS_LIM(sensor, CLOCK_CAPA_TYPE_CAPABILITY) &
82fe652254SSakari Ailus CCS_CLOCK_CAPA_TYPE_CAPABILITY_IREAL)
83fe652254SSakari Ailus val = ireal32_to_u32_mul_1000000(client, val);
84fe652254SSakari Ailus else
857d2f8ddaSSakari Ailus val = float_to_u32_mul_1000000(client, val);
86fe652254SSakari Ailus } else if (reg & CCS_FL_IREAL) {
87fe652254SSakari Ailus val = ireal32_to_u32_mul_1000000(client, val);
88fe652254SSakari Ailus }
897d2f8ddaSSakari Ailus
907d2f8ddaSSakari Ailus return val;
917d2f8ddaSSakari Ailus }
927d2f8ddaSSakari Ailus
93b24cc2a1SSakari Ailus /*
94b24cc2a1SSakari Ailus * Read a 8/16/32-bit i2c register. The value is returned in 'val'.
95b24cc2a1SSakari Ailus * Returns zero if successful, or non-zero otherwise.
96b24cc2a1SSakari Ailus */
__ccs_read_addr(struct ccs_sensor * sensor,u32 reg,u32 * val,bool only8,bool conv)97b24cc2a1SSakari Ailus static int __ccs_read_addr(struct ccs_sensor *sensor, u32 reg, u32 *val,
987d2f8ddaSSakari Ailus bool only8, bool conv)
99b24cc2a1SSakari Ailus {
10052932211SSakari Ailus u64 __val;
101b24cc2a1SSakari Ailus int rval;
102b24cc2a1SSakari Ailus
10352932211SSakari Ailus rval = cci_read(sensor->regmap, reg, &__val, NULL);
104b24cc2a1SSakari Ailus if (rval < 0)
105b24cc2a1SSakari Ailus return rval;
106b24cc2a1SSakari Ailus
10752932211SSakari Ailus *val = conv ? ccs_reg_conv(sensor, reg, __val) : __val;
108b24cc2a1SSakari Ailus
109b24cc2a1SSakari Ailus return 0;
110b24cc2a1SSakari Ailus }
111b24cc2a1SSakari Ailus
__ccs_static_data_read_ro_reg(struct ccs_reg * regs,size_t num_regs,u32 reg,u32 * val)112d180509cSSakari Ailus static int __ccs_static_data_read_ro_reg(struct ccs_reg *regs, size_t num_regs,
1131b398012SSakari Ailus u32 reg, u32 *val)
1141b398012SSakari Ailus {
11552932211SSakari Ailus unsigned int width = CCI_REG_WIDTH_BYTES(reg);
1161b398012SSakari Ailus size_t i;
1171b398012SSakari Ailus
1181b398012SSakari Ailus for (i = 0; i < num_regs; i++, regs++) {
119dffbdf37SSakari Ailus u8 *data;
1201b398012SSakari Ailus
1211b398012SSakari Ailus if (regs->addr + regs->len < CCS_REG_ADDR(reg) + width)
1221b398012SSakari Ailus continue;
1231b398012SSakari Ailus
1241b398012SSakari Ailus if (regs->addr > CCS_REG_ADDR(reg))
1251b398012SSakari Ailus break;
1261b398012SSakari Ailus
1271b398012SSakari Ailus data = ®s->value[CCS_REG_ADDR(reg) - regs->addr];
1281b398012SSakari Ailus
1291b398012SSakari Ailus switch (width) {
130dffbdf37SSakari Ailus case sizeof(u8):
1311b398012SSakari Ailus *val = *data;
1321b398012SSakari Ailus break;
133dffbdf37SSakari Ailus case sizeof(u16):
1341b398012SSakari Ailus *val = get_unaligned_be16(data);
1351b398012SSakari Ailus break;
136dffbdf37SSakari Ailus case sizeof(u32):
1371b398012SSakari Ailus *val = get_unaligned_be32(data);
1381b398012SSakari Ailus break;
1391b398012SSakari Ailus default:
1401b398012SSakari Ailus WARN_ON(1);
1411b398012SSakari Ailus return -EINVAL;
1421b398012SSakari Ailus }
1431b398012SSakari Ailus
1441b398012SSakari Ailus return 0;
1451b398012SSakari Ailus }
1461b398012SSakari Ailus
1471b398012SSakari Ailus return -ENOENT;
1481b398012SSakari Ailus }
1491b398012SSakari Ailus
150d180509cSSakari Ailus static int
ccs_static_data_read_ro_reg(struct ccs_sensor * sensor,u32 reg,u32 * val)151d180509cSSakari Ailus ccs_static_data_read_ro_reg(struct ccs_sensor *sensor, u32 reg, u32 *val)
1521b398012SSakari Ailus {
153d180509cSSakari Ailus if (!__ccs_static_data_read_ro_reg(sensor->sdata.sensor_read_only_regs,
1541b398012SSakari Ailus sensor->sdata.num_sensor_read_only_regs,
1551b398012SSakari Ailus reg, val))
1561b398012SSakari Ailus return 0;
1571b398012SSakari Ailus
158d180509cSSakari Ailus return __ccs_static_data_read_ro_reg(sensor->mdata.module_read_only_regs,
1591b398012SSakari Ailus sensor->mdata.num_module_read_only_regs,
1601b398012SSakari Ailus reg, val);
1611b398012SSakari Ailus }
1621b398012SSakari Ailus
ccs_read_addr_raw(struct ccs_sensor * sensor,u32 reg,u32 * val,bool force8,bool quirk,bool conv,bool data)1632989a457SSakari Ailus static int ccs_read_addr_raw(struct ccs_sensor *sensor, u32 reg, u32 *val,
1641b398012SSakari Ailus bool force8, bool quirk, bool conv, bool data)
165b24cc2a1SSakari Ailus {
166b24cc2a1SSakari Ailus int rval;
167b24cc2a1SSakari Ailus
1681b398012SSakari Ailus if (data) {
169d180509cSSakari Ailus rval = ccs_static_data_read_ro_reg(sensor, reg, val);
1701b398012SSakari Ailus if (!rval)
1711b398012SSakari Ailus return 0;
1721b398012SSakari Ailus }
1731b398012SSakari Ailus
1742989a457SSakari Ailus if (quirk) {
175b24cc2a1SSakari Ailus *val = 0;
176b24cc2a1SSakari Ailus rval = ccs_call_quirk(sensor, reg_access, false, ®, val);
177b24cc2a1SSakari Ailus if (rval == -ENOIOCTLCMD)
178b24cc2a1SSakari Ailus return 0;
179b24cc2a1SSakari Ailus if (rval < 0)
180b24cc2a1SSakari Ailus return rval;
181b24cc2a1SSakari Ailus
182b24cc2a1SSakari Ailus if (force8)
1837d2f8ddaSSakari Ailus return __ccs_read_addr(sensor, reg, val, true, conv);
1842989a457SSakari Ailus }
185b24cc2a1SSakari Ailus
1862989a457SSakari Ailus return __ccs_read_addr(sensor, reg, val,
1872989a457SSakari Ailus ccs_needs_quirk(sensor,
1887d2f8ddaSSakari Ailus CCS_QUIRK_FLAG_8BIT_READ_ONLY),
1897d2f8ddaSSakari Ailus conv);
190b24cc2a1SSakari Ailus }
191b24cc2a1SSakari Ailus
ccs_read_addr(struct ccs_sensor * sensor,u32 reg,u32 * val)192b24cc2a1SSakari Ailus int ccs_read_addr(struct ccs_sensor *sensor, u32 reg, u32 *val)
193b24cc2a1SSakari Ailus {
1941b398012SSakari Ailus return ccs_read_addr_raw(sensor, reg, val, false, true, true, true);
195b24cc2a1SSakari Ailus }
196b24cc2a1SSakari Ailus
ccs_read_addr_8only(struct ccs_sensor * sensor,u32 reg,u32 * val)197b24cc2a1SSakari Ailus int ccs_read_addr_8only(struct ccs_sensor *sensor, u32 reg, u32 *val)
198b24cc2a1SSakari Ailus {
1991b398012SSakari Ailus return ccs_read_addr_raw(sensor, reg, val, true, true, true, true);
2007d2f8ddaSSakari Ailus }
2017d2f8ddaSSakari Ailus
ccs_read_addr_noconv(struct ccs_sensor * sensor,u32 reg,u32 * val)2027d2f8ddaSSakari Ailus int ccs_read_addr_noconv(struct ccs_sensor *sensor, u32 reg, u32 *val)
2037d2f8ddaSSakari Ailus {
2041b398012SSakari Ailus return ccs_read_addr_raw(sensor, reg, val, false, true, false, true);
205b24cc2a1SSakari Ailus }
206b24cc2a1SSakari Ailus
207b24cc2a1SSakari Ailus /*
208b24cc2a1SSakari Ailus * Write to a 8/16-bit register.
209b24cc2a1SSakari Ailus * Returns zero if successful, or non-zero otherwise.
210b24cc2a1SSakari Ailus */
ccs_write_addr(struct ccs_sensor * sensor,u32 reg,u32 val)211b24cc2a1SSakari Ailus int ccs_write_addr(struct ccs_sensor *sensor, u32 reg, u32 val)
212b24cc2a1SSakari Ailus {
21352932211SSakari Ailus unsigned int retries = 10;
214b24cc2a1SSakari Ailus int rval;
215b24cc2a1SSakari Ailus
216b24cc2a1SSakari Ailus rval = ccs_call_quirk(sensor, reg_access, true, ®, &val);
217b24cc2a1SSakari Ailus if (rval == -ENOIOCTLCMD)
218b24cc2a1SSakari Ailus return 0;
219b24cc2a1SSakari Ailus if (rval < 0)
220b24cc2a1SSakari Ailus return rval;
221b24cc2a1SSakari Ailus
22252932211SSakari Ailus rval = 0;
22352932211SSakari Ailus do {
22452932211SSakari Ailus if (cci_write(sensor->regmap, reg, val, &rval))
22552932211SSakari Ailus fsleep(1000);
22652932211SSakari Ailus } while (rval && --retries);
22752932211SSakari Ailus
22852932211SSakari Ailus return rval;
229b24cc2a1SSakari Ailus }
2302538d322SSakari Ailus
2312538d322SSakari Ailus #define MAX_WRITE_LEN 32U
2322538d322SSakari Ailus
ccs_write_data_regs(struct ccs_sensor * sensor,struct ccs_reg * regs,size_t num_regs)2332538d322SSakari Ailus int ccs_write_data_regs(struct ccs_sensor *sensor, struct ccs_reg *regs,
2342538d322SSakari Ailus size_t num_regs)
2352538d322SSakari Ailus {
2362538d322SSakari Ailus struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
2372538d322SSakari Ailus size_t i;
2382538d322SSakari Ailus
2392538d322SSakari Ailus for (i = 0; i < num_regs; i++, regs++) {
2402538d322SSakari Ailus unsigned char *regdata = regs->value;
2412538d322SSakari Ailus unsigned int j;
24252932211SSakari Ailus int len;
2432538d322SSakari Ailus
24452932211SSakari Ailus for (j = 0; j < regs->len; j += len, regdata += len) {
2457a426098SSakari Ailus char printbuf[(MAX_WRITE_LEN << 1) +
2467a426098SSakari Ailus 1 /* \0 */] = { 0 };
24752932211SSakari Ailus unsigned int retries = 10;
2482538d322SSakari Ailus int rval;
2492538d322SSakari Ailus
25052932211SSakari Ailus len = min(regs->len - j, MAX_WRITE_LEN);
2512538d322SSakari Ailus
25252932211SSakari Ailus bin2hex(printbuf, regdata, len);
2537a426098SSakari Ailus dev_dbg(&client->dev,
2547a426098SSakari Ailus "writing msr reg 0x%4.4x value 0x%s\n",
2557a426098SSakari Ailus regs->addr + j, printbuf);
2567a426098SSakari Ailus
25752932211SSakari Ailus do {
25852932211SSakari Ailus rval = regmap_bulk_write(sensor->regmap,
25952932211SSakari Ailus regs->addr + j,
26052932211SSakari Ailus regdata, len);
26152932211SSakari Ailus if (rval)
26252932211SSakari Ailus fsleep(1000);
26352932211SSakari Ailus } while (rval && --retries);
2647a426098SSakari Ailus
2652538d322SSakari Ailus if (rval) {
2662538d322SSakari Ailus dev_err(&client->dev,
2672538d322SSakari Ailus "error writing %u octets to address 0x%4.4x\n",
26852932211SSakari Ailus len, regs->addr + j);
2692538d322SSakari Ailus return rval;
2702538d322SSakari Ailus }
2712538d322SSakari Ailus }
2722538d322SSakari Ailus }
2732538d322SSakari Ailus
2742538d322SSakari Ailus return 0;
2752538d322SSakari Ailus }
276