1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (c) 2012, Intel Corporation.
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"
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
25 #define CHANNEL_SCAN_INDEX_TIMESTAMP CHANNEL_SCAN_INDEX_MAX
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];
33 u32 illum
[CHANNEL_SCAN_INDEX_MAX
];
34 aligned_s64 timestamp
;
42 unsigned long als_scan_mask
[2];
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
,
54 static const u32 als_sensitivity_addresses
[] = {
55 HID_USAGE_SENSOR_DATA_LIGHT
,
56 HID_USAGE_SENSOR_LIGHT_ILLUM
,
59 /* Channel definitions */
60 static const struct iio_chan_spec als_channels
[] = {
62 .type
= IIO_INTENSITY
,
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
,
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
,
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
,
94 .type
= IIO_CHROMATICITY
,
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
,
106 .type
= IIO_CHROMATICITY
,
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
,
117 IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP
)
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
)
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;
131 /* Channel read_raw handler */
132 static int als_read_raw(struct iio_dev
*indio_dev
,
133 struct iio_chan_spec
const *chan
,
137 struct als_state
*als_state
= iio_priv(indio_dev
);
138 struct hid_sensor_hub_device
*hsdev
= als_state
->common_attributes
.hsdev
;
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
;
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
;
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
;
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
;
174 if (report_id
>= 0) {
175 hid_sensor_power_state(&als_state
->common_attributes
,
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
,
186 ret_type
= IIO_VAL_INT
;
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
;
193 case IIO_CHAN_INFO_OFFSET
:
194 *val
= als_state
->value_offset
;
195 ret_type
= IIO_VAL_INT
;
197 case IIO_CHAN_INFO_SAMP_FREQ
:
198 ret_type
= hid_sensor_read_samp_freq_value(
199 &als_state
->common_attributes
, val
, val2
);
201 case IIO_CHAN_INFO_HYSTERESIS
:
202 ret_type
= hid_sensor_read_raw_hyst_value(
203 &als_state
->common_attributes
, val
, val2
);
205 case IIO_CHAN_INFO_HYSTERESIS_RELATIVE
:
206 ret_type
= hid_sensor_read_raw_hyst_rel_value(
207 &als_state
->common_attributes
, val
, val2
);
217 /* Channel write_raw handler */
218 static int als_write_raw(struct iio_dev
*indio_dev
,
219 struct iio_chan_spec
const *chan
,
224 struct als_state
*als_state
= iio_priv(indio_dev
);
228 case IIO_CHAN_INFO_SAMP_FREQ
:
229 ret
= hid_sensor_write_samp_freq_value(
230 &als_state
->common_attributes
, val
, val2
);
232 case IIO_CHAN_INFO_HYSTERESIS
:
233 ret
= hid_sensor_write_raw_hyst_value(
234 &als_state
->common_attributes
, val
, val2
);
236 case IIO_CHAN_INFO_HYSTERESIS_RELATIVE
:
237 ret
= hid_sensor_write_raw_hyst_rel_value(
238 &als_state
->common_attributes
, val
, val2
);
247 static const struct iio_info als_info
= {
248 .read_raw
= &als_read_raw
,
249 .write_raw
= &als_write_raw
,
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
,
257 struct iio_dev
*indio_dev
= platform_get_drvdata(priv
);
258 struct als_state
*als_state
= iio_priv(indio_dev
);
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
);
265 iio_push_to_buffers_with_timestamp(indio_dev
, &als_state
->scan
,
266 als_state
->timestamp
);
267 als_state
->timestamp
= 0;
273 /* Capture samples in local storage */
274 static int als_capture_sample(struct hid_sensor_hub_device
*hsdev
,
276 size_t raw_len
, char *raw_data
,
279 struct iio_dev
*indio_dev
= platform_get_drvdata(priv
);
280 struct als_state
*als_state
= iio_priv(indio_dev
);
282 u32 sample_data
= *(u32
*)raw_data
;
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
;
290 case HID_USAGE_SENSOR_LIGHT_COLOR_TEMPERATURE
:
291 als_state
->scan
.illum
[CHANNEL_SCAN_INDEX_COLOR_TEMP
] = sample_data
;
294 case HID_USAGE_SENSOR_LIGHT_CHROMATICITY_X
:
295 als_state
->scan
.illum
[CHANNEL_SCAN_INDEX_CHROMATICITY_X
] = sample_data
;
298 case HID_USAGE_SENSOR_LIGHT_CHROMATICITY_Y
:
299 als_state
->scan
.illum
[CHANNEL_SCAN_INDEX_CHROMATICITY_Y
] = sample_data
;
302 case HID_USAGE_SENSOR_TIME_TIMESTAMP
:
303 als_state
->timestamp
= hid_sensor_convert_timestamp(&als_state
->common_attributes
,
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
,
318 struct als_state
*st
)
320 struct iio_chan_spec
*channels
;
324 channels
= st
->channels
;
326 for (i
= 0; i
< CHANNEL_SCAN_INDEX_MAX
; ++i
) {
327 ret
= sensor_hub_input_get_attribute_info(hsdev
,
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
);
340 dev_dbg(&pdev
->dev
, "als %x:%x\n", st
->als
[i
].index
,
341 st
->als
[i
].report_id
);
344 st
->num_channels
= index
;
345 /* Return success even if one usage id is present */
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
);
356 /* Function to initialize the processing for usage id */
357 static int hid_als_probe(struct platform_device
*pdev
)
359 struct hid_sensor_hub_device
*hsdev
= dev_get_platdata(&pdev
->dev
);
361 static const char *name
= "als";
362 struct iio_dev
*indio_dev
;
363 struct als_state
*als_state
;
365 indio_dev
= devm_iio_device_alloc(&pdev
->dev
, sizeof(struct als_state
));
368 platform_set_drvdata(pdev
, indio_dev
);
370 als_state
= iio_priv(indio_dev
);
371 als_state
->common_attributes
.hsdev
= hsdev
;
372 als_state
->common_attributes
.pdev
= pdev
;
374 ret
= hid_sensor_parse_common_attributes(hsdev
,
376 &als_state
->common_attributes
,
377 als_sensitivity_addresses
,
378 ARRAY_SIZE(als_sensitivity_addresses
));
380 dev_err(&pdev
->dev
, "failed to setup common attributes\n");
384 ret
= als_parse_report(pdev
, hsdev
,
388 dev_err(&pdev
->dev
, "failed to setup attributes\n");
392 /* Add timestamp channel */
393 als_state
->channels
[als_state
->num_channels
] = als_channels
[CHANNEL_SCAN_INDEX_TIMESTAMP
];
395 /* +1 for adding timestamp channel */
396 indio_dev
->num_channels
= als_state
->num_channels
+ 1;
398 indio_dev
->channels
= als_state
->channels
;
399 indio_dev
->available_scan_masks
= als_state
->als_scan_mask
;
401 indio_dev
->info
= &als_info
;
402 indio_dev
->name
= name
;
403 indio_dev
->modes
= INDIO_DIRECT_MODE
;
405 atomic_set(&als_state
->common_attributes
.data_ready
, 0);
407 ret
= hid_sensor_setup_trigger(indio_dev
, name
,
408 &als_state
->common_attributes
);
410 dev_err(&pdev
->dev
, "trigger setup failed\n");
414 ret
= iio_device_register(indio_dev
);
416 dev_err(&pdev
->dev
, "device register failed\n");
417 goto error_remove_trigger
;
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
);
425 dev_err(&pdev
->dev
, "callback reg failed\n");
426 goto error_iio_unreg
;
432 iio_device_unregister(indio_dev
);
433 error_remove_trigger
:
434 hid_sensor_remove_trigger(indio_dev
, &als_state
->common_attributes
);
438 /* Function to deinitialize the processing for usage id */
439 static void hid_als_remove(struct platform_device
*pdev
)
441 struct hid_sensor_hub_device
*hsdev
= dev_get_platdata(&pdev
->dev
);
442 struct iio_dev
*indio_dev
= platform_get_drvdata(pdev
);
443 struct als_state
*als_state
= iio_priv(indio_dev
);
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
);
450 static const struct platform_device_id hid_als_ids
[] = {
452 /* Format: HID-SENSOR-usage_id_in_hex_lowercase */
453 .name
= "HID-SENSOR-200041",
456 /* Format: HID-SENSOR-custom_sensor_tag-usage_id_in_hex_lowercase */
457 .name
= "HID-SENSOR-LISS-0041",
461 MODULE_DEVICE_TABLE(platform
, hid_als_ids
);
463 static struct platform_driver hid_als_platform_driver
= {
464 .id_table
= hid_als_ids
,
466 .name
= KBUILD_MODNAME
,
467 .pm
= &hid_sensor_pm_ops
,
469 .probe
= hid_als_probe
,
470 .remove
= hid_als_remove
,
472 module_platform_driver(hid_als_platform_driver
);
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");