Lines Matching +full:sensor +full:- +full:gain
1 // SPDX-License-Identifier: GPL-2.0-only
3 * ROHM Colour Sensor driver for
4 * - BU27008 RGBC sensor
5 * - BU27010 RGBC + Flickering sensor
22 #include <linux/iio/iio-gts-helper.h>
30 * At a quick glance to the data-sheet register tables, the BU27010 has all the
38 * Unfortunately, some of the wheel has been re-invented. Even though the names
43 * Chip-specific mapping from register addresses/bits to functionality is done
127 * enum bu27008_chan_type - BU27008 channel types
145 * enum bu27008_chan - BU27008 physical data channel
179 * Available scales with gain 1x - 1024x, timings 55, 100, 200, 400 mS
180 * Time impacts to gain: 1x, 2x, 4x, 8x.
182 * => Max total gain is HWGAIN * gain by integration time (8 * 1024) = 8192
184 * Max amplification is (HWGAIN * MAX integration-time multiplier) 1024 * 8
186 * scale 16.0 for HWGAIN1, INT-TIME 55 mS. This way the nano scale for MAX
187 * total gain 8192 will be 1953125
192 * On BU27010 available scales with gain 1x - 4096x,
193 * timings 55, 100, 200, 400 mS. Time impacts to gain: 1x, 2x, 4x, 8x.
195 * => Max total gain is HWGAIN * gain by integration time (8 * 4096)
197 * Using NANO precision for scale we must use scale 64x corresponding gain 1x
202 /* See the data sheet for the "Gain Setting" table */
292 * All the RGBC channels share the same gain.
293 * IR gain can be fine-tuned from the gain set for the RGBC by 2 bit, but this
294 * would yield quite complex gain setting. Especially since not all bit
295 * compinations are supported. And in any case setting GAIN for RGBC will
296 * always also change the IR-gain.
298 * On top of this, the selector '0' which corresponds to hw-gain 1X on RGBC,
299 * corresponds to gain 2X on IR. Rest of the selctors correspond to same gains
300 * though. This, however, makes it not possible to use shared gain for all
330 * We don't allow setting scale for IR (because of shared gain bits).
374 * Prevent changing gain/time config when scale is read/written.
376 * Prevent changing gain/time when data is read.
457 * gain and integration time settings and we need to ensure those are
463 * read-modify-write cycle (eg. regmap_update_bits()). Please, revise
487 * We do always set also the LOW bits of IR-gain because othervice we in bu27008_write_gain_sel()
488 * would risk resulting an invalid GAIN register value. in bu27008_write_gain_sel()
491 * values were such that HW could support both gain settings. in bu27008_write_gain_sel()
492 * Eg, when the shared bits were same for both gain values. in bu27008_write_gain_sel()
497 * This would end up with nasty logic for computing gain values for in bu27008_write_gain_sel()
498 * both channels - and rejecting them if shared bits changed. in bu27008_write_gain_sel()
502 * Maybe look-up a value where both gains are somehow optimized in bu27008_write_gain_sel()
507 * configurations but causes unexpected corner-cases. in bu27008_write_gain_sel()
517 return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL2, in bu27008_write_gain_sel()
527 * Gain 'selector' is composed of two registers. Selector is 6bit value, in bu27010_write_gain_sel()
528 * 4 high bits being the RGBC gain fieild in MODE_CONTROL1 register and in bu27010_write_gain_sel()
529 * two low bits being the channel specific gain in MODE_CONTROL2. in bu27010_write_gain_sel()
532 * the MODE_CONTROL1 value (RGBC gain part). in bu27010_write_gain_sel()
536 ret = regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL1, in bu27010_write_gain_sel()
553 return regmap_write(data->regmap, BU27008_REG_MODE_CONTROL2, regval); in bu27010_write_gain_sel()
561 * If we always "lock" the gain selectors for all channels to prevent in bu27008_get_gain_sel()
573 ret = regmap_read(data->regmap, BU27008_REG_MODE_CONTROL2, sel); in bu27008_get_gain_sel()
587 * We always "lock" the gain selectors for all channels to prevent in bu27010_get_gain_sel()
591 * Read the channel0 gain. in bu27010_get_gain_sel()
593 ret = regmap_read(data->regmap, BU27008_REG_MODE_CONTROL2, sel); in bu27010_get_gain_sel()
599 /* Read the shared gain */ in bu27010_get_gain_sel()
600 ret = regmap_read(data->regmap, BU27008_REG_MODE_CONTROL1, &tmp); in bu27010_get_gain_sel()
605 * The gain selector is made as a combination of common RGBC gain and in bu27010_get_gain_sel()
606 * the channel specific gain. The channel specific gain forms the low in bu27010_get_gain_sel()
607 * bits of selector and RGBC gain is appended right after it. in bu27010_get_gain_sel()
609 * Compose the selector from channel0 gain and shared RGBC gain. in bu27010_get_gain_sel()
620 ret = regmap_write_bits(data->regmap, BU27008_REG_SYSTEM_CONTROL, in bu27008_chip_init()
623 return dev_err_probe(data->dev, ret, "Sensor reset failed\n"); in bu27008_chip_init()
626 * The data-sheet does not tell how long performing the IC reset takes. in bu27008_chip_init()
627 * However, the data-sheet says the minimum time it takes the IC to be in bu27008_chip_init()
633 ret = regmap_reinit_cache(data->regmap, data->cd->regmap_cfg); in bu27008_chip_init()
635 dev_err(data->dev, "Failed to reinit reg cache\n"); in bu27008_chip_init()
644 ret = regmap_write_bits(data->regmap, BU27008_REG_SYSTEM_CONTROL, in bu27010_chip_init()
647 return dev_err_probe(data->dev, ret, "Sensor reset failed\n"); in bu27010_chip_init()
652 ret = regmap_write_bits(data->regmap, BU27010_REG_POWER, in bu27010_chip_init()
655 return dev_err_probe(data->dev, ret, "Sensor power-on failed\n"); in bu27010_chip_init()
660 ret = regmap_write_bits(data->regmap, BU27010_REG_RESET, in bu27010_chip_init()
663 return dev_err_probe(data->dev, ret, "Sensor powering failed\n"); in bu27010_chip_init()
672 * 01 => Data-ready (RGBC/IR) in bu27010_chip_init()
673 * 10 => Data-ready (flicker) in bu27010_chip_init()
677 * flicker FIFO would automagically disable data-ready IRQ. in bu27010_chip_init()
680 * just treat the RGBC data-ready as single bit which can be enabled / in bu27010_chip_init()
684 return regmap_clear_bits(data->regmap, BU27010_REG_MODE_CONTROL4, in bu27010_chip_init()
744 ret = regmap_read_poll_timeout(data->regmap, data->cd->valid_reg, in bu27008_chan_read_data()
751 ret = regmap_bulk_read(data->regmap, reg, &tmp, sizeof(tmp)); in bu27008_chan_read_data()
753 dev_err(data->dev, "Reading channel data failed\n"); in bu27008_chan_read_data()
760 static int bu27008_get_gain(struct bu27008_data *data, struct iio_gts *gts, int *gain) in bu27008_get_gain() argument
764 ret = data->cd->get_gain_sel(data, &sel); in bu27008_get_gain()
770 dev_err(data->dev, "unknown gain value 0x%x\n", sel); in bu27008_get_gain()
774 *gain = ret; in bu27008_get_gain()
779 static int bu27008_set_gain(struct bu27008_data *data, int gain) in bu27008_set_gain() argument
783 ret = iio_gts_find_sel_by_gain(&data->gts, gain); in bu27008_set_gain()
787 return data->cd->write_gain_sel(data, ret); in bu27008_set_gain()
794 ret = regmap_read(data->regmap, BU27008_REG_MODE_CONTROL1, &val); in bu27008_get_int_time_sel()
798 val &= data->cd->int_time_mask; in bu27008_get_int_time_sel()
799 val >>= ffs(data->cd->int_time_mask) - 1; in bu27008_get_int_time_sel()
808 sel <<= ffs(data->cd->int_time_mask) - 1; in bu27008_set_int_time_sel()
810 return regmap_update_bits(data->regmap, BU27008_REG_MODE_CONTROL1, in bu27008_set_int_time_sel()
811 data->cd->int_time_mask, sel); in bu27008_set_int_time_sel()
822 return iio_gts_find_int_time_by_sel(&data->gts, sel); in bu27008_get_int_time_us()
829 int gain, ret; in _bu27008_get_scale() local
832 gts = &data->gts_ir; in _bu27008_get_scale()
834 gts = &data->gts; in _bu27008_get_scale()
836 ret = bu27008_get_gain(data, gts, &gain); in _bu27008_get_scale()
844 return iio_gts_get_scale(gts, gain, ret, val, val2); in _bu27008_get_scale()
852 mutex_lock(&data->mutex); in bu27008_get_scale()
854 mutex_unlock(&data->mutex); in bu27008_get_scale()
863 ret = iio_gts_find_sel_by_int_time(&data->gts, time); in bu27008_set_int_time()
875 mutex_lock(&data->mutex); in bu27008_try_set_int_time()
881 if (!iio_gts_valid_time(&data->gts, int_time_new)) { in bu27008_try_set_int_time()
882 dev_dbg(data->dev, "Unsupported integration time %u\n", in bu27008_try_set_int_time()
885 ret = -EINVAL; in bu27008_try_set_int_time()
890 new_time_sel = iio_gts_find_sel_by_int_time(&data->gts, int_time_new); in bu27008_try_set_int_time()
894 ret = bu27008_get_gain(data, &data->gts, &old_gain); in bu27008_try_set_int_time()
898 ret = iio_gts_find_new_gain_sel_by_old_gain_time(&data->gts, old_gain, in bu27008_try_set_int_time()
905 dev_dbg(data->dev, in bu27008_try_set_int_time()
914 * can't support the scale - then the caller should be in bu27008_try_set_int_time()
918 ret = iio_find_closest_gain_low(&data->gts, new_gain, &ok); in bu27008_try_set_int_time()
920 dev_dbg(data->dev, "optimal gain out of range\n"); in bu27008_try_set_int_time()
923 dev_dbg(data->dev, in bu27008_try_set_int_time()
924 "Total gain increase. Risk of saturation"); in bu27008_try_set_int_time()
925 ret = iio_gts_get_min_gain(&data->gts); in bu27008_try_set_int_time()
930 dev_dbg(data->dev, "scale changed, new gain %u\n", new_gain); in bu27008_try_set_int_time()
940 mutex_unlock(&data->mutex); in bu27008_try_set_int_time()
948 return regmap_set_bits(data->regmap, data->cd->meas_en_reg, in bu27008_meas_set()
949 data->cd->meas_en_mask); in bu27008_meas_set()
950 return regmap_clear_bits(data->regmap, data->cd->meas_en_reg, in bu27008_meas_set()
951 data->cd->meas_en_mask); in bu27008_meas_set()
959 if (chan->scan_index == BU27008_BLUE) in bu27008_chan_cfg()
967 * chip type. Hence the open-coded FIELD_PREP here. We don't bother in bu27008_chan_cfg()
968 * zeroing the irrelevant bits though - update_bits takes care of that. in bu27008_chan_cfg()
970 chan_sel <<= ffs(data->cd->chan_sel_mask) - 1; in bu27008_chan_cfg()
972 return regmap_update_bits(data->regmap, data->cd->chan_sel_reg, in bu27008_chan_cfg()
997 ret = bu27008_chan_read_data(data, chan->address, val); in bu27008_read_one()
1002 dev_warn(data->dev, "measurement disabling failed\n"); in bu27008_read_one()
1018 return -EBUSY; in bu27008_read_raw()
1020 mutex_lock(&data->mutex); in bu27008_read_raw()
1022 mutex_unlock(&data->mutex); in bu27008_read_raw()
1029 ret = bu27008_get_scale(data, chan->scan_index == BU27008_IR, in bu27008_read_raw()
1047 return -EINVAL; in bu27008_read_raw()
1051 /* Called if the new scale could not be supported with existing int-time */
1057 for (i = 0; i < data->gts.num_itime; i++) { in bu27008_try_find_new_time_gain()
1058 new_time_sel = data->gts.itime_table[i].sel; in bu27008_try_find_new_time_gain()
1059 ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, in bu27008_try_find_new_time_gain()
1064 if (i == data->gts.num_itime) { in bu27008_try_find_new_time_gain()
1065 dev_err(data->dev, "Can't support scale %u %u\n", val, val2); in bu27008_try_find_new_time_gain()
1067 return -EINVAL; in bu27008_try_find_new_time_gain()
1079 if (chan->scan_index == BU27008_IR) in bu27008_set_scale()
1080 return -EINVAL; in bu27008_set_scale()
1082 mutex_lock(&data->mutex); in bu27008_set_scale()
1088 ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, time_sel, in bu27008_set_scale()
1096 ret = data->cd->write_gain_sel(data, gain_sel); in bu27008_set_scale()
1099 mutex_unlock(&data->mutex); in bu27008_set_scale()
1115 return -EINVAL; in bu27008_write_raw_get_fmt()
1140 ret = -EINVAL; in bu27008_write_raw()
1146 ret = -EINVAL; in bu27008_write_raw()
1162 return iio_gts_avail_times(&data->gts, vals, type, length); in bu27008_read_avail()
1164 if (chan->channel2 == IIO_MOD_LIGHT_IR) in bu27008_read_avail()
1165 return iio_gts_all_avail_scales(&data->gts_ir, vals, in bu27008_read_avail()
1167 return iio_gts_all_avail_scales(&data->gts, vals, type, length); in bu27008_read_avail()
1169 return -EINVAL; in bu27008_read_avail()
1180 if (test_bit(BU27008_BLUE, idev->active_scan_mask)) { in bu27008_update_scan_mode()
1181 if (test_bit(BU27008_CLEAR, idev->active_scan_mask)) in bu27008_update_scan_mode()
1189 chan_sel <<= ffs(data->cd->chan_sel_mask) - 1; in bu27008_update_scan_mode()
1191 return regmap_update_bits(data->regmap, data->cd->chan_sel_reg, in bu27008_update_scan_mode()
1192 data->cd->chan_sel_mask, chan_sel); in bu27008_update_scan_mode()
1211 ret = regmap_set_bits(data->regmap, data->cd->drdy_en_reg, in bu27008_trigger_set_state()
1212 data->cd->drdy_en_mask); in bu27008_trigger_set_state()
1214 ret = regmap_clear_bits(data->regmap, data->cd->drdy_en_reg, in bu27008_trigger_set_state()
1215 data->cd->drdy_en_mask); in bu27008_trigger_set_state()
1217 dev_err(data->dev, "Failed to set trigger state\n"); in bu27008_trigger_set_state()
1226 enable_irq(data->irq); in bu27008_trigger_reenable()
1237 struct iio_dev *idev = pf->indio_dev; in bu27008_trigger_handler()
1251 ret = regmap_read(data->regmap, data->cd->valid_reg, &dummy); in bu27008_trigger_handler()
1255 ret = regmap_bulk_read(data->regmap, BU27008_REG_DATA0_LO, &raw.chan, in bu27008_trigger_handler()
1260 iio_push_to_buffers_with_timestamp(idev, &raw, pf->timestamp); in bu27008_trigger_handler()
1262 iio_trigger_notify_done(idev->trig); in bu27008_trigger_handler()
1304 ret = devm_iio_triggered_buffer_setup(data->dev, idev, in bu27008_setup_trigger()
1309 return dev_err_probe(data->dev, ret, in bu27008_setup_trigger()
1312 itrig = devm_iio_trigger_alloc(data->dev, "%sdata-rdy-dev%d", in bu27008_setup_trigger()
1313 idev->name, iio_device_id(idev)); in bu27008_setup_trigger()
1315 return -ENOMEM; in bu27008_setup_trigger()
1317 data->trig = itrig; in bu27008_setup_trigger()
1319 itrig->ops = &bu27008_trigger_ops; in bu27008_setup_trigger()
1322 name = devm_kasprintf(data->dev, GFP_KERNEL, "%s-bu27008", in bu27008_setup_trigger()
1323 dev_name(data->dev)); in bu27008_setup_trigger()
1325 ret = devm_request_irq(data->dev, data->irq, in bu27008_setup_trigger()
1329 return dev_err_probe(data->dev, ret, "Could not request IRQ\n"); in bu27008_setup_trigger()
1331 ret = devm_iio_trigger_register(data->dev, itrig); in bu27008_setup_trigger()
1333 return dev_err_probe(data->dev, ret, in bu27008_setup_trigger()
1337 idev->trig = iio_trigger_get(itrig); in bu27008_setup_trigger()
1344 struct device *dev = &i2c->dev; in bu27008_probe()
1353 return -ENOMEM; in bu27008_probe()
1361 data->cd = device_get_match_data(&i2c->dev); in bu27008_probe()
1362 if (!data->cd) in bu27008_probe()
1363 return -ENODEV; in bu27008_probe()
1365 regmap = devm_regmap_init_i2c(i2c, data->cd->regmap_cfg); in bu27008_probe()
1373 return dev_err_probe(dev, ret, "Failed to access sensor\n"); in bu27008_probe()
1377 if (part_id != data->cd->part_id) in bu27008_probe()
1380 ret = devm_iio_init_iio_gts(dev, data->cd->scale1x, 0, data->cd->gains, in bu27008_probe()
1381 data->cd->num_gains, data->cd->itimes, in bu27008_probe()
1382 data->cd->num_itimes, &data->gts); in bu27008_probe()
1386 ret = devm_iio_init_iio_gts(dev, data->cd->scale1x, 0, data->cd->gains_ir, in bu27008_probe()
1387 data->cd->num_gains_ir, data->cd->itimes, in bu27008_probe()
1388 data->cd->num_itimes, &data->gts_ir); in bu27008_probe()
1392 mutex_init(&data->mutex); in bu27008_probe()
1393 data->regmap = regmap; in bu27008_probe()
1394 data->dev = dev; in bu27008_probe()
1395 data->irq = i2c->irq; in bu27008_probe()
1397 idev->channels = bu27008_channels; in bu27008_probe()
1398 idev->num_channels = ARRAY_SIZE(bu27008_channels); in bu27008_probe()
1399 idev->name = data->cd->name; in bu27008_probe()
1400 idev->info = &bu27008_info; in bu27008_probe()
1401 idev->modes = INDIO_DIRECT_MODE; in bu27008_probe()
1402 idev->available_scan_masks = bu27008_scan_masks; in bu27008_probe()
1404 ret = data->cd->chip_init(data); in bu27008_probe()
1408 if (i2c->irq) { in bu27008_probe()
1441 MODULE_DESCRIPTION("ROHM BU27008 and BU27010 colour sensor driver");