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

iio: add mcp4725 I2C DAC driver

v5:
* fix warnings (Jonathan Cameron)

v4:
* remove unused indio_dev pointer in mcp4725_data (Jonathan Cameron)
* use u16 instead of unsigned short in mcp4725_data (Jonathan Cameron)
* #include mcp4725.h from linux/iio/dac/

v3:
* move from staging to drivers/iio
* switch to chan_spec
* dev_get_drvdata() -> dev_to_iio_dev()
* annotate probe() and remove() with __devinit and __devexit

v2 (based on comments from Jonathan Cameron and Lars-Peter Clausen):
* did NOT switch to chan_spec yet
* rebase to staging-next tree, update iio header locations
* dropped dac.h #include, not needed
* strict_strtol() -> kstrtol()
* call iio_device_unregister() in remove()
* everything in one patch

Signed-off-by: Peter Meerwald <pmeerw@pmeerw.net>
Acked-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Peter Meerwald and committed by
Greg Kroah-Hartman
cf35ad61 1a135d1a

+255
+11
drivers/iio/dac/Kconfig
··· 118 118 This driver can also be built as a module. If so, the module 119 119 will be called max517. 120 120 121 + config MCP4725 122 + tristate "MCP4725 DAC driver" 123 + depends on I2C 124 + ---help--- 125 + Say Y here if you want to build a driver for the Microchip 126 + MCP 4725 12-bit digital-to-analog converter (DAC) with I2C 127 + interface. 128 + 129 + To compile this driver as a module, choose M here: the module 130 + will be called mcp4725. 131 + 121 132 endmenu
+1
drivers/iio/dac/Makefile
··· 13 13 obj-$(CONFIG_AD5791) += ad5791.o 14 14 obj-$(CONFIG_AD5686) += ad5686.o 15 15 obj-$(CONFIG_MAX517) += max517.o 16 + obj-$(CONFIG_MCP4725) += mcp4725.o
+227
drivers/iio/dac/mcp4725.c
··· 1 + /* 2 + * mcp4725.c - Support for Microchip MCP4725 3 + * 4 + * Copyright (C) 2012 Peter Meerwald <pmeerw@pmeerw.net> 5 + * 6 + * Based on max517 by Roland Stigge <stigge@antcom.de> 7 + * 8 + * This file is subject to the terms and conditions of version 2 of 9 + * the GNU General Public License. See the file COPYING in the main 10 + * directory of this archive for more details. 11 + * 12 + * driver for the Microchip I2C 12-bit digital-to-analog converter (DAC) 13 + * (7-bit I2C slave address 0x60, the three LSBs can be configured in 14 + * hardware) 15 + * 16 + * writing the DAC value to EEPROM is not supported 17 + */ 18 + 19 + #include <linux/module.h> 20 + #include <linux/init.h> 21 + #include <linux/i2c.h> 22 + #include <linux/err.h> 23 + 24 + #include <linux/iio/iio.h> 25 + #include <linux/iio/sysfs.h> 26 + 27 + #include <linux/iio/dac/mcp4725.h> 28 + 29 + #define MCP4725_DRV_NAME "mcp4725" 30 + 31 + struct mcp4725_data { 32 + struct i2c_client *client; 33 + u16 vref_mv; 34 + u16 dac_value; 35 + }; 36 + 37 + #ifdef CONFIG_PM_SLEEP 38 + static int mcp4725_suspend(struct device *dev) 39 + { 40 + u8 outbuf[2]; 41 + 42 + outbuf[0] = 0x3 << 4; /* power-down bits, 500 kOhm resistor */ 43 + outbuf[1] = 0; 44 + 45 + return i2c_master_send(to_i2c_client(dev), outbuf, 2); 46 + } 47 + 48 + static int mcp4725_resume(struct device *dev) 49 + { 50 + struct iio_dev *indio_dev = dev_to_iio_dev(dev); 51 + struct mcp4725_data *data = iio_priv(indio_dev); 52 + u8 outbuf[2]; 53 + 54 + /* restore previous DAC value */ 55 + outbuf[0] = (data->dac_value >> 8) & 0xf; 56 + outbuf[1] = data->dac_value & 0xff; 57 + 58 + return i2c_master_send(to_i2c_client(dev), outbuf, 2); 59 + } 60 + 61 + static SIMPLE_DEV_PM_OPS(mcp4725_pm_ops, mcp4725_suspend, mcp4725_resume); 62 + #define MCP4725_PM_OPS (&mcp4725_pm_ops) 63 + #else 64 + #define MCP4725_PM_OPS NULL 65 + #endif 66 + 67 + static const struct iio_chan_spec mcp4725_channel = { 68 + .type = IIO_VOLTAGE, 69 + .indexed = 1, 70 + .output = 1, 71 + .channel = 0, 72 + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | 73 + IIO_CHAN_INFO_SCALE_SHARED_BIT, 74 + .scan_type = IIO_ST('u', 12, 16, 0), 75 + }; 76 + 77 + static int mcp4725_set_value(struct iio_dev *indio_dev, int val) 78 + { 79 + struct mcp4725_data *data = iio_priv(indio_dev); 80 + u8 outbuf[2]; 81 + int ret; 82 + 83 + if (val >= (1 << 12) || val < 0) 84 + return -EINVAL; 85 + 86 + outbuf[0] = (val >> 8) & 0xf; 87 + outbuf[1] = val & 0xff; 88 + 89 + ret = i2c_master_send(data->client, outbuf, 2); 90 + if (ret < 0) 91 + return ret; 92 + else if (ret != 2) 93 + return -EIO; 94 + else 95 + return 0; 96 + } 97 + 98 + static int mcp4725_read_raw(struct iio_dev *indio_dev, 99 + struct iio_chan_spec const *chan, 100 + int *val, int *val2, long mask) 101 + { 102 + struct mcp4725_data *data = iio_priv(indio_dev); 103 + unsigned long scale_uv; 104 + 105 + switch (mask) { 106 + case IIO_CHAN_INFO_RAW: 107 + *val = data->dac_value; 108 + return IIO_VAL_INT; 109 + case IIO_CHAN_INFO_SCALE: 110 + scale_uv = (data->vref_mv * 1000) >> 12; 111 + *val = scale_uv / 1000000; 112 + *val2 = scale_uv % 1000000; 113 + return IIO_VAL_INT_PLUS_MICRO; 114 + } 115 + return -EINVAL; 116 + } 117 + 118 + static int mcp4725_write_raw(struct iio_dev *indio_dev, 119 + struct iio_chan_spec const *chan, 120 + int val, int val2, long mask) 121 + { 122 + struct mcp4725_data *data = iio_priv(indio_dev); 123 + int ret; 124 + 125 + switch (mask) { 126 + case IIO_CHAN_INFO_RAW: 127 + ret = mcp4725_set_value(indio_dev, val); 128 + data->dac_value = val; 129 + break; 130 + default: 131 + ret = -EINVAL; 132 + break; 133 + } 134 + 135 + return ret; 136 + } 137 + 138 + static const struct iio_info mcp4725_info = { 139 + .read_raw = mcp4725_read_raw, 140 + .write_raw = mcp4725_write_raw, 141 + .driver_module = THIS_MODULE, 142 + }; 143 + 144 + static int __devinit mcp4725_probe(struct i2c_client *client, 145 + const struct i2c_device_id *id) 146 + { 147 + struct mcp4725_data *data; 148 + struct iio_dev *indio_dev; 149 + struct mcp4725_platform_data *platform_data = client->dev.platform_data; 150 + u8 inbuf[3]; 151 + int err; 152 + 153 + if (!platform_data || !platform_data->vref_mv) { 154 + dev_err(&client->dev, "invalid platform data"); 155 + err = -EINVAL; 156 + goto exit; 157 + } 158 + 159 + indio_dev = iio_device_alloc(sizeof(*data)); 160 + if (indio_dev == NULL) { 161 + err = -ENOMEM; 162 + goto exit; 163 + } 164 + data = iio_priv(indio_dev); 165 + i2c_set_clientdata(client, indio_dev); 166 + data->client = client; 167 + 168 + indio_dev->dev.parent = &client->dev; 169 + indio_dev->info = &mcp4725_info; 170 + indio_dev->channels = &mcp4725_channel; 171 + indio_dev->num_channels = 1; 172 + indio_dev->modes = INDIO_DIRECT_MODE; 173 + 174 + data->vref_mv = platform_data->vref_mv; 175 + 176 + /* read current DAC value */ 177 + err = i2c_master_recv(client, inbuf, 3); 178 + if (err < 0) { 179 + dev_err(&client->dev, "failed to read DAC value"); 180 + goto exit_free_device; 181 + } 182 + data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4); 183 + 184 + err = iio_device_register(indio_dev); 185 + if (err) 186 + goto exit_free_device; 187 + 188 + dev_info(&client->dev, "MCP4725 DAC registered\n"); 189 + 190 + return 0; 191 + 192 + exit_free_device: 193 + iio_device_free(indio_dev); 194 + exit: 195 + return err; 196 + } 197 + 198 + static int __devexit mcp4725_remove(struct i2c_client *client) 199 + { 200 + struct iio_dev *indio_dev = i2c_get_clientdata(client); 201 + 202 + iio_device_unregister(indio_dev); 203 + iio_device_free(indio_dev); 204 + 205 + return 0; 206 + } 207 + 208 + static const struct i2c_device_id mcp4725_id[] = { 209 + { "mcp4725", 0 }, 210 + { } 211 + }; 212 + MODULE_DEVICE_TABLE(i2c, mcp4725_id); 213 + 214 + static struct i2c_driver mcp4725_driver = { 215 + .driver = { 216 + .name = MCP4725_DRV_NAME, 217 + .pm = MCP4725_PM_OPS, 218 + }, 219 + .probe = mcp4725_probe, 220 + .remove = __devexit_p(mcp4725_remove), 221 + .id_table = mcp4725_id, 222 + }; 223 + module_i2c_driver(mcp4725_driver); 224 + 225 + MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); 226 + MODULE_DESCRIPTION("MCP4725 12-bit DAC"); 227 + MODULE_LICENSE("GPL");
+16
include/linux/iio/dac/mcp4725.h
··· 1 + /* 2 + * MCP4725 DAC driver 3 + * 4 + * Copyright (C) 2012 Peter Meerwald <pmeerw@pmeerw.net> 5 + * 6 + * Licensed under the GPL-2 or later. 7 + */ 8 + 9 + #ifndef IIO_DAC_MCP4725_H_ 10 + #define IIO_DAC_MCP4725_H_ 11 + 12 + struct mcp4725_platform_data { 13 + u16 vref_mv; 14 + }; 15 + 16 + #endif /* IIO_DAC_MCP4725_H_ */