Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio:dac:ti-dac7612: Add driver for Texas Instruments DAC7612

It is a driver for Texas Instruments Dual, 12-Bit Serial Input
Digital-to-Analog Converter.

Datasheet of this chip:
http://www.ti.com/lit/ds/sbas106/sbas106.pdf

Signed-off-by: Ricardo Ribalda Delgado <ricardo@ribalda.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Ricardo Ribalda Delgado and committed by
Jonathan Cameron
977724d2 77c5a7f5

+201
+6
MAINTAINERS
··· 15082 15082 S: Maintained 15083 15083 F: sound/soc/ti/ 15084 15084 15085 + Texas Instruments' DAC7612 DAC Driver 15086 + M: Ricardo Ribalda <ricardo@ribalda.com> 15087 + L: linux-iio@vger.kernel.org 15088 + S: Supported 15089 + F: drivers/iio/dac/ti-dac7612.c 15090 + 15085 15091 THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER 15086 15092 M: Hans Verkuil <hverkuil@xs4all.nl> 15087 15093 L: linux-media@vger.kernel.org
+10
drivers/iio/dac/Kconfig
··· 375 375 376 376 If compiled as a module, it will be called ti-dac7311. 377 377 378 + config TI_DAC7612 379 + tristate "Texas Instruments 12-bit 2-channel DAC driver" 380 + depends on SPI_MASTER && GPIOLIB 381 + help 382 + Driver for the Texas Instruments DAC7612, DAC7612U, DAC7612UB 383 + The driver hand drive the load pin automatically, otherwise 384 + it needs to be toggled manually. 385 + 386 + If compiled as a module, it will be called ti-dac7612. 387 + 378 388 config VF610_DAC 379 389 tristate "Vybrid vf610 DAC driver" 380 390 depends on OF
+1
drivers/iio/dac/Makefile
··· 41 41 obj-$(CONFIG_TI_DAC082S085) += ti-dac082s085.o 42 42 obj-$(CONFIG_TI_DAC5571) += ti-dac5571.o 43 43 obj-$(CONFIG_TI_DAC7311) += ti-dac7311.o 44 + obj-$(CONFIG_TI_DAC7612) += ti-dac7612.o 44 45 obj-$(CONFIG_VF610_DAC) += vf610_dac.o
+184
drivers/iio/dac/ti-dac7612.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * DAC7612 Dual, 12-Bit Serial input Digital-to-Analog Converter 4 + * 5 + * Copyright 2019 Qtechnology A/S 6 + * 2019 Ricardo Ribalda <ricardo@ribalda.com> 7 + * 8 + * Licensed under the GPL-2. 9 + */ 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/spi/spi.h> 13 + #include <linux/gpio/consumer.h> 14 + #include <linux/iio/iio.h> 15 + 16 + #define DAC7612_RESOLUTION 12 17 + #define DAC7612_ADDRESS 4 18 + #define DAC7612_START 5 19 + 20 + struct dac7612 { 21 + struct spi_device *spi; 22 + struct gpio_desc *loaddacs; 23 + uint16_t cache[2]; 24 + 25 + /* 26 + * DMA (thus cache coherency maintenance) requires the 27 + * transfer buffers to live in their own cache lines. 28 + */ 29 + uint8_t data[2] ____cacheline_aligned; 30 + }; 31 + 32 + static int dac7612_cmd_single(struct dac7612 *priv, int channel, u16 val) 33 + { 34 + int ret; 35 + 36 + priv->data[0] = BIT(DAC7612_START) | (channel << DAC7612_ADDRESS); 37 + priv->data[0] |= val >> 8; 38 + priv->data[1] = val & 0xff; 39 + 40 + priv->cache[channel] = val; 41 + 42 + ret = spi_write(priv->spi, priv->data, sizeof(priv->data)); 43 + if (ret) 44 + return ret; 45 + 46 + gpiod_set_value(priv->loaddacs, 1); 47 + gpiod_set_value(priv->loaddacs, 0); 48 + 49 + return 0; 50 + } 51 + 52 + #define dac7612_CHANNEL(chan, name) { \ 53 + .type = IIO_VOLTAGE, \ 54 + .channel = (chan), \ 55 + .indexed = 1, \ 56 + .output = 1, \ 57 + .datasheet_name = name, \ 58 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 59 + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 60 + } 61 + 62 + static const struct iio_chan_spec dac7612_channels[] = { 63 + dac7612_CHANNEL(0, "OUTA"), 64 + dac7612_CHANNEL(1, "OUTB"), 65 + }; 66 + 67 + static int dac7612_read_raw(struct iio_dev *iio_dev, 68 + const struct iio_chan_spec *chan, 69 + int *val, int *val2, long mask) 70 + { 71 + struct dac7612 *priv; 72 + 73 + switch (mask) { 74 + case IIO_CHAN_INFO_RAW: 75 + priv = iio_priv(iio_dev); 76 + *val = priv->cache[chan->channel]; 77 + return IIO_VAL_INT; 78 + 79 + case IIO_CHAN_INFO_SCALE: 80 + *val = 1; 81 + return IIO_VAL_INT; 82 + 83 + default: 84 + return -EINVAL; 85 + } 86 + } 87 + 88 + static int dac7612_write_raw(struct iio_dev *iio_dev, 89 + const struct iio_chan_spec *chan, 90 + int val, int val2, long mask) 91 + { 92 + struct dac7612 *priv = iio_priv(iio_dev); 93 + int ret; 94 + 95 + if (mask != IIO_CHAN_INFO_RAW) 96 + return -EINVAL; 97 + 98 + if ((val >= BIT(DAC7612_RESOLUTION)) || val < 0 || val2) 99 + return -EINVAL; 100 + 101 + if (val == priv->cache[chan->channel]) 102 + return 0; 103 + 104 + mutex_lock(&iio_dev->mlock); 105 + ret = dac7612_cmd_single(priv, chan->channel, val); 106 + mutex_unlock(&iio_dev->mlock); 107 + 108 + return ret; 109 + } 110 + 111 + static const struct iio_info dac7612_info = { 112 + .read_raw = dac7612_read_raw, 113 + .write_raw = dac7612_write_raw, 114 + }; 115 + 116 + static int dac7612_probe(struct spi_device *spi) 117 + { 118 + struct iio_dev *iio_dev; 119 + struct dac7612 *priv; 120 + int i; 121 + int ret; 122 + 123 + iio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*priv)); 124 + if (!iio_dev) 125 + return -ENOMEM; 126 + 127 + priv = iio_priv(iio_dev); 128 + /* 129 + * LOADDACS pin can be controlled by the driver or externally. 130 + * When controlled by the driver, the DAC value is updated after 131 + * every write. 132 + * When the driver does not control the PIN, the user or an external 133 + * event can change the value of all DACs by pulsing down the LOADDACs 134 + * pin. 135 + */ 136 + priv->loaddacs = devm_gpiod_get_optional(&spi->dev, "ti,loaddacs", 137 + GPIOD_OUT_LOW); 138 + if (IS_ERR(priv->loaddacs)) 139 + return PTR_ERR(priv->loaddacs); 140 + priv->spi = spi; 141 + spi_set_drvdata(spi, iio_dev); 142 + iio_dev->dev.parent = &spi->dev; 143 + iio_dev->info = &dac7612_info; 144 + iio_dev->modes = INDIO_DIRECT_MODE; 145 + iio_dev->channels = dac7612_channels; 146 + iio_dev->num_channels = ARRAY_SIZE(priv->cache); 147 + iio_dev->name = spi_get_device_id(spi)->name; 148 + 149 + for (i = 0; i < ARRAY_SIZE(priv->cache); i++) { 150 + ret = dac7612_cmd_single(priv, i, 0); 151 + if (ret) 152 + return ret; 153 + } 154 + 155 + return devm_iio_device_register(&spi->dev, iio_dev); 156 + } 157 + 158 + static const struct spi_device_id dac7612_id[] = { 159 + {"ti-dac7612"}, 160 + {} 161 + }; 162 + MODULE_DEVICE_TABLE(spi, dac7612_id); 163 + 164 + static const struct of_device_id dac7612_of_match[] = { 165 + { .compatible = "ti,dac7612" }, 166 + { .compatible = "ti,dac7612u" }, 167 + { .compatible = "ti,dac7612ub" }, 168 + { }, 169 + }; 170 + MODULE_DEVICE_TABLE(of, dac7612_of_match); 171 + 172 + static struct spi_driver dac7612_driver = { 173 + .driver = { 174 + .name = "ti-dac7612", 175 + .of_match_table = dac7612_of_match, 176 + }, 177 + .probe = dac7612_probe, 178 + .id_table = dac7612_id, 179 + }; 180 + module_spi_driver(dac7612_driver); 181 + 182 + MODULE_AUTHOR("Ricardo Ribalda <ricardo@ribalda.com>"); 183 + MODULE_DESCRIPTION("Texas Instruments DAC7612 DAC driver"); 184 + MODULE_LICENSE("GPL v2");