diff options
author | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2015-05-14 10:21:16 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2015-05-17 04:37:45 -0400 |
commit | b87b0c0f81e8d11c881b726b886b7502ab67d884 (patch) | |
tree | 7de8a11229b47216e05fac441d11e71096877cc3 | |
parent | c06cee8d0865b7478484d9472155d8df83a10c06 (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/Kconfig | 10 | ||||
-rw-r--r-- | drivers/iio/dac/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/dac/m62332.c | 269 |
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 | ||
145 | config 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 | |||
145 | config MAX517 | 155 | config 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 | |||
16 | obj-$(CONFIG_AD5791) += ad5791.o | 16 | obj-$(CONFIG_AD5791) += ad5791.o |
17 | obj-$(CONFIG_AD5686) += ad5686.o | 17 | obj-$(CONFIG_AD5686) += ad5686.o |
18 | obj-$(CONFIG_AD7303) += ad7303.o | 18 | obj-$(CONFIG_AD7303) += ad7303.o |
19 | obj-$(CONFIG_M62332) += m62332.o | ||
19 | obj-$(CONFIG_MAX517) += max517.o | 20 | obj-$(CONFIG_MAX517) += max517.o |
20 | obj-$(CONFIG_MAX5821) += max5821.o | 21 | obj-$(CONFIG_MAX5821) += max5821.o |
21 | obj-$(CONFIG_MCP4725) += mcp4725.o | 22 | obj-$(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 | |||
32 | struct 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 | |||
43 | static 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 | |||
80 | out: | ||
81 | mutex_unlock(&data->mutex); | ||
82 | |||
83 | return res; | ||
84 | } | ||
85 | |||
86 | static 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 | |||
112 | static 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 | ||
133 | static 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 | |||
150 | static 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 | |||
164 | static 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 | |||
170 | static 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 | |||
187 | static const struct iio_chan_spec m62332_channels[M62332_CHANNELS] = { | ||
188 | M62332_CHANNEL(0), | ||
189 | M62332_CHANNEL(1) | ||
190 | }; | ||
191 | |||
192 | static 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 | |||
235 | err: | ||
236 | iio_map_array_unregister(indio_dev); | ||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | static 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 | |||
250 | static const struct i2c_device_id m62332_id[] = { | ||
251 | { "m62332", }, | ||
252 | { } | ||
253 | }; | ||
254 | MODULE_DEVICE_TABLE(i2c, m62332_id); | ||
255 | |||
256 | static 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 | }; | ||
265 | module_i2c_driver(m62332_driver); | ||
266 | |||
267 | MODULE_AUTHOR("Dmitry Eremin-Solenikov"); | ||
268 | MODULE_DESCRIPTION("M62332 8-bit DAC"); | ||
269 | MODULE_LICENSE("GPL v2"); | ||