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

iio: amplifiers: New driver for AD8366 Dual-Digital Variable Gain Amplifier

Changes since V1:

Apply review feedback:
Introduce and use IIO_CHAN_INFO_HARDWAREGAIN
Introduce and use Use IIO_VAL_INT_PLUS_MICRO_DB

Modify out of staging include paths.
Convert to new iio core API naming.

Changes since V2:

more sanity checking in write_raw

Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Acked-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Michael Hennerich and committed by
Greg Kroah-Hartman
e71d42e0 b65d6212

+248
+2
drivers/iio/Kconfig
··· 48 48 This value controls the maximum number of consumers that a 49 49 given trigger may handle. Default is 2. 50 50 51 + source "drivers/iio/amplifiers/Kconfig" 52 + 51 53 endif # IIO
+2
drivers/iio/Makefile
··· 8 8 industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o 9 9 10 10 obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o 11 + 12 + obj-y += amplifiers/
+17
drivers/iio/amplifiers/Kconfig
··· 1 + # 2 + # Gain Amplifiers, etc. 3 + # 4 + menu "Amplifiers" 5 + 6 + config AD8366 7 + tristate "Analog Devices AD8366 VGA" 8 + depends on SPI 9 + select BITREVERSE 10 + help 11 + Say yes here to build support for Analog Devices AD8366 12 + SPI Dual-Digital Variable Gain Amplifier (VGA). 13 + 14 + To compile this driver as a module, choose M here: the 15 + module will be called ad8366. 16 + 17 + endmenu
+5
drivers/iio/amplifiers/Makefile
··· 1 + # 2 + # Makefile iio/amplifiers 3 + # 4 + 5 + obj-$(CONFIG_AD8366) += ad8366.o
+222
drivers/iio/amplifiers/ad8366.c
··· 1 + /* 2 + * AD8366 SPI Dual-Digital Variable Gain Amplifier (VGA) 3 + * 4 + * Copyright 2012 Analog Devices Inc. 5 + * 6 + * Licensed under the GPL-2. 7 + */ 8 + 9 + #include <linux/device.h> 10 + #include <linux/kernel.h> 11 + #include <linux/slab.h> 12 + #include <linux/sysfs.h> 13 + #include <linux/spi/spi.h> 14 + #include <linux/regulator/consumer.h> 15 + #include <linux/err.h> 16 + #include <linux/module.h> 17 + #include <linux/bitrev.h> 18 + 19 + #include <linux/iio/iio.h> 20 + #include <linux/iio/sysfs.h> 21 + 22 + struct ad8366_state { 23 + struct spi_device *spi; 24 + struct regulator *reg; 25 + unsigned char ch[2]; 26 + /* 27 + * DMA (thus cache coherency maintenance) requires the 28 + * transfer buffers to live in their own cache lines. 29 + */ 30 + unsigned char data[2] ____cacheline_aligned; 31 + }; 32 + 33 + static int ad8366_write(struct iio_dev *indio_dev, 34 + unsigned char ch_a, char unsigned ch_b) 35 + { 36 + struct ad8366_state *st = iio_priv(indio_dev); 37 + int ret; 38 + 39 + ch_a = bitrev8(ch_a & 0x3F); 40 + ch_b = bitrev8(ch_b & 0x3F); 41 + 42 + st->data[0] = ch_b >> 4; 43 + st->data[1] = (ch_b << 4) | (ch_a >> 2); 44 + 45 + ret = spi_write(st->spi, st->data, ARRAY_SIZE(st->data)); 46 + if (ret < 0) 47 + dev_err(&indio_dev->dev, "write failed (%d)", ret); 48 + 49 + return ret; 50 + } 51 + 52 + static int ad8366_read_raw(struct iio_dev *indio_dev, 53 + struct iio_chan_spec const *chan, 54 + int *val, 55 + int *val2, 56 + long m) 57 + { 58 + struct ad8366_state *st = iio_priv(indio_dev); 59 + int ret; 60 + unsigned code; 61 + 62 + mutex_lock(&indio_dev->mlock); 63 + switch (m) { 64 + case IIO_CHAN_INFO_HARDWAREGAIN: 65 + code = st->ch[chan->channel]; 66 + 67 + /* Values in dB */ 68 + code = code * 253 + 4500; 69 + *val = code / 1000; 70 + *val2 = (code % 1000) * 1000; 71 + 72 + ret = IIO_VAL_INT_PLUS_MICRO_DB; 73 + break; 74 + default: 75 + ret = -EINVAL; 76 + } 77 + mutex_unlock(&indio_dev->mlock); 78 + 79 + return ret; 80 + }; 81 + 82 + static int ad8366_write_raw(struct iio_dev *indio_dev, 83 + struct iio_chan_spec const *chan, 84 + int val, 85 + int val2, 86 + long mask) 87 + { 88 + struct ad8366_state *st = iio_priv(indio_dev); 89 + unsigned code; 90 + int ret; 91 + 92 + if (val < 0 || val2 < 0) 93 + return -EINVAL; 94 + 95 + /* Values in dB */ 96 + code = (((u8)val * 1000) + ((u32)val2 / 1000)); 97 + 98 + if (code > 20500 || code < 4500) 99 + return -EINVAL; 100 + 101 + code = (code - 4500) / 253; 102 + 103 + mutex_lock(&indio_dev->mlock); 104 + switch (mask) { 105 + case IIO_CHAN_INFO_HARDWAREGAIN: 106 + st->ch[chan->channel] = code; 107 + ret = ad8366_write(indio_dev, st->ch[0], st->ch[1]); 108 + break; 109 + default: 110 + ret = -EINVAL; 111 + } 112 + mutex_unlock(&indio_dev->mlock); 113 + 114 + return ret; 115 + } 116 + 117 + static const struct iio_info ad8366_info = { 118 + .read_raw = &ad8366_read_raw, 119 + .write_raw = &ad8366_write_raw, 120 + .driver_module = THIS_MODULE, 121 + }; 122 + 123 + #define AD8366_CHAN(_channel) { \ 124 + .type = IIO_VOLTAGE, \ 125 + .output = 1, \ 126 + .indexed = 1, \ 127 + .channel = _channel, \ 128 + .info_mask = IIO_CHAN_INFO_HARDWAREGAIN_SEPARATE_BIT,\ 129 + } 130 + 131 + static const struct iio_chan_spec ad8366_channels[] = { 132 + AD8366_CHAN(0), 133 + AD8366_CHAN(1), 134 + }; 135 + 136 + static int __devinit ad8366_probe(struct spi_device *spi) 137 + { 138 + struct iio_dev *indio_dev; 139 + struct ad8366_state *st; 140 + int ret; 141 + 142 + indio_dev = iio_device_alloc(sizeof(*st)); 143 + if (indio_dev == NULL) 144 + return -ENOMEM; 145 + 146 + st = iio_priv(indio_dev); 147 + 148 + st->reg = regulator_get(&spi->dev, "vcc"); 149 + if (!IS_ERR(st->reg)) { 150 + ret = regulator_enable(st->reg); 151 + if (ret) 152 + goto error_put_reg; 153 + } 154 + 155 + spi_set_drvdata(spi, indio_dev); 156 + st->spi = spi; 157 + 158 + indio_dev->dev.parent = &spi->dev; 159 + indio_dev->name = spi_get_device_id(spi)->name; 160 + indio_dev->info = &ad8366_info; 161 + indio_dev->modes = INDIO_DIRECT_MODE; 162 + indio_dev->channels = ad8366_channels; 163 + indio_dev->num_channels = ARRAY_SIZE(ad8366_channels); 164 + 165 + ret = iio_device_register(indio_dev); 166 + if (ret) 167 + goto error_disable_reg; 168 + 169 + ad8366_write(indio_dev, 0 , 0); 170 + 171 + return 0; 172 + 173 + error_disable_reg: 174 + if (!IS_ERR(st->reg)) 175 + regulator_disable(st->reg); 176 + error_put_reg: 177 + if (!IS_ERR(st->reg)) 178 + regulator_put(st->reg); 179 + 180 + iio_device_free(indio_dev); 181 + 182 + return ret; 183 + } 184 + 185 + static int __devexit ad8366_remove(struct spi_device *spi) 186 + { 187 + struct iio_dev *indio_dev = spi_get_drvdata(spi); 188 + struct ad8366_state *st = iio_priv(indio_dev); 189 + struct regulator *reg = st->reg; 190 + 191 + iio_device_unregister(indio_dev); 192 + 193 + if (!IS_ERR(reg)) { 194 + regulator_disable(reg); 195 + regulator_put(reg); 196 + } 197 + 198 + iio_device_free(indio_dev); 199 + 200 + return 0; 201 + } 202 + 203 + static const struct spi_device_id ad8366_id[] = { 204 + {"ad8366", 0}, 205 + {} 206 + }; 207 + 208 + static struct spi_driver ad8366_driver = { 209 + .driver = { 210 + .name = KBUILD_MODNAME, 211 + .owner = THIS_MODULE, 212 + }, 213 + .probe = ad8366_probe, 214 + .remove = __devexit_p(ad8366_remove), 215 + .id_table = ad8366_id, 216 + }; 217 + 218 + module_spi_driver(ad8366_driver); 219 + 220 + MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); 221 + MODULE_DESCRIPTION("Analog Devices AD8366 VGA"); 222 + MODULE_LICENSE("GPL v2");