* [PATCH v2 1/3] iio: consumer.h: Fix kernel doc incosistency @ 2012-09-17 12:17 Lars-Peter Clausen 2012-09-17 12:17 ` [PATCH v2 2/3] iio:inkern: Add function to read the processed value Lars-Peter Clausen 2012-09-17 12:17 ` [PATCH v2 3/3] staging:iio:hwmon bridge: Use iio_read_channel_processed Lars-Peter Clausen 0 siblings, 2 replies; 5+ messages in thread From: Lars-Peter Clausen @ 2012-09-17 12:17 UTC (permalink / raw) To: Jonathan Cameron; +Cc: linux-iio, Milo Kim, anish kumar, Lars-Peter Clausen For the iio_read_channel_raw and iio_read_channel_scale the kerneldoc comment refers to an argument called "channel", while the argument is called "chan" in the function signature. This leads to the following warnings from kerneldoc: Warning(include/linux/iio/consumer.h:71): No description found for parameter 'chan' Warning(include/linux/iio/consumer.h:71): Excess function parameter 'channel' description in 'iio_read_channel_raw' Warning(include/linux/iio/consumer.h:109): No description found for parameter 'chan' Warning(include/linux/iio/consumer.h:109): Excess function parameter 'channel' description in 'iio_read_channel_scale' This patch fixes the warnings by naming them consistently. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> --- include/linux/iio/consumer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index 06ab4ec..62118dd 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -61,7 +61,7 @@ void iio_channel_release_all(struct iio_channel *chan); /** * iio_read_channel_raw() - read from a given channel - * @channel: The channel being queried. + * @chan: The channel being queried. * @val: Value read back. * * Note raw reads from iio channels are in adc counts and hence @@ -82,7 +82,7 @@ int iio_get_channel_type(struct iio_channel *channel, /** * iio_read_channel_scale() - read the scale value for a channel - * @channel: The channel being queried. + * @chan: The channel being queried. * @val: First part of value read back. * @val2: Second part of value read back. * -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/3] iio:inkern: Add function to read the processed value 2012-09-17 12:17 [PATCH v2 1/3] iio: consumer.h: Fix kernel doc incosistency Lars-Peter Clausen @ 2012-09-17 12:17 ` Lars-Peter Clausen 2012-09-17 20:55 ` Jonathan Cameron 2012-09-17 12:17 ` [PATCH v2 3/3] staging:iio:hwmon bridge: Use iio_read_channel_processed Lars-Peter Clausen 1 sibling, 1 reply; 5+ messages in thread From: Lars-Peter Clausen @ 2012-09-17 12:17 UTC (permalink / raw) To: Jonathan Cameron; +Cc: linux-iio, Milo Kim, anish kumar, Lars-Peter Clausen Add a function to read a processed value from a channel. The function will first attempt to read the IIO_CHAN_INFO_PROCESSED attribute. If that fails it will read the IIO_CHAN_INFO_RAW attribute and convert the result from a raw value to a processed value. The patch also introduces a function to convert raw value to a processed value and exports it, in case a user needs or wants to do the conversion by itself. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> --- Changes since v1: * Fix mixed up patch fragements between patch 2 and patch 3 --- drivers/iio/inkern.c | 114 ++++++++++++++++++++++++++++++++++++++---- include/linux/iio/consumer.h | 38 ++++++++++++++ include/linux/iio/iio.h | 17 +++++++ 3 files changed, 160 insertions(+), 9 deletions(-) diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 028c657..e53a7dd 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -229,9 +229,21 @@ void iio_channel_release_all(struct iio_channel *channels) } EXPORT_SYMBOL_GPL(iio_channel_release_all); +static int iio_channel_read(struct iio_channel *chan, int *val, int *val2, + enum iio_chan_info_enum info) +{ + int unused; + + if (val2 == NULL) + val2 = &unused; + + return chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel, + val, val2, info); +} + int iio_read_channel_raw(struct iio_channel *chan, int *val) { - int val2, ret; + int ret; mutex_lock(&chan->indio_dev->info_exist_lock); if (chan->indio_dev->info == NULL) { @@ -239,10 +251,7 @@ int iio_read_channel_raw(struct iio_channel *chan, int *val) goto err_unlock; } - ret = chan->indio_dev->info->read_raw(chan->indio_dev, - chan->channel, - val, &val2, - IIO_CHAN_INFO_RAW); + ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW); err_unlock: mutex_unlock(&chan->indio_dev->info_exist_lock); @@ -250,6 +259,96 @@ err_unlock: } EXPORT_SYMBOL_GPL(iio_read_channel_raw); +static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan, + int raw, int *processed, unsigned int scale) +{ + int scale_type, scale_val, scale_val2, offset; + s64 raw64 = raw; + int ret; + + ret = iio_channel_read(chan, &offset, NULL, IIO_CHAN_INFO_SCALE); + if (ret == 0) + raw64 += offset; + + scale_type = iio_channel_read(chan, &scale_val, &scale_val2, + IIO_CHAN_INFO_SCALE); + if (scale_type < 0) + return scale_type; + + switch (scale_type) { + case IIO_VAL_INT: + *processed = raw64 * scale_val; + break; + case IIO_VAL_INT_PLUS_MICRO: + if (scale_val2 < 0) + *processed = -raw64 * scale_val; + else + *processed = raw64 * scale_val; + *processed += div_s64(raw64 * (s64)scale_val2 * scale, 1000000LL); + break; + case IIO_VAL_INT_PLUS_NANO: + if (scale_val2 < 0) + *processed = -raw64 * scale_val; + else + *processed = raw64 * scale_val; + *processed += div_s64(raw64 * (s64)scale_val2 * scale, 1000000000LL); + break; + case IIO_VAL_FRACTIONAL: + *processed = div_s64(raw64 * (s64)scale_val * scale, scale_val2); + break; + default: + return -EINVAL; + } + + return 0; +} + +int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, + int *processed, unsigned int scale) +{ + int ret; + + mutex_lock(&chan->indio_dev->info_exist_lock); + if (chan->indio_dev->info == NULL) { + ret = -ENODEV; + goto err_unlock; + } + + ret = iio_convert_raw_to_processed_unlocked(chan, raw, processed, + scale); +err_unlock: + mutex_unlock(&chan->indio_dev->info_exist_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_convert_raw_to_processed); + +int iio_read_channel_processed(struct iio_channel *chan, int *val) +{ + int ret; + + mutex_lock(&chan->indio_dev->info_exist_lock); + if (chan->indio_dev->info == NULL) { + ret = -ENODEV; + goto err_unlock; + } + + if (iio_channel_has_info(chan->channel, IIO_CHAN_INFO_PROCESSED)) { + ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_PROCESSED); + } 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); + } + +err_unlock: + mutex_unlock(&chan->indio_dev->info_exist_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_read_channel_processed); + int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2) { int ret; @@ -260,10 +359,7 @@ int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2) goto err_unlock; } - ret = chan->indio_dev->info->read_raw(chan->indio_dev, - chan->channel, - val, val2, - IIO_CHAN_INFO_SCALE); + ret = iio_channel_read(chan, val, val2, IIO_CHAN_INFO_SCALE); err_unlock: mutex_unlock(&chan->indio_dev->info_exist_lock); diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index 62118dd..e875bcf 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -71,6 +71,21 @@ int iio_read_channel_raw(struct iio_channel *chan, int *val); /** + * iio_read_channel_processed() - read processed value from a given channel + * @chan: The channel being queried. + * @val: Value read back. + * + * Returns an error code or 0. + * + * This function will read a processed value from a channel. A processed value + * means that this value will have the correct unit and not some device internal + * representation. If the device does not support reporting a processed value + * the function will query the raw value and the channels scale and offset and + * do the appropriate transformation. + */ +int iio_read_channel_processed(struct iio_channel *chan, int *val); + +/** * iio_get_channel_type() - get the type of a channel * @channel: The channel being queried. * @type: The type of the channel. @@ -93,4 +108,27 @@ int iio_get_channel_type(struct iio_channel *channel, int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2); +/** + * iio_convert_raw_to_processed() - Converts a raw value to a processed value + * @chan: The channel being queried + * @raw: The raw IIO to convert + * @processed: The result of the conversion + * @scale: Scale factor to apply during the conversion + * + * Returns an error code or 0. + * + * This function converts a raw value to processed value for a specific channel. + * A raw value is the device internal representation of a sample and the value + * returned by iio_read_channel_raw, so the unit of that value is device + * depended. A processed value on the other hand is value has a normed unit + * according with the IIO specification. + * + * The scale factor allows to increase the precession of the returned value. For + * a scale factor of 1 the function will return the result in the normal IIO + * unit for the channel type. E.g. millivolt for voltage channels, if you want + * nanovolts instead pass 1000 as the scale factor. + */ +int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, + int *processed, unsigned int scale); + #endif diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 30affa5..c0ae76a 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -40,6 +40,8 @@ enum iio_chan_info_enum { #define IIO_CHAN_INFO_SHARED_BIT(type) BIT(type*2) #define IIO_CHAN_INFO_SEPARATE_BIT(type) BIT(type*2 + 1) +#define IIO_CHAN_INFO_BITS(type) (IIO_CHAN_INFO_SHARED_BIT(type) | \ + IIO_CHAN_INFO_SEPARATE_BIT(type)) #define IIO_CHAN_INFO_RAW_SEPARATE_BIT \ IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_RAW) @@ -261,6 +263,21 @@ struct iio_chan_spec { unsigned differential:1; }; + +/** + * iio_channel_has_info() - Checks whether a channel supports a info attribute + * @chan: The channel to be queried + * @type: Type of the info attribute to be checked + * + * Returns true if the channels supports reporting values for the given info + * attribute type, false otherwise. + */ +static inline bool iio_channel_has_info(const struct iio_chan_spec *chan, + enum iio_chan_info_enum type) +{ + return chan->info_mask & IIO_CHAN_INFO_BITS(type); +} + #define IIO_ST(si, rb, sb, sh) \ { .sign = si, .realbits = rb, .storagebits = sb, .shift = sh } -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/3] iio:inkern: Add function to read the processed value 2012-09-17 12:17 ` [PATCH v2 2/3] iio:inkern: Add function to read the processed value Lars-Peter Clausen @ 2012-09-17 20:55 ` Jonathan Cameron 2012-09-18 8:01 ` Lars-Peter Clausen 0 siblings, 1 reply; 5+ messages in thread From: Jonathan Cameron @ 2012-09-17 20:55 UTC (permalink / raw) To: Lars-Peter Clausen; +Cc: Jonathan Cameron, linux-iio, Milo Kim, anish kumar On 09/17/2012 01:17 PM, Lars-Peter Clausen wrote: > Add a function to read a processed value from a channel. The function will first > attempt to read the IIO_CHAN_INFO_PROCESSED attribute. If that fails it will > read the IIO_CHAN_INFO_RAW attribute and convert the result from a raw value to > a processed value. > > The patch also introduces a function to convert raw value to a processed value > and exports it, in case a user needs or wants to do the conversion by itself. > Another patch with a couple of overly long lines where readibility is not hurt by breaking them. Hence I have done so when merging. Please do fix the trivial stuff from checkpatch. Otherwise a good series and all merged to togreg branch. > Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> > --- > Changes since v1: > * Fix mixed up patch fragements between patch 2 and patch 3 > --- > drivers/iio/inkern.c | 114 ++++++++++++++++++++++++++++++++++++++---- > include/linux/iio/consumer.h | 38 ++++++++++++++ > include/linux/iio/iio.h | 17 +++++++ > 3 files changed, 160 insertions(+), 9 deletions(-) > > diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c > index 028c657..e53a7dd 100644 > --- a/drivers/iio/inkern.c > +++ b/drivers/iio/inkern.c > @@ -229,9 +229,21 @@ void iio_channel_release_all(struct iio_channel *channels) > } > EXPORT_SYMBOL_GPL(iio_channel_release_all); > > +static int iio_channel_read(struct iio_channel *chan, int *val, int *val2, > + enum iio_chan_info_enum info) > +{ > + int unused; > + > + if (val2 == NULL) > + val2 = &unused; > + > + return chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel, > + val, val2, info); > +} > + > int iio_read_channel_raw(struct iio_channel *chan, int *val) > { > - int val2, ret; > + int ret; > > mutex_lock(&chan->indio_dev->info_exist_lock); > if (chan->indio_dev->info == NULL) { > @@ -239,10 +251,7 @@ int iio_read_channel_raw(struct iio_channel *chan, int *val) > goto err_unlock; > } > > - ret = chan->indio_dev->info->read_raw(chan->indio_dev, > - chan->channel, > - val, &val2, > - IIO_CHAN_INFO_RAW); > + ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW); > err_unlock: > mutex_unlock(&chan->indio_dev->info_exist_lock); > > @@ -250,6 +259,96 @@ err_unlock: > } > EXPORT_SYMBOL_GPL(iio_read_channel_raw); > > +static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan, > + int raw, int *processed, unsigned int scale) > +{ > + int scale_type, scale_val, scale_val2, offset; > + s64 raw64 = raw; > + int ret; > + > + ret = iio_channel_read(chan, &offset, NULL, IIO_CHAN_INFO_SCALE); > + if (ret == 0) > + raw64 += offset; > + > + scale_type = iio_channel_read(chan, &scale_val, &scale_val2, > + IIO_CHAN_INFO_SCALE); > + if (scale_type < 0) > + return scale_type; > + > + switch (scale_type) { > + case IIO_VAL_INT: > + *processed = raw64 * scale_val; > + break; > + case IIO_VAL_INT_PLUS_MICRO: > + if (scale_val2 < 0) > + *processed = -raw64 * scale_val; > + else > + *processed = raw64 * scale_val; > + *processed += div_s64(raw64 * (s64)scale_val2 * scale, 1000000LL); > + break; > + case IIO_VAL_INT_PLUS_NANO: > + if (scale_val2 < 0) > + *processed = -raw64 * scale_val; > + else > + *processed = raw64 * scale_val; > + *processed += div_s64(raw64 * (s64)scale_val2 * scale, 1000000000LL); > + break; > + case IIO_VAL_FRACTIONAL: > + *processed = div_s64(raw64 * (s64)scale_val * scale, scale_val2); > + break; > + default: > + return -EINVAL; > + } > + > + return 0; > +} > + > +int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, > + int *processed, unsigned int scale) > +{ > + int ret; > + > + mutex_lock(&chan->indio_dev->info_exist_lock); > + if (chan->indio_dev->info == NULL) { > + ret = -ENODEV; > + goto err_unlock; > + } > + > + ret = iio_convert_raw_to_processed_unlocked(chan, raw, processed, > + scale); > +err_unlock: > + mutex_unlock(&chan->indio_dev->info_exist_lock); > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(iio_convert_raw_to_processed); > + > +int iio_read_channel_processed(struct iio_channel *chan, int *val) > +{ > + int ret; > + > + mutex_lock(&chan->indio_dev->info_exist_lock); > + if (chan->indio_dev->info == NULL) { > + ret = -ENODEV; > + goto err_unlock; > + } > + > + if (iio_channel_has_info(chan->channel, IIO_CHAN_INFO_PROCESSED)) { > + ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_PROCESSED); > + } 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); > + } > + > +err_unlock: > + mutex_unlock(&chan->indio_dev->info_exist_lock); > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(iio_read_channel_processed); > + > int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2) > { > int ret; > @@ -260,10 +359,7 @@ int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2) > goto err_unlock; > } > > - ret = chan->indio_dev->info->read_raw(chan->indio_dev, > - chan->channel, > - val, val2, > - IIO_CHAN_INFO_SCALE); > + ret = iio_channel_read(chan, val, val2, IIO_CHAN_INFO_SCALE); > err_unlock: > mutex_unlock(&chan->indio_dev->info_exist_lock); > > diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h > index 62118dd..e875bcf 100644 > --- a/include/linux/iio/consumer.h > +++ b/include/linux/iio/consumer.h > @@ -71,6 +71,21 @@ int iio_read_channel_raw(struct iio_channel *chan, > int *val); > > /** > + * iio_read_channel_processed() - read processed value from a given channel > + * @chan: The channel being queried. > + * @val: Value read back. > + * > + * Returns an error code or 0. > + * > + * This function will read a processed value from a channel. A processed value > + * means that this value will have the correct unit and not some device internal > + * representation. If the device does not support reporting a processed value > + * the function will query the raw value and the channels scale and offset and > + * do the appropriate transformation. > + */ > +int iio_read_channel_processed(struct iio_channel *chan, int *val); > + > +/** > * iio_get_channel_type() - get the type of a channel > * @channel: The channel being queried. > * @type: The type of the channel. > @@ -93,4 +108,27 @@ int iio_get_channel_type(struct iio_channel *channel, > int iio_read_channel_scale(struct iio_channel *chan, int *val, > int *val2); > > +/** > + * iio_convert_raw_to_processed() - Converts a raw value to a processed value > + * @chan: The channel being queried > + * @raw: The raw IIO to convert > + * @processed: The result of the conversion > + * @scale: Scale factor to apply during the conversion > + * > + * Returns an error code or 0. > + * > + * This function converts a raw value to processed value for a specific channel. > + * A raw value is the device internal representation of a sample and the value > + * returned by iio_read_channel_raw, so the unit of that value is device > + * depended. A processed value on the other hand is value has a normed unit > + * according with the IIO specification. > + * > + * The scale factor allows to increase the precession of the returned value. For > + * a scale factor of 1 the function will return the result in the normal IIO > + * unit for the channel type. E.g. millivolt for voltage channels, if you want > + * nanovolts instead pass 1000 as the scale factor. > + */ > +int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, > + int *processed, unsigned int scale); > + > #endif > diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h > index 30affa5..c0ae76a 100644 > --- a/include/linux/iio/iio.h > +++ b/include/linux/iio/iio.h > @@ -40,6 +40,8 @@ enum iio_chan_info_enum { > > #define IIO_CHAN_INFO_SHARED_BIT(type) BIT(type*2) > #define IIO_CHAN_INFO_SEPARATE_BIT(type) BIT(type*2 + 1) > +#define IIO_CHAN_INFO_BITS(type) (IIO_CHAN_INFO_SHARED_BIT(type) | \ > + IIO_CHAN_INFO_SEPARATE_BIT(type)) > > #define IIO_CHAN_INFO_RAW_SEPARATE_BIT \ > IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_RAW) > @@ -261,6 +263,21 @@ struct iio_chan_spec { > unsigned differential:1; > }; > > + > +/** > + * iio_channel_has_info() - Checks whether a channel supports a info attribute > + * @chan: The channel to be queried > + * @type: Type of the info attribute to be checked > + * > + * Returns true if the channels supports reporting values for the given info > + * attribute type, false otherwise. > + */ > +static inline bool iio_channel_has_info(const struct iio_chan_spec *chan, > + enum iio_chan_info_enum type) > +{ > + return chan->info_mask & IIO_CHAN_INFO_BITS(type); > +} > + > #define IIO_ST(si, rb, sb, sh) \ > { .sign = si, .realbits = rb, .storagebits = sb, .shift = sh } > > ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/3] iio:inkern: Add function to read the processed value 2012-09-17 20:55 ` Jonathan Cameron @ 2012-09-18 8:01 ` Lars-Peter Clausen 0 siblings, 0 replies; 5+ messages in thread From: Lars-Peter Clausen @ 2012-09-18 8:01 UTC (permalink / raw) To: Jonathan Cameron; +Cc: Jonathan Cameron, linux-iio, Milo Kim, anish kumar On 09/17/2012 10:55 PM, Jonathan Cameron wrote: > On 09/17/2012 01:17 PM, Lars-Peter Clausen wrote: >> Add a function to read a processed value from a channel. The function will first >> attempt to read the IIO_CHAN_INFO_PROCESSED attribute. If that fails it will >> read the IIO_CHAN_INFO_RAW attribute and convert the result from a raw value to >> a processed value. >> >> The patch also introduces a function to convert raw value to a processed value >> and exports it, in case a user needs or wants to do the conversion by itself. >> > Another patch with a couple of overly long lines where readibility is not hurt > by breaking them. Hence I have done so when merging. > Please do fix the trivial stuff from checkpatch. I tend to ignore the 80 line limit warnings from checkpatch on purpose if the line is only 81 or 82 characters long and breaking it would introduce a new line continuation. > > Otherwise a good series and all merged to togreg branch. > Thanks. >> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> >> --- >> Changes since v1: >> * Fix mixed up patch fragements between patch 2 and patch 3 >> --- >> drivers/iio/inkern.c | 114 ++++++++++++++++++++++++++++++++++++++---- >> include/linux/iio/consumer.h | 38 ++++++++++++++ >> include/linux/iio/iio.h | 17 +++++++ >> 3 files changed, 160 insertions(+), 9 deletions(-) >> >> diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c >> index 028c657..e53a7dd 100644 >> --- a/drivers/iio/inkern.c >> +++ b/drivers/iio/inkern.c >> @@ -229,9 +229,21 @@ void iio_channel_release_all(struct iio_channel *channels) >> } >> EXPORT_SYMBOL_GPL(iio_channel_release_all); >> >> +static int iio_channel_read(struct iio_channel *chan, int *val, int *val2, >> + enum iio_chan_info_enum info) >> +{ >> + int unused; >> + >> + if (val2 == NULL) >> + val2 = &unused; >> + >> + return chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel, >> + val, val2, info); >> +} >> + >> int iio_read_channel_raw(struct iio_channel *chan, int *val) >> { >> - int val2, ret; >> + int ret; >> >> mutex_lock(&chan->indio_dev->info_exist_lock); >> if (chan->indio_dev->info == NULL) { >> @@ -239,10 +251,7 @@ int iio_read_channel_raw(struct iio_channel *chan, int *val) >> goto err_unlock; >> } >> >> - ret = chan->indio_dev->info->read_raw(chan->indio_dev, >> - chan->channel, >> - val, &val2, >> - IIO_CHAN_INFO_RAW); >> + ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW); >> err_unlock: >> mutex_unlock(&chan->indio_dev->info_exist_lock); >> >> @@ -250,6 +259,96 @@ err_unlock: >> } >> EXPORT_SYMBOL_GPL(iio_read_channel_raw); >> >> +static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan, >> + int raw, int *processed, unsigned int scale) >> +{ >> + int scale_type, scale_val, scale_val2, offset; >> + s64 raw64 = raw; >> + int ret; >> + >> + ret = iio_channel_read(chan, &offset, NULL, IIO_CHAN_INFO_SCALE); >> + if (ret == 0) >> + raw64 += offset; >> + >> + scale_type = iio_channel_read(chan, &scale_val, &scale_val2, >> + IIO_CHAN_INFO_SCALE); >> + if (scale_type < 0) >> + return scale_type; >> + >> + switch (scale_type) { >> + case IIO_VAL_INT: >> + *processed = raw64 * scale_val; >> + break; >> + case IIO_VAL_INT_PLUS_MICRO: >> + if (scale_val2 < 0) >> + *processed = -raw64 * scale_val; >> + else >> + *processed = raw64 * scale_val; >> + *processed += div_s64(raw64 * (s64)scale_val2 * scale, 1000000LL); >> + break; >> + case IIO_VAL_INT_PLUS_NANO: >> + if (scale_val2 < 0) >> + *processed = -raw64 * scale_val; >> + else >> + *processed = raw64 * scale_val; >> + *processed += div_s64(raw64 * (s64)scale_val2 * scale, 1000000000LL); >> + break; >> + case IIO_VAL_FRACTIONAL: >> + *processed = div_s64(raw64 * (s64)scale_val * scale, scale_val2); >> + break; >> + default: >> + return -EINVAL; >> + } >> + >> + return 0; >> +} >> + >> +int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, >> + int *processed, unsigned int scale) >> +{ >> + int ret; >> + >> + mutex_lock(&chan->indio_dev->info_exist_lock); >> + if (chan->indio_dev->info == NULL) { >> + ret = -ENODEV; >> + goto err_unlock; >> + } >> + >> + ret = iio_convert_raw_to_processed_unlocked(chan, raw, processed, >> + scale); >> +err_unlock: >> + mutex_unlock(&chan->indio_dev->info_exist_lock); >> + >> + return ret; >> +} >> +EXPORT_SYMBOL_GPL(iio_convert_raw_to_processed); >> + >> +int iio_read_channel_processed(struct iio_channel *chan, int *val) >> +{ >> + int ret; >> + >> + mutex_lock(&chan->indio_dev->info_exist_lock); >> + if (chan->indio_dev->info == NULL) { >> + ret = -ENODEV; >> + goto err_unlock; >> + } >> + >> + if (iio_channel_has_info(chan->channel, IIO_CHAN_INFO_PROCESSED)) { >> + ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_PROCESSED); >> + } 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); >> + } >> + >> +err_unlock: >> + mutex_unlock(&chan->indio_dev->info_exist_lock); >> + >> + return ret; >> +} >> +EXPORT_SYMBOL_GPL(iio_read_channel_processed); >> + >> int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2) >> { >> int ret; >> @@ -260,10 +359,7 @@ int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2) >> goto err_unlock; >> } >> >> - ret = chan->indio_dev->info->read_raw(chan->indio_dev, >> - chan->channel, >> - val, val2, >> - IIO_CHAN_INFO_SCALE); >> + ret = iio_channel_read(chan, val, val2, IIO_CHAN_INFO_SCALE); >> err_unlock: >> mutex_unlock(&chan->indio_dev->info_exist_lock); >> >> diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h >> index 62118dd..e875bcf 100644 >> --- a/include/linux/iio/consumer.h >> +++ b/include/linux/iio/consumer.h >> @@ -71,6 +71,21 @@ int iio_read_channel_raw(struct iio_channel *chan, >> int *val); >> >> /** >> + * iio_read_channel_processed() - read processed value from a given channel >> + * @chan: The channel being queried. >> + * @val: Value read back. >> + * >> + * Returns an error code or 0. >> + * >> + * This function will read a processed value from a channel. A processed value >> + * means that this value will have the correct unit and not some device internal >> + * representation. If the device does not support reporting a processed value >> + * the function will query the raw value and the channels scale and offset and >> + * do the appropriate transformation. >> + */ >> +int iio_read_channel_processed(struct iio_channel *chan, int *val); >> + >> +/** >> * iio_get_channel_type() - get the type of a channel >> * @channel: The channel being queried. >> * @type: The type of the channel. >> @@ -93,4 +108,27 @@ int iio_get_channel_type(struct iio_channel *channel, >> int iio_read_channel_scale(struct iio_channel *chan, int *val, >> int *val2); >> >> +/** >> + * iio_convert_raw_to_processed() - Converts a raw value to a processed value >> + * @chan: The channel being queried >> + * @raw: The raw IIO to convert >> + * @processed: The result of the conversion >> + * @scale: Scale factor to apply during the conversion >> + * >> + * Returns an error code or 0. >> + * >> + * This function converts a raw value to processed value for a specific channel. >> + * A raw value is the device internal representation of a sample and the value >> + * returned by iio_read_channel_raw, so the unit of that value is device >> + * depended. A processed value on the other hand is value has a normed unit >> + * according with the IIO specification. >> + * >> + * The scale factor allows to increase the precession of the returned value. For >> + * a scale factor of 1 the function will return the result in the normal IIO >> + * unit for the channel type. E.g. millivolt for voltage channels, if you want >> + * nanovolts instead pass 1000 as the scale factor. >> + */ >> +int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, >> + int *processed, unsigned int scale); >> + >> #endif >> diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h >> index 30affa5..c0ae76a 100644 >> --- a/include/linux/iio/iio.h >> +++ b/include/linux/iio/iio.h >> @@ -40,6 +40,8 @@ enum iio_chan_info_enum { >> >> #define IIO_CHAN_INFO_SHARED_BIT(type) BIT(type*2) >> #define IIO_CHAN_INFO_SEPARATE_BIT(type) BIT(type*2 + 1) >> +#define IIO_CHAN_INFO_BITS(type) (IIO_CHAN_INFO_SHARED_BIT(type) | \ >> + IIO_CHAN_INFO_SEPARATE_BIT(type)) >> >> #define IIO_CHAN_INFO_RAW_SEPARATE_BIT \ >> IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_RAW) >> @@ -261,6 +263,21 @@ struct iio_chan_spec { >> unsigned differential:1; >> }; >> >> + >> +/** >> + * iio_channel_has_info() - Checks whether a channel supports a info attribute >> + * @chan: The channel to be queried >> + * @type: Type of the info attribute to be checked >> + * >> + * Returns true if the channels supports reporting values for the given info >> + * attribute type, false otherwise. >> + */ >> +static inline bool iio_channel_has_info(const struct iio_chan_spec *chan, >> + enum iio_chan_info_enum type) >> +{ >> + return chan->info_mask & IIO_CHAN_INFO_BITS(type); >> +} >> + >> #define IIO_ST(si, rb, sb, sh) \ >> { .sign = si, .realbits = rb, .storagebits = sb, .shift = sh } >> >> > -- > To unsubscribe from this list: send the line "unsubscribe linux-iio" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 3/3] staging:iio:hwmon bridge: Use iio_read_channel_processed 2012-09-17 12:17 [PATCH v2 1/3] iio: consumer.h: Fix kernel doc incosistency Lars-Peter Clausen 2012-09-17 12:17 ` [PATCH v2 2/3] iio:inkern: Add function to read the processed value Lars-Peter Clausen @ 2012-09-17 12:17 ` Lars-Peter Clausen 1 sibling, 0 replies; 5+ messages in thread From: Lars-Peter Clausen @ 2012-09-17 12:17 UTC (permalink / raw) To: Jonathan Cameron; +Cc: linux-iio, Milo Kim, anish kumar, Lars-Peter Clausen Use the iio_read_channel_processed function to read the sample value in the proper unit instead of using iio_read_channel_raw and iio_read_channel_scale and doing the unit conversion manually. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> --- Changes since v1: * Fix mixed up patch fragements between patch 2 and patch 3 --- drivers/staging/iio/iio_hwmon.c | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/drivers/staging/iio/iio_hwmon.c b/drivers/staging/iio/iio_hwmon.c index 69d4a3b..5d49122 100644 --- a/drivers/staging/iio/iio_hwmon.c +++ b/drivers/staging/iio/iio_hwmon.c @@ -42,40 +42,17 @@ static ssize_t iio_hwmon_read_val(struct device *dev, struct device_attribute *attr, char *buf) { - long result; - int val, ret, scaleint, scalepart; + int result; + int ret; struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); struct iio_hwmon_state *state = dev_get_drvdata(dev); - /* - * No locking between this pair, so theoretically possible - * the scale has changed. - */ - ret = iio_read_channel_raw(&state->channels[sattr->index], - &val); + ret = iio_read_channel_processed(&state->channels[sattr->index], + &result); if (ret < 0) return ret; - ret = iio_read_channel_scale(&state->channels[sattr->index], - &scaleint, &scalepart); - if (ret < 0) - return ret; - switch (ret) { - case IIO_VAL_INT: - result = val * scaleint; - break; - case IIO_VAL_INT_PLUS_MICRO: - result = (s64)val * (s64)scaleint + - div_s64((s64)val * (s64)scalepart, 1000000LL); - break; - case IIO_VAL_INT_PLUS_NANO: - result = (s64)val * (s64)scaleint + - div_s64((s64)val * (s64)scalepart, 1000000000LL); - break; - default: - return -EINVAL; - } - return sprintf(buf, "%ld\n", result); + return sprintf(buf, "%d\n", result); } static void iio_hwmon_free_attrs(struct iio_hwmon_state *st) -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-09-18 8:01 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-09-17 12:17 [PATCH v2 1/3] iio: consumer.h: Fix kernel doc incosistency Lars-Peter Clausen 2012-09-17 12:17 ` [PATCH v2 2/3] iio:inkern: Add function to read the processed value Lars-Peter Clausen 2012-09-17 20:55 ` Jonathan Cameron 2012-09-18 8:01 ` Lars-Peter Clausen 2012-09-17 12:17 ` [PATCH v2 3/3] staging:iio:hwmon bridge: Use iio_read_channel_processed Lars-Peter Clausen
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.