1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * drivers/media/i2c/ccs/ccs-reg-access.c |
4 | * |
5 | * Generic driver for MIPI CCS/SMIA/SMIA++ compliant camera sensors |
6 | * |
7 | * Copyright (C) 2020 Intel Corporation |
8 | * Copyright (C) 2011--2012 Nokia Corporation |
9 | * Contact: Sakari Ailus <sakari.ailus@linux.intel.com> |
10 | */ |
11 | |
12 | #include <asm/unaligned.h> |
13 | |
14 | #include <linux/delay.h> |
15 | #include <linux/i2c.h> |
16 | |
17 | #include "ccs.h" |
18 | #include "ccs-limits.h" |
19 | |
20 | static u32 float_to_u32_mul_1000000(struct i2c_client *client, u32 phloat) |
21 | { |
22 | s32 exp; |
23 | u64 man; |
24 | |
25 | if (phloat >= 0x80000000) { |
26 | dev_err(&client->dev, "this is a negative number\n" ); |
27 | return 0; |
28 | } |
29 | |
30 | if (phloat == 0x7f800000) |
31 | return ~0; /* Inf. */ |
32 | |
33 | if ((phloat & 0x7f800000) == 0x7f800000) { |
34 | dev_err(&client->dev, "NaN or other special number\n" ); |
35 | return 0; |
36 | } |
37 | |
38 | /* Valid cases begin here */ |
39 | if (phloat == 0) |
40 | return 0; /* Valid zero */ |
41 | |
42 | if (phloat > 0x4f800000) |
43 | return ~0; /* larger than 4294967295 */ |
44 | |
45 | /* |
46 | * Unbias exponent (note how phloat is now guaranteed to |
47 | * have 0 in the high bit) |
48 | */ |
49 | exp = ((int32_t)phloat >> 23) - 127; |
50 | |
51 | /* Extract mantissa, add missing '1' bit and it's in MHz */ |
52 | man = ((phloat & 0x7fffff) | 0x800000) * 1000000ULL; |
53 | |
54 | if (exp < 0) |
55 | man >>= -exp; |
56 | else |
57 | man <<= exp; |
58 | |
59 | man >>= 23; /* Remove mantissa bias */ |
60 | |
61 | return man & 0xffffffff; |
62 | } |
63 | |
64 | |
65 | static u32 ireal32_to_u32_mul_1000000(struct i2c_client *client, u32 val) |
66 | { |
67 | if (val >> 10 > U32_MAX / 15625) { |
68 | dev_warn(&client->dev, "value %u overflows!\n" , val); |
69 | return U32_MAX; |
70 | } |
71 | |
72 | return ((val >> 10) * 15625) + |
73 | (val & GENMASK(9, 0)) * 15625 / 1024; |
74 | } |
75 | |
76 | u32 ccs_reg_conv(struct ccs_sensor *sensor, u32 reg, u32 val) |
77 | { |
78 | struct i2c_client *client = v4l2_get_subdevdata(sd: &sensor->src->sd); |
79 | |
80 | if (reg & CCS_FL_FLOAT_IREAL) { |
81 | if (CCS_LIM(sensor, CLOCK_CAPA_TYPE_CAPABILITY) & |
82 | CCS_CLOCK_CAPA_TYPE_CAPABILITY_IREAL) |
83 | val = ireal32_to_u32_mul_1000000(client, val); |
84 | else |
85 | val = float_to_u32_mul_1000000(client, phloat: val); |
86 | } else if (reg & CCS_FL_IREAL) { |
87 | val = ireal32_to_u32_mul_1000000(client, val); |
88 | } |
89 | |
90 | return val; |
91 | } |
92 | |
93 | /* |
94 | * Read a 8/16/32-bit i2c register. The value is returned in 'val'. |
95 | * Returns zero if successful, or non-zero otherwise. |
96 | */ |
97 | static int __ccs_read_addr(struct ccs_sensor *sensor, u32 reg, u32 *val, |
98 | bool only8, bool conv) |
99 | { |
100 | u64 __val; |
101 | int rval; |
102 | |
103 | rval = cci_read(map: sensor->regmap, reg, val: &__val, NULL); |
104 | if (rval < 0) |
105 | return rval; |
106 | |
107 | *val = conv ? ccs_reg_conv(sensor, reg, val: __val) : __val; |
108 | |
109 | return 0; |
110 | } |
111 | |
112 | static int __ccs_static_data_read_ro_reg(struct ccs_reg *regs, size_t num_regs, |
113 | u32 reg, u32 *val) |
114 | { |
115 | unsigned int width = CCI_REG_WIDTH_BYTES(reg); |
116 | size_t i; |
117 | |
118 | for (i = 0; i < num_regs; i++, regs++) { |
119 | u8 *data; |
120 | |
121 | if (regs->addr + regs->len < CCS_REG_ADDR(reg) + width) |
122 | continue; |
123 | |
124 | if (regs->addr > CCS_REG_ADDR(reg)) |
125 | break; |
126 | |
127 | data = ®s->value[CCS_REG_ADDR(reg) - regs->addr]; |
128 | |
129 | switch (width) { |
130 | case sizeof(u8): |
131 | *val = *data; |
132 | break; |
133 | case sizeof(u16): |
134 | *val = get_unaligned_be16(p: data); |
135 | break; |
136 | case sizeof(u32): |
137 | *val = get_unaligned_be32(p: data); |
138 | break; |
139 | default: |
140 | WARN_ON(1); |
141 | return -EINVAL; |
142 | } |
143 | |
144 | return 0; |
145 | } |
146 | |
147 | return -ENOENT; |
148 | } |
149 | |
150 | static int |
151 | ccs_static_data_read_ro_reg(struct ccs_sensor *sensor, u32 reg, u32 *val) |
152 | { |
153 | if (!__ccs_static_data_read_ro_reg(regs: sensor->sdata.sensor_read_only_regs, |
154 | num_regs: sensor->sdata.num_sensor_read_only_regs, |
155 | reg, val)) |
156 | return 0; |
157 | |
158 | return __ccs_static_data_read_ro_reg(regs: sensor->mdata.module_read_only_regs, |
159 | num_regs: sensor->mdata.num_module_read_only_regs, |
160 | reg, val); |
161 | } |
162 | |
163 | static int ccs_read_addr_raw(struct ccs_sensor *sensor, u32 reg, u32 *val, |
164 | bool force8, bool quirk, bool conv, bool data) |
165 | { |
166 | int rval; |
167 | |
168 | if (data) { |
169 | rval = ccs_static_data_read_ro_reg(sensor, reg, val); |
170 | if (!rval) |
171 | return 0; |
172 | } |
173 | |
174 | if (quirk) { |
175 | *val = 0; |
176 | rval = ccs_call_quirk(sensor, reg_access, false, ®, val); |
177 | if (rval == -ENOIOCTLCMD) |
178 | return 0; |
179 | if (rval < 0) |
180 | return rval; |
181 | |
182 | if (force8) |
183 | return __ccs_read_addr(sensor, reg, val, only8: true, conv); |
184 | } |
185 | |
186 | return __ccs_read_addr(sensor, reg, val, |
187 | ccs_needs_quirk(sensor, |
188 | CCS_QUIRK_FLAG_8BIT_READ_ONLY), |
189 | conv); |
190 | } |
191 | |
192 | int ccs_read_addr(struct ccs_sensor *sensor, u32 reg, u32 *val) |
193 | { |
194 | return ccs_read_addr_raw(sensor, reg, val, force8: false, quirk: true, conv: true, data: true); |
195 | } |
196 | |
197 | int ccs_read_addr_8only(struct ccs_sensor *sensor, u32 reg, u32 *val) |
198 | { |
199 | return ccs_read_addr_raw(sensor, reg, val, force8: true, quirk: true, conv: true, data: true); |
200 | } |
201 | |
202 | int ccs_read_addr_noconv(struct ccs_sensor *sensor, u32 reg, u32 *val) |
203 | { |
204 | return ccs_read_addr_raw(sensor, reg, val, force8: false, quirk: true, conv: false, data: true); |
205 | } |
206 | |
207 | /* |
208 | * Write to a 8/16-bit register. |
209 | * Returns zero if successful, or non-zero otherwise. |
210 | */ |
211 | int ccs_write_addr(struct ccs_sensor *sensor, u32 reg, u32 val) |
212 | { |
213 | unsigned int retries = 10; |
214 | int rval; |
215 | |
216 | rval = ccs_call_quirk(sensor, reg_access, true, ®, &val); |
217 | if (rval == -ENOIOCTLCMD) |
218 | return 0; |
219 | if (rval < 0) |
220 | return rval; |
221 | |
222 | rval = 0; |
223 | do { |
224 | if (cci_write(map: sensor->regmap, reg, val, err: &rval)) |
225 | fsleep(usecs: 1000); |
226 | } while (rval && --retries); |
227 | |
228 | return rval; |
229 | } |
230 | |
231 | #define MAX_WRITE_LEN 32U |
232 | |
233 | int ccs_write_data_regs(struct ccs_sensor *sensor, struct ccs_reg *regs, |
234 | size_t num_regs) |
235 | { |
236 | struct i2c_client *client = v4l2_get_subdevdata(sd: &sensor->src->sd); |
237 | size_t i; |
238 | |
239 | for (i = 0; i < num_regs; i++, regs++) { |
240 | unsigned char *regdata = regs->value; |
241 | unsigned int j; |
242 | int len; |
243 | |
244 | for (j = 0; j < regs->len; j += len, regdata += len) { |
245 | char printbuf[(MAX_WRITE_LEN << 1) + |
246 | 1 /* \0 */] = { 0 }; |
247 | unsigned int retries = 10; |
248 | int rval; |
249 | |
250 | len = min(regs->len - j, MAX_WRITE_LEN); |
251 | |
252 | bin2hex(dst: printbuf, src: regdata, count: len); |
253 | dev_dbg(&client->dev, |
254 | "writing msr reg 0x%4.4x value 0x%s\n" , |
255 | regs->addr + j, printbuf); |
256 | |
257 | do { |
258 | rval = regmap_bulk_write(map: sensor->regmap, |
259 | reg: regs->addr + j, |
260 | val: regdata, val_count: len); |
261 | if (rval) |
262 | fsleep(usecs: 1000); |
263 | } while (rval && --retries); |
264 | |
265 | if (rval) { |
266 | dev_err(&client->dev, |
267 | "error writing %u octets to address 0x%4.4x\n" , |
268 | len, regs->addr + j); |
269 | return rval; |
270 | } |
271 | } |
272 | } |
273 | |
274 | return 0; |
275 | } |
276 | |