Loading drivers/iio/light/ltr501.c +89 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #define LTR501_ALS_CONTR 0x80 /* ALS operation mode, SW reset */ #define LTR501_PS_CONTR 0x81 /* PS operation mode */ #define LTR501_ALS_MEAS_RATE 0x85 /* ALS integ time, measurement rate*/ #define LTR501_PART_ID 0x86 #define LTR501_MANUFAC_ID 0x87 #define LTR501_ALS_DATA1 0x88 /* 16-bit, little endian */ Loading @@ -49,11 +50,17 @@ #define LTR501_REGMAP_NAME "ltr501_regmap" static const int int_time_mapping[] = {100000, 50000, 200000, 400000}; static const struct reg_field reg_field_it = REG_FIELD(LTR501_ALS_MEAS_RATE, 3, 4); struct ltr501_data { struct i2c_client *client; struct mutex lock_als, lock_ps; u8 als_contr, ps_contr; struct regmap *regmap; struct regmap_field *reg_it; }; static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask) Loading @@ -74,6 +81,58 @@ static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask) return -EIO; } static int ltr501_set_it_time(struct ltr501_data *data, int it) { int ret, i, index = -1, status; for (i = 0; i < ARRAY_SIZE(int_time_mapping); i++) { if (int_time_mapping[i] == it) { index = i; break; } } /* Make sure integ time index is valid */ if (index < 0) return -EINVAL; ret = regmap_read(data->regmap, LTR501_ALS_CONTR, &status); if (ret < 0) return ret; if (status & LTR501_CONTR_ALS_GAIN_MASK) { /* * 200 ms and 400 ms integ time can only be * used in dynamic range 1 */ if (index > 1) return -EINVAL; } else /* 50 ms integ time can only be used in dynamic range 2 */ if (index == 1) return -EINVAL; return regmap_field_write(data->reg_it, index); } /* read int time in micro seconds */ static int ltr501_read_it_time(struct ltr501_data *data, int *val, int *val2) { int ret, index; ret = regmap_field_read(data->reg_it, &index); if (ret < 0) return ret; /* Make sure integ time index is valid */ if (index < 0 || index >= ARRAY_SIZE(int_time_mapping)) return -EINVAL; *val2 = int_time_mapping[index]; *val = 0; return IIO_VAL_INT_PLUS_MICRO; } static int ltr501_read_als(struct ltr501_data *data, __le16 buf[2]) { int ret; Loading Loading @@ -121,7 +180,8 @@ static int ltr501_read_ps(struct ltr501_data *data) static const struct iio_chan_spec ltr501_channels[] = { LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0), LTR501_INTENSITY_CHANNEL(1, LTR501_ALS_DATA1, IIO_MOD_LIGHT_IR, BIT(IIO_CHAN_INFO_SCALE)), BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_INT_TIME)), { .type = IIO_PROXIMITY, .address = LTR501_PS_DATA, Loading Loading @@ -196,6 +256,13 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } case IIO_CHAN_INFO_INT_TIME: switch (chan->type) { case IIO_INTENSITY: return ltr501_read_it_time(data, val, val2); default: return -EINVAL; } } return -EINVAL; } Loading Loading @@ -246,16 +313,30 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, default: return -EINVAL; } case IIO_CHAN_INFO_INT_TIME: switch (chan->type) { case IIO_INTENSITY: if (val != 0) return -EINVAL; mutex_lock(&data->lock_als); i = ltr501_set_it_time(data, val2); mutex_unlock(&data->lock_als); return i; default: return -EINVAL; } } return -EINVAL; } static IIO_CONST_ATTR(in_proximity_scale_available, "1 0.25 0.125 0.0625"); static IIO_CONST_ATTR(in_intensity_scale_available, "1 0.005"); static IIO_CONST_ATTR_INT_TIME_AVAIL("0.05 0.1 0.2 0.4"); static struct attribute *ltr501_attributes[] = { &iio_const_attr_in_proximity_scale_available.dev_attr.attr, &iio_const_attr_in_intensity_scale_available.dev_attr.attr, &iio_const_attr_integration_time_available.dev_attr.attr, NULL }; Loading Loading @@ -404,6 +485,13 @@ static int ltr501_probe(struct i2c_client *client, mutex_init(&data->lock_als); mutex_init(&data->lock_ps); data->reg_it = devm_regmap_field_alloc(&client->dev, regmap, reg_field_it); if (IS_ERR(data->reg_it)) { dev_err(&client->dev, "Integ time reg field init failed.\n"); return PTR_ERR(data->reg_it); } ret = regmap_read(data->regmap, LTR501_PART_ID, &partid); if (ret < 0) return ret; Loading Loading
drivers/iio/light/ltr501.c +89 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #define LTR501_ALS_CONTR 0x80 /* ALS operation mode, SW reset */ #define LTR501_PS_CONTR 0x81 /* PS operation mode */ #define LTR501_ALS_MEAS_RATE 0x85 /* ALS integ time, measurement rate*/ #define LTR501_PART_ID 0x86 #define LTR501_MANUFAC_ID 0x87 #define LTR501_ALS_DATA1 0x88 /* 16-bit, little endian */ Loading @@ -49,11 +50,17 @@ #define LTR501_REGMAP_NAME "ltr501_regmap" static const int int_time_mapping[] = {100000, 50000, 200000, 400000}; static const struct reg_field reg_field_it = REG_FIELD(LTR501_ALS_MEAS_RATE, 3, 4); struct ltr501_data { struct i2c_client *client; struct mutex lock_als, lock_ps; u8 als_contr, ps_contr; struct regmap *regmap; struct regmap_field *reg_it; }; static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask) Loading @@ -74,6 +81,58 @@ static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask) return -EIO; } static int ltr501_set_it_time(struct ltr501_data *data, int it) { int ret, i, index = -1, status; for (i = 0; i < ARRAY_SIZE(int_time_mapping); i++) { if (int_time_mapping[i] == it) { index = i; break; } } /* Make sure integ time index is valid */ if (index < 0) return -EINVAL; ret = regmap_read(data->regmap, LTR501_ALS_CONTR, &status); if (ret < 0) return ret; if (status & LTR501_CONTR_ALS_GAIN_MASK) { /* * 200 ms and 400 ms integ time can only be * used in dynamic range 1 */ if (index > 1) return -EINVAL; } else /* 50 ms integ time can only be used in dynamic range 2 */ if (index == 1) return -EINVAL; return regmap_field_write(data->reg_it, index); } /* read int time in micro seconds */ static int ltr501_read_it_time(struct ltr501_data *data, int *val, int *val2) { int ret, index; ret = regmap_field_read(data->reg_it, &index); if (ret < 0) return ret; /* Make sure integ time index is valid */ if (index < 0 || index >= ARRAY_SIZE(int_time_mapping)) return -EINVAL; *val2 = int_time_mapping[index]; *val = 0; return IIO_VAL_INT_PLUS_MICRO; } static int ltr501_read_als(struct ltr501_data *data, __le16 buf[2]) { int ret; Loading Loading @@ -121,7 +180,8 @@ static int ltr501_read_ps(struct ltr501_data *data) static const struct iio_chan_spec ltr501_channels[] = { LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0), LTR501_INTENSITY_CHANNEL(1, LTR501_ALS_DATA1, IIO_MOD_LIGHT_IR, BIT(IIO_CHAN_INFO_SCALE)), BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_INT_TIME)), { .type = IIO_PROXIMITY, .address = LTR501_PS_DATA, Loading Loading @@ -196,6 +256,13 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } case IIO_CHAN_INFO_INT_TIME: switch (chan->type) { case IIO_INTENSITY: return ltr501_read_it_time(data, val, val2); default: return -EINVAL; } } return -EINVAL; } Loading Loading @@ -246,16 +313,30 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, default: return -EINVAL; } case IIO_CHAN_INFO_INT_TIME: switch (chan->type) { case IIO_INTENSITY: if (val != 0) return -EINVAL; mutex_lock(&data->lock_als); i = ltr501_set_it_time(data, val2); mutex_unlock(&data->lock_als); return i; default: return -EINVAL; } } return -EINVAL; } static IIO_CONST_ATTR(in_proximity_scale_available, "1 0.25 0.125 0.0625"); static IIO_CONST_ATTR(in_intensity_scale_available, "1 0.005"); static IIO_CONST_ATTR_INT_TIME_AVAIL("0.05 0.1 0.2 0.4"); static struct attribute *ltr501_attributes[] = { &iio_const_attr_in_proximity_scale_available.dev_attr.attr, &iio_const_attr_in_intensity_scale_available.dev_attr.attr, &iio_const_attr_integration_time_available.dev_attr.attr, NULL }; Loading Loading @@ -404,6 +485,13 @@ static int ltr501_probe(struct i2c_client *client, mutex_init(&data->lock_als); mutex_init(&data->lock_ps); data->reg_it = devm_regmap_field_alloc(&client->dev, regmap, reg_field_it); if (IS_ERR(data->reg_it)) { dev_err(&client->dev, "Integ time reg field init failed.\n"); return PTR_ERR(data->reg_it); } ret = regmap_read(data->regmap, LTR501_PART_ID, &partid); if (ret < 0) return ret; Loading