This is work in progress. A new IIO ABI allowing floating value read and write through sysfs has to be defined first. Signed-off-by: Mathieu Othacehe <m.othacehe@xxxxxxxxx> --- drivers/iio/light/isl29501.c | 121 ++++++++++++++++++++++++++++++++--- 1 file changed, 112 insertions(+), 9 deletions(-) diff --git a/drivers/iio/light/isl29501.c b/drivers/iio/light/isl29501.c index ea4a2ced1004..8698b7caee9b 100644 --- a/drivers/iio/light/isl29501.c +++ b/drivers/iio/light/isl29501.c @@ -112,11 +112,17 @@ struct isl29501_private { enum isl29501_register_name { REG_DISTANCE, + REG_AMPLITUDE, REG_PHASE, + REG_I_RAW, + REG_Q_RAW, REG_TEMPERATURE, REG_AMBIENT_LIGHT, REG_GAIN, + REG_I_BIAS, + REG_Q_BIAS, REG_GAIN_BIAS, + REG_AMPL_BIAS, REG_PHASE_EXP, REG_CALIB_PHASE_TEMP_A, REG_CALIB_PHASE_TEMP_B, @@ -133,6 +139,7 @@ enum isl29501_register_name { struct isl29501_register_desc { u8 msb; u8 lsb; + u8 exp; }; static const struct isl29501_register_desc isl29501_registers[] = { @@ -140,10 +147,25 @@ static const struct isl29501_register_desc isl29501_registers[] = { .msb = ISL29501_DISTANCE_MSB_DATA, .lsb = ISL29501_DISTANCE_LSB_DATA, }, + [REG_AMPLITUDE] = { + .msb = ISL29501_MAGNITUDE_MSB, + .lsb = ISL29501_MAGNITUDE_LSB, + .exp = ISL29501_MAGNITUDE_EXPONENT, + }, [REG_PHASE] = { .msb = ISL29501_PHASE_MSB, .lsb = ISL29501_PHASE_LSB, }, + [REG_I_RAW] = { + .msb = ISL29501_I_RAW_MSB, + .lsb = ISL29501_I_RAW_LSB, + .exp = ISL29501_I_RAW_EXPONENT, + }, + [REG_Q_RAW] = { + .msb = ISL29501_Q_RAW_MSB, + .lsb = ISL29501_Q_RAW_LSB, + .exp = ISL29501_Q_RAW_EXPONENT, + }, [REG_TEMPERATURE] = { .lsb = ISL29501_DIE_TEMPERATURE, }, @@ -154,10 +176,25 @@ static const struct isl29501_register_desc isl29501_registers[] = { .msb = ISL29501_GAIN_MSB, .lsb = ISL29501_GAIN_LSB, }, + [REG_I_BIAS] = { + .msb = ISL29501_CROSSTALK_I_MSB, + .lsb = ISL29501_CROSSTALK_I_LSB, + .exp = ISL29501_CROSSTALK_I_EXPONENT, + }, + [REG_Q_BIAS] = { + .msb = ISL29501_CROSSTALK_Q_MSB, + .lsb = ISL29501_CROSSTALK_Q_LSB, + .exp = ISL29501_CROSSTALK_Q_EXPONENT, + }, [REG_GAIN_BIAS] = { .msb = ISL29501_CROSSTALK_GAIN_MSB, .lsb = ISL29501_CROSSTALK_GAIN_LSB, }, + [REG_AMPL_BIAS] = { + .msb = ISL29501_MAGNITUDE_REF_MSB, + .lsb = ISL29501_MAGNITUDE_REF_LSB, + .exp = ISL29501_MAGNITUDE_REF_EXP, + }, [REG_PHASE_EXP] = { .lsb = ISL29501_PHASE_EXPONENT, }, @@ -199,7 +236,7 @@ static int isl29501_register_read(struct isl29501_private *isl29501, u32 *val) { const struct isl29501_register_desc *reg = &isl29501_registers[name]; - u8 msb = 0, lsb = 0; + u8 msb = 0, lsb = 0, exp = 0; s32 ret; mutex_lock(&isl29501->lock); @@ -216,9 +253,16 @@ static int isl29501_register_read(struct isl29501_private *isl29501, goto err; lsb = ret; } + + if (reg->exp) { + ret = i2c_smbus_read_byte_data(isl29501->client, reg->exp); + if (ret < 0) + goto err; + exp = ret; + } mutex_unlock(&isl29501->lock); - *val = (msb << 8) + lsb; + *val = ((msb << 8) + lsb) << exp; return 0; err: @@ -238,9 +282,14 @@ static u32 isl29501_register_write(struct isl29501_private *isl29501, if (!reg->msb && value > U8_MAX) return -ERANGE; - if (value > U16_MAX) + if (!reg->exp && value > U16_MAX) return -ERANGE; + if (reg->exp) { + /* TODO: Implement float write */ + return -EINVAL; + } + if (!reg->msb) { lsb = value & 0xFF; } else { @@ -519,6 +568,28 @@ static const struct iio_chan_spec isl29501_channels[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), }, + { + .type = IIO_INTENSITY, + .scan_index = -1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBBIAS), + }, + { + .type = IIO_INTENSITY, + .scan_index = -1, + .modified = 1, + .channel2 = IIO_MOD_I, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBBIAS), + }, + { + .type = IIO_INTENSITY, + .scan_index = -1, + .modified = 1, + .channel2 = IIO_MOD_Q, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBBIAS), + }, { .type = IIO_CURRENT, .scan_index = -1, @@ -633,13 +704,23 @@ static int isl29501_get_raw(struct isl29501_private *isl29501, return IIO_VAL_INT; case IIO_INTENSITY: - ret = isl29501_register_read(isl29501, - REG_AMBIENT_LIGHT, - raw); - if (ret < 0) - return ret; + switch (chan->channel2) { + case IIO_NO_MOD: + case IIO_MOD_I: + case IIO_MOD_Q: + /* TODO: implement float read */ + return -EINVAL; + case IIO_MOD_LIGHT_CLEAR: + ret = isl29501_register_read(isl29501, + REG_AMBIENT_LIGHT, + raw); + if (ret < 0) + return ret; - return IIO_VAL_INT; + return IIO_VAL_INT; + default: + return -EINVAL; + } case IIO_PHASE: ret = isl29501_register_read(isl29501, REG_PHASE, raw); if (ret < 0) @@ -684,6 +765,8 @@ static int isl29501_get_scale(struct isl29501_private *isl29501, return IIO_VAL_INT_PLUS_NANO; case IIO_INTENSITY: + if (chan->channel2 != IIO_MOD_LIGHT_CLEAR) + return -EINVAL; /* light = raw_light * 35 / 10000 (mA) */ *val = 35; *val2 = 10000; @@ -729,6 +812,16 @@ static int isl29501_get_calibbias(struct isl29501_private *isl29501, return isl29501_register_read(isl29501, REG_DISTANCE_BIAS, bias); + case IIO_INTENSITY: + switch (chan->channel2) { + case IIO_NO_MOD: + case IIO_MOD_I: + case IIO_MOD_Q: + /* TODO: Implement float read */ + return -EINVAL; + default: + return -EINVAL; + } case IIO_TEMP: return isl29501_register_read(isl29501, REG_TEMPERATURE_BIAS, @@ -858,6 +951,16 @@ static int isl29501_set_calibbias(struct isl29501_private *isl29501, return isl29501_register_write(isl29501, REG_DISTANCE_BIAS, bias); + case IIO_INTENSITY: + switch (chan->channel2) { + case IIO_NO_MOD: + case IIO_MOD_I: + case IIO_MOD_Q: + /* TODO: Implement float read */ + return -EINVAL; + default: + return -EINVAL; + } case IIO_TEMP: return isl29501_register_write(isl29501, REG_TEMPERATURE_BIAS, -- 2.17.1 -- To unsubscribe from this list: send the line "unsubscribe linux-iio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html