Merge tag 'iio-for-6.9a' of http://git.kernel.org/pub/scm/linux/kernel/git/jic23...
[linux-2.6-microblaze.git] / drivers / iio / light / hid-sensor-als.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * HID Sensors Driver
4  * Copyright (c) 2012, Intel Corporation.
5  */
6 #include <linux/device.h>
7 #include <linux/platform_device.h>
8 #include <linux/module.h>
9 #include <linux/mod_devicetable.h>
10 #include <linux/slab.h>
11 #include <linux/hid-sensor-hub.h>
12 #include <linux/iio/iio.h>
13 #include <linux/iio/buffer.h>
14 #include "../common/hid-sensors/hid-sensor-trigger.h"
15
16 enum {
17         CHANNEL_SCAN_INDEX_INTENSITY,
18         CHANNEL_SCAN_INDEX_ILLUM,
19         CHANNEL_SCAN_INDEX_COLOR_TEMP,
20         CHANNEL_SCAN_INDEX_CHROMATICITY_X,
21         CHANNEL_SCAN_INDEX_CHROMATICITY_Y,
22         CHANNEL_SCAN_INDEX_MAX
23 };
24
25 #define CHANNEL_SCAN_INDEX_TIMESTAMP CHANNEL_SCAN_INDEX_MAX
26
27 struct als_state {
28         struct hid_sensor_hub_callbacks callbacks;
29         struct hid_sensor_common common_attributes;
30         struct hid_sensor_hub_attribute_info als[CHANNEL_SCAN_INDEX_MAX];
31         struct iio_chan_spec channels[CHANNEL_SCAN_INDEX_MAX + 1];
32         struct {
33                 u32 illum[CHANNEL_SCAN_INDEX_MAX];
34                 u64 timestamp __aligned(8);
35         } scan;
36         int scale_pre_decml;
37         int scale_post_decml;
38         int scale_precision;
39         int value_offset;
40         int num_channels;
41         s64 timestamp;
42         unsigned long als_scan_mask[2];
43 };
44
45 /* The order of usage ids must match scan index starting from CHANNEL_SCAN_INDEX_INTENSITY */
46 static const u32 als_usage_ids[] = {
47         HID_USAGE_SENSOR_LIGHT_ILLUM,
48         HID_USAGE_SENSOR_LIGHT_ILLUM,
49         HID_USAGE_SENSOR_LIGHT_COLOR_TEMPERATURE,
50         HID_USAGE_SENSOR_LIGHT_CHROMATICITY_X,
51         HID_USAGE_SENSOR_LIGHT_CHROMATICITY_Y,
52 };
53
54 static const u32 als_sensitivity_addresses[] = {
55         HID_USAGE_SENSOR_DATA_LIGHT,
56         HID_USAGE_SENSOR_LIGHT_ILLUM,
57 };
58
59 /* Channel definitions */
60 static const struct iio_chan_spec als_channels[] = {
61         {
62                 .type = IIO_INTENSITY,
63                 .modified = 1,
64                 .channel2 = IIO_MOD_LIGHT_BOTH,
65                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
66                 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
67                 BIT(IIO_CHAN_INFO_SCALE) |
68                 BIT(IIO_CHAN_INFO_SAMP_FREQ) |
69                 BIT(IIO_CHAN_INFO_HYSTERESIS) |
70                 BIT(IIO_CHAN_INFO_HYSTERESIS_RELATIVE),
71                 .scan_index = CHANNEL_SCAN_INDEX_INTENSITY,
72         },
73         {
74                 .type = IIO_LIGHT,
75                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
76                 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
77                 BIT(IIO_CHAN_INFO_SCALE) |
78                 BIT(IIO_CHAN_INFO_SAMP_FREQ) |
79                 BIT(IIO_CHAN_INFO_HYSTERESIS) |
80                 BIT(IIO_CHAN_INFO_HYSTERESIS_RELATIVE),
81                 .scan_index = CHANNEL_SCAN_INDEX_ILLUM,
82         },
83         {
84                 .type = IIO_COLORTEMP,
85                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
86                 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
87                 BIT(IIO_CHAN_INFO_SCALE) |
88                 BIT(IIO_CHAN_INFO_SAMP_FREQ) |
89                 BIT(IIO_CHAN_INFO_HYSTERESIS) |
90                 BIT(IIO_CHAN_INFO_HYSTERESIS_RELATIVE),
91                 .scan_index = CHANNEL_SCAN_INDEX_COLOR_TEMP,
92         },
93         {
94                 .type = IIO_CHROMATICITY,
95                 .modified = 1,
96                 .channel2 = IIO_MOD_X,
97                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
98                 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
99                 BIT(IIO_CHAN_INFO_SCALE) |
100                 BIT(IIO_CHAN_INFO_SAMP_FREQ) |
101                 BIT(IIO_CHAN_INFO_HYSTERESIS) |
102                 BIT(IIO_CHAN_INFO_HYSTERESIS_RELATIVE),
103                 .scan_index = CHANNEL_SCAN_INDEX_CHROMATICITY_X,
104         },
105         {
106                 .type = IIO_CHROMATICITY,
107                 .modified = 1,
108                 .channel2 = IIO_MOD_Y,
109                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
110                 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
111                 BIT(IIO_CHAN_INFO_SCALE) |
112                 BIT(IIO_CHAN_INFO_SAMP_FREQ) |
113                 BIT(IIO_CHAN_INFO_HYSTERESIS) |
114                 BIT(IIO_CHAN_INFO_HYSTERESIS_RELATIVE),
115                 .scan_index = CHANNEL_SCAN_INDEX_CHROMATICITY_Y,
116         },
117         IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP)
118 };
119
120 /* Adjust channel real bits based on report descriptor */
121 static void als_adjust_channel_bit_mask(struct iio_chan_spec *channels,
122                                         int channel, int size)
123 {
124         channels[channel].scan_type.sign = 's';
125         /* Real storage bits will change based on the report desc. */
126         channels[channel].scan_type.realbits = size * 8;
127         /* Maximum size of a sample to capture is u32 */
128         channels[channel].scan_type.storagebits = sizeof(u32) * 8;
129 }
130
131 /* Channel read_raw handler */
132 static int als_read_raw(struct iio_dev *indio_dev,
133                               struct iio_chan_spec const *chan,
134                               int *val, int *val2,
135                               long mask)
136 {
137         struct als_state *als_state = iio_priv(indio_dev);
138         struct hid_sensor_hub_device *hsdev = als_state->common_attributes.hsdev;
139         int report_id = -1;
140         u32 address;
141         int ret_type;
142         s32 min;
143
144         *val = 0;
145         *val2 = 0;
146         switch (mask) {
147         case IIO_CHAN_INFO_RAW:
148                 switch (chan->scan_index) {
149                 case  CHANNEL_SCAN_INDEX_INTENSITY:
150                 case  CHANNEL_SCAN_INDEX_ILLUM:
151                         report_id = als_state->als[chan->scan_index].report_id;
152                         min = als_state->als[chan->scan_index].logical_minimum;
153                         address = HID_USAGE_SENSOR_LIGHT_ILLUM;
154                         break;
155                 case  CHANNEL_SCAN_INDEX_COLOR_TEMP:
156                         report_id = als_state->als[chan->scan_index].report_id;
157                         min = als_state->als[chan->scan_index].logical_minimum;
158                         address = HID_USAGE_SENSOR_LIGHT_COLOR_TEMPERATURE;
159                         break;
160                 case  CHANNEL_SCAN_INDEX_CHROMATICITY_X:
161                         report_id = als_state->als[chan->scan_index].report_id;
162                         min = als_state->als[chan->scan_index].logical_minimum;
163                         address = HID_USAGE_SENSOR_LIGHT_CHROMATICITY_X;
164                         break;
165                 case  CHANNEL_SCAN_INDEX_CHROMATICITY_Y:
166                         report_id = als_state->als[chan->scan_index].report_id;
167                         min = als_state->als[chan->scan_index].logical_minimum;
168                         address = HID_USAGE_SENSOR_LIGHT_CHROMATICITY_Y;
169                         break;
170                 default:
171                         report_id = -1;
172                         break;
173                 }
174                 if (report_id >= 0) {
175                         hid_sensor_power_state(&als_state->common_attributes,
176                                                 true);
177                         *val = sensor_hub_input_attr_get_raw_value(
178                                         hsdev, hsdev->usage, address, report_id,
179                                         SENSOR_HUB_SYNC, min < 0);
180                         hid_sensor_power_state(&als_state->common_attributes,
181                                                 false);
182                 } else {
183                         *val = 0;
184                         return -EINVAL;
185                 }
186                 ret_type = IIO_VAL_INT;
187                 break;
188         case IIO_CHAN_INFO_SCALE:
189                 *val = als_state->scale_pre_decml;
190                 *val2 = als_state->scale_post_decml;
191                 ret_type = als_state->scale_precision;
192                 break;
193         case IIO_CHAN_INFO_OFFSET:
194                 *val = als_state->value_offset;
195                 ret_type = IIO_VAL_INT;
196                 break;
197         case IIO_CHAN_INFO_SAMP_FREQ:
198                 ret_type = hid_sensor_read_samp_freq_value(
199                                 &als_state->common_attributes, val, val2);
200                 break;
201         case IIO_CHAN_INFO_HYSTERESIS:
202                 ret_type = hid_sensor_read_raw_hyst_value(
203                                 &als_state->common_attributes, val, val2);
204                 break;
205         case IIO_CHAN_INFO_HYSTERESIS_RELATIVE:
206                 ret_type = hid_sensor_read_raw_hyst_rel_value(
207                                 &als_state->common_attributes, val, val2);
208                 break;
209         default:
210                 ret_type = -EINVAL;
211                 break;
212         }
213
214         return ret_type;
215 }
216
217 /* Channel write_raw handler */
218 static int als_write_raw(struct iio_dev *indio_dev,
219                                struct iio_chan_spec const *chan,
220                                int val,
221                                int val2,
222                                long mask)
223 {
224         struct als_state *als_state = iio_priv(indio_dev);
225         int ret = 0;
226
227         switch (mask) {
228         case IIO_CHAN_INFO_SAMP_FREQ:
229                 ret = hid_sensor_write_samp_freq_value(
230                                 &als_state->common_attributes, val, val2);
231                 break;
232         case IIO_CHAN_INFO_HYSTERESIS:
233                 ret = hid_sensor_write_raw_hyst_value(
234                                 &als_state->common_attributes, val, val2);
235                 break;
236         case IIO_CHAN_INFO_HYSTERESIS_RELATIVE:
237                 ret = hid_sensor_write_raw_hyst_rel_value(
238                                 &als_state->common_attributes, val, val2);
239                 break;
240         default:
241                 ret = -EINVAL;
242         }
243
244         return ret;
245 }
246
247 static const struct iio_info als_info = {
248         .read_raw = &als_read_raw,
249         .write_raw = &als_write_raw,
250 };
251
252 /* Callback handler to send event after all samples are received and captured */
253 static int als_proc_event(struct hid_sensor_hub_device *hsdev,
254                                 unsigned usage_id,
255                                 void *priv)
256 {
257         struct iio_dev *indio_dev = platform_get_drvdata(priv);
258         struct als_state *als_state = iio_priv(indio_dev);
259
260         dev_dbg(&indio_dev->dev, "als_proc_event\n");
261         if (atomic_read(&als_state->common_attributes.data_ready)) {
262                 if (!als_state->timestamp)
263                         als_state->timestamp = iio_get_time_ns(indio_dev);
264
265                 iio_push_to_buffers_with_timestamp(indio_dev, &als_state->scan,
266                                                    als_state->timestamp);
267                 als_state->timestamp = 0;
268         }
269
270         return 0;
271 }
272
273 /* Capture samples in local storage */
274 static int als_capture_sample(struct hid_sensor_hub_device *hsdev,
275                                 unsigned usage_id,
276                                 size_t raw_len, char *raw_data,
277                                 void *priv)
278 {
279         struct iio_dev *indio_dev = platform_get_drvdata(priv);
280         struct als_state *als_state = iio_priv(indio_dev);
281         int ret = -EINVAL;
282         u32 sample_data = *(u32 *)raw_data;
283
284         switch (usage_id) {
285         case HID_USAGE_SENSOR_LIGHT_ILLUM:
286                 als_state->scan.illum[CHANNEL_SCAN_INDEX_INTENSITY] = sample_data;
287                 als_state->scan.illum[CHANNEL_SCAN_INDEX_ILLUM] = sample_data;
288                 ret = 0;
289                 break;
290         case HID_USAGE_SENSOR_LIGHT_COLOR_TEMPERATURE:
291                 als_state->scan.illum[CHANNEL_SCAN_INDEX_COLOR_TEMP] = sample_data;
292                 ret = 0;
293                 break;
294         case HID_USAGE_SENSOR_LIGHT_CHROMATICITY_X:
295                 als_state->scan.illum[CHANNEL_SCAN_INDEX_CHROMATICITY_X] = sample_data;
296                 ret = 0;
297                 break;
298         case HID_USAGE_SENSOR_LIGHT_CHROMATICITY_Y:
299                 als_state->scan.illum[CHANNEL_SCAN_INDEX_CHROMATICITY_Y] = sample_data;
300                 ret = 0;
301                 break;
302         case HID_USAGE_SENSOR_TIME_TIMESTAMP:
303                 als_state->timestamp = hid_sensor_convert_timestamp(&als_state->common_attributes,
304                                                                     *(s64 *)raw_data);
305                 ret = 0;
306                 break;
307         default:
308                 break;
309         }
310
311         return ret;
312 }
313
314 /* Parse report which is specific to an usage id*/
315 static int als_parse_report(struct platform_device *pdev,
316                                 struct hid_sensor_hub_device *hsdev,
317                                 unsigned usage_id,
318                                 struct als_state *st)
319 {
320         struct iio_chan_spec *channels;
321         int ret, index = 0;
322         int i;
323
324         channels = st->channels;
325
326         for (i = 0; i < CHANNEL_SCAN_INDEX_MAX; ++i) {
327                 ret = sensor_hub_input_get_attribute_info(hsdev,
328                                                 HID_INPUT_REPORT,
329                                                 usage_id,
330                                                 als_usage_ids[i],
331                                                 &st->als[i]);
332                 if (ret < 0)
333                         continue;
334
335                 channels[index] = als_channels[i];
336                 st->als_scan_mask[0] |= BIT(i);
337                 als_adjust_channel_bit_mask(channels, index, st->als[i].size);
338                 ++index;
339
340                 dev_dbg(&pdev->dev, "als %x:%x\n", st->als[i].index,
341                         st->als[i].report_id);
342         }
343
344         st->num_channels = index;
345         /* Return success even if one usage id is present */
346         if (index)
347                 ret = 0;
348
349         st->scale_precision = hid_sensor_format_scale(usage_id,
350                                 &st->als[CHANNEL_SCAN_INDEX_INTENSITY],
351                                 &st->scale_pre_decml, &st->scale_post_decml);
352
353         return ret;
354 }
355
356 /* Function to initialize the processing for usage id */
357 static int hid_als_probe(struct platform_device *pdev)
358 {
359         int ret = 0;
360         static const char *name = "als";
361         struct iio_dev *indio_dev;
362         struct als_state *als_state;
363         struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
364
365         indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct als_state));
366         if (!indio_dev)
367                 return -ENOMEM;
368         platform_set_drvdata(pdev, indio_dev);
369
370         als_state = iio_priv(indio_dev);
371         als_state->common_attributes.hsdev = hsdev;
372         als_state->common_attributes.pdev = pdev;
373
374         ret = hid_sensor_parse_common_attributes(hsdev,
375                                         hsdev->usage,
376                                         &als_state->common_attributes,
377                                         als_sensitivity_addresses,
378                                         ARRAY_SIZE(als_sensitivity_addresses));
379         if (ret) {
380                 dev_err(&pdev->dev, "failed to setup common attributes\n");
381                 return ret;
382         }
383
384         ret = als_parse_report(pdev, hsdev,
385                                hsdev->usage,
386                                als_state);
387         if (ret) {
388                 dev_err(&pdev->dev, "failed to setup attributes\n");
389                 return ret;
390         }
391
392         /* Add timestamp channel */
393         als_state->channels[als_state->num_channels] = als_channels[CHANNEL_SCAN_INDEX_TIMESTAMP];
394
395         /* +1 for adding timestamp channel */
396         indio_dev->num_channels = als_state->num_channels + 1;
397
398         indio_dev->channels = als_state->channels;
399         indio_dev->available_scan_masks = als_state->als_scan_mask;
400
401         indio_dev->info = &als_info;
402         indio_dev->name = name;
403         indio_dev->modes = INDIO_DIRECT_MODE;
404
405         atomic_set(&als_state->common_attributes.data_ready, 0);
406
407         ret = hid_sensor_setup_trigger(indio_dev, name,
408                                 &als_state->common_attributes);
409         if (ret < 0) {
410                 dev_err(&pdev->dev, "trigger setup failed\n");
411                 return ret;
412         }
413
414         ret = iio_device_register(indio_dev);
415         if (ret) {
416                 dev_err(&pdev->dev, "device register failed\n");
417                 goto error_remove_trigger;
418         }
419
420         als_state->callbacks.send_event = als_proc_event;
421         als_state->callbacks.capture_sample = als_capture_sample;
422         als_state->callbacks.pdev = pdev;
423         ret = sensor_hub_register_callback(hsdev, hsdev->usage, &als_state->callbacks);
424         if (ret < 0) {
425                 dev_err(&pdev->dev, "callback reg failed\n");
426                 goto error_iio_unreg;
427         }
428
429         return ret;
430
431 error_iio_unreg:
432         iio_device_unregister(indio_dev);
433 error_remove_trigger:
434         hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes);
435         return ret;
436 }
437
438 /* Function to deinitialize the processing for usage id */
439 static void hid_als_remove(struct platform_device *pdev)
440 {
441         struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
442         struct iio_dev *indio_dev = platform_get_drvdata(pdev);
443         struct als_state *als_state = iio_priv(indio_dev);
444
445         sensor_hub_remove_callback(hsdev, hsdev->usage);
446         iio_device_unregister(indio_dev);
447         hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes);
448 }
449
450 static const struct platform_device_id hid_als_ids[] = {
451         {
452                 /* Format: HID-SENSOR-usage_id_in_hex_lowercase */
453                 .name = "HID-SENSOR-200041",
454         },
455         {
456                 /* Format: HID-SENSOR-custom_sensor_tag-usage_id_in_hex_lowercase */
457                 .name = "HID-SENSOR-LISS-0041",
458         },
459         { /* sentinel */ }
460 };
461 MODULE_DEVICE_TABLE(platform, hid_als_ids);
462
463 static struct platform_driver hid_als_platform_driver = {
464         .id_table = hid_als_ids,
465         .driver = {
466                 .name   = KBUILD_MODNAME,
467                 .pm     = &hid_sensor_pm_ops,
468         },
469         .probe          = hid_als_probe,
470         .remove_new     = hid_als_remove,
471 };
472 module_platform_driver(hid_als_platform_driver);
473
474 MODULE_DESCRIPTION("HID Sensor ALS");
475 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
476 MODULE_LICENSE("GPL");
477 MODULE_IMPORT_NS(IIO_HID);