ret = regmap_clear_bits(data->regmap, BH1745_MODE_CTRL2,
BH1745_CTRL2_RGBC_EN); if (ret)
dev_err(dev, "Failed to turn off device\n");
}
staticint bh1745_get_scale(struct bh1745_data *data, int *val, int *val2)
{ int ret; int value; int gain_sel, int_time_sel; int gain; conststruct iio_itime_sel_mul *int_time;
ret = regmap_read(data->regmap, BH1745_MODE_CTRL2, &value); if (ret) return ret;
gain_sel = FIELD_GET(BH1745_CTRL2_ADC_GAIN_MASK, value);
gain = iio_gts_find_gain_by_sel(&data->gts, gain_sel);
ret = regmap_read(data->regmap, BH1745_MODE_CTRL1, &value); if (ret) return ret;
return iio_gts_get_scale(&data->gts, gain, int_time->time_us, val,
val2);
}
staticint bh1745_set_scale(struct bh1745_data *data, int val)
{ struct device *dev = data->dev; int ret; int value; int hw_gain_sel, current_int_time_sel, new_int_time_sel;
ret = regmap_read(data->regmap, BH1745_MODE_CTRL1, &value); if (ret) return ret;
current_int_time_sel = FIELD_GET(BH1745_CTRL1_MEASUREMENT_TIME_MASK,
value);
ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts,
current_int_time_sel,
val, 0, &hw_gain_sel); if (ret) { for (int i = 0; i < data->gts.num_itime; i++) {
new_int_time_sel = data->gts.itime_table[i].sel;
if (new_int_time_sel == current_int_time_sel) continue;
ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts,
new_int_time_sel,
val, 0,
&hw_gain_sel); if (!ret) break;
}
if (ret) {
dev_dbg(dev, "Unsupported scale value requested: %d\n",
val); return -EINVAL;
}
ret = regmap_write_bits(data->regmap, BH1745_MODE_CTRL1,
BH1745_CTRL1_MEASUREMENT_TIME_MASK,
new_int_time_sel); if (ret) return ret;
}
staticint bh1745_set_int_time(struct bh1745_data *data, int val, int val2)
{ struct device *dev = data->dev; int ret; int value; int current_int_time, current_hwgain_sel, current_hwgain; int new_hwgain, new_hwgain_sel, new_int_time_sel; int req_int_time = (1000000 * val) + val2;
if (!iio_gts_valid_time(&data->gts, req_int_time)) {
dev_dbg(dev, "Unsupported integration time requested: %d\n",
req_int_time); return -EINVAL;
}
ret = bh1745_get_int_time(data, ¤t_int_time); if (ret) return ret;
if (current_int_time == req_int_time) return 0;
ret = regmap_read(data->regmap, BH1745_MODE_CTRL2, &value); if (ret) return ret;
current_hwgain_sel = FIELD_GET(BH1745_CTRL2_ADC_GAIN_MASK, value);
current_hwgain = iio_gts_find_gain_by_sel(&data->gts,
current_hwgain_sel);
ret = iio_gts_find_new_gain_by_old_gain_time(&data->gts, current_hwgain,
current_int_time,
req_int_time,
&new_hwgain); if (new_hwgain < 0) {
dev_dbg(dev, "No corresponding gain for requested integration time\n"); return ret;
}
if (ret) { bool in_range;
new_hwgain = iio_find_closest_gain_low(&data->gts, new_hwgain,
&in_range); if (new_hwgain < 0) {
new_hwgain = iio_gts_get_min_gain(&data->gts); if (new_hwgain < 0) return ret;
}
if (!in_range)
dev_dbg(dev, "Optimal gain out of range\n");
dev_dbg(dev, "Scale changed, new hw_gain %d\n", new_hwgain);
}
new_hwgain_sel = iio_gts_find_sel_by_gain(&data->gts, new_hwgain); if (new_hwgain_sel < 0) return new_hwgain_sel;
ret = regmap_write_bits(data->regmap, BH1745_MODE_CTRL2,
BH1745_CTRL2_ADC_GAIN_MASK,
new_hwgain_sel); if (ret) return ret;
new_int_time_sel = iio_gts_find_sel_by_int_time(&data->gts,
req_int_time); if (new_int_time_sel < 0) return new_int_time_sel;
staticint bh1745_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{ struct bh1745_data *data = iio_priv(indio_dev); int ret; int value;
switch (mask) { case IIO_CHAN_INFO_RAW: if (!iio_device_claim_direct(indio_dev)) return -EBUSY;
ret = regmap_bulk_read(data->regmap, chan->address, &value, 2);
iio_device_release_direct(indio_dev); if (ret) return ret;
*val = value;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE: {
guard(mutex)(&data->lock);
ret = bh1745_get_scale(data, val, val2); if (ret) return ret;
return IIO_VAL_INT;
}
case IIO_CHAN_INFO_INT_TIME: {
guard(mutex)(&data->lock);
*val = 0;
ret = bh1745_get_int_time(data, val2); if (ret) return 0;
return IIO_VAL_INT_PLUS_MICRO;
}
default: return -EINVAL;
}
}
staticint bh1745_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask)
{ struct bh1745_data *data = iio_priv(indio_dev);
guard(mutex)(&data->lock); switch (mask) { case IIO_CHAN_INFO_SCALE: return bh1745_set_scale(data, val);
case IIO_CHAN_INFO_INT_TIME: return bh1745_set_int_time(data, val, val2);
default: return -EINVAL;
}
}
staticint bh1745_write_raw_get_fmt(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, long mask)
{ switch (mask) { case IIO_CHAN_INFO_SCALE: return IIO_VAL_INT;
case IIO_CHAN_INFO_INT_TIME: return IIO_VAL_INT_PLUS_MICRO;
default: return -EINVAL;
}
}
staticint bh1745_read_thresh(struct iio_dev *indio_dev, conststruct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir, enum iio_event_info info, int *val, int *val2)
{ struct bh1745_data *data = iio_priv(indio_dev); int ret;
switch (info) { case IIO_EV_INFO_VALUE: switch (dir) { case IIO_EV_DIR_RISING:
ret = regmap_bulk_read(data->regmap, BH1745_TH_LSB,
val, 2); if (ret) return ret;
return IIO_VAL_INT;
case IIO_EV_DIR_FALLING:
ret = regmap_bulk_read(data->regmap, BH1745_TL_LSB,
val, 2); if (ret) return ret;
return IIO_VAL_INT;
default: return -EINVAL;
}
case IIO_EV_INFO_PERIOD:
ret = regmap_read(data->regmap, BH1745_PERSISTENCE, val); if (ret) return ret;
return IIO_VAL_INT;
default: return -EINVAL;
}
}
staticint bh1745_write_thresh(struct iio_dev *indio_dev, conststruct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir, enum iio_event_info info, int val, int val2)
{ struct bh1745_data *data = iio_priv(indio_dev); int ret;
switch (info) { case IIO_EV_INFO_VALUE: if (val < 0x0 || val > 0xFFFF) return -EINVAL;
switch (dir) { case IIO_EV_DIR_RISING:
ret = regmap_bulk_write(data->regmap, BH1745_TH_LSB,
&val, 2); if (ret) return ret;
return IIO_VAL_INT;
case IIO_EV_DIR_FALLING:
ret = regmap_bulk_write(data->regmap, BH1745_TL_LSB,
&val, 2); if (ret) return ret;
return IIO_VAL_INT;
default: return -EINVAL;
}
case IIO_EV_INFO_PERIOD: if (val < BH1745_PRESISTENCE_UPDATE_TOGGLE ||
val > BH1745_PRESISTENCE_UPDATE_EIGHT_MEASUREMENT) return -EINVAL;
ret = regmap_write(data->regmap, BH1745_PERSISTENCE, val); if (ret) return ret;
return IIO_VAL_INT;
default: return -EINVAL;
}
}
staticint bh1745_read_event_config(struct iio_dev *indio_dev, conststruct iio_chan_spec *chan, enum iio_event_type type, enum iio_event_direction dir)
{ struct bh1745_data *data = iio_priv(indio_dev); int ret; int value; int int_src;
ret = regmap_read(data->regmap, BH1745_INTR, &value); if (ret) return ret;
if (!FIELD_GET(BH1745_INTR_ENABLE, value)) return 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.