/* ADC integration time, field value to time in ms */ #define TSL2591_FVAL_TO_MSEC(x) (((x) + 1) * 100) /* ADC integration time, field value to time in seconds */ #define TSL2591_FVAL_TO_SEC(x) ((x) + 1) /* ADC integration time, time in seconds to field value */ #define TSL2591_SEC_TO_FVAL(x) ((x) - 1)
staticint tsl2591_gain_to_multiplier(const u8 als_gain)
{ switch (als_gain) { case TSL2591_CTRL_ALS_LOW_GAIN: return TSL2591_CTRL_ALS_LOW_GAIN_MULTIPLIER; case TSL2591_CTRL_ALS_MED_GAIN: return TSL2591_CTRL_ALS_MED_GAIN_MULTIPLIER; case TSL2591_CTRL_ALS_HIGH_GAIN: return TSL2591_CTRL_ALS_HIGH_GAIN_MULTIPLIER; case TSL2591_CTRL_ALS_MAX_GAIN: return TSL2591_CTRL_ALS_MAX_GAIN_MULTIPLIER; default: return -EINVAL;
}
}
staticint tsl2591_multiplier_to_gain(const u32 multiplier)
{ switch (multiplier) { case TSL2591_CTRL_ALS_LOW_GAIN_MULTIPLIER: return TSL2591_CTRL_ALS_LOW_GAIN; case TSL2591_CTRL_ALS_MED_GAIN_MULTIPLIER: return TSL2591_CTRL_ALS_MED_GAIN; case TSL2591_CTRL_ALS_HIGH_GAIN_MULTIPLIER: return TSL2591_CTRL_ALS_HIGH_GAIN; case TSL2591_CTRL_ALS_MAX_GAIN_MULTIPLIER: return TSL2591_CTRL_ALS_MAX_GAIN; default: return -EINVAL;
}
}
staticint tsl2591_persist_cycle_to_lit(const u8 als_persist)
{ switch (als_persist) { case TSL2591_PRST_ALS_INT_CYCLE_ANY: return1; case TSL2591_PRST_ALS_INT_CYCLE_2: return2; case TSL2591_PRST_ALS_INT_CYCLE_3: return3; case TSL2591_PRST_ALS_INT_CYCLE_5: return5; case TSL2591_PRST_ALS_INT_CYCLE_10: return10; case TSL2591_PRST_ALS_INT_CYCLE_15: return15; case TSL2591_PRST_ALS_INT_CYCLE_20: return20; case TSL2591_PRST_ALS_INT_CYCLE_25: return25; case TSL2591_PRST_ALS_INT_CYCLE_30: return30; case TSL2591_PRST_ALS_INT_CYCLE_35: return35; case TSL2591_PRST_ALS_INT_CYCLE_40: return40; case TSL2591_PRST_ALS_INT_CYCLE_45: return45; case TSL2591_PRST_ALS_INT_CYCLE_50: return50; case TSL2591_PRST_ALS_INT_CYCLE_55: return55; case TSL2591_PRST_ALS_INT_CYCLE_60: return60; default: return -EINVAL;
}
}
staticint tsl2591_compatible_int_time(struct tsl2591_chip *chip, const u32 als_integration_time)
{ switch (als_integration_time) { case TSL2591_CTRL_ALS_INTEGRATION_100MS: case TSL2591_CTRL_ALS_INTEGRATION_200MS: case TSL2591_CTRL_ALS_INTEGRATION_300MS: case TSL2591_CTRL_ALS_INTEGRATION_400MS: case TSL2591_CTRL_ALS_INTEGRATION_500MS: case TSL2591_CTRL_ALS_INTEGRATION_600MS: return0; default: return -EINVAL;
}
}
staticint tsl2591_als_time_to_fval(const u32 als_integration_time)
{ int i;
for (i = 0; i < ARRAY_SIZE(tsl2591_int_time_available); i++) { if (als_integration_time == tsl2591_int_time_available[i]) return TSL2591_SEC_TO_FVAL(als_integration_time);
}
return -EINVAL;
}
staticint tsl2591_compatible_gain(struct tsl2591_chip *chip, const u8 als_gain)
{ switch (als_gain) { case TSL2591_CTRL_ALS_LOW_GAIN: case TSL2591_CTRL_ALS_MED_GAIN: case TSL2591_CTRL_ALS_HIGH_GAIN: case TSL2591_CTRL_ALS_MAX_GAIN: return0; default: return -EINVAL;
}
}
staticint tsl2591_compatible_als_persist_cycle(struct tsl2591_chip *chip, const u32 als_persist)
{ switch (als_persist) { case TSL2591_PRST_ALS_INT_CYCLE_ANY: case TSL2591_PRST_ALS_INT_CYCLE_2: case TSL2591_PRST_ALS_INT_CYCLE_3: case TSL2591_PRST_ALS_INT_CYCLE_5: case TSL2591_PRST_ALS_INT_CYCLE_10: case TSL2591_PRST_ALS_INT_CYCLE_15: case TSL2591_PRST_ALS_INT_CYCLE_20: case TSL2591_PRST_ALS_INT_CYCLE_25: case TSL2591_PRST_ALS_INT_CYCLE_30: case TSL2591_PRST_ALS_INT_CYCLE_35: case TSL2591_PRST_ALS_INT_CYCLE_40: case TSL2591_PRST_ALS_INT_CYCLE_45: case TSL2591_PRST_ALS_INT_CYCLE_50: case TSL2591_PRST_ALS_INT_CYCLE_55: case TSL2591_PRST_ALS_INT_CYCLE_60: return0; default: return -EINVAL;
}
}
staticint tsl2591_check_als_valid(struct i2c_client *client)
{ int ret;
ret = i2c_smbus_read_byte_data(client, TSL2591_CMD_NOP | TSL2591_STATUS); if (ret < 0) {
dev_err(&client->dev, "Failed to read register\n"); return -EINVAL;
}
/* Check for status ALS valid flag for up to 100ms */
ret = readx_poll_timeout(tsl2591_check_als_valid, client,
val, val == TSL2591_STS_VAL_HIGH_MASK,
TSL2591_DELAY_PERIOD_US,
TSL2591_DELAY_PERIOD_US * TSL2591_ALS_STS_VALID_COUNT); if (ret)
dev_err(&client->dev, "Timed out waiting for valid ALS data\n");
ret = i2c_smbus_write_byte_data(client,
TSL2591_CMD_NOP | TSL2591_CONTROL,
als_settings.als_int_time | als_settings.als_gain); if (ret)
dev_err(&client->dev, "Failed to set als gain & int time\n");
ret = i2c_smbus_write_byte_data(client,
TSL2591_CMD_NOP | TSL2591_AILTL,
als_lower_l); if (ret) {
dev_err(&client->dev, "Failed to set als lower threshold\n"); return ret;
}
ret = i2c_smbus_write_byte_data(client,
TSL2591_CMD_NOP | TSL2591_AILTH,
als_lower_h); if (ret) {
dev_err(&client->dev, "Failed to set als lower threshold\n"); return ret;
}
ret = i2c_smbus_write_byte_data(client,
TSL2591_CMD_NOP | TSL2591_AIHTL,
als_upper_l); if (ret) {
dev_err(&client->dev, "Failed to set als upper threshold\n"); return ret;
}
ret = i2c_smbus_write_byte_data(client,
TSL2591_CMD_NOP | TSL2591_AIHTH,
als_upper_h); if (ret) {
dev_err(&client->dev, "Failed to set als upper threshold\n"); return ret;
}
ret = i2c_smbus_write_byte_data(client,
TSL2591_CMD_NOP | TSL2591_PERSIST,
als_persist); if (ret)
dev_err(&client->dev, "Failed to set als persist cycle\n");
ret = i2c_smbus_write_byte_data(client,
TSL2591_CMD_NOP | TSL2591_ENABLE,
state); if (ret)
dev_err(&client->dev, "Failed to set the power state to %#04x\n", state);
staticint tsl2591_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{ struct tsl2591_chip *chip = iio_priv(indio_dev); struct i2c_client *client = chip->client; int ret;
pm_runtime_get_sync(&client->dev);
mutex_lock(&chip->als_mutex);
switch (mask) { case IIO_CHAN_INFO_RAW: if (chan->type != IIO_INTENSITY) {
ret = -EINVAL; goto err_unlock;
}
ret = tsl2591_read_channel_data(indio_dev, chan, val, val2); if (ret < 0) goto err_unlock;
ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_PROCESSED: if (chan->type != IIO_LIGHT) {
ret = -EINVAL; goto err_unlock;
}
ret = tsl2591_read_channel_data(indio_dev, chan, val, val2); if (ret < 0) break;
ret = IIO_VAL_INT_PLUS_MICRO; break; case IIO_CHAN_INFO_INT_TIME: if (chan->type != IIO_INTENSITY) {
ret = -EINVAL; goto err_unlock;
}
*val = TSL2591_FVAL_TO_SEC(chip->als_settings.als_int_time);
ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_CALIBSCALE: if (chan->type != IIO_INTENSITY) {
ret = -EINVAL; goto err_unlock;
}
*val = tsl2591_gain_to_multiplier(chip->als_settings.als_gain);
ret = IIO_VAL_INT; break; default:
ret = -EINVAL; break;
}
staticint tsl2591_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask)
{ struct tsl2591_chip *chip = iio_priv(indio_dev); int int_time; int gain; int ret;
mutex_lock(&chip->als_mutex);
switch (mask) { case IIO_CHAN_INFO_INT_TIME:
int_time = tsl2591_als_time_to_fval(val); if (int_time < 0) {
ret = int_time; goto err_unlock;
}
ret = tsl2591_compatible_int_time(chip, int_time); if (ret < 0) goto err_unlock;
chip->als_settings.als_int_time = int_time; break; case IIO_CHAN_INFO_CALIBSCALE:
gain = tsl2591_multiplier_to_gain(val); if (gain < 0) {
ret = gain; goto err_unlock;
}
ret = tsl2591_compatible_gain(chip, gain); if (ret < 0) goto err_unlock;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_err(&client->dev, "I2C smbus byte data functionality is not supported\n"); return -EOPNOTSUPP;
}
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); if (!indio_dev) return -ENOMEM;
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.