switch ->is_visible() to returning umode_t
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / iio / dac / ad5446.c
blobdc46b6d6eaa31e8e13f91c3b761c16c3ae8d9616
1 /*
2 * AD5446 SPI DAC driver
4 * Copyright 2010 Analog Devices Inc.
6 * Licensed under the GPL-2 or later.
7 */
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 #include <linux/module.h>
21 #include "../iio.h"
22 #include "../sysfs.h"
23 #include "dac.h"
25 #include "ad5446.h"
27 static void ad5446_store_sample(struct ad5446_state *st, unsigned val)
29 st->data.d16 = cpu_to_be16(AD5446_LOAD |
30 (val << st->chip_info->left_shift));
33 static void ad5542_store_sample(struct ad5446_state *st, unsigned val)
35 st->data.d16 = cpu_to_be16(val << st->chip_info->left_shift);
38 static void ad5620_store_sample(struct ad5446_state *st, unsigned val)
40 st->data.d16 = cpu_to_be16(AD5620_LOAD |
41 (val << st->chip_info->left_shift));
44 static void ad5660_store_sample(struct ad5446_state *st, unsigned val)
46 val |= AD5660_LOAD;
47 st->data.d24[0] = (val >> 16) & 0xFF;
48 st->data.d24[1] = (val >> 8) & 0xFF;
49 st->data.d24[2] = val & 0xFF;
52 static void ad5620_store_pwr_down(struct ad5446_state *st, unsigned mode)
54 st->data.d16 = cpu_to_be16(mode << 14);
57 static void ad5660_store_pwr_down(struct ad5446_state *st, unsigned mode)
59 unsigned val = mode << 16;
61 st->data.d24[0] = (val >> 16) & 0xFF;
62 st->data.d24[1] = (val >> 8) & 0xFF;
63 st->data.d24[2] = val & 0xFF;
66 static ssize_t ad5446_write(struct device *dev,
67 struct device_attribute *attr,
68 const char *buf,
69 size_t len)
71 struct iio_dev *indio_dev = dev_get_drvdata(dev);
72 struct ad5446_state *st = iio_priv(indio_dev);
73 int ret;
74 long val;
76 ret = strict_strtol(buf, 10, &val);
77 if (ret)
78 goto error_ret;
80 if (val > RES_MASK(st->chip_info->bits)) {
81 ret = -EINVAL;
82 goto error_ret;
85 mutex_lock(&indio_dev->mlock);
86 st->cached_val = val;
87 st->chip_info->store_sample(st, val);
88 ret = spi_sync(st->spi, &st->msg);
89 mutex_unlock(&indio_dev->mlock);
91 error_ret:
92 return ret ? ret : len;
95 static IIO_DEV_ATTR_OUT_RAW(0, ad5446_write, 0);
97 static ssize_t ad5446_show_scale(struct device *dev,
98 struct device_attribute *attr,
99 char *buf)
101 struct iio_dev *indio_dev = dev_get_drvdata(dev);
102 struct ad5446_state *st = iio_priv(indio_dev);
103 /* Corresponds to Vref / 2^(bits) */
104 unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits;
106 return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
108 static IIO_DEVICE_ATTR(out_voltage_scale, S_IRUGO, ad5446_show_scale, NULL, 0);
110 static ssize_t ad5446_write_powerdown_mode(struct device *dev,
111 struct device_attribute *attr,
112 const char *buf, size_t len)
114 struct iio_dev *indio_dev = dev_get_drvdata(dev);
115 struct ad5446_state *st = iio_priv(indio_dev);
117 if (sysfs_streq(buf, "1kohm_to_gnd"))
118 st->pwr_down_mode = MODE_PWRDWN_1k;
119 else if (sysfs_streq(buf, "100kohm_to_gnd"))
120 st->pwr_down_mode = MODE_PWRDWN_100k;
121 else if (sysfs_streq(buf, "three_state"))
122 st->pwr_down_mode = MODE_PWRDWN_TRISTATE;
123 else
124 return -EINVAL;
126 return len;
129 static ssize_t ad5446_read_powerdown_mode(struct device *dev,
130 struct device_attribute *attr, char *buf)
132 struct iio_dev *indio_dev = dev_get_drvdata(dev);
133 struct ad5446_state *st = iio_priv(indio_dev);
135 char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"};
137 return sprintf(buf, "%s\n", mode[st->pwr_down_mode]);
140 static ssize_t ad5446_read_dac_powerdown(struct device *dev,
141 struct device_attribute *attr,
142 char *buf)
144 struct iio_dev *indio_dev = dev_get_drvdata(dev);
145 struct ad5446_state *st = iio_priv(indio_dev);
147 return sprintf(buf, "%d\n", st->pwr_down);
150 static ssize_t ad5446_write_dac_powerdown(struct device *dev,
151 struct device_attribute *attr,
152 const char *buf, size_t len)
154 struct iio_dev *indio_dev = dev_get_drvdata(dev);
155 struct ad5446_state *st = iio_priv(indio_dev);
156 unsigned long readin;
157 int ret;
159 ret = strict_strtol(buf, 10, &readin);
160 if (ret)
161 return ret;
163 if (readin > 1)
164 ret = -EINVAL;
166 mutex_lock(&indio_dev->mlock);
167 st->pwr_down = readin;
169 if (st->pwr_down)
170 st->chip_info->store_pwr_down(st, st->pwr_down_mode);
171 else
172 st->chip_info->store_sample(st, st->cached_val);
174 ret = spi_sync(st->spi, &st->msg);
175 mutex_unlock(&indio_dev->mlock);
177 return ret ? ret : len;
180 static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO | S_IWUSR,
181 ad5446_read_powerdown_mode,
182 ad5446_write_powerdown_mode, 0);
184 static IIO_CONST_ATTR(out_voltage_powerdown_mode_available,
185 "1kohm_to_gnd 100kohm_to_gnd three_state");
187 static IIO_DEVICE_ATTR(out_voltage0_powerdown, S_IRUGO | S_IWUSR,
188 ad5446_read_dac_powerdown,
189 ad5446_write_dac_powerdown, 0);
191 static struct attribute *ad5446_attributes[] = {
192 &iio_dev_attr_out_voltage0_raw.dev_attr.attr,
193 &iio_dev_attr_out_voltage_scale.dev_attr.attr,
194 &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
195 &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
196 &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
197 NULL,
200 static umode_t ad5446_attr_is_visible(struct kobject *kobj,
201 struct attribute *attr, int n)
203 struct device *dev = container_of(kobj, struct device, kobj);
204 struct iio_dev *indio_dev = dev_get_drvdata(dev);
205 struct ad5446_state *st = iio_priv(indio_dev);
207 umode_t mode = attr->mode;
209 if (!st->chip_info->store_pwr_down &&
210 (attr == &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr ||
211 attr == &iio_dev_attr_out_voltage_powerdown_mode.
212 dev_attr.attr ||
213 attr ==
214 &iio_const_attr_out_voltage_powerdown_mode_available.
215 dev_attr.attr))
216 mode = 0;
218 return mode;
221 static const struct attribute_group ad5446_attribute_group = {
222 .attrs = ad5446_attributes,
223 .is_visible = ad5446_attr_is_visible,
226 static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
227 [ID_AD5444] = {
228 .bits = 12,
229 .storagebits = 16,
230 .left_shift = 2,
231 .store_sample = ad5446_store_sample,
233 [ID_AD5446] = {
234 .bits = 14,
235 .storagebits = 16,
236 .left_shift = 0,
237 .store_sample = ad5446_store_sample,
239 [ID_AD5541A] = {
240 .bits = 16,
241 .storagebits = 16,
242 .left_shift = 0,
243 .store_sample = ad5542_store_sample,
245 [ID_AD5542A] = {
246 .bits = 16,
247 .storagebits = 16,
248 .left_shift = 0,
249 .store_sample = ad5542_store_sample,
251 [ID_AD5543] = {
252 .bits = 16,
253 .storagebits = 16,
254 .left_shift = 0,
255 .store_sample = ad5542_store_sample,
257 [ID_AD5512A] = {
258 .bits = 12,
259 .storagebits = 16,
260 .left_shift = 4,
261 .store_sample = ad5542_store_sample,
263 [ID_AD5553] = {
264 .bits = 14,
265 .storagebits = 16,
266 .left_shift = 0,
267 .store_sample = ad5542_store_sample,
269 [ID_AD5601] = {
270 .bits = 8,
271 .storagebits = 16,
272 .left_shift = 6,
273 .store_sample = ad5542_store_sample,
274 .store_pwr_down = ad5620_store_pwr_down,
276 [ID_AD5611] = {
277 .bits = 10,
278 .storagebits = 16,
279 .left_shift = 4,
280 .store_sample = ad5542_store_sample,
281 .store_pwr_down = ad5620_store_pwr_down,
283 [ID_AD5621] = {
284 .bits = 12,
285 .storagebits = 16,
286 .left_shift = 2,
287 .store_sample = ad5542_store_sample,
288 .store_pwr_down = ad5620_store_pwr_down,
290 [ID_AD5620_2500] = {
291 .bits = 12,
292 .storagebits = 16,
293 .left_shift = 2,
294 .int_vref_mv = 2500,
295 .store_sample = ad5620_store_sample,
296 .store_pwr_down = ad5620_store_pwr_down,
298 [ID_AD5620_1250] = {
299 .bits = 12,
300 .storagebits = 16,
301 .left_shift = 2,
302 .int_vref_mv = 1250,
303 .store_sample = ad5620_store_sample,
304 .store_pwr_down = ad5620_store_pwr_down,
306 [ID_AD5640_2500] = {
307 .bits = 14,
308 .storagebits = 16,
309 .left_shift = 0,
310 .int_vref_mv = 2500,
311 .store_sample = ad5620_store_sample,
312 .store_pwr_down = ad5620_store_pwr_down,
314 [ID_AD5640_1250] = {
315 .bits = 14,
316 .storagebits = 16,
317 .left_shift = 0,
318 .int_vref_mv = 1250,
319 .store_sample = ad5620_store_sample,
320 .store_pwr_down = ad5620_store_pwr_down,
322 [ID_AD5660_2500] = {
323 .bits = 16,
324 .storagebits = 24,
325 .left_shift = 0,
326 .int_vref_mv = 2500,
327 .store_sample = ad5660_store_sample,
328 .store_pwr_down = ad5660_store_pwr_down,
330 [ID_AD5660_1250] = {
331 .bits = 16,
332 .storagebits = 24,
333 .left_shift = 0,
334 .int_vref_mv = 1250,
335 .store_sample = ad5660_store_sample,
336 .store_pwr_down = ad5660_store_pwr_down,
340 static const struct iio_info ad5446_info = {
341 .attrs = &ad5446_attribute_group,
342 .driver_module = THIS_MODULE,
345 static int __devinit ad5446_probe(struct spi_device *spi)
347 struct ad5446_state *st;
348 struct iio_dev *indio_dev;
349 struct regulator *reg;
350 int ret, voltage_uv = 0;
352 reg = regulator_get(&spi->dev, "vcc");
353 if (!IS_ERR(reg)) {
354 ret = regulator_enable(reg);
355 if (ret)
356 goto error_put_reg;
358 voltage_uv = regulator_get_voltage(reg);
361 indio_dev = iio_allocate_device(sizeof(*st));
362 if (indio_dev == NULL) {
363 ret = -ENOMEM;
364 goto error_disable_reg;
366 st = iio_priv(indio_dev);
367 st->chip_info =
368 &ad5446_chip_info_tbl[spi_get_device_id(spi)->driver_data];
370 spi_set_drvdata(spi, indio_dev);
371 st->reg = reg;
372 st->spi = spi;
374 /* Estabilish that the iio_dev is a child of the spi device */
375 indio_dev->dev.parent = &spi->dev;
376 indio_dev->name = spi_get_device_id(spi)->name;
377 indio_dev->info = &ad5446_info;
378 indio_dev->modes = INDIO_DIRECT_MODE;
380 /* Setup default message */
382 st->xfer.tx_buf = &st->data;
383 st->xfer.len = st->chip_info->storagebits / 8;
385 spi_message_init(&st->msg);
386 spi_message_add_tail(&st->xfer, &st->msg);
388 switch (spi_get_device_id(spi)->driver_data) {
389 case ID_AD5620_2500:
390 case ID_AD5620_1250:
391 case ID_AD5640_2500:
392 case ID_AD5640_1250:
393 case ID_AD5660_2500:
394 case ID_AD5660_1250:
395 st->vref_mv = st->chip_info->int_vref_mv;
396 break;
397 default:
398 if (voltage_uv)
399 st->vref_mv = voltage_uv / 1000;
400 else
401 dev_warn(&spi->dev,
402 "reference voltage unspecified\n");
405 ret = iio_device_register(indio_dev);
406 if (ret)
407 goto error_free_device;
409 return 0;
411 error_free_device:
412 iio_free_device(indio_dev);
413 error_disable_reg:
414 if (!IS_ERR(reg))
415 regulator_disable(reg);
416 error_put_reg:
417 if (!IS_ERR(reg))
418 regulator_put(reg);
420 return ret;
423 static int ad5446_remove(struct spi_device *spi)
425 struct iio_dev *indio_dev = spi_get_drvdata(spi);
426 struct ad5446_state *st = iio_priv(indio_dev);
428 iio_device_unregister(indio_dev);
429 if (!IS_ERR(st->reg)) {
430 regulator_disable(st->reg);
431 regulator_put(st->reg);
433 iio_free_device(indio_dev);
435 return 0;
438 static const struct spi_device_id ad5446_id[] = {
439 {"ad5444", ID_AD5444},
440 {"ad5446", ID_AD5446},
441 {"ad5512a", ID_AD5512A},
442 {"ad5541a", ID_AD5541A},
443 {"ad5542a", ID_AD5542A},
444 {"ad5543", ID_AD5543},
445 {"ad5553", ID_AD5553},
446 {"ad5601", ID_AD5601},
447 {"ad5611", ID_AD5611},
448 {"ad5621", ID_AD5621},
449 {"ad5620-2500", ID_AD5620_2500}, /* AD5620/40/60: */
450 {"ad5620-1250", ID_AD5620_1250}, /* part numbers may look differently */
451 {"ad5640-2500", ID_AD5640_2500},
452 {"ad5640-1250", ID_AD5640_1250},
453 {"ad5660-2500", ID_AD5660_2500},
454 {"ad5660-1250", ID_AD5660_1250},
458 static struct spi_driver ad5446_driver = {
459 .driver = {
460 .name = "ad5446",
461 .bus = &spi_bus_type,
462 .owner = THIS_MODULE,
464 .probe = ad5446_probe,
465 .remove = __devexit_p(ad5446_remove),
466 .id_table = ad5446_id,
469 static int __init ad5446_init(void)
471 return spi_register_driver(&ad5446_driver);
473 module_init(ad5446_init);
475 static void __exit ad5446_exit(void)
477 spi_unregister_driver(&ad5446_driver);
479 module_exit(ad5446_exit);
481 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
482 MODULE_DESCRIPTION("Analog Devices AD5444/AD5446 DAC");
483 MODULE_LICENSE("GPL v2");
484 MODULE_ALIAS("spi:ad5446");