iio: dac: dac5571: Support powerdown for multi-channel

The driver currently only allows channel 0 to be powered down but the
multi-channel variants of the hardware allow each channel to be powered
down separately and with separate power down modes.  Add support for
this.

Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
Acked-by: Sean Nyekjaer <sean@geanix.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
Vincent Whitchurch 2020-08-04 11:31:38 +02:00 коммит произвёл Jonathan Cameron
Родитель abfa391721
Коммит 5dfb88af3d
1 изменённых файлов: 15 добавлений и 14 удалений

Просмотреть файл

@ -47,8 +47,8 @@ struct dac5571_data {
struct mutex lock; struct mutex lock;
struct regulator *vref; struct regulator *vref;
u16 val[4]; u16 val[4];
bool powerdown; bool powerdown[4];
u8 powerdown_mode; u8 powerdown_mode[4];
struct dac5571_spec const *spec; struct dac5571_spec const *spec;
int (*dac5571_cmd)(struct dac5571_data *data, int channel, u16 val); int (*dac5571_cmd)(struct dac5571_data *data, int channel, u16 val);
int (*dac5571_pwrdwn)(struct dac5571_data *data, int channel, u8 pwrdwn); int (*dac5571_pwrdwn)(struct dac5571_data *data, int channel, u8 pwrdwn);
@ -125,7 +125,7 @@ static int dac5571_get_powerdown_mode(struct iio_dev *indio_dev,
{ {
struct dac5571_data *data = iio_priv(indio_dev); struct dac5571_data *data = iio_priv(indio_dev);
return data->powerdown_mode; return data->powerdown_mode[chan->channel];
} }
static int dac5571_set_powerdown_mode(struct iio_dev *indio_dev, static int dac5571_set_powerdown_mode(struct iio_dev *indio_dev,
@ -135,17 +135,17 @@ static int dac5571_set_powerdown_mode(struct iio_dev *indio_dev,
struct dac5571_data *data = iio_priv(indio_dev); struct dac5571_data *data = iio_priv(indio_dev);
int ret = 0; int ret = 0;
if (data->powerdown_mode == mode) if (data->powerdown_mode[chan->channel] == mode)
return 0; return 0;
mutex_lock(&data->lock); mutex_lock(&data->lock);
if (data->powerdown) { if (data->powerdown[chan->channel]) {
ret = data->dac5571_pwrdwn(data, chan->channel, ret = data->dac5571_pwrdwn(data, chan->channel,
DAC5571_POWERDOWN(mode)); DAC5571_POWERDOWN(mode));
if (ret) if (ret)
goto out; goto out;
} }
data->powerdown_mode = mode; data->powerdown_mode[chan->channel] = mode;
out: out:
mutex_unlock(&data->lock); mutex_unlock(&data->lock);
@ -167,7 +167,7 @@ static ssize_t dac5571_read_powerdown(struct iio_dev *indio_dev,
{ {
struct dac5571_data *data = iio_priv(indio_dev); struct dac5571_data *data = iio_priv(indio_dev);
return sprintf(buf, "%d\n", data->powerdown); return sprintf(buf, "%d\n", data->powerdown[chan->channel]);
} }
static ssize_t dac5571_write_powerdown(struct iio_dev *indio_dev, static ssize_t dac5571_write_powerdown(struct iio_dev *indio_dev,
@ -183,19 +183,20 @@ static ssize_t dac5571_write_powerdown(struct iio_dev *indio_dev,
if (ret) if (ret)
return ret; return ret;
if (data->powerdown == powerdown) if (data->powerdown[chan->channel] == powerdown)
return len; return len;
mutex_lock(&data->lock); mutex_lock(&data->lock);
if (powerdown) if (powerdown)
ret = data->dac5571_pwrdwn(data, chan->channel, ret = data->dac5571_pwrdwn(data, chan->channel,
DAC5571_POWERDOWN(data->powerdown_mode)); DAC5571_POWERDOWN(data->powerdown_mode[chan->channel]));
else else
ret = data->dac5571_cmd(data, chan->channel, data->val[0]); ret = data->dac5571_cmd(data, chan->channel,
data->val[chan->channel]);
if (ret) if (ret)
goto out; goto out;
data->powerdown = powerdown; data->powerdown[chan->channel] = powerdown;
out: out:
mutex_unlock(&data->lock); mutex_unlock(&data->lock);
@ -209,9 +210,9 @@ static const struct iio_chan_spec_ext_info dac5571_ext_info[] = {
.name = "powerdown", .name = "powerdown",
.read = dac5571_read_powerdown, .read = dac5571_read_powerdown,
.write = dac5571_write_powerdown, .write = dac5571_write_powerdown,
.shared = IIO_SHARED_BY_TYPE, .shared = IIO_SEPARATE,
}, },
IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, &dac5571_powerdown_mode), IIO_ENUM("powerdown_mode", IIO_SEPARATE, &dac5571_powerdown_mode),
IIO_ENUM_AVAILABLE("powerdown_mode", &dac5571_powerdown_mode), IIO_ENUM_AVAILABLE("powerdown_mode", &dac5571_powerdown_mode),
{}, {},
}; };
@ -276,7 +277,7 @@ static int dac5571_write_raw(struct iio_dev *indio_dev,
if (val >= (1 << data->spec->resolution) || val < 0) if (val >= (1 << data->spec->resolution) || val < 0)
return -EINVAL; return -EINVAL;
if (data->powerdown) if (data->powerdown[chan->channel])
return -EBUSY; return -EBUSY;
mutex_lock(&data->lock); mutex_lock(&data->lock);