Skip to content

Commit

Permalink
iio: si1133: read 24-bit signed integer for measurement
Browse files Browse the repository at this point in the history
The chip is configured in 24 bit mode. The values read from
it must always be treated as is. This fixes the issue by
replacing the previous 16 bits value by a 24 bits buffer.

This changes affects the value output by previous version of
the driver, since the least significant byte was missing.
The upper half of 16 bit values previously output are now
the upper half of a 24 bit value.

Fixes: e01e7ea ("iio: light: introduce si1133")

Reported-by: Simon Goyette <[email protected]>
Co-authored-by: Guillaume Champagne <[email protected]>
Signed-off-by: Maxime Roussin-Bélanger <[email protected]>
Signed-off-by: Guillaume Champagne <[email protected]>
Signed-off-by: Jonathan Cameron <[email protected]>
  • Loading branch information
2 people authored and jic23 committed Mar 8, 2020
1 parent ea52c21 commit 328b50e
Showing 1 changed file with 24 additions and 13 deletions.
37 changes: 24 additions & 13 deletions drivers/iio/light/si1133.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@
#define SI1133_INPUT_FRACTION_LOW 15
#define SI1133_LUX_OUTPUT_FRACTION 12
#define SI1133_LUX_BUFFER_SIZE 9
#define SI1133_MEASURE_BUFFER_SIZE 3

#define SI1133_SIGN_BIT_INDEX 23

static const int si1133_scale_available[] = {
1, 2, 4, 8, 16, 32, 64, 128};
Expand Down Expand Up @@ -234,13 +237,13 @@ static const struct si1133_lux_coeff lux_coeff = {
}
};

static int si1133_calculate_polynomial_inner(u32 input, u8 fraction, u16 mag,
static int si1133_calculate_polynomial_inner(s32 input, u8 fraction, u16 mag,
s8 shift)
{
return ((input << fraction) / mag) << shift;
}

static int si1133_calculate_output(u32 x, u32 y, u8 x_order, u8 y_order,
static int si1133_calculate_output(s32 x, s32 y, u8 x_order, u8 y_order,
u8 input_fraction, s8 sign,
const struct si1133_coeff *coeffs)
{
Expand Down Expand Up @@ -276,7 +279,7 @@ static int si1133_calculate_output(u32 x, u32 y, u8 x_order, u8 y_order,
* The algorithm is from:
* https://siliconlabs.github.io/Gecko_SDK_Doc/efm32zg/html/si1133_8c_source.html#l00716
*/
static int si1133_calc_polynomial(u32 x, u32 y, u8 input_fraction, u8 num_coeff,
static int si1133_calc_polynomial(s32 x, s32 y, u8 input_fraction, u8 num_coeff,
const struct si1133_coeff *coeffs)
{
u8 x_order, y_order;
Expand Down Expand Up @@ -614,7 +617,7 @@ static int si1133_measure(struct si1133_data *data,
{
int err;

__be16 resp;
u8 buffer[SI1133_MEASURE_BUFFER_SIZE];

err = si1133_set_adcmux(data, 0, chan->channel);
if (err)
Expand All @@ -625,12 +628,13 @@ static int si1133_measure(struct si1133_data *data,
if (err)
return err;

err = si1133_bulk_read(data, SI1133_REG_HOSTOUT(0), sizeof(resp),
(u8 *)&resp);
err = si1133_bulk_read(data, SI1133_REG_HOSTOUT(0), sizeof(buffer),
buffer);
if (err)
return err;

*val = be16_to_cpu(resp);
*val = sign_extend32((buffer[0] << 16) | (buffer[1] << 8) | buffer[2],
SI1133_SIGN_BIT_INDEX);

return err;
}
Expand Down Expand Up @@ -704,9 +708,9 @@ static int si1133_get_lux(struct si1133_data *data, int *val)
{
int err;
int lux;
u32 high_vis;
u32 low_vis;
u32 ir;
s32 high_vis;
s32 low_vis;
s32 ir;
u8 buffer[SI1133_LUX_BUFFER_SIZE];

/* Activate lux channels */
Expand All @@ -719,9 +723,16 @@ static int si1133_get_lux(struct si1133_data *data, int *val)
if (err)
return err;

high_vis = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
low_vis = (buffer[3] << 16) | (buffer[4] << 8) | buffer[5];
ir = (buffer[6] << 16) | (buffer[7] << 8) | buffer[8];
high_vis =
sign_extend32((buffer[0] << 16) | (buffer[1] << 8) | buffer[2],
SI1133_SIGN_BIT_INDEX);

low_vis =
sign_extend32((buffer[3] << 16) | (buffer[4] << 8) | buffer[5],
SI1133_SIGN_BIT_INDEX);

ir = sign_extend32((buffer[6] << 16) | (buffer[7] << 8) | buffer[8],
SI1133_SIGN_BIT_INDEX);

if (high_vis > SI1133_ADC_THRESHOLD || ir > SI1133_ADC_THRESHOLD)
lux = si1133_calc_polynomial(high_vis, ir,
Expand Down

0 comments on commit 328b50e

Please sign in to comment.