linux/drivers/staging/iio/dac/ad5446.c
<<
>>
Prefs
   1/*
   2 * AD5446 SPI DAC driver
   3 *
   4 * Copyright 2010 Analog Devices Inc.
   5 *
   6 * Licensed under the GPL-2 or later.
   7 */
   8
   9#include <linux/interrupt.h>
  10#include <linux/workqueue.h>
  11#include <linux/device.h>
  12#include <linux/kernel.h>
  13#include <linux/slab.h>
  14#include <linux/sysfs.h>
  15#include <linux/list.h>
  16#include <linux/spi/spi.h>
  17#include <linux/regulator/consumer.h>
  18#include <linux/err.h>
  19
  20#include "../iio.h"
  21#include "../sysfs.h"
  22#include "dac.h"
  23
  24#include "ad5446.h"
  25
  26static void ad5446_store_sample(struct ad5446_state *st, unsigned val)
  27{
  28        st->data.d16 = cpu_to_be16(AD5446_LOAD |
  29                                        (val << st->chip_info->left_shift));
  30}
  31
  32static void ad5542_store_sample(struct ad5446_state *st, unsigned val)
  33{
  34        st->data.d16 = cpu_to_be16(val << st->chip_info->left_shift);
  35}
  36
  37static void ad5620_store_sample(struct ad5446_state *st, unsigned val)
  38{
  39        st->data.d16 = cpu_to_be16(AD5620_LOAD |
  40                                        (val << st->chip_info->left_shift));
  41}
  42
  43static void ad5660_store_sample(struct ad5446_state *st, unsigned val)
  44{
  45        val |= AD5660_LOAD;
  46        st->data.d24[0] = (val >> 16) & 0xFF;
  47        st->data.d24[1] = (val >> 8) & 0xFF;
  48        st->data.d24[2] = val & 0xFF;
  49}
  50
  51static ssize_t ad5446_write(struct device *dev,
  52                struct device_attribute *attr,
  53                const char *buf,
  54                size_t len)
  55{
  56        struct iio_dev *dev_info = dev_get_drvdata(dev);
  57        struct ad5446_state *st = dev_info->dev_data;
  58        int ret;
  59        long val;
  60
  61        ret = strict_strtol(buf, 10, &val);
  62        if (ret)
  63                goto error_ret;
  64
  65        if (val > RES_MASK(st->chip_info->bits)) {
  66                ret = -EINVAL;
  67                goto error_ret;
  68        }
  69
  70        mutex_lock(&dev_info->mlock);
  71        st->chip_info->store_sample(st, val);
  72        ret = spi_sync(st->spi, &st->msg);
  73        mutex_unlock(&dev_info->mlock);
  74
  75error_ret:
  76        return ret ? ret : len;
  77}
  78
  79static IIO_DEV_ATTR_OUT_RAW(0, ad5446_write, 0);
  80
  81static ssize_t ad5446_show_scale(struct device *dev,
  82                                struct device_attribute *attr,
  83                                char *buf)
  84{
  85        struct iio_dev *dev_info = dev_get_drvdata(dev);
  86        struct ad5446_state *st = iio_dev_get_devdata(dev_info);
  87        /* Corresponds to Vref / 2^(bits) */
  88        unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits;
  89
  90        return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
  91}
  92static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5446_show_scale, NULL, 0);
  93
  94static ssize_t ad5446_show_name(struct device *dev,
  95                                 struct device_attribute *attr,
  96                                 char *buf)
  97{
  98        struct iio_dev *dev_info = dev_get_drvdata(dev);
  99        struct ad5446_state *st = iio_dev_get_devdata(dev_info);
 100
 101        return sprintf(buf, "%s\n", spi_get_device_id(st->spi)->name);
 102}
 103static IIO_DEVICE_ATTR(name, S_IRUGO, ad5446_show_name, NULL, 0);
 104
 105static struct attribute *ad5446_attributes[] = {
 106        &iio_dev_attr_out0_raw.dev_attr.attr,
 107        &iio_dev_attr_out_scale.dev_attr.attr,
 108        &iio_dev_attr_name.dev_attr.attr,
 109        NULL,
 110};
 111
 112static const struct attribute_group ad5446_attribute_group = {
 113        .attrs = ad5446_attributes,
 114};
 115
 116static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
 117        [ID_AD5444] = {
 118                .bits = 12,
 119                .storagebits = 16,
 120                .left_shift = 2,
 121                .store_sample = ad5446_store_sample,
 122        },
 123        [ID_AD5446] = {
 124                .bits = 14,
 125                .storagebits = 16,
 126                .left_shift = 0,
 127                .store_sample = ad5446_store_sample,
 128        },
 129        [ID_AD5542A] = {
 130                .bits = 16,
 131                .storagebits = 16,
 132                .left_shift = 0,
 133                .store_sample = ad5542_store_sample,
 134        },
 135        [ID_AD5512A] = {
 136                .bits = 12,
 137                .storagebits = 16,
 138                .left_shift = 4,
 139                .store_sample = ad5542_store_sample,
 140        },
 141        [ID_AD5620_2500] = {
 142                .bits = 12,
 143                .storagebits = 16,
 144                .left_shift = 2,
 145                .int_vref_mv = 2500,
 146                .store_sample = ad5620_store_sample,
 147        },
 148        [ID_AD5620_1250] = {
 149                .bits = 12,
 150                .storagebits = 16,
 151                .left_shift = 2,
 152                .int_vref_mv = 1250,
 153                .store_sample = ad5620_store_sample,
 154        },
 155        [ID_AD5640_2500] = {
 156                .bits = 14,
 157                .storagebits = 16,
 158                .left_shift = 0,
 159                .int_vref_mv = 2500,
 160                .store_sample = ad5620_store_sample,
 161        },
 162        [ID_AD5640_1250] = {
 163                .bits = 14,
 164                .storagebits = 16,
 165                .left_shift = 0,
 166                .int_vref_mv = 1250,
 167                .store_sample = ad5620_store_sample,
 168        },
 169        [ID_AD5660_2500] = {
 170                .bits = 16,
 171                .storagebits = 24,
 172                .left_shift = 0,
 173                .int_vref_mv = 2500,
 174                .store_sample = ad5660_store_sample,
 175        },
 176        [ID_AD5660_1250] = {
 177                .bits = 16,
 178                .storagebits = 24,
 179                .left_shift = 0,
 180                .int_vref_mv = 1250,
 181                .store_sample = ad5660_store_sample,
 182        },
 183};
 184
 185static int __devinit ad5446_probe(struct spi_device *spi)
 186{
 187        struct ad5446_state *st;
 188        int ret, voltage_uv = 0;
 189
 190        st = kzalloc(sizeof(*st), GFP_KERNEL);
 191        if (st == NULL) {
 192                ret = -ENOMEM;
 193                goto error_ret;
 194        }
 195
 196        st->reg = regulator_get(&spi->dev, "vcc");
 197        if (!IS_ERR(st->reg)) {
 198                ret = regulator_enable(st->reg);
 199                if (ret)
 200                        goto error_put_reg;
 201
 202                voltage_uv = regulator_get_voltage(st->reg);
 203        }
 204
 205        st->chip_info =
 206                &ad5446_chip_info_tbl[spi_get_device_id(spi)->driver_data];
 207
 208        spi_set_drvdata(spi, st);
 209
 210        st->spi = spi;
 211
 212        st->indio_dev = iio_allocate_device();
 213        if (st->indio_dev == NULL) {
 214                ret = -ENOMEM;
 215                goto error_disable_reg;
 216        }
 217
 218        /* Estabilish that the iio_dev is a child of the spi device */
 219        st->indio_dev->dev.parent = &spi->dev;
 220        st->indio_dev->attrs = &ad5446_attribute_group;
 221        st->indio_dev->dev_data = (void *)(st);
 222        st->indio_dev->driver_module = THIS_MODULE;
 223        st->indio_dev->modes = INDIO_DIRECT_MODE;
 224
 225        /* Setup default message */
 226
 227        st->xfer.tx_buf = &st->data;
 228        st->xfer.len = st->chip_info->storagebits / 8;
 229
 230        spi_message_init(&st->msg);
 231        spi_message_add_tail(&st->xfer, &st->msg);
 232
 233        switch (spi_get_device_id(spi)->driver_data) {
 234                case ID_AD5620_2500:
 235                case ID_AD5620_1250:
 236                case ID_AD5640_2500:
 237                case ID_AD5640_1250:
 238                case ID_AD5660_2500:
 239                case ID_AD5660_1250:
 240                        st->vref_mv = st->chip_info->int_vref_mv;
 241                        break;
 242                default:
 243                        if (voltage_uv)
 244                                st->vref_mv = voltage_uv / 1000;
 245                        else
 246                                dev_warn(&spi->dev,
 247                                         "reference voltage unspecified\n");
 248        }
 249
 250        ret = iio_device_register(st->indio_dev);
 251        if (ret)
 252                goto error_free_device;
 253
 254        return 0;
 255
 256error_free_device:
 257        iio_free_device(st->indio_dev);
 258error_disable_reg:
 259        if (!IS_ERR(st->reg))
 260                regulator_disable(st->reg);
 261error_put_reg:
 262        if (!IS_ERR(st->reg))
 263                regulator_put(st->reg);
 264        kfree(st);
 265error_ret:
 266        return ret;
 267}
 268
 269static int ad5446_remove(struct spi_device *spi)
 270{
 271        struct ad5446_state *st = spi_get_drvdata(spi);
 272        struct iio_dev *indio_dev = st->indio_dev;
 273
 274        iio_device_unregister(indio_dev);
 275        if (!IS_ERR(st->reg)) {
 276                regulator_disable(st->reg);
 277                regulator_put(st->reg);
 278        }
 279        kfree(st);
 280        return 0;
 281}
 282
 283static const struct spi_device_id ad5446_id[] = {
 284        {"ad5444", ID_AD5444},
 285        {"ad5446", ID_AD5446},
 286        {"ad5542a", ID_AD5542A},
 287        {"ad5512a", ID_AD5512A},
 288        {"ad5620-2500", ID_AD5620_2500}, /* AD5620/40/60: */
 289        {"ad5620-1250", ID_AD5620_1250}, /* part numbers may look differently */
 290        {"ad5640-2500", ID_AD5640_2500},
 291        {"ad5640-1250", ID_AD5640_1250},
 292        {"ad5660-2500", ID_AD5660_2500},
 293        {"ad5660-1250", ID_AD5660_1250},
 294        {}
 295};
 296
 297static struct spi_driver ad5446_driver = {
 298        .driver = {
 299                .name   = "ad5446",
 300                .bus    = &spi_bus_type,
 301                .owner  = THIS_MODULE,
 302        },
 303        .probe          = ad5446_probe,
 304        .remove         = __devexit_p(ad5446_remove),
 305        .id_table       = ad5446_id,
 306};
 307
 308static int __init ad5446_init(void)
 309{
 310        return spi_register_driver(&ad5446_driver);
 311}
 312module_init(ad5446_init);
 313
 314static void __exit ad5446_exit(void)
 315{
 316        spi_unregister_driver(&ad5446_driver);
 317}
 318module_exit(ad5446_exit);
 319
 320MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 321MODULE_DESCRIPTION("Analog Devices AD5444/AD5446 DAC");
 322MODULE_LICENSE("GPL v2");
 323MODULE_ALIAS("spi:ad5446");
 324