Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: hid-sensor-als: Assign channels dynamically

Instead of assuming that every channel defined statically by
als_channels[] is present, assign dynamically based on presence of the
respective usage id in the descriptor. This will allow to register ALS
with limited channel support. Append the timestamp as the last channel.

Update available_scan_mask to specify all channels which are present.

There is no intentional function changes done.

Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Link: https://lore.kernel.org/r/20240205185926.3030521-2-srinivas.pandruvada@linux.intel.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Srinivas Pandruvada and committed by
Jonathan Cameron
f2a71ebd ca2f16c3

+35 -16
+35 -16
drivers/iio/light/hid-sensor-als.c
··· 25 25 struct hid_sensor_hub_callbacks callbacks; 26 26 struct hid_sensor_common common_attributes; 27 27 struct hid_sensor_hub_attribute_info als[CHANNEL_SCAN_INDEX_MAX]; 28 + struct iio_chan_spec channels[CHANNEL_SCAN_INDEX_MAX + 1]; 28 29 struct { 29 30 u32 illum[CHANNEL_SCAN_INDEX_MAX]; 30 31 u64 timestamp __aligned(8); ··· 34 33 int scale_post_decml; 35 34 int scale_precision; 36 35 int value_offset; 36 + int num_channels; 37 37 s64 timestamp; 38 + unsigned long als_scan_mask[2]; 39 + }; 40 + 41 + /* The order of usage ids must match scan index starting from CHANNEL_SCAN_INDEX_INTENSITY */ 42 + static const u32 als_usage_ids[] = { 43 + HID_USAGE_SENSOR_LIGHT_ILLUM, 44 + HID_USAGE_SENSOR_LIGHT_ILLUM, 38 45 }; 39 46 40 47 static const u32 als_sensitivity_addresses[] = { ··· 246 237 /* Parse report which is specific to an usage id*/ 247 238 static int als_parse_report(struct platform_device *pdev, 248 239 struct hid_sensor_hub_device *hsdev, 249 - struct iio_chan_spec *channels, 250 240 unsigned usage_id, 251 241 struct als_state *st) 252 242 { 253 - int ret; 243 + struct iio_chan_spec *channels; 244 + int ret, index = 0; 254 245 int i; 255 246 256 - for (i = 0; i <= CHANNEL_SCAN_INDEX_ILLUM; ++i) { 247 + channels = st->channels; 248 + 249 + for (i = 0; i < CHANNEL_SCAN_INDEX_MAX; ++i) { 257 250 ret = sensor_hub_input_get_attribute_info(hsdev, 258 251 HID_INPUT_REPORT, 259 252 usage_id, 260 - HID_USAGE_SENSOR_LIGHT_ILLUM, 253 + als_usage_ids[i], 261 254 &st->als[i]); 262 255 if (ret < 0) 263 - return ret; 264 - als_adjust_channel_bit_mask(channels, i, st->als[i].size); 256 + continue; 257 + 258 + channels[index] = als_channels[i]; 259 + st->als_scan_mask[0] |= BIT(i); 260 + als_adjust_channel_bit_mask(channels, index, st->als[i].size); 261 + ++index; 265 262 266 263 dev_dbg(&pdev->dev, "als %x:%x\n", st->als[i].index, 267 264 st->als[i].report_id); 268 265 } 266 + 267 + st->num_channels = index; 268 + /* Return success even if one usage id is present */ 269 + if (index) 270 + ret = 0; 269 271 270 272 st->scale_precision = hid_sensor_format_scale(usage_id, 271 273 &st->als[CHANNEL_SCAN_INDEX_INTENSITY], ··· 313 293 return ret; 314 294 } 315 295 316 - indio_dev->channels = devm_kmemdup(&pdev->dev, als_channels, 317 - sizeof(als_channels), GFP_KERNEL); 318 - if (!indio_dev->channels) { 319 - dev_err(&pdev->dev, "failed to duplicate channels\n"); 320 - return -ENOMEM; 321 - } 322 - 323 296 ret = als_parse_report(pdev, hsdev, 324 - (struct iio_chan_spec *)indio_dev->channels, 325 297 hsdev->usage, 326 298 als_state); 327 299 if (ret) { ··· 321 309 return ret; 322 310 } 323 311 324 - indio_dev->num_channels = 325 - ARRAY_SIZE(als_channels); 312 + /* Add timestamp channel */ 313 + als_state->channels[als_state->num_channels] = als_channels[CHANNEL_SCAN_INDEX_TIMESTAMP]; 314 + 315 + /* +1 for adding timestamp channel */ 316 + indio_dev->num_channels = als_state->num_channels + 1; 317 + 318 + indio_dev->channels = als_state->channels; 319 + indio_dev->available_scan_masks = als_state->als_scan_mask; 320 + 326 321 indio_dev->info = &als_info; 327 322 indio_dev->name = name; 328 323 indio_dev->modes = INDIO_DIRECT_MODE;