diff options
Diffstat (limited to 'drivers/iio/adc/ad7192.c')
-rw-r--r-- | drivers/iio/adc/ad7192.c | 124 |
1 files changed, 65 insertions, 59 deletions
diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c index cfaf8f7e0a07..530e1d307860 100644 --- a/drivers/iio/adc/ad7192.c +++ b/drivers/iio/adc/ad7192.c @@ -7,6 +7,7 @@ #include <linux/interrupt.h> #include <linux/bitfield.h> +#include <linux/cleanup.h> #include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/device.h> @@ -256,6 +257,9 @@ static ssize_t ad7192_write_syscalib(struct iio_dev *indio_dev, if (ret) return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + temp = st->syscalib_mode[chan->channel]; if (sys_calib) { if (temp == AD7192_SYSCALIB_ZERO_SCALE) @@ -266,6 +270,8 @@ static ssize_t ad7192_write_syscalib(struct iio_dev *indio_dev, chan->address); } + iio_device_release_direct(indio_dev); + return ret ? ret : len; } @@ -693,9 +699,8 @@ static ssize_t ad7192_set(struct device *dev, if (ret < 0) return ret; - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; switch ((u32)this_attr->address) { case AD7192_REG_GPOCON: @@ -718,7 +723,7 @@ static ssize_t ad7192_set(struct device *dev, ret = -EINVAL; } - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret ? ret : len; } @@ -945,82 +950,83 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, return -EINVAL; } -static int ad7192_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) +static int __ad7192_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) { struct ad7192_state *st = iio_priv(indio_dev); - int ret, i, div; + int i, div; unsigned int tmp; - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; - - mutex_lock(&st->lock); + guard(mutex)(&st->lock); switch (mask) { case IIO_CHAN_INFO_SCALE: - ret = -EINVAL; - for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) - if (val2 == st->scale_avail[i][1]) { - ret = 0; - tmp = st->conf; - st->conf &= ~AD7192_CONF_GAIN_MASK; - st->conf |= FIELD_PREP(AD7192_CONF_GAIN_MASK, i); - if (tmp == st->conf) - break; - ad_sd_write_reg(&st->sd, AD7192_REG_CONF, - 3, st->conf); - ad7192_calibrate_all(st); - break; - } - break; - case IIO_CHAN_INFO_SAMP_FREQ: - if (!val) { - ret = -EINVAL; - break; + for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) { + if (val2 != st->scale_avail[i][1]) + continue; + + tmp = st->conf; + st->conf &= ~AD7192_CONF_GAIN_MASK; + st->conf |= FIELD_PREP(AD7192_CONF_GAIN_MASK, i); + if (tmp == st->conf) + return 0; + ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf); + ad7192_calibrate_all(st); + return 0; } + return -EINVAL; + case IIO_CHAN_INFO_SAMP_FREQ: + if (!val) + return -EINVAL; div = st->fclk / (val * ad7192_get_f_order(st) * 1024); - if (div < 1 || div > 1023) { - ret = -EINVAL; - break; - } + if (div < 1 || div > 1023) + return -EINVAL; st->mode &= ~AD7192_MODE_RATE_MASK; st->mode |= FIELD_PREP(AD7192_MODE_RATE_MASK, div); ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); ad7192_update_filter_freq_avail(st); - break; + return 0; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - ret = ad7192_set_3db_filter_freq(st, val, val2 / 1000); - break; + return ad7192_set_3db_filter_freq(st, val, val2 / 1000); case IIO_CHAN_INFO_OVERSAMPLING_RATIO: - ret = -EINVAL; - for (i = 0; i < ARRAY_SIZE(st->oversampling_ratio_avail); i++) - if (val == st->oversampling_ratio_avail[i]) { - ret = 0; - tmp = st->mode; - st->mode &= ~AD7192_MODE_AVG_MASK; - st->mode |= FIELD_PREP(AD7192_MODE_AVG_MASK, i); - if (tmp == st->mode) - break; - ad_sd_write_reg(&st->sd, AD7192_REG_MODE, - 3, st->mode); - break; - } - ad7192_update_filter_freq_avail(st); - break; + for (i = 0; i < ARRAY_SIZE(st->oversampling_ratio_avail); i++) { + if (val != st->oversampling_ratio_avail[i]) + continue; + + tmp = st->mode; + st->mode &= ~AD7192_MODE_AVG_MASK; + st->mode |= FIELD_PREP(AD7192_MODE_AVG_MASK, i); + if (tmp == st->mode) + return 0; + ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); + ad7192_update_filter_freq_avail(st); + return 0; + } + return -EINVAL; default: - ret = -EINVAL; + return -EINVAL; } +} + +static int ad7192_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + int ret; + + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; - mutex_unlock(&st->lock); + ret = __ad7192_write_raw(indio_dev, chan, val, val2, mask); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; } |