aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2015-05-14 10:21:16 -0400
committerJonathan Cameron <jic23@kernel.org>2015-05-17 04:37:45 -0400
commitb87b0c0f81e8d11c881b726b886b7502ab67d884 (patch)
tree7de8a11229b47216e05fac441d11e71096877cc3
parentc06cee8d0865b7478484d9472155d8df83a10c06 (diff)
iio: add m62332 DAC driver
m62332 is a simple 2-channel DAC used on several Sharp Zaurus boards to control LCD voltage, backlight and sound. The driver use regulators to control the reference voltage and enabling/disabling the DAC. Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r--drivers/iio/dac/Kconfig10
-rw-r--r--drivers/iio/dac/Makefile1
-rw-r--r--drivers/iio/dac/m62332.c269
3 files changed, 280 insertions, 0 deletions
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 13471a76e5bf..e701e28fb1cd 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -142,6 +142,16 @@ config AD7303
142 To compile this driver as module choose M here: the module will be called 142 To compile this driver as module choose M here: the module will be called
143 ad7303. 143 ad7303.
144 144
145config M62332
146 tristate "Mitsubishi M62332 DAC driver"
147 depends on I2C
148 help
149 If you say yes here you get support for the Mitsubishi M62332
150 (I2C 8-Bit DACs with rail-to-rail outputs).
151
152 This driver can also be built as a module. If so, the module
153 will be called m62332.
154
145config MAX517 155config MAX517
146 tristate "Maxim MAX517/518/519/520/521 DAC driver" 156 tristate "Maxim MAX517/518/519/520/521 DAC driver"
147 depends on I2C 157 depends on I2C
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 52be7e1acf16..63ae05633e0c 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_AD5764) += ad5764.o
16obj-$(CONFIG_AD5791) += ad5791.o 16obj-$(CONFIG_AD5791) += ad5791.o
17obj-$(CONFIG_AD5686) += ad5686.o 17obj-$(CONFIG_AD5686) += ad5686.o
18obj-$(CONFIG_AD7303) += ad7303.o 18obj-$(CONFIG_AD7303) += ad7303.o
19obj-$(CONFIG_M62332) += m62332.o
19obj-$(CONFIG_MAX517) += max517.o 20obj-$(CONFIG_MAX517) += max517.o
20obj-$(CONFIG_MAX5821) += max5821.o 21obj-$(CONFIG_MAX5821) += max5821.o
21obj-$(CONFIG_MCP4725) += mcp4725.o 22obj-$(CONFIG_MCP4725) += mcp4725.o
diff --git a/drivers/iio/dac/m62332.c b/drivers/iio/dac/m62332.c
new file mode 100644
index 000000000000..c23d7fa889ee
--- /dev/null
+++ b/drivers/iio/dac/m62332.c
@@ -0,0 +1,269 @@
1/*
2 * m62332.c - Support for Mitsubishi m62332 DAC
3 *
4 * Copyright (c) 2014 Dmitry Eremin-Solenikov
5 *
6 * Based on max517 driver:
7 * Copyright (C) 2010, 2011 Roland Stigge <stigge@antcom.de>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20#include <linux/module.h>
21#include <linux/slab.h>
22#include <linux/i2c.h>
23#include <linux/err.h>
24
25#include <linux/iio/iio.h>
26#include <linux/iio/driver.h>
27
28#include <linux/regulator/consumer.h>
29
30#define M62332_CHANNELS 2
31
32struct m62332_data {
33 struct i2c_client *client;
34 u16 vref_mv;
35 struct regulator *vcc;
36 struct mutex mutex;
37 u8 raw[M62332_CHANNELS];
38#ifdef CONFIG_PM_SLEEP
39 u8 save[M62332_CHANNELS];
40#endif
41};
42
43static int m62332_set_value(struct iio_dev *indio_dev,
44 u8 val, int channel)
45{
46 struct m62332_data *data = iio_priv(indio_dev);
47 struct i2c_client *client = data->client;
48 u8 outbuf[2];
49 int res;
50
51 if (val == data->raw[channel])
52 return 0;
53
54 outbuf[0] = channel;
55 outbuf[1] = val;
56
57 mutex_lock(&data->mutex);
58
59 if (val) {
60 res = regulator_enable(data->vcc);
61 if (res)
62 goto out;
63 }
64
65 res = i2c_master_send(client, outbuf, 2);
66 if (res >= 0 && res != 2)
67 res = -EIO;
68 if (res < 0)
69 goto out;
70
71 data->raw[channel] = val;
72
73 if (!val)
74 regulator_disable(data->vcc);
75
76 mutex_unlock(&data->mutex);
77
78 return 0;
79
80out:
81 mutex_unlock(&data->mutex);
82
83 return res;
84}
85
86static int m62332_read_raw(struct iio_dev *indio_dev,
87 struct iio_chan_spec const *chan,
88 int *val,
89 int *val2,
90 long m)
91{
92 struct m62332_data *data = iio_priv(indio_dev);
93
94 switch (m) {
95 case IIO_CHAN_INFO_SCALE:
96 /* Corresponds to Vref / 2^(bits) */
97 *val = data->vref_mv;
98 *val2 = 8;
99 return IIO_VAL_FRACTIONAL_LOG2;
100 case IIO_CHAN_INFO_RAW:
101 *val = data->raw[chan->channel];
102 return IIO_VAL_INT;
103 case IIO_CHAN_INFO_OFFSET:
104 *val = 1;
105 return IIO_VAL_INT;
106 default:
107 break;
108 }
109 return -EINVAL;
110}
111
112static int m62332_write_raw(struct iio_dev *indio_dev,
113 struct iio_chan_spec const *chan, int val, int val2, long mask)
114{
115 int ret;
116
117 switch (mask) {
118 case IIO_CHAN_INFO_RAW:
119 if (val < 0 || val > 255)
120 return -EINVAL;
121
122 ret = m62332_set_value(indio_dev, val, chan->channel);
123 break;
124 default:
125 ret = -EINVAL;
126 break;
127 }
128
129 return ret;
130}
131
132#ifdef CONFIG_PM_SLEEP
133static int m62332_suspend(struct device *dev)
134{
135 struct i2c_client *client = to_i2c_client(dev);
136 struct iio_dev *indio_dev = i2c_get_clientdata(client);
137 struct m62332_data *data = iio_priv(indio_dev);
138 int ret;
139
140 data->save[0] = data->raw[0];
141 data->save[1] = data->raw[1];
142
143 ret = m62332_set_value(indio_dev, 0, 0);
144 if (ret < 0)
145 return ret;
146
147 return m62332_set_value(indio_dev, 0, 1);
148}
149
150static int m62332_resume(struct device *dev)
151{
152 struct i2c_client *client = to_i2c_client(dev);
153 struct iio_dev *indio_dev = i2c_get_clientdata(client);
154 struct m62332_data *data = iio_priv(indio_dev);
155 int ret;
156
157 ret = m62332_set_value(indio_dev, data->save[0], 0);
158 if (ret < 0)
159 return ret;
160
161 return m62332_set_value(indio_dev, data->save[1], 1);
162}
163
164static SIMPLE_DEV_PM_OPS(m62332_pm_ops, m62332_suspend, m62332_resume);
165#define M62332_PM_OPS (&m62332_pm_ops)
166#else
167#define M62332_PM_OPS NULL
168#endif
169
170static const struct iio_info m62332_info = {
171 .read_raw = m62332_read_raw,
172 .write_raw = m62332_write_raw,
173 .driver_module = THIS_MODULE,
174};
175
176#define M62332_CHANNEL(chan) { \
177 .type = IIO_VOLTAGE, \
178 .indexed = 1, \
179 .output = 1, \
180 .channel = (chan), \
181 .datasheet_name = "CH" #chan, \
182 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
183 BIT(IIO_CHAN_INFO_SCALE) | \
184 BIT(IIO_CHAN_INFO_OFFSET), \
185}
186
187static const struct iio_chan_spec m62332_channels[M62332_CHANNELS] = {
188 M62332_CHANNEL(0),
189 M62332_CHANNEL(1)
190};
191
192static int m62332_probe(struct i2c_client *client,
193 const struct i2c_device_id *id)
194{
195 struct m62332_data *data;
196 struct iio_dev *indio_dev;
197 int ret;
198
199 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
200 if (!indio_dev)
201 return -ENOMEM;
202 data = iio_priv(indio_dev);
203 i2c_set_clientdata(client, indio_dev);
204 data->client = client;
205
206 mutex_init(&data->mutex);
207
208 data->vcc = devm_regulator_get(&client->dev, "VCC");
209 if (IS_ERR(data->vcc))
210 return PTR_ERR(data->vcc);
211
212 /* establish that the iio_dev is a child of the i2c device */
213 indio_dev->dev.parent = &client->dev;
214
215 indio_dev->num_channels = M62332_CHANNELS;
216 indio_dev->channels = m62332_channels;
217 indio_dev->modes = INDIO_DIRECT_MODE;
218 indio_dev->info = &m62332_info;
219
220 ret = regulator_get_voltage(data->vcc);
221 if (ret < 0)
222 return ret;
223 data->vref_mv = ret / 1000; /* mV */
224
225 ret = iio_map_array_register(indio_dev, client->dev.platform_data);
226 if (ret < 0)
227 return ret;
228
229 ret = iio_device_register(indio_dev);
230 if (ret < 0)
231 goto err;
232
233 return 0;
234
235err:
236 iio_map_array_unregister(indio_dev);
237 return ret;
238}
239
240static int m62332_remove(struct i2c_client *client)
241{
242 struct iio_dev *indio_dev = i2c_get_clientdata(client);
243
244 iio_device_unregister(indio_dev);
245 iio_map_array_unregister(indio_dev);
246
247 return 0;
248}
249
250static const struct i2c_device_id m62332_id[] = {
251 { "m62332", },
252 { }
253};
254MODULE_DEVICE_TABLE(i2c, m62332_id);
255
256static struct i2c_driver m62332_driver = {
257 .driver = {
258 .name = "m62332",
259 .pm = M62332_PM_OPS,
260 },
261 .probe = m62332_probe,
262 .remove = m62332_remove,
263 .id_table = m62332_id,
264};
265module_i2c_driver(m62332_driver);
266
267MODULE_AUTHOR("Dmitry Eremin-Solenikov");
268MODULE_DESCRIPTION("M62332 8-bit DAC");
269MODULE_LICENSE("GPL v2");