Lines Matching +full:period +full:- +full:scale
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * APDS-9306/APDS-9306-065 Ambient Light Sensor
5 * Datasheet: https://docs.broadcom.com/doc/AV02-4755EN
27 #include <linux/iio/iio-gts-helper.h>
57 #define APDS9306_ALS_THRES_VAL_MAX (BIT(20) - 1)
67 * struct part_id_gts_multiplier - Part no. and corresponding gts multiplier
69 * GTS (Gain Time Scale) are helper functions for Light sensors which along
90 * for apds9306 and 43 uW per sq cm (293.69 lux) for apds9306-065.
93 * Lux = (raw + offset) * scale; offset can be any value by userspace.
95 * Scale table by IIO GTS Helpers = (1 / HG) * (1 / ITG) * Multiplier.
101 * Lux per ADC count at 3x and 32x for apds9306-065 = 293.69 / 2000
103 * The Multiplier for the scale table provided to userspace:
104 * IIO GTS scale Multiplier for apds9306 = (340.134 / 2000) * 32 * 3 = 16.326432
105 * and for apds9306-065 = (293.69 / 2000) * 32 * 3 = 14.09712
134 * struct apds9306_regfields - apds9306 regmap fields definitions
161 * struct apds9306_data - apds9306 private data and registers definitions
164 * @gts: IIO Gain Time Scale structure
188 * Available scales with gain 1x - 18x, timings 3.125, 25, 50, 100, 200, 400 ms
388 struct device *dev = data->dev; in apds9306_regfield_init()
389 struct regmap *regmap = data->regmap; in apds9306_regfield_init()
391 struct apds9306_regfields *rf = &data->rf; in apds9306_regfield_init()
396 rf->sw_reset = tmp; in apds9306_regfield_init()
401 rf->en = tmp; in apds9306_regfield_init()
406 rf->intg_time = tmp; in apds9306_regfield_init()
411 rf->repeat_rate = tmp; in apds9306_regfield_init()
416 rf->gain = tmp; in apds9306_regfield_init()
421 rf->int_src = tmp; in apds9306_regfield_init()
426 rf->int_thresh_var_en = tmp; in apds9306_regfield_init()
431 rf->int_en = tmp; in apds9306_regfield_init()
436 rf->int_persist_val = tmp; in apds9306_regfield_init()
441 rf->int_thresh_var_val = tmp; in apds9306_regfield_init()
448 struct apds9306_regfields *rf = &data->rf; in apds9306_power_state()
453 ret = regmap_field_write(rf->en, 1); in apds9306_power_state()
461 return regmap_field_write(rf->en, 0); in apds9306_power_state()
466 struct device *dev = data->dev; in apds9306_read_data()
468 struct apds9306_regfields *rf = &data->rf; in apds9306_read_data()
474 ret = pm_runtime_resume_and_get(data->dev); in apds9306_read_data()
478 ret = regmap_field_read(rf->intg_time, &intg_time_idx); in apds9306_read_data()
482 ret = regmap_field_read(rf->repeat_rate, &repeat_rate_idx); in apds9306_read_data()
486 ret = regmap_field_read(rf->int_src, &int_src); in apds9306_read_data()
490 intg_time = iio_gts_find_int_time_by_sel(&data->gts, intg_time_idx); in apds9306_read_data()
494 /* Whichever is greater - integration time period or sampling period. */ in apds9306_read_data()
501 data->read_data_available = 0; in apds9306_read_data()
509 ret = regmap_read_poll_timeout(data->regmap, APDS9306_MAIN_STATUS_REG, in apds9306_read_data()
510 status, data->read_data_available || in apds9306_read_data()
532 ret = regmap_bulk_read(data->regmap, reg, buff, sizeof(buff)); in apds9306_read_data()
540 pm_runtime_mark_last_busy(data->dev); in apds9306_read_data()
541 pm_runtime_put_autosuspend(data->dev); in apds9306_read_data()
548 struct apds9306_regfields *rf = &data->rf; in apds9306_intg_time_get()
551 ret = regmap_field_read(rf->intg_time, &intg_time_idx); in apds9306_intg_time_get()
555 ret = iio_gts_find_int_time_by_sel(&data->gts, intg_time_idx); in apds9306_intg_time_get()
566 struct device *dev = data->dev; in apds9306_intg_time_set()
567 struct apds9306_regfields *rf = &data->rf; in apds9306_intg_time_set()
572 if (!iio_gts_valid_time(&data->gts, val2)) { in apds9306_intg_time_set()
574 return -EINVAL; in apds9306_intg_time_set()
577 ret = regmap_field_read(rf->intg_time, &intg_time_idx); in apds9306_intg_time_set()
581 ret = regmap_field_read(rf->gain, &gain_idx); in apds9306_intg_time_set()
585 intg_old = iio_gts_find_int_time_by_sel(&data->gts, intg_time_idx); in apds9306_intg_time_set()
592 gain_old = iio_gts_find_gain_by_sel(&data->gts, gain_idx); in apds9306_intg_time_set()
596 iio_gts_find_new_gain_by_old_gain_time(&data->gts, gain_old, intg_old, in apds9306_intg_time_set()
604 gain_new_closest = iio_find_closest_gain_low(&data->gts, gain_new, &ok); in apds9306_intg_time_set()
606 gain_new_closest = iio_gts_get_min_gain(&data->gts); in apds9306_intg_time_set()
613 ret = iio_gts_find_sel_by_int_time(&data->gts, val2); in apds9306_intg_time_set()
617 ret = regmap_field_write(rf->intg_time, ret); in apds9306_intg_time_set()
621 ret = iio_gts_find_sel_by_gain(&data->gts, gain_new_closest); in apds9306_intg_time_set()
625 return regmap_field_write(rf->gain, ret); in apds9306_intg_time_set()
631 struct apds9306_regfields *rf = &data->rf; in apds9306_sampling_freq_get()
634 ret = regmap_field_read(rf->repeat_rate, &repeat_rate_idx); in apds9306_sampling_freq_get()
639 return -EINVAL; in apds9306_sampling_freq_get()
650 struct apds9306_regfields *rf = &data->rf; in apds9306_sampling_freq_set()
656 return regmap_field_write(rf->repeat_rate, i); in apds9306_sampling_freq_set()
659 return -EINVAL; in apds9306_sampling_freq_set()
664 struct apds9306_regfields *rf = &data->rf; in apds9306_scale_get()
667 ret = regmap_field_read(rf->gain, &gain_idx); in apds9306_scale_get()
671 ret = regmap_field_read(rf->intg_time, &intg_time_idx); in apds9306_scale_get()
675 gain = iio_gts_find_gain_by_sel(&data->gts, gain_idx); in apds9306_scale_get()
679 intg = iio_gts_find_int_time_by_sel(&data->gts, intg_time_idx); in apds9306_scale_get()
683 return iio_gts_get_scale(&data->gts, gain, intg, val, val2); in apds9306_scale_get()
688 struct apds9306_regfields *rf = &data->rf; in apds9306_scale_set()
691 ret = regmap_field_read(rf->intg_time, &intg_time_idx); in apds9306_scale_set()
695 ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, in apds9306_scale_set()
698 for (i = 0; i < data->gts.num_itime; i++) { in apds9306_scale_set()
699 time_sel = data->gts.itime_table[i].sel; in apds9306_scale_set()
704 ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, in apds9306_scale_set()
710 return -EINVAL; in apds9306_scale_set()
712 ret = regmap_field_write(rf->intg_time, time_sel); in apds9306_scale_set()
717 return regmap_field_write(rf->gain, gain_sel); in apds9306_scale_set()
722 struct apds9306_regfields *rf = &data->rf; in apds9306_event_period_get()
723 int period, ret; in apds9306_event_period_get() local
725 ret = regmap_field_read(rf->int_persist_val, &period); in apds9306_event_period_get()
729 if (!in_range(period, 0, APDS9306_ALS_PERSIST_NUM_VALS)) in apds9306_event_period_get()
730 return -EINVAL; in apds9306_event_period_get()
732 *val = period; in apds9306_event_period_get()
739 struct apds9306_regfields *rf = &data->rf; in apds9306_event_period_set()
742 return -EINVAL; in apds9306_event_period_set()
744 return regmap_field_write(rf->int_persist_val, val); in apds9306_event_period_set()
758 return -EINVAL; in apds9306_event_thresh_get()
760 ret = regmap_bulk_read(data->regmap, var, buff, sizeof(buff)); in apds9306_event_thresh_get()
780 return -EINVAL; in apds9306_event_thresh_set()
783 return -EINVAL; in apds9306_event_thresh_set()
787 return regmap_bulk_write(data->regmap, var, buff, sizeof(buff)); in apds9306_event_thresh_set()
792 struct apds9306_regfields *rf = &data->rf; in apds9306_event_thresh_adaptive_get()
795 ret = regmap_field_read(rf->int_thresh_var_val, &thr_adpt); in apds9306_event_thresh_adaptive_get()
800 return -EINVAL; in apds9306_event_thresh_adaptive_get()
809 struct apds9306_regfields *rf = &data->rf; in apds9306_event_thresh_adaptive_set()
812 return -EINVAL; in apds9306_event_thresh_adaptive_set()
814 return regmap_field_write(rf->int_thresh_var_val, val); in apds9306_event_thresh_adaptive_set()
826 if (chan->channel2 == IIO_MOD_LIGHT_CLEAR) in apds9306_read_raw()
863 return -EINVAL; in apds9306_read_raw()
876 return iio_gts_avail_times(&data->gts, vals, type, length); in apds9306_read_avail()
878 return iio_gts_all_avail_scales(&data->gts, vals, type, length); in apds9306_read_avail()
886 return -EINVAL; in apds9306_read_avail()
902 return -EINVAL; in apds9306_write_raw_get_fmt()
912 guard(mutex)(&data->mutex); in apds9306_write_raw()
917 return -EINVAL; in apds9306_write_raw()
924 return -EINVAL; in apds9306_write_raw()
932 struct apds9306_regfields *rf = &data->rf; in apds9306_irq_handler()
941 ret = regmap_read(data->regmap, APDS9306_MAIN_STATUS_REG, &status); in apds9306_irq_handler()
943 dev_err_ratelimited(data->dev, "status reg read failed\n"); in apds9306_irq_handler()
947 ret = regmap_field_read(rf->int_src, &int_src); in apds9306_irq_handler()
966 * If a one-shot read through sysfs is underway at the same time in apds9306_irq_handler()
972 data->read_data_available = 1; in apds9306_irq_handler()
1004 return -EINVAL; in apds9306_read_event()
1026 return -EINVAL; in apds9306_write_event()
1036 struct apds9306_regfields *rf = &data->rf; in apds9306_read_event_config()
1041 guard(mutex)(&data->mutex); in apds9306_read_event_config()
1043 ret = regmap_field_read(rf->int_src, &int_src); in apds9306_read_event_config()
1047 ret = regmap_field_read(rf->int_en, &int_en); in apds9306_read_event_config()
1051 if (chan->type == IIO_LIGHT) in apds9306_read_event_config()
1054 if (chan->type == IIO_INTENSITY) in apds9306_read_event_config()
1057 return -EINVAL; in apds9306_read_event_config()
1060 ret = regmap_field_read(rf->int_thresh_var_en, &int_en); in apds9306_read_event_config()
1066 return -EINVAL; in apds9306_read_event_config()
1077 struct apds9306_regfields *rf = &data->rf; in apds9306_write_event_config()
1082 guard(mutex)(&data->mutex); in apds9306_write_event_config()
1084 ret = regmap_field_read(rf->int_en, &enabled); in apds9306_write_event_config()
1095 if (chan->type == IIO_LIGHT) in apds9306_write_event_config()
1096 ret = regmap_field_write(rf->int_src, 1); in apds9306_write_event_config()
1097 else if (chan->type == IIO_INTENSITY) in apds9306_write_event_config()
1098 ret = regmap_field_write(rf->int_src, 0); in apds9306_write_event_config()
1100 return -EINVAL; in apds9306_write_event_config()
1108 ret = regmap_field_write(rf->int_en, 1); in apds9306_write_event_config()
1112 return pm_runtime_resume_and_get(data->dev); in apds9306_write_event_config()
1117 ret = regmap_field_write(rf->int_en, 0); in apds9306_write_event_config()
1121 pm_runtime_mark_last_busy(data->dev); in apds9306_write_event_config()
1122 pm_runtime_put_autosuspend(data->dev); in apds9306_write_event_config()
1128 return regmap_field_write(rf->int_thresh_var_en, state); in apds9306_write_event_config()
1130 return -EINVAL; in apds9306_write_event_config()
1157 ret = regmap_read(data->regmap, APDS9306_PART_ID_REG, &part_id); in apds9306_init_iio_gts()
1166 return -ENOENT; in apds9306_init_iio_gts()
1168 return devm_iio_init_iio_gts(data->dev, in apds9306_init_iio_gts()
1173 &data->gts); in apds9306_init_iio_gts()
1179 struct apds9306_regfields *rf = &data->rf; in apds9306_powerdown()
1182 ret = regmap_field_write(rf->int_thresh_var_en, 0); in apds9306_powerdown()
1186 ret = regmap_field_write(rf->int_en, 0); in apds9306_powerdown()
1195 struct apds9306_regfields *rf = &data->rf; in apds9306_device_init()
1202 ret = regmap_field_write(rf->intg_time, APDS9306_MEAS_MODE_100MS); in apds9306_device_init()
1206 ret = regmap_field_write(rf->repeat_rate, APDS9306_SAMP_FREQ_10HZ); in apds9306_device_init()
1210 ret = regmap_field_write(rf->gain, APDS9306_GSEL_3X); in apds9306_device_init()
1214 ret = regmap_field_write(rf->int_src, APDS9306_INT_SRC_ALS); in apds9306_device_init()
1218 ret = regmap_field_write(rf->int_en, 0); in apds9306_device_init()
1222 return regmap_field_write(rf->int_thresh_var_en, 0); in apds9306_device_init()
1227 struct device *dev = data->dev; in apds9306_pm_init()
1251 struct device *dev = &client->dev; in apds9306_probe()
1258 return -ENOMEM; in apds9306_probe()
1262 mutex_init(&data->mutex); in apds9306_probe()
1264 data->regmap = devm_regmap_init_i2c(client, &apds9306_regmap); in apds9306_probe()
1265 if (IS_ERR(data->regmap)) in apds9306_probe()
1266 return dev_err_probe(dev, PTR_ERR(data->regmap), in apds9306_probe()
1269 data->dev = dev; in apds9306_probe()
1280 indio_dev->name = "apds9306"; in apds9306_probe()
1281 indio_dev->modes = INDIO_DIRECT_MODE; in apds9306_probe()
1282 if (client->irq) { in apds9306_probe()
1283 indio_dev->info = &apds9306_info; in apds9306_probe()
1284 indio_dev->channels = apds9306_channels_with_events; in apds9306_probe()
1285 indio_dev->num_channels = ARRAY_SIZE(apds9306_channels_with_events); in apds9306_probe()
1286 ret = devm_request_threaded_irq(dev, client->irq, NULL, in apds9306_probe()
1293 indio_dev->info = &apds9306_info_no_events; in apds9306_probe()
1294 indio_dev->channels = apds9306_channels_without_events; in apds9306_probe()
1295 indio_dev->num_channels = in apds9306_probe()