1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2df38a4a7SSean Nyekjaer /* 3df38a4a7SSean Nyekjaer * ti-dac5571.c - Texas Instruments 8/10/12-bit 1/4-channel DAC driver 4df38a4a7SSean Nyekjaer * 5df38a4a7SSean Nyekjaer * Copyright (C) 2018 Prevas A/S 6df38a4a7SSean Nyekjaer * 73593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac5571.pdf 83593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac6571.pdf 93593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac7571.pdf 103593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac5574.pdf 113593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac6574.pdf 123593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac7574.pdf 133593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac5573.pdf 143593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac6573.pdf 153593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac7573.pdf 16df38a4a7SSean Nyekjaer */ 17df38a4a7SSean Nyekjaer 18df38a4a7SSean Nyekjaer #include <linux/iio/iio.h> 19df38a4a7SSean Nyekjaer #include <linux/i2c.h> 20df38a4a7SSean Nyekjaer #include <linux/module.h> 21df38a4a7SSean Nyekjaer #include <linux/of_device.h> 22df38a4a7SSean Nyekjaer #include <linux/of.h> 23df38a4a7SSean Nyekjaer #include <linux/regulator/consumer.h> 24df38a4a7SSean Nyekjaer 25df38a4a7SSean Nyekjaer enum chip_id { 26df38a4a7SSean Nyekjaer single_8bit, single_10bit, single_12bit, 27df38a4a7SSean Nyekjaer quad_8bit, quad_10bit, quad_12bit 28df38a4a7SSean Nyekjaer }; 29df38a4a7SSean Nyekjaer 30df38a4a7SSean Nyekjaer struct dac5571_spec { 31df38a4a7SSean Nyekjaer u8 num_channels; 32df38a4a7SSean Nyekjaer u8 resolution; 33df38a4a7SSean Nyekjaer }; 34df38a4a7SSean Nyekjaer 35df38a4a7SSean Nyekjaer static const struct dac5571_spec dac5571_spec[] = { 36df38a4a7SSean Nyekjaer [single_8bit] = {.num_channels = 1, .resolution = 8}, 37df38a4a7SSean Nyekjaer [single_10bit] = {.num_channels = 1, .resolution = 10}, 38df38a4a7SSean Nyekjaer [single_12bit] = {.num_channels = 1, .resolution = 12}, 39df38a4a7SSean Nyekjaer [quad_8bit] = {.num_channels = 4, .resolution = 8}, 40df38a4a7SSean Nyekjaer [quad_10bit] = {.num_channels = 4, .resolution = 10}, 41df38a4a7SSean Nyekjaer [quad_12bit] = {.num_channels = 4, .resolution = 12}, 42df38a4a7SSean Nyekjaer }; 43df38a4a7SSean Nyekjaer 44df38a4a7SSean Nyekjaer struct dac5571_data { 45df38a4a7SSean Nyekjaer struct i2c_client *client; 46df38a4a7SSean Nyekjaer int id; 47df38a4a7SSean Nyekjaer struct mutex lock; 48df38a4a7SSean Nyekjaer struct regulator *vref; 49df38a4a7SSean Nyekjaer u16 val[4]; 50*5dfb88afSVincent Whitchurch bool powerdown[4]; 51*5dfb88afSVincent Whitchurch u8 powerdown_mode[4]; 52df38a4a7SSean Nyekjaer struct dac5571_spec const *spec; 53df38a4a7SSean Nyekjaer int (*dac5571_cmd)(struct dac5571_data *data, int channel, u16 val); 54df38a4a7SSean Nyekjaer int (*dac5571_pwrdwn)(struct dac5571_data *data, int channel, u8 pwrdwn); 55df38a4a7SSean Nyekjaer u8 buf[3] ____cacheline_aligned; 56df38a4a7SSean Nyekjaer }; 57df38a4a7SSean Nyekjaer 58df38a4a7SSean Nyekjaer #define DAC5571_POWERDOWN(mode) ((mode) + 1) 59df38a4a7SSean Nyekjaer #define DAC5571_POWERDOWN_FLAG BIT(0) 60df38a4a7SSean Nyekjaer #define DAC5571_CHANNEL_SELECT 1 61df38a4a7SSean Nyekjaer #define DAC5571_LOADMODE_DIRECT BIT(4) 62df38a4a7SSean Nyekjaer #define DAC5571_SINGLE_PWRDWN_BITS 4 63df38a4a7SSean Nyekjaer #define DAC5571_QUAD_PWRDWN_BITS 6 64df38a4a7SSean Nyekjaer 65df38a4a7SSean Nyekjaer static int dac5571_cmd_single(struct dac5571_data *data, int channel, u16 val) 66df38a4a7SSean Nyekjaer { 67df38a4a7SSean Nyekjaer unsigned int shift; 68df38a4a7SSean Nyekjaer 69df38a4a7SSean Nyekjaer shift = 12 - data->spec->resolution; 70df38a4a7SSean Nyekjaer data->buf[1] = val << shift; 71df38a4a7SSean Nyekjaer data->buf[0] = val >> (8 - shift); 72df38a4a7SSean Nyekjaer 73df38a4a7SSean Nyekjaer if (i2c_master_send(data->client, data->buf, 2) != 2) 74df38a4a7SSean Nyekjaer return -EIO; 75df38a4a7SSean Nyekjaer 76df38a4a7SSean Nyekjaer return 0; 77df38a4a7SSean Nyekjaer } 78df38a4a7SSean Nyekjaer 79df38a4a7SSean Nyekjaer static int dac5571_cmd_quad(struct dac5571_data *data, int channel, u16 val) 80df38a4a7SSean Nyekjaer { 81df38a4a7SSean Nyekjaer unsigned int shift; 82df38a4a7SSean Nyekjaer 83df38a4a7SSean Nyekjaer shift = 16 - data->spec->resolution; 84df38a4a7SSean Nyekjaer data->buf[2] = val << shift; 85df38a4a7SSean Nyekjaer data->buf[1] = (val >> (8 - shift)); 86df38a4a7SSean Nyekjaer data->buf[0] = (channel << DAC5571_CHANNEL_SELECT) | 87df38a4a7SSean Nyekjaer DAC5571_LOADMODE_DIRECT; 88df38a4a7SSean Nyekjaer 89df38a4a7SSean Nyekjaer if (i2c_master_send(data->client, data->buf, 3) != 3) 90df38a4a7SSean Nyekjaer return -EIO; 91df38a4a7SSean Nyekjaer 92df38a4a7SSean Nyekjaer return 0; 93df38a4a7SSean Nyekjaer } 94df38a4a7SSean Nyekjaer 95df38a4a7SSean Nyekjaer static int dac5571_pwrdwn_single(struct dac5571_data *data, int channel, u8 pwrdwn) 96df38a4a7SSean Nyekjaer { 97df38a4a7SSean Nyekjaer data->buf[1] = 0; 98df38a4a7SSean Nyekjaer data->buf[0] = pwrdwn << DAC5571_SINGLE_PWRDWN_BITS; 99df38a4a7SSean Nyekjaer 100df38a4a7SSean Nyekjaer if (i2c_master_send(data->client, data->buf, 2) != 2) 101df38a4a7SSean Nyekjaer return -EIO; 102df38a4a7SSean Nyekjaer 103df38a4a7SSean Nyekjaer return 0; 104df38a4a7SSean Nyekjaer } 105df38a4a7SSean Nyekjaer 106df38a4a7SSean Nyekjaer static int dac5571_pwrdwn_quad(struct dac5571_data *data, int channel, u8 pwrdwn) 107df38a4a7SSean Nyekjaer { 108df38a4a7SSean Nyekjaer data->buf[2] = 0; 109df38a4a7SSean Nyekjaer data->buf[1] = pwrdwn << DAC5571_QUAD_PWRDWN_BITS; 110df38a4a7SSean Nyekjaer data->buf[0] = (channel << DAC5571_CHANNEL_SELECT) | 111df38a4a7SSean Nyekjaer DAC5571_LOADMODE_DIRECT | DAC5571_POWERDOWN_FLAG; 112df38a4a7SSean Nyekjaer 113df38a4a7SSean Nyekjaer if (i2c_master_send(data->client, data->buf, 3) != 3) 114df38a4a7SSean Nyekjaer return -EIO; 115df38a4a7SSean Nyekjaer 116df38a4a7SSean Nyekjaer return 0; 117df38a4a7SSean Nyekjaer } 118df38a4a7SSean Nyekjaer 119df38a4a7SSean Nyekjaer static const char *const dac5571_powerdown_modes[] = { 120df38a4a7SSean Nyekjaer "1kohm_to_gnd", "100kohm_to_gnd", "three_state", 121df38a4a7SSean Nyekjaer }; 122df38a4a7SSean Nyekjaer 123df38a4a7SSean Nyekjaer static int dac5571_get_powerdown_mode(struct iio_dev *indio_dev, 124df38a4a7SSean Nyekjaer const struct iio_chan_spec *chan) 125df38a4a7SSean Nyekjaer { 126df38a4a7SSean Nyekjaer struct dac5571_data *data = iio_priv(indio_dev); 127df38a4a7SSean Nyekjaer 128*5dfb88afSVincent Whitchurch return data->powerdown_mode[chan->channel]; 129df38a4a7SSean Nyekjaer } 130df38a4a7SSean Nyekjaer 131df38a4a7SSean Nyekjaer static int dac5571_set_powerdown_mode(struct iio_dev *indio_dev, 132df38a4a7SSean Nyekjaer const struct iio_chan_spec *chan, 133df38a4a7SSean Nyekjaer unsigned int mode) 134df38a4a7SSean Nyekjaer { 135df38a4a7SSean Nyekjaer struct dac5571_data *data = iio_priv(indio_dev); 136df38a4a7SSean Nyekjaer int ret = 0; 137df38a4a7SSean Nyekjaer 138*5dfb88afSVincent Whitchurch if (data->powerdown_mode[chan->channel] == mode) 139df38a4a7SSean Nyekjaer return 0; 140df38a4a7SSean Nyekjaer 141df38a4a7SSean Nyekjaer mutex_lock(&data->lock); 142*5dfb88afSVincent Whitchurch if (data->powerdown[chan->channel]) { 143df38a4a7SSean Nyekjaer ret = data->dac5571_pwrdwn(data, chan->channel, 144df38a4a7SSean Nyekjaer DAC5571_POWERDOWN(mode)); 145df38a4a7SSean Nyekjaer if (ret) 146df38a4a7SSean Nyekjaer goto out; 147df38a4a7SSean Nyekjaer } 148*5dfb88afSVincent Whitchurch data->powerdown_mode[chan->channel] = mode; 149df38a4a7SSean Nyekjaer 150df38a4a7SSean Nyekjaer out: 151df38a4a7SSean Nyekjaer mutex_unlock(&data->lock); 152df38a4a7SSean Nyekjaer 153df38a4a7SSean Nyekjaer return ret; 154df38a4a7SSean Nyekjaer } 155df38a4a7SSean Nyekjaer 156df38a4a7SSean Nyekjaer static const struct iio_enum dac5571_powerdown_mode = { 157df38a4a7SSean Nyekjaer .items = dac5571_powerdown_modes, 158df38a4a7SSean Nyekjaer .num_items = ARRAY_SIZE(dac5571_powerdown_modes), 159df38a4a7SSean Nyekjaer .get = dac5571_get_powerdown_mode, 160df38a4a7SSean Nyekjaer .set = dac5571_set_powerdown_mode, 161df38a4a7SSean Nyekjaer }; 162df38a4a7SSean Nyekjaer 163df38a4a7SSean Nyekjaer static ssize_t dac5571_read_powerdown(struct iio_dev *indio_dev, 164df38a4a7SSean Nyekjaer uintptr_t private, 165df38a4a7SSean Nyekjaer const struct iio_chan_spec *chan, 166df38a4a7SSean Nyekjaer char *buf) 167df38a4a7SSean Nyekjaer { 168df38a4a7SSean Nyekjaer struct dac5571_data *data = iio_priv(indio_dev); 169df38a4a7SSean Nyekjaer 170*5dfb88afSVincent Whitchurch return sprintf(buf, "%d\n", data->powerdown[chan->channel]); 171df38a4a7SSean Nyekjaer } 172df38a4a7SSean Nyekjaer 173df38a4a7SSean Nyekjaer static ssize_t dac5571_write_powerdown(struct iio_dev *indio_dev, 174df38a4a7SSean Nyekjaer uintptr_t private, 175df38a4a7SSean Nyekjaer const struct iio_chan_spec *chan, 176df38a4a7SSean Nyekjaer const char *buf, size_t len) 177df38a4a7SSean Nyekjaer { 178df38a4a7SSean Nyekjaer struct dac5571_data *data = iio_priv(indio_dev); 179df38a4a7SSean Nyekjaer bool powerdown; 180df38a4a7SSean Nyekjaer int ret; 181df38a4a7SSean Nyekjaer 182df38a4a7SSean Nyekjaer ret = strtobool(buf, &powerdown); 183df38a4a7SSean Nyekjaer if (ret) 184df38a4a7SSean Nyekjaer return ret; 185df38a4a7SSean Nyekjaer 186*5dfb88afSVincent Whitchurch if (data->powerdown[chan->channel] == powerdown) 187df38a4a7SSean Nyekjaer return len; 188df38a4a7SSean Nyekjaer 189df38a4a7SSean Nyekjaer mutex_lock(&data->lock); 190df38a4a7SSean Nyekjaer if (powerdown) 191df38a4a7SSean Nyekjaer ret = data->dac5571_pwrdwn(data, chan->channel, 192*5dfb88afSVincent Whitchurch DAC5571_POWERDOWN(data->powerdown_mode[chan->channel])); 193df38a4a7SSean Nyekjaer else 194*5dfb88afSVincent Whitchurch ret = data->dac5571_cmd(data, chan->channel, 195*5dfb88afSVincent Whitchurch data->val[chan->channel]); 196df38a4a7SSean Nyekjaer if (ret) 197df38a4a7SSean Nyekjaer goto out; 198df38a4a7SSean Nyekjaer 199*5dfb88afSVincent Whitchurch data->powerdown[chan->channel] = powerdown; 200df38a4a7SSean Nyekjaer 201df38a4a7SSean Nyekjaer out: 202df38a4a7SSean Nyekjaer mutex_unlock(&data->lock); 203df38a4a7SSean Nyekjaer 204df38a4a7SSean Nyekjaer return ret ? ret : len; 205df38a4a7SSean Nyekjaer } 206df38a4a7SSean Nyekjaer 207df38a4a7SSean Nyekjaer 208df38a4a7SSean Nyekjaer static const struct iio_chan_spec_ext_info dac5571_ext_info[] = { 209df38a4a7SSean Nyekjaer { 210df38a4a7SSean Nyekjaer .name = "powerdown", 211df38a4a7SSean Nyekjaer .read = dac5571_read_powerdown, 212df38a4a7SSean Nyekjaer .write = dac5571_write_powerdown, 213*5dfb88afSVincent Whitchurch .shared = IIO_SEPARATE, 214df38a4a7SSean Nyekjaer }, 215*5dfb88afSVincent Whitchurch IIO_ENUM("powerdown_mode", IIO_SEPARATE, &dac5571_powerdown_mode), 216df38a4a7SSean Nyekjaer IIO_ENUM_AVAILABLE("powerdown_mode", &dac5571_powerdown_mode), 217df38a4a7SSean Nyekjaer {}, 218df38a4a7SSean Nyekjaer }; 219df38a4a7SSean Nyekjaer 220df38a4a7SSean Nyekjaer #define dac5571_CHANNEL(chan, name) { \ 221df38a4a7SSean Nyekjaer .type = IIO_VOLTAGE, \ 222df38a4a7SSean Nyekjaer .channel = (chan), \ 223df38a4a7SSean Nyekjaer .address = (chan), \ 224df38a4a7SSean Nyekjaer .indexed = true, \ 225df38a4a7SSean Nyekjaer .output = true, \ 226df38a4a7SSean Nyekjaer .datasheet_name = name, \ 227df38a4a7SSean Nyekjaer .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 228df38a4a7SSean Nyekjaer .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 229df38a4a7SSean Nyekjaer .ext_info = dac5571_ext_info, \ 230df38a4a7SSean Nyekjaer } 231df38a4a7SSean Nyekjaer 232df38a4a7SSean Nyekjaer static const struct iio_chan_spec dac5571_channels[] = { 233df38a4a7SSean Nyekjaer dac5571_CHANNEL(0, "A"), 234df38a4a7SSean Nyekjaer dac5571_CHANNEL(1, "B"), 235df38a4a7SSean Nyekjaer dac5571_CHANNEL(2, "C"), 236df38a4a7SSean Nyekjaer dac5571_CHANNEL(3, "D"), 237df38a4a7SSean Nyekjaer }; 238df38a4a7SSean Nyekjaer 239df38a4a7SSean Nyekjaer static int dac5571_read_raw(struct iio_dev *indio_dev, 240df38a4a7SSean Nyekjaer struct iio_chan_spec const *chan, 241df38a4a7SSean Nyekjaer int *val, int *val2, long mask) 242df38a4a7SSean Nyekjaer { 243df38a4a7SSean Nyekjaer struct dac5571_data *data = iio_priv(indio_dev); 244df38a4a7SSean Nyekjaer int ret; 245df38a4a7SSean Nyekjaer 246df38a4a7SSean Nyekjaer switch (mask) { 247df38a4a7SSean Nyekjaer case IIO_CHAN_INFO_RAW: 248df38a4a7SSean Nyekjaer *val = data->val[chan->channel]; 249df38a4a7SSean Nyekjaer return IIO_VAL_INT; 250df38a4a7SSean Nyekjaer 251df38a4a7SSean Nyekjaer case IIO_CHAN_INFO_SCALE: 252df38a4a7SSean Nyekjaer ret = regulator_get_voltage(data->vref); 253df38a4a7SSean Nyekjaer if (ret < 0) 254df38a4a7SSean Nyekjaer return ret; 255df38a4a7SSean Nyekjaer 256df38a4a7SSean Nyekjaer *val = ret / 1000; 257df38a4a7SSean Nyekjaer *val2 = data->spec->resolution; 258df38a4a7SSean Nyekjaer return IIO_VAL_FRACTIONAL_LOG2; 259df38a4a7SSean Nyekjaer 260df38a4a7SSean Nyekjaer default: 261df38a4a7SSean Nyekjaer return -EINVAL; 262df38a4a7SSean Nyekjaer } 263df38a4a7SSean Nyekjaer } 264df38a4a7SSean Nyekjaer 265df38a4a7SSean Nyekjaer static int dac5571_write_raw(struct iio_dev *indio_dev, 266df38a4a7SSean Nyekjaer struct iio_chan_spec const *chan, 267df38a4a7SSean Nyekjaer int val, int val2, long mask) 268df38a4a7SSean Nyekjaer { 269df38a4a7SSean Nyekjaer struct dac5571_data *data = iio_priv(indio_dev); 270df38a4a7SSean Nyekjaer int ret; 271df38a4a7SSean Nyekjaer 272df38a4a7SSean Nyekjaer switch (mask) { 273df38a4a7SSean Nyekjaer case IIO_CHAN_INFO_RAW: 274df38a4a7SSean Nyekjaer if (data->val[chan->channel] == val) 275df38a4a7SSean Nyekjaer return 0; 276df38a4a7SSean Nyekjaer 277df38a4a7SSean Nyekjaer if (val >= (1 << data->spec->resolution) || val < 0) 278df38a4a7SSean Nyekjaer return -EINVAL; 279df38a4a7SSean Nyekjaer 280*5dfb88afSVincent Whitchurch if (data->powerdown[chan->channel]) 281df38a4a7SSean Nyekjaer return -EBUSY; 282df38a4a7SSean Nyekjaer 283df38a4a7SSean Nyekjaer mutex_lock(&data->lock); 284df38a4a7SSean Nyekjaer ret = data->dac5571_cmd(data, chan->channel, val); 285df38a4a7SSean Nyekjaer if (ret == 0) 286df38a4a7SSean Nyekjaer data->val[chan->channel] = val; 287df38a4a7SSean Nyekjaer mutex_unlock(&data->lock); 288df38a4a7SSean Nyekjaer return ret; 289df38a4a7SSean Nyekjaer 290df38a4a7SSean Nyekjaer default: 291df38a4a7SSean Nyekjaer return -EINVAL; 292df38a4a7SSean Nyekjaer } 293df38a4a7SSean Nyekjaer } 294df38a4a7SSean Nyekjaer 295df38a4a7SSean Nyekjaer static int dac5571_write_raw_get_fmt(struct iio_dev *indio_dev, 296df38a4a7SSean Nyekjaer struct iio_chan_spec const *chan, 297df38a4a7SSean Nyekjaer long mask) 298df38a4a7SSean Nyekjaer { 299df38a4a7SSean Nyekjaer return IIO_VAL_INT; 300df38a4a7SSean Nyekjaer } 301df38a4a7SSean Nyekjaer 302df38a4a7SSean Nyekjaer static const struct iio_info dac5571_info = { 303df38a4a7SSean Nyekjaer .read_raw = dac5571_read_raw, 304df38a4a7SSean Nyekjaer .write_raw = dac5571_write_raw, 305df38a4a7SSean Nyekjaer .write_raw_get_fmt = dac5571_write_raw_get_fmt, 306df38a4a7SSean Nyekjaer }; 307df38a4a7SSean Nyekjaer 308df38a4a7SSean Nyekjaer static int dac5571_probe(struct i2c_client *client, 309df38a4a7SSean Nyekjaer const struct i2c_device_id *id) 310df38a4a7SSean Nyekjaer { 311df38a4a7SSean Nyekjaer struct device *dev = &client->dev; 312df38a4a7SSean Nyekjaer const struct dac5571_spec *spec; 313df38a4a7SSean Nyekjaer struct dac5571_data *data; 314df38a4a7SSean Nyekjaer struct iio_dev *indio_dev; 315df38a4a7SSean Nyekjaer int ret, i; 316df38a4a7SSean Nyekjaer 317df38a4a7SSean Nyekjaer indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 318df38a4a7SSean Nyekjaer if (!indio_dev) 319df38a4a7SSean Nyekjaer return -ENOMEM; 320df38a4a7SSean Nyekjaer 321df38a4a7SSean Nyekjaer data = iio_priv(indio_dev); 322df38a4a7SSean Nyekjaer i2c_set_clientdata(client, indio_dev); 323df38a4a7SSean Nyekjaer data->client = client; 324df38a4a7SSean Nyekjaer 325df38a4a7SSean Nyekjaer indio_dev->info = &dac5571_info; 326df38a4a7SSean Nyekjaer indio_dev->name = id->name; 327df38a4a7SSean Nyekjaer indio_dev->modes = INDIO_DIRECT_MODE; 328df38a4a7SSean Nyekjaer indio_dev->channels = dac5571_channels; 329df38a4a7SSean Nyekjaer 330df38a4a7SSean Nyekjaer spec = &dac5571_spec[id->driver_data]; 331df38a4a7SSean Nyekjaer indio_dev->num_channels = spec->num_channels; 332df38a4a7SSean Nyekjaer data->spec = spec; 333df38a4a7SSean Nyekjaer 334df38a4a7SSean Nyekjaer data->vref = devm_regulator_get(dev, "vref"); 335df38a4a7SSean Nyekjaer if (IS_ERR(data->vref)) 336df38a4a7SSean Nyekjaer return PTR_ERR(data->vref); 337df38a4a7SSean Nyekjaer 338df38a4a7SSean Nyekjaer ret = regulator_enable(data->vref); 339df38a4a7SSean Nyekjaer if (ret < 0) 340df38a4a7SSean Nyekjaer return ret; 341df38a4a7SSean Nyekjaer 342df38a4a7SSean Nyekjaer mutex_init(&data->lock); 343df38a4a7SSean Nyekjaer 344df38a4a7SSean Nyekjaer switch (spec->num_channels) { 345df38a4a7SSean Nyekjaer case 1: 346df38a4a7SSean Nyekjaer data->dac5571_cmd = dac5571_cmd_single; 347df38a4a7SSean Nyekjaer data->dac5571_pwrdwn = dac5571_pwrdwn_single; 348df38a4a7SSean Nyekjaer break; 349df38a4a7SSean Nyekjaer case 4: 350df38a4a7SSean Nyekjaer data->dac5571_cmd = dac5571_cmd_quad; 351df38a4a7SSean Nyekjaer data->dac5571_pwrdwn = dac5571_pwrdwn_quad; 352df38a4a7SSean Nyekjaer break; 353df38a4a7SSean Nyekjaer default: 354df38a4a7SSean Nyekjaer goto err; 355df38a4a7SSean Nyekjaer } 356df38a4a7SSean Nyekjaer 357df38a4a7SSean Nyekjaer for (i = 0; i < spec->num_channels; i++) { 358df38a4a7SSean Nyekjaer ret = data->dac5571_cmd(data, i, 0); 359df38a4a7SSean Nyekjaer if (ret) { 360df38a4a7SSean Nyekjaer dev_err(dev, "failed to initialize channel %d to 0\n", i); 361df38a4a7SSean Nyekjaer goto err; 362df38a4a7SSean Nyekjaer } 363df38a4a7SSean Nyekjaer } 364df38a4a7SSean Nyekjaer 365df38a4a7SSean Nyekjaer ret = iio_device_register(indio_dev); 366df38a4a7SSean Nyekjaer if (ret) 367df38a4a7SSean Nyekjaer goto err; 368df38a4a7SSean Nyekjaer 369df38a4a7SSean Nyekjaer return 0; 370df38a4a7SSean Nyekjaer 371df38a4a7SSean Nyekjaer err: 372df38a4a7SSean Nyekjaer regulator_disable(data->vref); 373df38a4a7SSean Nyekjaer return ret; 374df38a4a7SSean Nyekjaer } 375df38a4a7SSean Nyekjaer 376df38a4a7SSean Nyekjaer static int dac5571_remove(struct i2c_client *i2c) 377df38a4a7SSean Nyekjaer { 378df38a4a7SSean Nyekjaer struct iio_dev *indio_dev = i2c_get_clientdata(i2c); 379df38a4a7SSean Nyekjaer struct dac5571_data *data = iio_priv(indio_dev); 380df38a4a7SSean Nyekjaer 381df38a4a7SSean Nyekjaer iio_device_unregister(indio_dev); 382df38a4a7SSean Nyekjaer regulator_disable(data->vref); 383df38a4a7SSean Nyekjaer 384df38a4a7SSean Nyekjaer return 0; 385df38a4a7SSean Nyekjaer } 386df38a4a7SSean Nyekjaer 387df38a4a7SSean Nyekjaer #ifdef CONFIG_OF 388df38a4a7SSean Nyekjaer static const struct of_device_id dac5571_of_id[] = { 389df38a4a7SSean Nyekjaer {.compatible = "ti,dac5571"}, 390df38a4a7SSean Nyekjaer {.compatible = "ti,dac6571"}, 391df38a4a7SSean Nyekjaer {.compatible = "ti,dac7571"}, 392df38a4a7SSean Nyekjaer {.compatible = "ti,dac5574"}, 393df38a4a7SSean Nyekjaer {.compatible = "ti,dac6574"}, 394df38a4a7SSean Nyekjaer {.compatible = "ti,dac7574"}, 395df38a4a7SSean Nyekjaer {.compatible = "ti,dac5573"}, 396df38a4a7SSean Nyekjaer {.compatible = "ti,dac6573"}, 397df38a4a7SSean Nyekjaer {.compatible = "ti,dac7573"}, 398df38a4a7SSean Nyekjaer {} 399df38a4a7SSean Nyekjaer }; 400df38a4a7SSean Nyekjaer MODULE_DEVICE_TABLE(of, dac5571_of_id); 401df38a4a7SSean Nyekjaer #endif 402df38a4a7SSean Nyekjaer 403df38a4a7SSean Nyekjaer static const struct i2c_device_id dac5571_id[] = { 404df38a4a7SSean Nyekjaer {"dac5571", single_8bit}, 405df38a4a7SSean Nyekjaer {"dac6571", single_10bit}, 406df38a4a7SSean Nyekjaer {"dac7571", single_12bit}, 407df38a4a7SSean Nyekjaer {"dac5574", quad_8bit}, 408df38a4a7SSean Nyekjaer {"dac6574", quad_10bit}, 409df38a4a7SSean Nyekjaer {"dac7574", quad_12bit}, 410df38a4a7SSean Nyekjaer {"dac5573", quad_8bit}, 411df38a4a7SSean Nyekjaer {"dac6573", quad_10bit}, 412df38a4a7SSean Nyekjaer {"dac7573", quad_12bit}, 413df38a4a7SSean Nyekjaer {} 414df38a4a7SSean Nyekjaer }; 415df38a4a7SSean Nyekjaer MODULE_DEVICE_TABLE(i2c, dac5571_id); 416df38a4a7SSean Nyekjaer 417df38a4a7SSean Nyekjaer static struct i2c_driver dac5571_driver = { 418df38a4a7SSean Nyekjaer .driver = { 419df38a4a7SSean Nyekjaer .name = "ti-dac5571", 42091d05d76SMarcus Folkesson .of_match_table = of_match_ptr(dac5571_of_id), 421df38a4a7SSean Nyekjaer }, 422df38a4a7SSean Nyekjaer .probe = dac5571_probe, 423df38a4a7SSean Nyekjaer .remove = dac5571_remove, 424df38a4a7SSean Nyekjaer .id_table = dac5571_id, 425df38a4a7SSean Nyekjaer }; 426df38a4a7SSean Nyekjaer module_i2c_driver(dac5571_driver); 427df38a4a7SSean Nyekjaer 428d43102f5SSean Nyekjaer MODULE_AUTHOR("Sean Nyekjaer <sean@geanix.dk>"); 429df38a4a7SSean Nyekjaer MODULE_DESCRIPTION("Texas Instruments 8/10/12-bit 1/4-channel DAC driver"); 430df38a4a7SSean Nyekjaer MODULE_LICENSE("GPL v2"); 431