]> Pileus Git - ~andy/linux/blobdiff - drivers/staging/iio/dac/ad5446.c
Merge branch 'staging-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[~andy/linux] / drivers / staging / iio / dac / ad5446.c
index ec701e939b6b2a960fcc2ba755110fb1cb1a1dd4..693e7482524c2878c1d6b07a2c398fb57c9e314a 100644 (file)
 
 static void ad5446_store_sample(struct ad5446_state *st, unsigned val)
 {
-       st->data.d16 = cpu_to_be16(AD5446_LOAD |
-                                       (val << st->chip_info->left_shift));
+       st->data.d16 = cpu_to_be16(AD5446_LOAD | val);
 }
 
 static void ad5542_store_sample(struct ad5446_state *st, unsigned val)
 {
-       st->data.d16 = cpu_to_be16(val << st->chip_info->left_shift);
+       st->data.d16 = cpu_to_be16(val);
 }
 
 static void ad5620_store_sample(struct ad5446_state *st, unsigned val)
 {
-       st->data.d16 = cpu_to_be16(AD5620_LOAD |
-                                       (val << st->chip_info->left_shift));
+       st->data.d16 = cpu_to_be16(AD5620_LOAD | val);
 }
 
 static void ad5660_store_sample(struct ad5446_state *st, unsigned val)
@@ -63,50 +61,6 @@ static void ad5660_store_pwr_down(struct ad5446_state *st, unsigned mode)
        st->data.d24[2] = val & 0xFF;
 }
 
-static ssize_t ad5446_write(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf,
-               size_t len)
-{
-       struct iio_dev *indio_dev = dev_get_drvdata(dev);
-       struct ad5446_state *st = iio_priv(indio_dev);
-       int ret;
-       long val;
-
-       ret = strict_strtol(buf, 10, &val);
-       if (ret)
-               goto error_ret;
-
-       if (val > RES_MASK(st->chip_info->bits)) {
-               ret = -EINVAL;
-               goto error_ret;
-       }
-
-       mutex_lock(&indio_dev->mlock);
-       st->cached_val = val;
-       st->chip_info->store_sample(st, val);
-       ret = spi_sync(st->spi, &st->msg);
-       mutex_unlock(&indio_dev->mlock);
-
-error_ret:
-       return ret ? ret : len;
-}
-
-static IIO_DEV_ATTR_OUT_RAW(0, ad5446_write, 0);
-
-static ssize_t ad5446_show_scale(struct device *dev,
-                               struct device_attribute *attr,
-                               char *buf)
-{
-       struct iio_dev *indio_dev = dev_get_drvdata(dev);
-       struct ad5446_state *st = iio_priv(indio_dev);
-       /* Corresponds to Vref / 2^(bits) */
-       unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits;
-
-       return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
-}
-static IIO_DEVICE_ATTR(out_voltage_scale, S_IRUGO, ad5446_show_scale, NULL, 0);
-
 static ssize_t ad5446_write_powerdown_mode(struct device *dev,
                                       struct device_attribute *attr,
                                       const char *buf, size_t len)
@@ -189,8 +143,6 @@ static IIO_DEVICE_ATTR(out_voltage0_powerdown, S_IRUGO | S_IWUSR,
                        ad5446_write_dac_powerdown, 0);
 
 static struct attribute *ad5446_attributes[] = {
-       &iio_dev_attr_out_voltage0_raw.dev_attr.attr,
-       &iio_dev_attr_out_voltage_scale.dev_attr.attr,
        &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
        &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
        &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
@@ -223,121 +175,148 @@ static const struct attribute_group ad5446_attribute_group = {
        .is_visible = ad5446_attr_is_visible,
 };
 
+#define AD5446_CHANNEL(bits, storage, shift) { \
+       .type = IIO_VOLTAGE, \
+       .indexed = 1, \
+       .output = 1, \
+       .channel = 0, \
+       .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+       .scan_type = IIO_ST('u', (bits), (storage), (shift)) \
+}
+
 static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
        [ID_AD5444] = {
-               .bits = 12,
-               .storagebits = 16,
-               .left_shift = 2,
+               .channel = AD5446_CHANNEL(12, 16, 2),
                .store_sample = ad5446_store_sample,
        },
        [ID_AD5446] = {
-               .bits = 14,
-               .storagebits = 16,
-               .left_shift = 0,
+               .channel = AD5446_CHANNEL(14, 16, 0),
                .store_sample = ad5446_store_sample,
        },
        [ID_AD5541A] = {
-               .bits = 16,
-               .storagebits = 16,
-               .left_shift = 0,
+               .channel = AD5446_CHANNEL(16, 16, 0),
                .store_sample = ad5542_store_sample,
        },
        [ID_AD5542A] = {
-               .bits = 16,
-               .storagebits = 16,
-               .left_shift = 0,
+               .channel = AD5446_CHANNEL(16, 16, 0),
                .store_sample = ad5542_store_sample,
        },
        [ID_AD5543] = {
-               .bits = 16,
-               .storagebits = 16,
-               .left_shift = 0,
+               .channel = AD5446_CHANNEL(16, 16, 0),
                .store_sample = ad5542_store_sample,
        },
        [ID_AD5512A] = {
-               .bits = 12,
-               .storagebits = 16,
-               .left_shift = 4,
+               .channel = AD5446_CHANNEL(12, 16, 4),
                .store_sample = ad5542_store_sample,
        },
        [ID_AD5553] = {
-               .bits = 14,
-               .storagebits = 16,
-               .left_shift = 0,
+               .channel = AD5446_CHANNEL(14, 16, 0),
                .store_sample = ad5542_store_sample,
        },
        [ID_AD5601] = {
-               .bits = 8,
-               .storagebits = 16,
-               .left_shift = 6,
+               .channel = AD5446_CHANNEL(8, 16, 6),
                .store_sample = ad5542_store_sample,
                .store_pwr_down = ad5620_store_pwr_down,
        },
        [ID_AD5611] = {
-               .bits = 10,
-               .storagebits = 16,
-               .left_shift = 4,
+               .channel = AD5446_CHANNEL(10, 16, 4),
                .store_sample = ad5542_store_sample,
                .store_pwr_down = ad5620_store_pwr_down,
        },
        [ID_AD5621] = {
-               .bits = 12,
-               .storagebits = 16,
-               .left_shift = 2,
+               .channel = AD5446_CHANNEL(12, 16, 2),
                .store_sample = ad5542_store_sample,
                .store_pwr_down = ad5620_store_pwr_down,
        },
        [ID_AD5620_2500] = {
-               .bits = 12,
-               .storagebits = 16,
-               .left_shift = 2,
+               .channel = AD5446_CHANNEL(12, 16, 2),
                .int_vref_mv = 2500,
                .store_sample = ad5620_store_sample,
                .store_pwr_down = ad5620_store_pwr_down,
        },
        [ID_AD5620_1250] = {
-               .bits = 12,
-               .storagebits = 16,
-               .left_shift = 2,
+               .channel = AD5446_CHANNEL(12, 16, 2),
                .int_vref_mv = 1250,
                .store_sample = ad5620_store_sample,
                .store_pwr_down = ad5620_store_pwr_down,
        },
        [ID_AD5640_2500] = {
-               .bits = 14,
-               .storagebits = 16,
-               .left_shift = 0,
+               .channel = AD5446_CHANNEL(14, 16, 0),
                .int_vref_mv = 2500,
                .store_sample = ad5620_store_sample,
                .store_pwr_down = ad5620_store_pwr_down,
        },
        [ID_AD5640_1250] = {
-               .bits = 14,
-               .storagebits = 16,
-               .left_shift = 0,
+               .channel = AD5446_CHANNEL(14, 16, 0),
                .int_vref_mv = 1250,
                .store_sample = ad5620_store_sample,
                .store_pwr_down = ad5620_store_pwr_down,
        },
        [ID_AD5660_2500] = {
-               .bits = 16,
-               .storagebits = 24,
-               .left_shift = 0,
+               .channel = AD5446_CHANNEL(16, 16, 0),
                .int_vref_mv = 2500,
                .store_sample = ad5660_store_sample,
                .store_pwr_down = ad5660_store_pwr_down,
        },
        [ID_AD5660_1250] = {
-               .bits = 16,
-               .storagebits = 24,
-               .left_shift = 0,
+               .channel = AD5446_CHANNEL(16, 16, 0),
                .int_vref_mv = 1250,
                .store_sample = ad5660_store_sample,
                .store_pwr_down = ad5660_store_pwr_down,
        },
 };
 
+static int ad5446_read_raw(struct iio_dev *indio_dev,
+                          struct iio_chan_spec const *chan,
+                          int *val,
+                          int *val2,
+                          long m)
+{
+       struct ad5446_state *st = iio_priv(indio_dev);
+       unsigned long scale_uv;
+
+       switch (m) {
+       case IIO_CHAN_INFO_SCALE:
+               scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits;
+               *val =  scale_uv / 1000;
+               *val2 = (scale_uv % 1000) * 1000;
+               return IIO_VAL_INT_PLUS_MICRO;
+
+       }
+       return -EINVAL;
+}
+
+static int ad5446_write_raw(struct iio_dev *indio_dev,
+                              struct iio_chan_spec const *chan,
+                              int val,
+                              int val2,
+                              long mask)
+{
+       struct ad5446_state *st = iio_priv(indio_dev);
+       int ret;
+
+       switch (mask) {
+       case 0:
+               if (val >= (1 << chan->scan_type.realbits) || val < 0)
+                       return -EINVAL;
+
+               val <<= chan->scan_type.shift;
+               mutex_lock(&indio_dev->mlock);
+               st->cached_val = val;
+               st->chip_info->store_sample(st, val);
+               ret = spi_sync(st->spi, &st->msg);
+               mutex_unlock(&indio_dev->mlock);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
 static const struct iio_info ad5446_info = {
+       .read_raw = ad5446_read_raw,
+       .write_raw = ad5446_write_raw,
        .attrs = &ad5446_attribute_group,
        .driver_module = THIS_MODULE,
 };
@@ -376,11 +355,13 @@ static int __devinit ad5446_probe(struct spi_device *spi)
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->info = &ad5446_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->channels = &st->chip_info->channel;
+       indio_dev->num_channels = 1;
 
        /* Setup default message */
 
        st->xfer.tx_buf = &st->data;
-       st->xfer.len = st->chip_info->storagebits / 8;
+       st->xfer.len = st->chip_info->channel.scan_type.storagebits / 8;
 
        spi_message_init(&st->msg);
        spi_message_add_tail(&st->xfer, &st->msg);
@@ -454,11 +435,11 @@ static const struct spi_device_id ad5446_id[] = {
        {"ad5660-1250", ID_AD5660_1250},
        {}
 };
+MODULE_DEVICE_TABLE(spi, ad5446_id);
 
 static struct spi_driver ad5446_driver = {
        .driver = {
                .name   = "ad5446",
-               .bus    = &spi_bus_type,
                .owner  = THIS_MODULE,
        },
        .probe          = ad5446_probe,
@@ -470,4 +451,3 @@ module_spi_driver(ad5446_driver);
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 MODULE_DESCRIPTION("Analog Devices AD5444/AD5446 DAC");
 MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("spi:ad5446");