Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / iio / light / cm32181.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2013 Capella Microsystems Inc.
4  * Author: Kevin Tsai <ktsai@capellamicro.com>
5  */
6
7 #include <linux/delay.h>
8 #include <linux/err.h>
9 #include <linux/i2c.h>
10 #include <linux/mutex.h>
11 #include <linux/module.h>
12 #include <linux/interrupt.h>
13 #include <linux/regulator/consumer.h>
14 #include <linux/iio/iio.h>
15 #include <linux/iio/sysfs.h>
16 #include <linux/iio/events.h>
17 #include <linux/init.h>
18
19 /* Registers Address */
20 #define CM32181_REG_ADDR_CMD            0x00
21 #define CM32181_REG_ADDR_ALS            0x04
22 #define CM32181_REG_ADDR_STATUS         0x06
23 #define CM32181_REG_ADDR_ID             0x07
24
25 /* Number of Configurable Registers */
26 #define CM32181_CONF_REG_NUM            0x01
27
28 /* CMD register */
29 #define CM32181_CMD_ALS_ENABLE          0x00
30 #define CM32181_CMD_ALS_DISABLE         0x01
31 #define CM32181_CMD_ALS_INT_EN          0x02
32
33 #define CM32181_CMD_ALS_IT_SHIFT        6
34 #define CM32181_CMD_ALS_IT_MASK         (0x0F << CM32181_CMD_ALS_IT_SHIFT)
35 #define CM32181_CMD_ALS_IT_DEFAULT      (0x00 << CM32181_CMD_ALS_IT_SHIFT)
36
37 #define CM32181_CMD_ALS_SM_SHIFT        11
38 #define CM32181_CMD_ALS_SM_MASK         (0x03 << CM32181_CMD_ALS_SM_SHIFT)
39 #define CM32181_CMD_ALS_SM_DEFAULT      (0x01 << CM32181_CMD_ALS_SM_SHIFT)
40
41 #define CM32181_MLUX_PER_BIT            5       /* ALS_SM=01 IT=800ms */
42 #define CM32181_MLUX_PER_BIT_BASE_IT    800000  /* Based on IT=800ms */
43 #define CM32181_CALIBSCALE_DEFAULT      1000
44 #define CM32181_CALIBSCALE_RESOLUTION   1000
45 #define MLUX_PER_LUX                    1000
46
47 static const u8 cm32181_reg[CM32181_CONF_REG_NUM] = {
48         CM32181_REG_ADDR_CMD,
49 };
50
51 static const int als_it_bits[] = {12, 8, 0, 1, 2, 3};
52 static const int als_it_value[] = {25000, 50000, 100000, 200000, 400000,
53         800000};
54
55 struct cm32181_chip {
56         struct i2c_client *client;
57         struct mutex lock;
58         u16 conf_regs[CM32181_CONF_REG_NUM];
59         int calibscale;
60 };
61
62 /**
63  * cm32181_reg_init() - Initialize CM32181 registers
64  * @cm32181:    pointer of struct cm32181.
65  *
66  * Initialize CM32181 ambient light sensor register to default values.
67  *
68  * Return: 0 for success; otherwise for error code.
69  */
70 static int cm32181_reg_init(struct cm32181_chip *cm32181)
71 {
72         struct i2c_client *client = cm32181->client;
73         int i;
74         s32 ret;
75
76         ret = i2c_smbus_read_word_data(client, CM32181_REG_ADDR_ID);
77         if (ret < 0)
78                 return ret;
79
80         /* check device ID */
81         if ((ret & 0xFF) != 0x81)
82                 return -ENODEV;
83
84         /* Default Values */
85         cm32181->conf_regs[CM32181_REG_ADDR_CMD] = CM32181_CMD_ALS_ENABLE |
86                         CM32181_CMD_ALS_IT_DEFAULT | CM32181_CMD_ALS_SM_DEFAULT;
87         cm32181->calibscale = CM32181_CALIBSCALE_DEFAULT;
88
89         /* Initialize registers*/
90         for (i = 0; i < CM32181_CONF_REG_NUM; i++) {
91                 ret = i2c_smbus_write_word_data(client, cm32181_reg[i],
92                         cm32181->conf_regs[i]);
93                 if (ret < 0)
94                         return ret;
95         }
96
97         return 0;
98 }
99
100 /**
101  *  cm32181_read_als_it() - Get sensor integration time (ms)
102  *  @cm32181:   pointer of struct cm32181
103  *  @val2:      pointer of int to load the als_it value.
104  *
105  *  Report the current integartion time by millisecond.
106  *
107  *  Return: IIO_VAL_INT_PLUS_MICRO for success, otherwise -EINVAL.
108  */
109 static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val2)
110 {
111         u16 als_it;
112         int i;
113
114         als_it = cm32181->conf_regs[CM32181_REG_ADDR_CMD];
115         als_it &= CM32181_CMD_ALS_IT_MASK;
116         als_it >>= CM32181_CMD_ALS_IT_SHIFT;
117         for (i = 0; i < ARRAY_SIZE(als_it_bits); i++) {
118                 if (als_it == als_it_bits[i]) {
119                         *val2 = als_it_value[i];
120                         return IIO_VAL_INT_PLUS_MICRO;
121                 }
122         }
123
124         return -EINVAL;
125 }
126
127 /**
128  * cm32181_write_als_it() - Write sensor integration time
129  * @cm32181:    pointer of struct cm32181.
130  * @val:        integration time by millisecond.
131  *
132  * Convert integration time (ms) to sensor value.
133  *
134  * Return: i2c_smbus_write_word_data command return value.
135  */
136 static int cm32181_write_als_it(struct cm32181_chip *cm32181, int val)
137 {
138         struct i2c_client *client = cm32181->client;
139         u16 als_it;
140         int ret, i, n;
141
142         n = ARRAY_SIZE(als_it_value);
143         for (i = 0; i < n; i++)
144                 if (val <= als_it_value[i])
145                         break;
146         if (i >= n)
147                 i = n - 1;
148
149         als_it = als_it_bits[i];
150         als_it <<= CM32181_CMD_ALS_IT_SHIFT;
151
152         mutex_lock(&cm32181->lock);
153         cm32181->conf_regs[CM32181_REG_ADDR_CMD] &=
154                 ~CM32181_CMD_ALS_IT_MASK;
155         cm32181->conf_regs[CM32181_REG_ADDR_CMD] |=
156                 als_it;
157         ret = i2c_smbus_write_word_data(client, CM32181_REG_ADDR_CMD,
158                         cm32181->conf_regs[CM32181_REG_ADDR_CMD]);
159         mutex_unlock(&cm32181->lock);
160
161         return ret;
162 }
163
164 /**
165  * cm32181_get_lux() - report current lux value
166  * @cm32181:    pointer of struct cm32181.
167  *
168  * Convert sensor raw data to lux.  It depends on integration
169  * time and calibscale variable.
170  *
171  * Return: Positive value is lux, otherwise is error code.
172  */
173 static int cm32181_get_lux(struct cm32181_chip *cm32181)
174 {
175         struct i2c_client *client = cm32181->client;
176         int ret;
177         int als_it;
178         unsigned long lux;
179
180         ret = cm32181_read_als_it(cm32181, &als_it);
181         if (ret < 0)
182                 return -EINVAL;
183
184         lux = CM32181_MLUX_PER_BIT;
185         lux *= CM32181_MLUX_PER_BIT_BASE_IT;
186         lux /= als_it;
187
188         ret = i2c_smbus_read_word_data(client, CM32181_REG_ADDR_ALS);
189         if (ret < 0)
190                 return ret;
191
192         lux *= ret;
193         lux *= cm32181->calibscale;
194         lux /= CM32181_CALIBSCALE_RESOLUTION;
195         lux /= MLUX_PER_LUX;
196
197         if (lux > 0xFFFF)
198                 lux = 0xFFFF;
199
200         return lux;
201 }
202
203 static int cm32181_read_raw(struct iio_dev *indio_dev,
204                             struct iio_chan_spec const *chan,
205                             int *val, int *val2, long mask)
206 {
207         struct cm32181_chip *cm32181 = iio_priv(indio_dev);
208         int ret;
209
210         switch (mask) {
211         case IIO_CHAN_INFO_PROCESSED:
212                 ret = cm32181_get_lux(cm32181);
213                 if (ret < 0)
214                         return ret;
215                 *val = ret;
216                 return IIO_VAL_INT;
217         case IIO_CHAN_INFO_CALIBSCALE:
218                 *val = cm32181->calibscale;
219                 return IIO_VAL_INT;
220         case IIO_CHAN_INFO_INT_TIME:
221                 *val = 0;
222                 ret = cm32181_read_als_it(cm32181, val2);
223                 return ret;
224         }
225
226         return -EINVAL;
227 }
228
229 static int cm32181_write_raw(struct iio_dev *indio_dev,
230                              struct iio_chan_spec const *chan,
231                              int val, int val2, long mask)
232 {
233         struct cm32181_chip *cm32181 = iio_priv(indio_dev);
234         int ret;
235
236         switch (mask) {
237         case IIO_CHAN_INFO_CALIBSCALE:
238                 cm32181->calibscale = val;
239                 return val;
240         case IIO_CHAN_INFO_INT_TIME:
241                 ret = cm32181_write_als_it(cm32181, val2);
242                 return ret;
243         }
244
245         return -EINVAL;
246 }
247
248 /**
249  * cm32181_get_it_available() - Get available ALS IT value
250  * @dev:        pointer of struct device.
251  * @attr:       pointer of struct device_attribute.
252  * @buf:        pointer of return string buffer.
253  *
254  * Display the available integration time values by millisecond.
255  *
256  * Return: string length.
257  */
258 static ssize_t cm32181_get_it_available(struct device *dev,
259                         struct device_attribute *attr, char *buf)
260 {
261         int i, n, len;
262
263         n = ARRAY_SIZE(als_it_value);
264         for (i = 0, len = 0; i < n; i++)
265                 len += sprintf(buf + len, "0.%06u ", als_it_value[i]);
266         return len + sprintf(buf + len, "\n");
267 }
268
269 static const struct iio_chan_spec cm32181_channels[] = {
270         {
271                 .type = IIO_LIGHT,
272                 .info_mask_separate =
273                         BIT(IIO_CHAN_INFO_PROCESSED) |
274                         BIT(IIO_CHAN_INFO_CALIBSCALE) |
275                         BIT(IIO_CHAN_INFO_INT_TIME),
276         }
277 };
278
279 static IIO_DEVICE_ATTR(in_illuminance_integration_time_available,
280                         S_IRUGO, cm32181_get_it_available, NULL, 0);
281
282 static struct attribute *cm32181_attributes[] = {
283         &iio_dev_attr_in_illuminance_integration_time_available.dev_attr.attr,
284         NULL,
285 };
286
287 static const struct attribute_group cm32181_attribute_group = {
288         .attrs = cm32181_attributes
289 };
290
291 static const struct iio_info cm32181_info = {
292         .read_raw               = &cm32181_read_raw,
293         .write_raw              = &cm32181_write_raw,
294         .attrs                  = &cm32181_attribute_group,
295 };
296
297 static int cm32181_probe(struct i2c_client *client,
298                         const struct i2c_device_id *id)
299 {
300         struct cm32181_chip *cm32181;
301         struct iio_dev *indio_dev;
302         int ret;
303
304         indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*cm32181));
305         if (!indio_dev) {
306                 dev_err(&client->dev, "devm_iio_device_alloc failed\n");
307                 return -ENOMEM;
308         }
309
310         cm32181 = iio_priv(indio_dev);
311         i2c_set_clientdata(client, indio_dev);
312         cm32181->client = client;
313
314         mutex_init(&cm32181->lock);
315         indio_dev->dev.parent = &client->dev;
316         indio_dev->channels = cm32181_channels;
317         indio_dev->num_channels = ARRAY_SIZE(cm32181_channels);
318         indio_dev->info = &cm32181_info;
319         indio_dev->name = id->name;
320         indio_dev->modes = INDIO_DIRECT_MODE;
321
322         ret = cm32181_reg_init(cm32181);
323         if (ret) {
324                 dev_err(&client->dev,
325                         "%s: register init failed\n",
326                         __func__);
327                 return ret;
328         }
329
330         ret = devm_iio_device_register(&client->dev, indio_dev);
331         if (ret) {
332                 dev_err(&client->dev,
333                         "%s: regist device failed\n",
334                         __func__);
335                 return ret;
336         }
337
338         return 0;
339 }
340
341 static const struct i2c_device_id cm32181_id[] = {
342         { "cm32181", 0 },
343         { }
344 };
345
346 MODULE_DEVICE_TABLE(i2c, cm32181_id);
347
348 static const struct of_device_id cm32181_of_match[] = {
349         { .compatible = "capella,cm32181" },
350         { }
351 };
352 MODULE_DEVICE_TABLE(of, cm32181_of_match);
353
354 static struct i2c_driver cm32181_driver = {
355         .driver = {
356                 .name   = "cm32181",
357                 .of_match_table = of_match_ptr(cm32181_of_match),
358         },
359         .id_table       = cm32181_id,
360         .probe          = cm32181_probe,
361 };
362
363 module_i2c_driver(cm32181_driver);
364
365 MODULE_AUTHOR("Kevin Tsai <ktsai@capellamicro.com>");
366 MODULE_DESCRIPTION("CM32181 ambient light sensor driver");
367 MODULE_LICENSE("GPL");