staticint veml6030_get_it(struct veml6030_data *data, int *val, int *val2)
{ int ret, it_idx;
ret = regmap_field_read(data->rf.it, &it_idx); if (ret) return ret;
ret = iio_gts_find_int_time_by_sel(&data->gts, it_idx); if (ret < 0) return ret;
*val2 = ret;
*val = 0;
return IIO_VAL_INT_PLUS_MICRO;
}
staticint veml6030_set_it(struct iio_dev *indio_dev, int val, int val2)
{ struct veml6030_data *data = iio_priv(indio_dev); int ret, gain_idx, it_idx, new_gain, prev_gain, prev_it; bool in_range;
if (val || !iio_gts_valid_time(&data->gts, val2)) return -EINVAL;
ret = regmap_field_read(data->rf.it, &it_idx); if (ret) return ret;
ret = regmap_field_read(data->rf.gain, &gain_idx); if (ret) return ret;
prev_it = iio_gts_find_int_time_by_sel(&data->gts, it_idx); if (prev_it < 0) return prev_it;
if (prev_it == val2) return0;
prev_gain = iio_gts_find_gain_by_sel(&data->gts, gain_idx); if (prev_gain < 0) return prev_gain;
ret = iio_gts_find_new_gain_by_gain_time_min(&data->gts, prev_gain, prev_it,
val2, &new_gain, &in_range); if (ret) return ret;
if (!in_range)
dev_dbg(&data->client->dev, "Optimal gain out of range\n");
ret = iio_gts_find_sel_by_int_time(&data->gts, val2); if (ret < 0) return ret;
ret = regmap_field_write(data->rf.it, ret); if (ret) return ret;
ret = iio_gts_find_sel_by_gain(&data->gts, new_gain); if (ret < 0) return ret;
return regmap_field_write(data->rf.gain, ret);
}
staticint veml6030_read_persistence(struct iio_dev *indio_dev, int *val, int *val2)
{ int ret, reg, period, x, y; struct veml6030_data *data = iio_priv(indio_dev);
ret = veml6030_get_it(data, &x, &y); if (ret < 0) return ret;
ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®); if (ret) {
dev_err(&data->client->dev, "can't read als conf register %d\n", ret);
}
/* integration time multiplied by 1/2/4/8 */
period = y * (1 << ((reg >> 4) & 0x03));
*val = period / 1000000;
*val2 = period % 1000000;
return IIO_VAL_INT_PLUS_MICRO;
}
staticint veml6030_write_persistence(struct iio_dev *indio_dev, int val, int val2)
{ int ret, period, x, y; struct veml6030_data *data = iio_priv(indio_dev);
ret = veml6030_get_it(data, &x, &y); if (ret < 0) return ret;
if (!val) {
period = val2 / y;
} else { if ((val == 1) && (val2 == 600000))
period = 1600000 / y; elseif ((val == 3) && (val2 == 200000))
period = 3200000 / y; elseif ((val == 6) && (val2 == 400000))
period = 6400000 / y; else
period = -1;
}
if (period <= 0 || period > 8 || hweight8(period) != 1) return -EINVAL;
ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
VEML6030_ALS_PERS, (ffs(period) - 1) << 4); if (ret)
dev_err(&data->client->dev, "can't set persistence value %d\n", ret);
return ret;
}
staticint veml6030_set_scale(struct iio_dev *indio_dev, int val, int val2)
{ int ret, gain_sel, it_idx, it_sel; struct veml6030_data *data = iio_priv(indio_dev);
ret = regmap_field_read(data->rf.it, &it_idx); if (ret) return ret;
ret = iio_gts_find_gain_time_sel_for_scale(&data->gts, val, val2,
&gain_sel, &it_sel); if (ret) return ret;
ret = regmap_field_write(data->rf.it, it_sel); if (ret) return ret;
ret = regmap_field_write(data->rf.gain, gain_sel); if (ret) return ret;
return0;
}
staticint veml6030_read_thresh(struct iio_dev *indio_dev, int *val, int *val2, int dir)
{ int ret, reg; struct veml6030_data *data = iio_priv(indio_dev);
if (dir == IIO_EV_DIR_RISING)
ret = regmap_read(data->regmap, VEML6030_REG_ALS_WH, ®); else
ret = regmap_read(data->regmap, VEML6030_REG_ALS_WL, ®); if (ret) {
dev_err(&data->client->dev, "can't read als threshold value %d\n", ret); return ret;
}
*val = reg & 0xffff; return IIO_VAL_INT;
}
staticint veml6030_write_thresh(struct iio_dev *indio_dev, int val, int val2, int dir)
{ int ret; struct veml6030_data *data = iio_priv(indio_dev);
if (val > 0xFFFF || val < 0 || val2) return -EINVAL;
if (dir == IIO_EV_DIR_RISING) {
ret = regmap_write(data->regmap, VEML6030_REG_ALS_WH, val); if (ret)
dev_err(&data->client->dev, "can't set high threshold %d\n", ret);
} else {
ret = regmap_write(data->regmap, VEML6030_REG_ALS_WL, val); if (ret)
dev_err(&data->client->dev, "can't set low threshold %d\n", ret);
}
return ret;
}
staticint veml6030_get_total_gain(struct veml6030_data *data)
{ int gain, it, reg, ret;
ret = regmap_field_read(data->rf.gain, ®); if (ret) return ret;
gain = iio_gts_find_gain_by_sel(&data->gts, reg); if (gain < 0) return gain;
ret = regmap_field_read(data->rf.it, ®); if (ret) return ret;
it = iio_gts_find_int_time_by_sel(&data->gts, reg); if (it < 0) return it;
return iio_gts_get_total_gain(&data->gts, gain, it);
}
staticint veml6030_get_scale(struct veml6030_data *data, int *val, int *val2)
{ int gain, it, reg, ret;
ret = regmap_field_read(data->rf.gain, ®); if (ret) return ret;
gain = iio_gts_find_gain_by_sel(&data->gts, reg); if (gain < 0) return gain;
ret = regmap_field_read(data->rf.it, ®); if (ret) return ret;
it = iio_gts_find_int_time_by_sel(&data->gts, reg); if (it < 0) return it;
ret = iio_gts_get_scale(&data->gts, gain, it, val, val2); if (ret) return ret;
return IIO_VAL_INT_PLUS_NANO;
}
staticint veml6030_process_als(struct veml6030_data *data, int raw, int *val, int *val2)
{ int total_gain;
total_gain = veml6030_get_total_gain(data); if (total_gain < 0) return total_gain;
*val = raw * data->chip->max_scale / total_gain / 10000;
*val2 = raw * data->chip->max_scale / total_gain % 10000 * 100;
return IIO_VAL_INT_PLUS_MICRO;
}
/* *Providebothrawaswellaslightreadinginlux. *light(inlux)=resolution*rawreading
*/ staticint veml6030_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{ int ret, reg; struct veml6030_data *data = iio_priv(indio_dev); struct regmap *regmap = data->regmap; struct device *dev = &data->client->dev;
switch (mask) { case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_PROCESSED: switch (chan->type) { case IIO_LIGHT:
ret = regmap_read(regmap, VEML6030_REG_ALS_DATA, ®); if (ret < 0) {
dev_err(dev, "can't read als data %d\n", ret); return ret;
} if (mask == IIO_CHAN_INFO_PROCESSED) return veml6030_process_als(data, reg, val, val2);
*val = reg; return IIO_VAL_INT; case IIO_INTENSITY:
ret = regmap_read(regmap, VEML6030_REG_WH_DATA, ®); if (ret < 0) {
dev_err(dev, "can't read white data %d\n", ret); return ret;
}
*val = reg; return IIO_VAL_INT; default: return -EINVAL;
} case IIO_CHAN_INFO_INT_TIME: return veml6030_get_it(data, val, val2); case IIO_CHAN_INFO_SCALE: return veml6030_get_scale(data, val, val2); default: return -EINVAL;
}
}
staticint veml6030_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, constint **vals, int *type, int *length, long mask)
{ struct veml6030_data *data = iio_priv(indio_dev);
switch (mask) { case IIO_CHAN_INFO_INT_TIME: return iio_gts_avail_times(&data->gts, vals, type, length); case IIO_CHAN_INFO_SCALE: return iio_gts_all_avail_scales(&data->gts, vals, type, length);
}
return -EINVAL;
}
staticint veml6030_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask)
{ switch (mask) { case IIO_CHAN_INFO_INT_TIME: return veml6030_set_it(indio_dev, val, val2); case IIO_CHAN_INFO_SCALE: return veml6030_set_scale(indio_dev, val, val2); default: return -EINVAL;
}
}
staticint veml6030_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_PLUS_NANO; case IIO_CHAN_INFO_INT_TIME: return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL;
}
}
staticint veml6030_read_event_val(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)
{ switch (info) { case IIO_EV_INFO_VALUE: switch (dir) { case IIO_EV_DIR_RISING: case IIO_EV_DIR_FALLING: return veml6030_read_thresh(indio_dev, val, val2, dir); default: return -EINVAL;
} break; case IIO_EV_INFO_PERIOD: return veml6030_read_persistence(indio_dev, val, val2); default: return -EINVAL;
}
}
ret = veml6030_als_shut_down(data); if (ret < 0) {
dev_err(&data->client->dev, "can't disable als to configure interrupt %d\n", ret); return ret;
}
/* enable interrupt + power on */
ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
VEML6030_ALS_INT_EN | VEML6030_ALS_SD, state << 1); if (ret)
dev_err(&data->client->dev, "can't enable interrupt & poweron als %d\n", ret);
ret = devm_iio_init_iio_gts(dev, 2, 150400000,
veml6030_gain_sel, ARRAY_SIZE(veml6030_gain_sel),
veml6030_it_sel, ARRAY_SIZE(veml6030_it_sel),
&data->gts); if (ret) return dev_err_probe(dev, ret, "failed to init iio gts\n");
ret = veml6030_als_shut_down(data); if (ret) return dev_err_probe(dev, ret, "can't shutdown als\n");
ret = regmap_write(data->regmap, VEML6030_REG_ALS_CONF, 0x1001); if (ret) return dev_err_probe(dev, ret, "can't setup als configs\n");
ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_PSM,
VEML6030_PSM | VEML6030_PSM_EN, 0x03); if (ret) return dev_err_probe(dev, ret, "can't setup default PSM\n");
ret = regmap_write(data->regmap, VEML6030_REG_ALS_WH, 0xFFFF); if (ret) return dev_err_probe(dev, ret, "can't setup high threshold\n");
ret = regmap_write(data->regmap, VEML6030_REG_ALS_WL, 0x0000); if (ret) return dev_err_probe(dev, ret, "can't setup low threshold\n");
ret = veml6030_als_pwr_on(data); if (ret) return dev_err_probe(dev, ret, "can't poweron als\n");
ret = devm_add_action_or_reset(dev, veml6030_als_shut_down_action, data); if (ret < 0) return ret;
/* Clear stale interrupt status bits if any during start */
ret = regmap_read(data->regmap, VEML6030_REG_ALS_INT, &val); if (ret < 0) return dev_err_probe(dev, ret, "can't clear als interrupt status\n");
ret = devm_iio_init_iio_gts(dev, 0, 409600000,
veml6035_gain_sel, ARRAY_SIZE(veml6035_gain_sel),
veml6030_it_sel, ARRAY_SIZE(veml6030_it_sel),
&data->gts); if (ret) return dev_err_probe(dev, ret, "failed to init iio gts\n");
ret = veml6030_als_shut_down(data); if (ret) return dev_err_probe(dev, ret, "can't shutdown als\n");
ret = regmap_write(data->regmap, VEML6030_REG_ALS_CONF,
VEML6035_SENS | VEML6035_CHAN_EN | VEML6030_ALS_SD); if (ret) return dev_err_probe(dev, ret, "can't setup als configs\n");
ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_PSM,
VEML6030_PSM | VEML6030_PSM_EN, 0x03); if (ret) return dev_err_probe(dev, ret, "can't setup default PSM\n");
ret = regmap_write(data->regmap, VEML6030_REG_ALS_WH, 0xFFFF); if (ret) return dev_err_probe(dev, ret, "can't setup high threshold\n");
ret = regmap_write(data->regmap, VEML6030_REG_ALS_WL, 0x0000); if (ret) return dev_err_probe(dev, ret, "can't setup low threshold\n");
ret = veml6030_als_pwr_on(data); if (ret) return dev_err_probe(dev, ret, "can't poweron als\n");
ret = devm_add_action_or_reset(dev, veml6030_als_shut_down_action, data); if (ret < 0) return ret;
/* Clear stale interrupt status bits if any during start */
ret = regmap_read(data->regmap, VEML6030_REG_ALS_INT, &val); if (ret < 0) return dev_err_probe(dev, ret, "can't clear als interrupt status\n");
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.