]> Git Repo - linux.git/blob - drivers/media/i2c/ccs/ccs-reg-access.c
Merge tag 'cxl-for-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl
[linux.git] / drivers / media / i2c / ccs / ccs-reg-access.c
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 <[email protected]>
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 /*
66  * Read a 8/16/32-bit i2c register.  The value is returned in 'val'.
67  * Returns zero if successful, or non-zero otherwise.
68  */
69 static int ____ccs_read_addr(struct ccs_sensor *sensor, u16 reg, u16 len,
70                              u32 *val)
71 {
72         struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
73         struct i2c_msg msg;
74         unsigned char data_buf[sizeof(u32)] = { 0 };
75         unsigned char offset_buf[sizeof(u16)];
76         int r;
77
78         if (len > sizeof(data_buf))
79                 return -EINVAL;
80
81         msg.addr = client->addr;
82         msg.flags = 0;
83         msg.len = sizeof(offset_buf);
84         msg.buf = offset_buf;
85         put_unaligned_be16(reg, offset_buf);
86
87         r = i2c_transfer(client->adapter, &msg, 1);
88         if (r != 1) {
89                 if (r >= 0)
90                         r = -EBUSY;
91                 goto err;
92         }
93
94         msg.len = len;
95         msg.flags = I2C_M_RD;
96         msg.buf = &data_buf[sizeof(data_buf) - len];
97
98         r = i2c_transfer(client->adapter, &msg, 1);
99         if (r != 1) {
100                 if (r >= 0)
101                         r = -EBUSY;
102                 goto err;
103         }
104
105         *val = get_unaligned_be32(data_buf);
106
107         return 0;
108
109 err:
110         dev_err(&client->dev, "read from offset 0x%x error %d\n", reg, r);
111
112         return r;
113 }
114
115 /* Read a register using 8-bit access only. */
116 static int ____ccs_read_addr_8only(struct ccs_sensor *sensor, u16 reg,
117                                    u16 len, u32 *val)
118 {
119         unsigned int i;
120         int rval;
121
122         *val = 0;
123
124         for (i = 0; i < len; i++) {
125                 u32 val8;
126
127                 rval = ____ccs_read_addr(sensor, reg + i, 1, &val8);
128                 if (rval < 0)
129                         return rval;
130                 *val |= val8 << ((len - i - 1) << 3);
131         }
132
133         return 0;
134 }
135
136 unsigned int ccs_reg_width(u32 reg)
137 {
138         if (reg & CCS_FL_16BIT)
139                 return sizeof(u16);
140         if (reg & CCS_FL_32BIT)
141                 return sizeof(u32);
142
143         return sizeof(u8);
144 }
145
146 static u32 ireal32_to_u32_mul_1000000(struct i2c_client *client, u32 val)
147 {
148         if (val >> 10 > U32_MAX / 15625) {
149                 dev_warn(&client->dev, "value %u overflows!\n", val);
150                 return U32_MAX;
151         }
152
153         return ((val >> 10) * 15625) +
154                 (val & GENMASK(9, 0)) * 15625 / 1024;
155 }
156
157 u32 ccs_reg_conv(struct ccs_sensor *sensor, u32 reg, u32 val)
158 {
159         struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
160
161         if (reg & CCS_FL_FLOAT_IREAL) {
162                 if (CCS_LIM(sensor, CLOCK_CAPA_TYPE_CAPABILITY) &
163                     CCS_CLOCK_CAPA_TYPE_CAPABILITY_IREAL)
164                         val = ireal32_to_u32_mul_1000000(client, val);
165                 else
166                         val = float_to_u32_mul_1000000(client, val);
167         } else if (reg & CCS_FL_IREAL) {
168                 val = ireal32_to_u32_mul_1000000(client, val);
169         }
170
171         return val;
172 }
173
174 /*
175  * Read a 8/16/32-bit i2c register.  The value is returned in 'val'.
176  * Returns zero if successful, or non-zero otherwise.
177  */
178 static int __ccs_read_addr(struct ccs_sensor *sensor, u32 reg, u32 *val,
179                            bool only8, bool conv)
180 {
181         unsigned int len = ccs_reg_width(reg);
182         int rval;
183
184         if (!only8)
185                 rval = ____ccs_read_addr(sensor, CCS_REG_ADDR(reg), len, val);
186         else
187                 rval = ____ccs_read_addr_8only(sensor, CCS_REG_ADDR(reg), len,
188                                                val);
189         if (rval < 0)
190                 return rval;
191
192         if (!conv)
193                 return 0;
194
195         *val = ccs_reg_conv(sensor, reg, *val);
196
197         return 0;
198 }
199
200 static int __ccs_read_data(struct ccs_reg *regs, size_t num_regs,
201                            u32 reg, u32 *val)
202 {
203         unsigned int width = ccs_reg_width(reg);
204         size_t i;
205
206         for (i = 0; i < num_regs; i++, regs++) {
207                 u8 *data;
208
209                 if (regs->addr + regs->len < CCS_REG_ADDR(reg) + width)
210                         continue;
211
212                 if (regs->addr > CCS_REG_ADDR(reg))
213                         break;
214
215                 data = &regs->value[CCS_REG_ADDR(reg) - regs->addr];
216
217                 switch (width) {
218                 case sizeof(u8):
219                         *val = *data;
220                         break;
221                 case sizeof(u16):
222                         *val = get_unaligned_be16(data);
223                         break;
224                 case sizeof(u32):
225                         *val = get_unaligned_be32(data);
226                         break;
227                 default:
228                         WARN_ON(1);
229                         return -EINVAL;
230                 }
231
232                 return 0;
233         }
234
235         return -ENOENT;
236 }
237
238 static int ccs_read_data(struct ccs_sensor *sensor, u32 reg, u32 *val)
239 {
240         if (!__ccs_read_data(sensor->sdata.sensor_read_only_regs,
241                              sensor->sdata.num_sensor_read_only_regs,
242                              reg, val))
243                 return 0;
244
245         return __ccs_read_data(sensor->mdata.module_read_only_regs,
246                                sensor->mdata.num_module_read_only_regs,
247                                reg, val);
248 }
249
250 static int ccs_read_addr_raw(struct ccs_sensor *sensor, u32 reg, u32 *val,
251                              bool force8, bool quirk, bool conv, bool data)
252 {
253         int rval;
254
255         if (data) {
256                 rval = ccs_read_data(sensor, reg, val);
257                 if (!rval)
258                         return 0;
259         }
260
261         if (quirk) {
262                 *val = 0;
263                 rval = ccs_call_quirk(sensor, reg_access, false, &reg, val);
264                 if (rval == -ENOIOCTLCMD)
265                         return 0;
266                 if (rval < 0)
267                         return rval;
268
269                 if (force8)
270                         return __ccs_read_addr(sensor, reg, val, true, conv);
271         }
272
273         return __ccs_read_addr(sensor, reg, val,
274                                ccs_needs_quirk(sensor,
275                                                CCS_QUIRK_FLAG_8BIT_READ_ONLY),
276                                conv);
277 }
278
279 int ccs_read_addr(struct ccs_sensor *sensor, u32 reg, u32 *val)
280 {
281         return ccs_read_addr_raw(sensor, reg, val, false, true, true, true);
282 }
283
284 int ccs_read_addr_8only(struct ccs_sensor *sensor, u32 reg, u32 *val)
285 {
286         return ccs_read_addr_raw(sensor, reg, val, true, true, true, true);
287 }
288
289 int ccs_read_addr_noconv(struct ccs_sensor *sensor, u32 reg, u32 *val)
290 {
291         return ccs_read_addr_raw(sensor, reg, val, false, true, false, true);
292 }
293
294 static int ccs_write_retry(struct i2c_client *client, struct i2c_msg *msg)
295 {
296         unsigned int retries;
297         int r;
298
299         for (retries = 0; retries < 10; retries++) {
300                 /*
301                  * Due to unknown reason sensor stops responding. This
302                  * loop is a temporaty solution until the root cause
303                  * is found.
304                  */
305                 r = i2c_transfer(client->adapter, msg, 1);
306                 if (r != 1) {
307                         usleep_range(1000, 2000);
308                         continue;
309                 }
310
311                 if (retries)
312                         dev_err(&client->dev,
313                                 "sensor i2c stall encountered. retries: %d\n",
314                                 retries);
315                 return 0;
316         }
317
318         return r;
319 }
320
321 int ccs_write_addr_no_quirk(struct ccs_sensor *sensor, u32 reg, u32 val)
322 {
323         struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
324         struct i2c_msg msg;
325         unsigned char data[6];
326         unsigned int len = ccs_reg_width(reg);
327         int r;
328
329         if (len > sizeof(data) - 2)
330                 return -EINVAL;
331
332         msg.addr = client->addr;
333         msg.flags = 0; /* Write */
334         msg.len = 2 + len;
335         msg.buf = data;
336
337         put_unaligned_be16(CCS_REG_ADDR(reg), data);
338         put_unaligned_be32(val << (8 * (sizeof(val) - len)), data + 2);
339
340         dev_dbg(&client->dev, "writing reg 0x%4.4x value 0x%*.*x (%u)\n",
341                 CCS_REG_ADDR(reg), ccs_reg_width(reg) << 1,
342                 ccs_reg_width(reg) << 1, val, val);
343
344         r = ccs_write_retry(client, &msg);
345         if (r)
346                 dev_err(&client->dev,
347                         "wrote 0x%x to offset 0x%x error %d\n", val,
348                         CCS_REG_ADDR(reg), r);
349
350         return r;
351 }
352
353 /*
354  * Write to a 8/16-bit register.
355  * Returns zero if successful, or non-zero otherwise.
356  */
357 int ccs_write_addr(struct ccs_sensor *sensor, u32 reg, u32 val)
358 {
359         int rval;
360
361         rval = ccs_call_quirk(sensor, reg_access, true, &reg, &val);
362         if (rval == -ENOIOCTLCMD)
363                 return 0;
364         if (rval < 0)
365                 return rval;
366
367         return ccs_write_addr_no_quirk(sensor, reg, val);
368 }
369
370 #define MAX_WRITE_LEN   32U
371
372 int ccs_write_data_regs(struct ccs_sensor *sensor, struct ccs_reg *regs,
373                         size_t num_regs)
374 {
375         struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
376         unsigned char buf[2 + MAX_WRITE_LEN];
377         struct i2c_msg msg = {
378                 .addr = client->addr,
379                 .buf = buf,
380         };
381         size_t i;
382
383         for (i = 0; i < num_regs; i++, regs++) {
384                 unsigned char *regdata = regs->value;
385                 unsigned int j;
386
387                 for (j = 0; j < regs->len;
388                      j += msg.len - 2, regdata += msg.len - 2) {
389                         char printbuf[(MAX_WRITE_LEN << 1) +
390                                       1 /* \0 */] = { 0 };
391                         int rval;
392
393                         msg.len = min(regs->len - j, MAX_WRITE_LEN);
394
395                         bin2hex(printbuf, regdata, msg.len);
396                         dev_dbg(&client->dev,
397                                 "writing msr reg 0x%4.4x value 0x%s\n",
398                                 regs->addr + j, printbuf);
399
400                         put_unaligned_be16(regs->addr + j, buf);
401                         memcpy(buf + 2, regdata, msg.len);
402
403                         msg.len += 2;
404
405                         rval = ccs_write_retry(client, &msg);
406                         if (rval) {
407                                 dev_err(&client->dev,
408                                         "error writing %u octets to address 0x%4.4x\n",
409                                         msg.len, regs->addr + j);
410                                 return rval;
411                         }
412                 }
413         }
414
415         return 0;
416 }
This page took 0.056963 seconds and 4 git commands to generate.