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/interrupt.h> 10 #include <linux/irq.h> 11 #include <linux/slab.h> 12 #include <linux/delay.h> 13 #include <linux/hid-sensor-hub.h> 14 #include <linux/iio/iio.h> 15 #include <linux/iio/sysfs.h> 16 #include <linux/iio/buffer.h> 17 #include "../common/hid-sensors/hid-sensor-trigger.h" 18 19 enum { 20 CHANNEL_SCAN_INDEX_INTENSITY = 0, 21 CHANNEL_SCAN_INDEX_ILLUM = 1, 22 CHANNEL_SCAN_INDEX_MAX 23 }; 24 25 struct als_state { 26 struct hid_sensor_hub_callbacks callbacks; 27 struct hid_sensor_common common_attributes; 28 struct hid_sensor_hub_attribute_info als_illum; 29 u32 illum[CHANNEL_SCAN_INDEX_MAX]; 30 int scale_pre_decml; 31 int scale_post_decml; 32 int scale_precision; 33 int value_offset; 34 }; 35 36 /* Channel definitions */ 37 static const struct iio_chan_spec als_channels[] = { 38 { 39 .type = IIO_INTENSITY, 40 .modified = 1, 41 .channel2 = IIO_MOD_LIGHT_BOTH, 42 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 43 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 44 BIT(IIO_CHAN_INFO_SCALE) | 45 BIT(IIO_CHAN_INFO_SAMP_FREQ) | 46 BIT(IIO_CHAN_INFO_HYSTERESIS), 47 .scan_index = CHANNEL_SCAN_INDEX_INTENSITY, 48 }, 49 { 50 .type = IIO_LIGHT, 51 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 52 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 53 BIT(IIO_CHAN_INFO_SCALE) | 54 BIT(IIO_CHAN_INFO_SAMP_FREQ) | 55 BIT(IIO_CHAN_INFO_HYSTERESIS), 56 .scan_index = CHANNEL_SCAN_INDEX_ILLUM, 57 } 58 }; 59 60 /* Adjust channel real bits based on report descriptor */ 61 static void als_adjust_channel_bit_mask(struct iio_chan_spec *channels, 62 int channel, int size) 63 { 64 channels[channel].scan_type.sign = 's'; 65 /* Real storage bits will change based on the report desc. */ 66 channels[channel].scan_type.realbits = size * 8; 67 /* Maximum size of a sample to capture is u32 */ 68 channels[channel].scan_type.storagebits = sizeof(u32) * 8; 69 } 70 71 /* Channel read_raw handler */ 72 static int als_read_raw(struct iio_dev *indio_dev, 73 struct iio_chan_spec const *chan, 74 int *val, int *val2, 75 long mask) 76 { 77 struct als_state *als_state = iio_priv(indio_dev); 78 int report_id = -1; 79 u32 address; 80 int ret_type; 81 s32 min; 82 83 *val = 0; 84 *val2 = 0; 85 switch (mask) { 86 case IIO_CHAN_INFO_RAW: 87 switch (chan->scan_index) { 88 case CHANNEL_SCAN_INDEX_INTENSITY: 89 case CHANNEL_SCAN_INDEX_ILLUM: 90 report_id = als_state->als_illum.report_id; 91 min = als_state->als_illum.logical_minimum; 92 address = HID_USAGE_SENSOR_LIGHT_ILLUM; 93 break; 94 default: 95 report_id = -1; 96 break; 97 } 98 if (report_id >= 0) { 99 hid_sensor_power_state(&als_state->common_attributes, 100 true); 101 *val = sensor_hub_input_attr_get_raw_value( 102 als_state->common_attributes.hsdev, 103 HID_USAGE_SENSOR_ALS, address, 104 report_id, 105 SENSOR_HUB_SYNC, 106 min < 0); 107 hid_sensor_power_state(&als_state->common_attributes, 108 false); 109 } else { 110 *val = 0; 111 return -EINVAL; 112 } 113 ret_type = IIO_VAL_INT; 114 break; 115 case IIO_CHAN_INFO_SCALE: 116 *val = als_state->scale_pre_decml; 117 *val2 = als_state->scale_post_decml; 118 ret_type = als_state->scale_precision; 119 break; 120 case IIO_CHAN_INFO_OFFSET: 121 *val = als_state->value_offset; 122 ret_type = IIO_VAL_INT; 123 break; 124 case IIO_CHAN_INFO_SAMP_FREQ: 125 ret_type = hid_sensor_read_samp_freq_value( 126 &als_state->common_attributes, val, val2); 127 break; 128 case IIO_CHAN_INFO_HYSTERESIS: 129 ret_type = hid_sensor_read_raw_hyst_value( 130 &als_state->common_attributes, val, val2); 131 break; 132 default: 133 ret_type = -EINVAL; 134 break; 135 } 136 137 return ret_type; 138 } 139 140 /* Channel write_raw handler */ 141 static int als_write_raw(struct iio_dev *indio_dev, 142 struct iio_chan_spec const *chan, 143 int val, 144 int val2, 145 long mask) 146 { 147 struct als_state *als_state = iio_priv(indio_dev); 148 int ret = 0; 149 150 switch (mask) { 151 case IIO_CHAN_INFO_SAMP_FREQ: 152 ret = hid_sensor_write_samp_freq_value( 153 &als_state->common_attributes, val, val2); 154 break; 155 case IIO_CHAN_INFO_HYSTERESIS: 156 ret = hid_sensor_write_raw_hyst_value( 157 &als_state->common_attributes, val, val2); 158 break; 159 default: 160 ret = -EINVAL; 161 } 162 163 return ret; 164 } 165 166 static const struct iio_info als_info = { 167 .read_raw = &als_read_raw, 168 .write_raw = &als_write_raw, 169 }; 170 171 /* Function to push data to buffer */ 172 static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data, 173 int len) 174 { 175 dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); 176 iio_push_to_buffers(indio_dev, data); 177 } 178 179 /* Callback handler to send event after all samples are received and captured */ 180 static int als_proc_event(struct hid_sensor_hub_device *hsdev, 181 unsigned usage_id, 182 void *priv) 183 { 184 struct iio_dev *indio_dev = platform_get_drvdata(priv); 185 struct als_state *als_state = iio_priv(indio_dev); 186 187 dev_dbg(&indio_dev->dev, "als_proc_event\n"); 188 if (atomic_read(&als_state->common_attributes.data_ready)) 189 hid_sensor_push_data(indio_dev, 190 &als_state->illum, 191 sizeof(als_state->illum)); 192 193 return 0; 194 } 195 196 /* Capture samples in local storage */ 197 static int als_capture_sample(struct hid_sensor_hub_device *hsdev, 198 unsigned usage_id, 199 size_t raw_len, char *raw_data, 200 void *priv) 201 { 202 struct iio_dev *indio_dev = platform_get_drvdata(priv); 203 struct als_state *als_state = iio_priv(indio_dev); 204 int ret = -EINVAL; 205 u32 sample_data = *(u32 *)raw_data; 206 207 switch (usage_id) { 208 case HID_USAGE_SENSOR_LIGHT_ILLUM: 209 als_state->illum[CHANNEL_SCAN_INDEX_INTENSITY] = sample_data; 210 als_state->illum[CHANNEL_SCAN_INDEX_ILLUM] = sample_data; 211 ret = 0; 212 break; 213 default: 214 break; 215 } 216 217 return ret; 218 } 219 220 /* Parse report which is specific to an usage id*/ 221 static int als_parse_report(struct platform_device *pdev, 222 struct hid_sensor_hub_device *hsdev, 223 struct iio_chan_spec *channels, 224 unsigned usage_id, 225 struct als_state *st) 226 { 227 int ret; 228 229 ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT, 230 usage_id, 231 HID_USAGE_SENSOR_LIGHT_ILLUM, 232 &st->als_illum); 233 if (ret < 0) 234 return ret; 235 als_adjust_channel_bit_mask(channels, CHANNEL_SCAN_INDEX_INTENSITY, 236 st->als_illum.size); 237 als_adjust_channel_bit_mask(channels, CHANNEL_SCAN_INDEX_ILLUM, 238 st->als_illum.size); 239 240 dev_dbg(&pdev->dev, "als %x:%x\n", st->als_illum.index, 241 st->als_illum.report_id); 242 243 st->scale_precision = hid_sensor_format_scale( 244 HID_USAGE_SENSOR_ALS, 245 &st->als_illum, 246 &st->scale_pre_decml, &st->scale_post_decml); 247 248 /* Set Sensitivity field ids, when there is no individual modifier */ 249 if (st->common_attributes.sensitivity.index < 0) { 250 sensor_hub_input_get_attribute_info(hsdev, 251 HID_FEATURE_REPORT, usage_id, 252 HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS | 253 HID_USAGE_SENSOR_DATA_LIGHT, 254 &st->common_attributes.sensitivity); 255 dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n", 256 st->common_attributes.sensitivity.index, 257 st->common_attributes.sensitivity.report_id); 258 } 259 return ret; 260 } 261 262 /* Function to initialize the processing for usage id */ 263 static int hid_als_probe(struct platform_device *pdev) 264 { 265 int ret = 0; 266 static const char *name = "als"; 267 struct iio_dev *indio_dev; 268 struct als_state *als_state; 269 struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; 270 271 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct als_state)); 272 if (!indio_dev) 273 return -ENOMEM; 274 platform_set_drvdata(pdev, indio_dev); 275 276 als_state = iio_priv(indio_dev); 277 als_state->common_attributes.hsdev = hsdev; 278 als_state->common_attributes.pdev = pdev; 279 280 ret = hid_sensor_parse_common_attributes(hsdev, HID_USAGE_SENSOR_ALS, 281 &als_state->common_attributes); 282 if (ret) { 283 dev_err(&pdev->dev, "failed to setup common attributes\n"); 284 return ret; 285 } 286 287 indio_dev->channels = kmemdup(als_channels, 288 sizeof(als_channels), GFP_KERNEL); 289 if (!indio_dev->channels) { 290 dev_err(&pdev->dev, "failed to duplicate channels\n"); 291 return -ENOMEM; 292 } 293 294 ret = als_parse_report(pdev, hsdev, 295 (struct iio_chan_spec *)indio_dev->channels, 296 HID_USAGE_SENSOR_ALS, als_state); 297 if (ret) { 298 dev_err(&pdev->dev, "failed to setup attributes\n"); 299 goto error_free_dev_mem; 300 } 301 302 indio_dev->num_channels = 303 ARRAY_SIZE(als_channels); 304 indio_dev->dev.parent = &pdev->dev; 305 indio_dev->info = &als_info; 306 indio_dev->name = name; 307 indio_dev->modes = INDIO_DIRECT_MODE; 308 309 atomic_set(&als_state->common_attributes.data_ready, 0); 310 311 ret = hid_sensor_setup_trigger(indio_dev, name, 312 &als_state->common_attributes); 313 if (ret < 0) { 314 dev_err(&pdev->dev, "trigger setup failed\n"); 315 goto error_free_dev_mem; 316 } 317 318 ret = iio_device_register(indio_dev); 319 if (ret) { 320 dev_err(&pdev->dev, "device register failed\n"); 321 goto error_remove_trigger; 322 } 323 324 als_state->callbacks.send_event = als_proc_event; 325 als_state->callbacks.capture_sample = als_capture_sample; 326 als_state->callbacks.pdev = pdev; 327 ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_ALS, 328 &als_state->callbacks); 329 if (ret < 0) { 330 dev_err(&pdev->dev, "callback reg failed\n"); 331 goto error_iio_unreg; 332 } 333 334 return ret; 335 336 error_iio_unreg: 337 iio_device_unregister(indio_dev); 338 error_remove_trigger: 339 hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes); 340 error_free_dev_mem: 341 kfree(indio_dev->channels); 342 return ret; 343 } 344 345 /* Function to deinitialize the processing for usage id */ 346 static int hid_als_remove(struct platform_device *pdev) 347 { 348 struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; 349 struct iio_dev *indio_dev = platform_get_drvdata(pdev); 350 struct als_state *als_state = iio_priv(indio_dev); 351 352 sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_ALS); 353 iio_device_unregister(indio_dev); 354 hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes); 355 kfree(indio_dev->channels); 356 357 return 0; 358 } 359 360 static const struct platform_device_id hid_als_ids[] = { 361 { 362 /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ 363 .name = "HID-SENSOR-200041", 364 }, 365 { /* sentinel */ } 366 }; 367 MODULE_DEVICE_TABLE(platform, hid_als_ids); 368 369 static struct platform_driver hid_als_platform_driver = { 370 .id_table = hid_als_ids, 371 .driver = { 372 .name = KBUILD_MODNAME, 373 .pm = &hid_sensor_pm_ops, 374 }, 375 .probe = hid_als_probe, 376 .remove = hid_als_remove, 377 }; 378 module_platform_driver(hid_als_platform_driver); 379 380 MODULE_DESCRIPTION("HID Sensor ALS"); 381 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); 382 MODULE_LICENSE("GPL"); 383