GNU Linux-libre 4.19.245-gnu1
[releases.git] / drivers / iio / light / zopt2201.c
1 /*
2  * zopt2201.c - Support for IDT ZOPT2201 ambient light and UV B sensor
3  *
4  * Copyright 2017 Peter Meerwald-Stadler <pmeerw@pmeerw.net>
5  *
6  * This file is subject to the terms and conditions of version 2 of
7  * the GNU General Public License.  See the file COPYING in the main
8  * directory of this archive for more details.
9  *
10  * Datasheet: https://www.idt.com/document/dst/zopt2201-datasheet
11  * 7-bit I2C slave addresses 0x53 (default) or 0x52 (programmed)
12  *
13  * TODO: interrupt support, ALS/UVB raw mode
14  */
15
16 #include <linux/module.h>
17 #include <linux/i2c.h>
18 #include <linux/mutex.h>
19 #include <linux/err.h>
20 #include <linux/delay.h>
21
22 #include <linux/iio/iio.h>
23 #include <linux/iio/sysfs.h>
24
25 #define ZOPT2201_DRV_NAME "zopt2201"
26
27 /* Registers */
28 #define ZOPT2201_MAIN_CTRL              0x00
29 #define ZOPT2201_LS_MEAS_RATE           0x04
30 #define ZOPT2201_LS_GAIN                0x05
31 #define ZOPT2201_PART_ID                0x06
32 #define ZOPT2201_MAIN_STATUS            0x07
33 #define ZOPT2201_ALS_DATA               0x0d /* LSB first, 13 to 20 bits */
34 #define ZOPT2201_UVB_DATA               0x10 /* LSB first, 13 to 20 bits */
35 #define ZOPT2201_UV_COMP_DATA           0x13 /* LSB first, 13 to 20 bits */
36 #define ZOPT2201_COMP_DATA              0x16 /* LSB first, 13 to 20 bits */
37 #define ZOPT2201_INT_CFG                0x19
38 #define ZOPT2201_INT_PST                0x1a
39
40 #define ZOPT2201_MAIN_CTRL_LS_MODE      BIT(3) /* 0 .. ALS, 1 .. UV B */
41 #define ZOPT2201_MAIN_CTRL_LS_EN        BIT(1)
42
43 /* Values for ZOPT2201_LS_MEAS_RATE resolution / bit width */
44 #define ZOPT2201_MEAS_RES_20BIT         0 /* takes 400 ms */
45 #define ZOPT2201_MEAS_RES_19BIT         1 /* takes 200 ms */
46 #define ZOPT2201_MEAS_RES_18BIT         2 /* takes 100 ms, default */
47 #define ZOPT2201_MEAS_RES_17BIT         3 /* takes 50 ms */
48 #define ZOPT2201_MEAS_RES_16BIT         4 /* takes 25 ms */
49 #define ZOPT2201_MEAS_RES_13BIT         5 /* takes 3.125 ms */
50 #define ZOPT2201_MEAS_RES_SHIFT         4
51
52 /* Values for ZOPT2201_LS_MEAS_RATE measurement rate */
53 #define ZOPT2201_MEAS_FREQ_25MS         0
54 #define ZOPT2201_MEAS_FREQ_50MS         1
55 #define ZOPT2201_MEAS_FREQ_100MS        2 /* default */
56 #define ZOPT2201_MEAS_FREQ_200MS        3
57 #define ZOPT2201_MEAS_FREQ_500MS        4
58 #define ZOPT2201_MEAS_FREQ_1000MS       5
59 #define ZOPT2201_MEAS_FREQ_2000MS       6
60
61 /* Values for ZOPT2201_LS_GAIN */
62 #define ZOPT2201_LS_GAIN_1              0
63 #define ZOPT2201_LS_GAIN_3              1
64 #define ZOPT2201_LS_GAIN_6              2
65 #define ZOPT2201_LS_GAIN_9              3
66 #define ZOPT2201_LS_GAIN_18             4
67
68 /* Values for ZOPT2201_MAIN_STATUS */
69 #define ZOPT2201_MAIN_STATUS_POWERON    BIT(5)
70 #define ZOPT2201_MAIN_STATUS_INT        BIT(4)
71 #define ZOPT2201_MAIN_STATUS_DRDY       BIT(3)
72
73 #define ZOPT2201_PART_NUMBER            0xb2
74
75 struct zopt2201_data {
76         struct i2c_client *client;
77         struct mutex lock;
78         u8 gain;
79         u8 res;
80         u8 rate;
81 };
82
83 static const struct {
84         unsigned int gain; /* gain factor */
85         unsigned int scale; /* micro lux per count */
86 } zopt2201_gain_als[] = {
87         {  1, 19200000 },
88         {  3,  6400000 },
89         {  6,  3200000 },
90         {  9,  2133333 },
91         { 18,  1066666 },
92 };
93
94 static const struct {
95         unsigned int gain; /* gain factor */
96         unsigned int scale; /* micro W/m2 per count */
97 } zopt2201_gain_uvb[] = {
98         {  1, 460800 },
99         {  3, 153600 },
100         {  6,  76800 },
101         {  9,  51200 },
102         { 18,  25600 },
103 };
104
105 static const struct {
106         unsigned int bits; /* sensor resolution in bits */
107         unsigned long us; /* measurement time in micro seconds */
108 } zopt2201_resolution[] = {
109         { 20, 400000 },
110         { 19, 200000 },
111         { 18, 100000 },
112         { 17,  50000 },
113         { 16,  25000 },
114         { 13,   3125 },
115 };
116
117 static const struct {
118         unsigned int scale, uscale; /* scale factor as integer + micro */
119         u8 gain; /* gain register value */
120         u8 res; /* resolution register value */
121 } zopt2201_scale_als[] = {
122         { 19, 200000, 0, 5 },
123         {  6, 400000, 1, 5 },
124         {  3, 200000, 2, 5 },
125         {  2, 400000, 0, 4 },
126         {  2, 133333, 3, 5 },
127         {  1, 200000, 0, 3 },
128         {  1,  66666, 4, 5 },
129         {  0, 800000, 1, 4 },
130         {  0, 600000, 0, 2 },
131         {  0, 400000, 2, 4 },
132         {  0, 300000, 0, 1 },
133         {  0, 266666, 3, 4 },
134         {  0, 200000, 2, 3 },
135         {  0, 150000, 0, 0 },
136         {  0, 133333, 4, 4 },
137         {  0, 100000, 2, 2 },
138         {  0,  66666, 4, 3 },
139         {  0,  50000, 2, 1 },
140         {  0,  33333, 4, 2 },
141         {  0,  25000, 2, 0 },
142         {  0,  16666, 4, 1 },
143         {  0,   8333, 4, 0 },
144 };
145
146 static const struct {
147         unsigned int scale, uscale; /* scale factor as integer + micro */
148         u8 gain; /* gain register value */
149         u8 res; /* resolution register value */
150 } zopt2201_scale_uvb[] = {
151         { 0, 460800, 0, 5 },
152         { 0, 153600, 1, 5 },
153         { 0,  76800, 2, 5 },
154         { 0,  57600, 0, 4 },
155         { 0,  51200, 3, 5 },
156         { 0,  28800, 0, 3 },
157         { 0,  25600, 4, 5 },
158         { 0,  19200, 1, 4 },
159         { 0,  14400, 0, 2 },
160         { 0,   9600, 2, 4 },
161         { 0,   7200, 0, 1 },
162         { 0,   6400, 3, 4 },
163         { 0,   4800, 2, 3 },
164         { 0,   3600, 0, 0 },
165         { 0,   3200, 4, 4 },
166         { 0,   2400, 2, 2 },
167         { 0,   1600, 4, 3 },
168         { 0,   1200, 2, 1 },
169         { 0,    800, 4, 2 },
170         { 0,    600, 2, 0 },
171         { 0,    400, 4, 1 },
172         { 0,    200, 4, 0 },
173 };
174
175 static int zopt2201_enable_mode(struct zopt2201_data *data, bool uvb_mode)
176 {
177         u8 out = ZOPT2201_MAIN_CTRL_LS_EN;
178
179         if (uvb_mode)
180                 out |= ZOPT2201_MAIN_CTRL_LS_MODE;
181
182         return i2c_smbus_write_byte_data(data->client, ZOPT2201_MAIN_CTRL, out);
183 }
184
185 static int zopt2201_read(struct zopt2201_data *data, u8 reg)
186 {
187         struct i2c_client *client = data->client;
188         int tries = 10;
189         u8 buf[3];
190         int ret;
191
192         mutex_lock(&data->lock);
193         ret = zopt2201_enable_mode(data, reg == ZOPT2201_UVB_DATA);
194         if (ret < 0)
195                 goto fail;
196
197         while (tries--) {
198                 unsigned long t = zopt2201_resolution[data->res].us;
199
200                 if (t <= 20000)
201                         usleep_range(t, t + 1000);
202                 else
203                         msleep(t / 1000);
204                 ret = i2c_smbus_read_byte_data(client, ZOPT2201_MAIN_STATUS);
205                 if (ret < 0)
206                         goto fail;
207                 if (ret & ZOPT2201_MAIN_STATUS_DRDY)
208                         break;
209         }
210
211         if (tries < 0) {
212                 ret = -ETIMEDOUT;
213                 goto fail;
214         }
215
216         ret = i2c_smbus_read_i2c_block_data(client, reg, sizeof(buf), buf);
217         if (ret < 0)
218                 goto fail;
219
220         ret = i2c_smbus_write_byte_data(client, ZOPT2201_MAIN_CTRL, 0x00);
221         if (ret < 0)
222                 goto fail;
223         mutex_unlock(&data->lock);
224
225         return (buf[2] << 16) | (buf[1] << 8) | buf[0];
226
227 fail:
228         mutex_unlock(&data->lock);
229         return ret;
230 }
231
232 static const struct iio_chan_spec zopt2201_channels[] = {
233         {
234                 .type = IIO_LIGHT,
235                 .address = ZOPT2201_ALS_DATA,
236                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
237                                       BIT(IIO_CHAN_INFO_SCALE),
238                 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
239         },
240         {
241                 .type = IIO_INTENSITY,
242                 .modified = 1,
243                 .channel2 = IIO_MOD_LIGHT_UV,
244                 .address = ZOPT2201_UVB_DATA,
245                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
246                                       BIT(IIO_CHAN_INFO_SCALE),
247                 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
248         },
249         {
250                 .type = IIO_UVINDEX,
251                 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
252         },
253 };
254
255 static int zopt2201_read_raw(struct iio_dev *indio_dev,
256                                 struct iio_chan_spec const *chan,
257                                 int *val, int *val2, long mask)
258 {
259         struct zopt2201_data *data = iio_priv(indio_dev);
260         u64 tmp;
261         int ret;
262
263         switch (mask) {
264         case IIO_CHAN_INFO_RAW:
265                 ret = zopt2201_read(data, chan->address);
266                 if (ret < 0)
267                         return ret;
268                 *val = ret;
269                 return IIO_VAL_INT;
270         case IIO_CHAN_INFO_PROCESSED:
271                 ret = zopt2201_read(data, ZOPT2201_UVB_DATA);
272                 if (ret < 0)
273                         return ret;
274                 *val = ret * 18 *
275                         (1 << (20 - zopt2201_resolution[data->res].bits)) /
276                         zopt2201_gain_uvb[data->gain].gain;
277                 return IIO_VAL_INT;
278         case IIO_CHAN_INFO_SCALE:
279                 switch (chan->address) {
280                 case ZOPT2201_ALS_DATA:
281                         *val = zopt2201_gain_als[data->gain].scale;
282                         break;
283                 case ZOPT2201_UVB_DATA:
284                         *val = zopt2201_gain_uvb[data->gain].scale;
285                         break;
286                 default:
287                         return -EINVAL;
288                 }
289
290                 *val2 = 1000000;
291                 *val2 *= (1 << (zopt2201_resolution[data->res].bits - 13));
292                 tmp = div_s64(*val * 1000000ULL, *val2);
293                 *val = div_s64_rem(tmp, 1000000, val2);
294
295                 return IIO_VAL_INT_PLUS_MICRO;
296         case IIO_CHAN_INFO_INT_TIME:
297                 *val = 0;
298                 *val2 = zopt2201_resolution[data->res].us;
299                 return IIO_VAL_INT_PLUS_MICRO;
300         default:
301                 return -EINVAL;
302         }
303 }
304
305 static int zopt2201_set_resolution(struct zopt2201_data *data, u8 res)
306 {
307         int ret;
308
309         ret = i2c_smbus_write_byte_data(data->client, ZOPT2201_LS_MEAS_RATE,
310                                         (res << ZOPT2201_MEAS_RES_SHIFT) |
311                                         data->rate);
312         if (ret < 0)
313                 return ret;
314
315         data->res = res;
316
317         return 0;
318 }
319
320 static int zopt2201_write_resolution(struct zopt2201_data *data,
321                                      int val, int val2)
322 {
323         int i, ret;
324
325         if (val != 0)
326                 return -EINVAL;
327
328         for (i = 0; i < ARRAY_SIZE(zopt2201_resolution); i++)
329                 if (val2 == zopt2201_resolution[i].us) {
330                         mutex_lock(&data->lock);
331                         ret = zopt2201_set_resolution(data, i);
332                         mutex_unlock(&data->lock);
333                         return ret;
334                 }
335
336         return -EINVAL;
337 }
338
339 static int zopt2201_set_gain(struct zopt2201_data *data, u8 gain)
340 {
341         int ret;
342
343         ret = i2c_smbus_write_byte_data(data->client, ZOPT2201_LS_GAIN, gain);
344         if (ret < 0)
345                 return ret;
346
347         data->gain = gain;
348
349         return 0;
350 }
351
352 static int zopt2201_write_scale_als_by_idx(struct zopt2201_data *data, int idx)
353 {
354         int ret;
355
356         mutex_lock(&data->lock);
357         ret = zopt2201_set_resolution(data, zopt2201_scale_als[idx].res);
358         if (ret < 0)
359                 goto unlock;
360
361         ret = zopt2201_set_gain(data, zopt2201_scale_als[idx].gain);
362
363 unlock:
364         mutex_unlock(&data->lock);
365         return ret;
366 }
367
368 static int zopt2201_write_scale_als(struct zopt2201_data *data,
369                                      int val, int val2)
370 {
371         int i;
372
373         for (i = 0; i < ARRAY_SIZE(zopt2201_scale_als); i++)
374                 if (val == zopt2201_scale_als[i].scale &&
375                     val2 == zopt2201_scale_als[i].uscale) {
376                         return zopt2201_write_scale_als_by_idx(data, i);
377                 }
378
379         return -EINVAL;
380 }
381
382 static int zopt2201_write_scale_uvb_by_idx(struct zopt2201_data *data, int idx)
383 {
384         int ret;
385
386         mutex_lock(&data->lock);
387         ret = zopt2201_set_resolution(data, zopt2201_scale_als[idx].res);
388         if (ret < 0)
389                 goto unlock;
390
391         ret = zopt2201_set_gain(data, zopt2201_scale_als[idx].gain);
392
393 unlock:
394         mutex_unlock(&data->lock);
395         return ret;
396 }
397
398 static int zopt2201_write_scale_uvb(struct zopt2201_data *data,
399                                      int val, int val2)
400 {
401         int i;
402
403         for (i = 0; i < ARRAY_SIZE(zopt2201_scale_uvb); i++)
404                 if (val == zopt2201_scale_uvb[i].scale &&
405                     val2 == zopt2201_scale_uvb[i].uscale)
406                         return zopt2201_write_scale_uvb_by_idx(data, i);
407
408         return -EINVAL;
409 }
410
411 static int zopt2201_write_raw(struct iio_dev *indio_dev,
412                               struct iio_chan_spec const *chan,
413                               int val, int val2, long mask)
414 {
415         struct zopt2201_data *data = iio_priv(indio_dev);
416
417         switch (mask) {
418         case IIO_CHAN_INFO_INT_TIME:
419                 return zopt2201_write_resolution(data, val, val2);
420         case IIO_CHAN_INFO_SCALE:
421                 switch (chan->address) {
422                 case ZOPT2201_ALS_DATA:
423                         return zopt2201_write_scale_als(data, val, val2);
424                 case ZOPT2201_UVB_DATA:
425                         return zopt2201_write_scale_uvb(data, val, val2);
426                 default:
427                         return -EINVAL;
428                 }
429         }
430
431         return -EINVAL;
432 }
433
434 static ssize_t zopt2201_show_int_time_available(struct device *dev,
435                                                 struct device_attribute *attr,
436                                                 char *buf)
437 {
438         size_t len = 0;
439         int i;
440
441         for (i = 0; i < ARRAY_SIZE(zopt2201_resolution); i++)
442                 len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06lu ",
443                                  zopt2201_resolution[i].us);
444         buf[len - 1] = '\n';
445
446         return len;
447 }
448
449 static IIO_DEV_ATTR_INT_TIME_AVAIL(zopt2201_show_int_time_available);
450
451 static ssize_t zopt2201_show_als_scale_avail(struct device *dev,
452                                              struct device_attribute *attr,
453                                              char *buf)
454 {
455         ssize_t len = 0;
456         int i;
457
458         for (i = 0; i < ARRAY_SIZE(zopt2201_scale_als); i++)
459                 len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06u ",
460                                  zopt2201_scale_als[i].scale,
461                                  zopt2201_scale_als[i].uscale);
462         buf[len - 1] = '\n';
463
464         return len;
465 }
466
467 static ssize_t zopt2201_show_uvb_scale_avail(struct device *dev,
468                                              struct device_attribute *attr,
469                                              char *buf)
470 {
471         ssize_t len = 0;
472         int i;
473
474         for (i = 0; i < ARRAY_SIZE(zopt2201_scale_uvb); i++)
475                 len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06u ",
476                                  zopt2201_scale_uvb[i].scale,
477                                  zopt2201_scale_uvb[i].uscale);
478         buf[len - 1] = '\n';
479
480         return len;
481 }
482
483 static IIO_DEVICE_ATTR(in_illuminance_scale_available, 0444,
484                        zopt2201_show_als_scale_avail, NULL, 0);
485 static IIO_DEVICE_ATTR(in_intensity_uv_scale_available, 0444,
486                        zopt2201_show_uvb_scale_avail, NULL, 0);
487
488 static struct attribute *zopt2201_attributes[] = {
489         &iio_dev_attr_integration_time_available.dev_attr.attr,
490         &iio_dev_attr_in_illuminance_scale_available.dev_attr.attr,
491         &iio_dev_attr_in_intensity_uv_scale_available.dev_attr.attr,
492         NULL
493 };
494
495 static const struct attribute_group zopt2201_attribute_group = {
496         .attrs = zopt2201_attributes,
497 };
498
499 static const struct iio_info zopt2201_info = {
500         .read_raw = zopt2201_read_raw,
501         .write_raw = zopt2201_write_raw,
502         .attrs = &zopt2201_attribute_group,
503 };
504
505 static int zopt2201_probe(struct i2c_client *client,
506                           const struct i2c_device_id *id)
507 {
508         struct zopt2201_data *data;
509         struct iio_dev *indio_dev;
510         int ret;
511
512         if (!i2c_check_functionality(client->adapter,
513                                      I2C_FUNC_SMBUS_READ_I2C_BLOCK))
514                 return -EOPNOTSUPP;
515
516         ret = i2c_smbus_read_byte_data(client, ZOPT2201_PART_ID);
517         if (ret < 0)
518                 return ret;
519         if (ret != ZOPT2201_PART_NUMBER)
520                 return -ENODEV;
521
522         indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
523         if (!indio_dev)
524                 return -ENOMEM;
525
526         data = iio_priv(indio_dev);
527         i2c_set_clientdata(client, indio_dev);
528         data->client = client;
529         mutex_init(&data->lock);
530
531         indio_dev->dev.parent = &client->dev;
532         indio_dev->info = &zopt2201_info;
533         indio_dev->channels = zopt2201_channels;
534         indio_dev->num_channels = ARRAY_SIZE(zopt2201_channels);
535         indio_dev->name = ZOPT2201_DRV_NAME;
536         indio_dev->modes = INDIO_DIRECT_MODE;
537
538         data->rate = ZOPT2201_MEAS_FREQ_100MS;
539         ret = zopt2201_set_resolution(data, ZOPT2201_MEAS_RES_18BIT);
540         if (ret < 0)
541                 return ret;
542
543         ret = zopt2201_set_gain(data, ZOPT2201_LS_GAIN_3);
544         if (ret < 0)
545                 return ret;
546
547         return devm_iio_device_register(&client->dev, indio_dev);
548 }
549
550 static const struct i2c_device_id zopt2201_id[] = {
551         { "zopt2201", 0 },
552         { }
553 };
554 MODULE_DEVICE_TABLE(i2c, zopt2201_id);
555
556 static struct i2c_driver zopt2201_driver = {
557         .driver = {
558                 .name   = ZOPT2201_DRV_NAME,
559         },
560         .probe  = zopt2201_probe,
561         .id_table = zopt2201_id,
562 };
563
564 module_i2c_driver(zopt2201_driver);
565
566 MODULE_AUTHOR("Peter Meerwald-Stadler <pmeerw@pmeerw.net>");
567 MODULE_DESCRIPTION("IDT ZOPT2201 ambient light and UV B sensor driver");
568 MODULE_LICENSE("GPL");