Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

iio: afe: iio-rescale: Support processed channels

It happens that an ADC will only provide raw or processed
voltage conversion channels. (adc/ab8500-gpadc.c).
On the Samsung GT-I9070 this is used for a light sensor
and current sense amplifier so we need to think of something.

The idea is to allow processed channels and scale them
with 1/1 and then the rescaler can modify the result
on top.

Link: https://lore.kernel.org/linux-iio/20201101232211.1194304-1-linus.walleij@linaro.org/
Cc: Peter Rosin <peda@axentia.se>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Peter Rosin <peda@axentia.se>
Link: https://lore.kernel.org/r/20210518092741.403080-1-linus.walleij@linaro.org
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Linus Walleij and committed by
Jonathan Cameron
53ebee94 842b1722

+35 -6
+35 -6
drivers/iio/afe/iio-rescale.c
··· 29 29 struct iio_channel *source; 30 30 struct iio_chan_spec chan; 31 31 struct iio_chan_spec_ext_info *ext_info; 32 + bool chan_processed; 32 33 s32 numerator; 33 34 s32 denominator; 34 35 }; ··· 44 43 45 44 switch (mask) { 46 45 case IIO_CHAN_INFO_RAW: 47 - return iio_read_channel_raw(rescale->source, val); 46 + if (rescale->chan_processed) 47 + /* 48 + * When only processed channels are supported, we 49 + * read the processed data and scale it by 1/1 50 + * augmented with whatever the rescaler has calculated. 51 + */ 52 + return iio_read_channel_processed(rescale->source, val); 53 + else 54 + return iio_read_channel_raw(rescale->source, val); 48 55 49 56 case IIO_CHAN_INFO_SCALE: 50 - ret = iio_read_channel_scale(rescale->source, val, val2); 57 + if (rescale->chan_processed) { 58 + /* 59 + * Processed channels are scaled 1-to-1 60 + */ 61 + *val = 1; 62 + *val2 = 1; 63 + ret = IIO_VAL_FRACTIONAL; 64 + } else { 65 + ret = iio_read_channel_scale(rescale->source, val, val2); 66 + } 51 67 switch (ret) { 52 68 case IIO_VAL_FRACTIONAL: 53 69 *val *= rescale->numerator; ··· 148 130 chan->ext_info = rescale->ext_info; 149 131 chan->type = rescale->cfg->type; 150 132 151 - if (!iio_channel_has_info(schan, IIO_CHAN_INFO_RAW) || 152 - !iio_channel_has_info(schan, IIO_CHAN_INFO_SCALE)) { 153 - dev_err(dev, "source channel does not support raw/scale\n"); 133 + if (iio_channel_has_info(schan, IIO_CHAN_INFO_RAW) || 134 + iio_channel_has_info(schan, IIO_CHAN_INFO_SCALE)) { 135 + dev_info(dev, "using raw+scale source channel\n"); 136 + } else if (iio_channel_has_info(schan, IIO_CHAN_INFO_PROCESSED)) { 137 + dev_info(dev, "using processed channel\n"); 138 + rescale->chan_processed = true; 139 + } else { 140 + dev_err(dev, "source channel is not supported\n"); 154 141 return -EINVAL; 155 142 } 156 143 157 144 chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 158 145 BIT(IIO_CHAN_INFO_SCALE); 159 146 160 - if (iio_channel_has_available(schan, IIO_CHAN_INFO_RAW)) 147 + /* 148 + * Using .read_avail() is fringe to begin with and makes no sense 149 + * whatsoever for processed channels, so we make sure that this cannot 150 + * be called on a processed channel. 151 + */ 152 + if (iio_channel_has_available(schan, IIO_CHAN_INFO_RAW) && 153 + !rescale->chan_processed) 161 154 chan->info_mask_separate_available |= BIT(IIO_CHAN_INFO_RAW); 162 155 163 156 return 0;