iio: Provide iio_read_channel_processed_scale() API
authorLinus Walleij <linus.walleij@linaro.org>
Mon, 8 Mar 2021 10:02:18 +0000 (11:02 +0100)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Thu, 25 Mar 2021 19:13:51 +0000 (19:13 +0000)
Since the old iio_read_channel_processed() would
lose precision if we fall back to reading raw and
scaling, we introduce a new API that will pass in
a scale factor when reading a processed channel:
iio_read_channel_processed_scale().

Refactor iio_read_channel_processed() as a special
case with scale factor 1.

Cc: Peter Rosin <peda@axentia.se>
Cc: Chris Lesiak <chris.lesiak@licor.com>
Cc: Jonathan Cameron <jic23@kernel.org>
Cc: linux-iio@vger.kernel.org
Link: https://lore.kernel.org/linux-iio/20201224011607.1059534-1-linus.walleij@linaro.org/
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20210308100219.2732156-1-linus.walleij@linaro.org
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/inkern.c
include/linux/iio/consumer.h

index db77a2d..c61fc06 100644 (file)
@@ -688,7 +688,8 @@ int iio_read_channel_offset(struct iio_channel *chan, int *val, int *val2)
 }
 EXPORT_SYMBOL_GPL(iio_read_channel_offset);
 
-int iio_read_channel_processed(struct iio_channel *chan, int *val)
+int iio_read_channel_processed_scale(struct iio_channel *chan, int *val,
+                                    unsigned int scale)
 {
        int ret;
 
@@ -701,11 +702,15 @@ int iio_read_channel_processed(struct iio_channel *chan, int *val)
        if (iio_channel_has_info(chan->channel, IIO_CHAN_INFO_PROCESSED)) {
                ret = iio_channel_read(chan, val, NULL,
                                       IIO_CHAN_INFO_PROCESSED);
+               if (ret)
+                       goto err_unlock;
+               *val *= scale;
        } else {
                ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW);
                if (ret < 0)
                        goto err_unlock;
-               ret = iio_convert_raw_to_processed_unlocked(chan, *val, val, 1);
+               ret = iio_convert_raw_to_processed_unlocked(chan, *val, val,
+                                                           scale);
        }
 
 err_unlock:
@@ -713,6 +718,13 @@ err_unlock:
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(iio_read_channel_processed_scale);
+
+int iio_read_channel_processed(struct iio_channel *chan, int *val)
+{
+       /* This is just a special case with scale factor 1 */
+       return iio_read_channel_processed_scale(chan, val, 1);
+}
 EXPORT_SYMBOL_GPL(iio_read_channel_processed);
 
 int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2)
index 0a90ba8..5fa5957 100644 (file)
@@ -241,6 +241,21 @@ int iio_read_channel_average_raw(struct iio_channel *chan, int *val);
  */
 int iio_read_channel_processed(struct iio_channel *chan, int *val);
 
+/**
+ * iio_read_channel_processed_scale() - read and scale a processed value
+ * @chan:              The channel being queried.
+ * @val:               Value read back.
+ * @scale:             Scale factor to apply during the conversion
+ *
+ * Returns an error code or 0.
+ *
+ * This function will read a processed value from a channel. This will work
+ * like @iio_read_channel_processed() but also scale with an additional
+ * scale factor while attempting to minimize any precision loss.
+ */
+int iio_read_channel_processed_scale(struct iio_channel *chan, int *val,
+                                    unsigned int scale);
+
 /**
  * iio_write_channel_attribute() - Write values to the device attribute.
  * @chan:      The channel being queried.