Skip to content

Commit

Permalink
iio/adc: ingenic: Fix channel offsets in buffer
Browse files Browse the repository at this point in the history
Consumers expect the buffer to only contain enabled channels. While
preparing the buffer, the driver makes two mistakes:
1) It inserts empty data for disabled channels.
2) Each ADC readout contains samples for two 16-bit channels. If either
   of them is active, the whole 32-bit sample is pushed into the buffer
   as-is.

Both of those issues cause the active channels to appear at the wrong
offsets in the buffer. Fix the above by demuxing samples for active
channels only.

This has remained unnoticed, as all the consumers so far were only using
channels 0 and 1, leaving them unaffected by changes introduced in this
commit.

Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
Tested-by: Paul Cercueil <paul@crapouillou.net>
  • Loading branch information
zear authored and intel-lab-lkp committed May 21, 2023
1 parent a508fbf commit ffc0198
Showing 1 changed file with 13 additions and 7 deletions.
20 changes: 13 additions & 7 deletions drivers/iio/adc/ingenic-adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -802,13 +802,19 @@ static irqreturn_t ingenic_adc_irq(int irq, void *data)
struct ingenic_adc *adc = iio_priv(iio_dev);
unsigned long mask = iio_dev->active_scan_mask[0];
unsigned int i;
u32 tdat[3];

for (i = 0; i < ARRAY_SIZE(tdat); mask >>= 2, i++) {
if (mask & 0x3)
tdat[i] = readl(adc->base + JZ_ADC_REG_ADTCH);
else
tdat[i] = 0;
u16 tdat[6];
u32 val;

memset(tdat, 0, ARRAY_SIZE(tdat));
for (i = 0; mask && i < ARRAY_SIZE(tdat); mask >>= 2) {
if (mask & 0x3) {
val = readl(adc->base + JZ_ADC_REG_ADTCH);
/* Two channels per sample. Demux active. */
if (mask & BIT(0))
tdat[i++] = val & 0xffff;
if (mask & BIT(1))
tdat[i++] = val >> 16;
}
}

iio_push_to_buffers(iio_dev, tdat);
Expand Down

0 comments on commit ffc0198

Please sign in to comment.