aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-io.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-06-13 14:35:29 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-08-08 01:59:44 -0400
commitbe3ea3b9e8df64acb3606055c01291f0b58876a6 (patch)
treee2256f913cc23b5a0c504f947a4a0a5bcb256523 /sound/soc/soc-io.c
parent322a8b034003c0d46d39af85bf24fee27b902f48 (diff)
ASoC: Use new register map API for ASoC generic physical I/O
Remove all the ASoC specific physical I/O code and replace it with calls into the regmap API. The bulk write code can only be used safely if all regmap calls are locked with the CODEC lock, we need to add bulk support to the regmap API or replace the code with an open coded loop (though currently it has no users...). Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Liam Girdwood <lrg@ti.com>
Diffstat (limited to 'sound/soc/soc-io.c')
-rw-r--r--sound/soc/soc-io.c319
1 files changed, 34 insertions, 285 deletions
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index cca490c80589..b56e1c4bb9e6 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -13,26 +13,13 @@
13 13
14#include <linux/i2c.h> 14#include <linux/i2c.h>
15#include <linux/spi/spi.h> 15#include <linux/spi/spi.h>
16#include <linux/regmap.h>
16#include <sound/soc.h> 17#include <sound/soc.h>
17 18
18#include <trace/events/asoc.h> 19#include <trace/events/asoc.h>
19 20
20#ifdef CONFIG_SPI_MASTER 21static int hw_write(struct snd_soc_codec *codec, unsigned int reg,
21static int do_spi_write(void *control, const char *data, int len) 22 unsigned int value)
22{
23 struct spi_device *spi = control;
24 int ret;
25
26 ret = spi_write(spi, data, len);
27 if (ret < 0)
28 return ret;
29
30 return len;
31}
32#endif
33
34static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg,
35 unsigned int value, const void *data, int len)
36{ 23{
37 int ret; 24 int ret;
38 25
@@ -49,13 +36,7 @@ static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg,
49 return 0; 36 return 0;
50 } 37 }
51 38
52 ret = codec->hw_write(codec->control_data, data, len); 39 return regmap_write(codec->control_data, reg, value);
53 if (ret == len)
54 return 0;
55 if (ret < 0)
56 return ret;
57 else
58 return -EIO;
59} 40}
60 41
61static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg) 42static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
@@ -69,8 +50,11 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
69 if (codec->cache_only) 50 if (codec->cache_only)
70 return -1; 51 return -1;
71 52
72 BUG_ON(!codec->hw_read); 53 ret = regmap_read(codec->control_data, reg, &val);
73 return codec->hw_read(codec, reg); 54 if (ret == 0)
55 return val;
56 else
57 return ret;
74 } 58 }
75 59
76 ret = snd_soc_cache_read(codec, reg, &val); 60 ret = snd_soc_cache_read(codec, reg, &val);
@@ -79,183 +63,18 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
79 return val; 63 return val;
80} 64}
81 65
82static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
83 unsigned int value)
84{
85 u16 data;
86
87 data = cpu_to_be16((reg << 12) | (value & 0xffffff));
88
89 return do_hw_write(codec, reg, value, &data, 2);
90}
91
92static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
93 unsigned int value)
94{
95 u16 data;
96
97 data = cpu_to_be16((reg << 9) | (value & 0x1ff));
98
99 return do_hw_write(codec, reg, value, &data, 2);
100}
101
102static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
103 unsigned int value)
104{
105 u8 data[2];
106
107 reg &= 0xff;
108 data[0] = reg;
109 data[1] = value & 0xff;
110
111 return do_hw_write(codec, reg, value, data, 2);
112}
113
114static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
115 unsigned int value)
116{
117 u8 data[3];
118 u16 val = cpu_to_be16(value);
119
120 data[0] = reg;
121 memcpy(&data[1], &val, sizeof(val));
122
123 return do_hw_write(codec, reg, value, data, 3);
124}
125
126#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
127static unsigned int do_i2c_read(struct snd_soc_codec *codec,
128 void *reg, int reglen,
129 void *data, int datalen)
130{
131 struct i2c_msg xfer[2];
132 int ret;
133 struct i2c_client *client = codec->control_data;
134
135 /* Write register */
136 xfer[0].addr = client->addr;
137 xfer[0].flags = 0;
138 xfer[0].len = reglen;
139 xfer[0].buf = reg;
140
141 /* Read data */
142 xfer[1].addr = client->addr;
143 xfer[1].flags = I2C_M_RD;
144 xfer[1].len = datalen;
145 xfer[1].buf = data;
146
147 ret = i2c_transfer(client->adapter, xfer, 2);
148 if (ret == 2)
149 return 0;
150 else if (ret < 0)
151 return ret;
152 else
153 return -EIO;
154}
155#endif
156
157#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
158static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec,
159 unsigned int r)
160{
161 u8 reg = r;
162 u8 data;
163 int ret;
164
165 ret = do_i2c_read(codec, &reg, 1, &data, 1);
166 if (ret < 0)
167 return 0;
168 return data;
169}
170#else
171#define snd_soc_8_8_read_i2c NULL
172#endif
173
174#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
175static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec,
176 unsigned int r)
177{
178 u8 reg = r;
179 u16 data;
180 int ret;
181
182 ret = do_i2c_read(codec, &reg, 1, &data, 2);
183 if (ret < 0)
184 return 0;
185 return (data >> 8) | ((data & 0xff) << 8);
186}
187#else
188#define snd_soc_8_16_read_i2c NULL
189#endif
190
191#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
192static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec,
193 unsigned int r)
194{
195 u16 reg = r;
196 u8 data;
197 int ret;
198
199 ret = do_i2c_read(codec, &reg, 2, &data, 1);
200 if (ret < 0)
201 return 0;
202 return data;
203}
204#else
205#define snd_soc_16_8_read_i2c NULL
206#endif
207
208static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
209 unsigned int value)
210{
211 u8 data[3];
212 u16 rval = cpu_to_be16(reg);
213
214 memcpy(data, &rval, sizeof(rval));
215 data[2] = value;
216
217 return do_hw_write(codec, reg, value, data, 3);
218}
219
220#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
221static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec,
222 unsigned int r)
223{
224 u16 reg = cpu_to_be16(r);
225 u16 data;
226 int ret;
227
228 ret = do_i2c_read(codec, &reg, 2, &data, 2);
229 if (ret < 0)
230 return 0;
231 return be16_to_cpu(data);
232}
233#else
234#define snd_soc_16_16_read_i2c NULL
235#endif
236
237static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
238 unsigned int value)
239{
240 u16 data[2];
241
242 data[0] = cpu_to_be16(reg);
243 data[1] = cpu_to_be16(value);
244
245 return do_hw_write(codec, reg, value, data, sizeof(data));
246}
247
248/* Primitive bulk write support for soc-cache. The data pointed to by 66/* Primitive bulk write support for soc-cache. The data pointed to by
249 * `data' needs to already be in the form the hardware expects 67 * `data' needs to already be in the form the hardware expects. Any
250 * including any leading register specific data. Any data written 68 * data written through this function will not go through the cache as
251 * through this function will not go through the cache as it only 69 * it only handles writing to volatile or out of bounds registers.
252 * handles writing to volatile or out of bounds registers. 70 *
71 * This is currently only supported for devices using the regmap API
72 * wrappers.
253 */ 73 */
254static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int reg, 74static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec,
75 unsigned int reg,
255 const void *data, size_t len) 76 const void *data, size_t len)
256{ 77{
257 int ret;
258
259 /* To ensure that we don't get out of sync with the cache, check 78 /* To ensure that we don't get out of sync with the cache, check
260 * whether the base register is volatile or if we've directly asked 79 * whether the base register is volatile or if we've directly asked
261 * to bypass the cache. Out of bounds registers are considered 80 * to bypass the cache. Out of bounds registers are considered
@@ -266,66 +85,9 @@ static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int r
266 && reg < codec->driver->reg_cache_size) 85 && reg < codec->driver->reg_cache_size)
267 return -EINVAL; 86 return -EINVAL;
268 87
269 switch (codec->control_type) { 88 return regmap_raw_write(codec->control_data, reg, data, len);
270#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
271 case SND_SOC_I2C:
272 ret = i2c_master_send(to_i2c_client(codec->dev), data, len);
273 break;
274#endif
275#if defined(CONFIG_SPI_MASTER)
276 case SND_SOC_SPI:
277 ret = spi_write(to_spi_device(codec->dev), data, len);
278 break;
279#endif
280 default:
281 BUG();
282 }
283
284 if (ret == len)
285 return 0;
286 if (ret < 0)
287 return ret;
288 else
289 return -EIO;
290} 89}
291 90
292static struct {
293 int addr_bits;
294 int data_bits;
295 int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int);
296 unsigned int (*read)(struct snd_soc_codec *, unsigned int);
297 unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
298} io_types[] = {
299 {
300 .addr_bits = 4, .data_bits = 12,
301 .write = snd_soc_4_12_write,
302 },
303 {
304 .addr_bits = 7, .data_bits = 9,
305 .write = snd_soc_7_9_write,
306 },
307 {
308 .addr_bits = 8, .data_bits = 8,
309 .write = snd_soc_8_8_write,
310 .i2c_read = snd_soc_8_8_read_i2c,
311 },
312 {
313 .addr_bits = 8, .data_bits = 16,
314 .write = snd_soc_8_16_write,
315 .i2c_read = snd_soc_8_16_read_i2c,
316 },
317 {
318 .addr_bits = 16, .data_bits = 8,
319 .write = snd_soc_16_8_write,
320 .i2c_read = snd_soc_16_8_read_i2c,
321 },
322 {
323 .addr_bits = 16, .data_bits = 16,
324 .write = snd_soc_16_16_write,
325 .i2c_read = snd_soc_16_16_read_i2c,
326 },
327};
328
329/** 91/**
330 * snd_soc_codec_set_cache_io: Set up standard I/O functions. 92 * snd_soc_codec_set_cache_io: Set up standard I/O functions.
331 * 93 *
@@ -349,47 +111,34 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
349 int addr_bits, int data_bits, 111 int addr_bits, int data_bits,
350 enum snd_soc_control_type control) 112 enum snd_soc_control_type control)
351{ 113{
352 int i; 114 struct regmap_config config;
353
354 for (i = 0; i < ARRAY_SIZE(io_types); i++)
355 if (io_types[i].addr_bits == addr_bits &&
356 io_types[i].data_bits == data_bits)
357 break;
358 if (i == ARRAY_SIZE(io_types)) {
359 printk(KERN_ERR
360 "No I/O functions for %d bit address %d bit data\n",
361 addr_bits, data_bits);
362 return -EINVAL;
363 }
364 115
365 codec->write = io_types[i].write; 116 memset(&config, 0, sizeof(config));
117 codec->write = hw_write;
366 codec->read = hw_read; 118 codec->read = hw_read;
367 codec->bulk_write_raw = snd_soc_hw_bulk_write_raw; 119 codec->bulk_write_raw = snd_soc_hw_bulk_write_raw;
368 120
121 config.reg_bits = addr_bits;
122 config.val_bits = data_bits;
123
369 switch (control) { 124 switch (control) {
370 case SND_SOC_I2C: 125 case SND_SOC_I2C:
371#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) 126 codec->control_data = regmap_init_i2c(to_i2c_client(codec->dev),
372 codec->hw_write = (hw_write_t)i2c_master_send; 127 &config);
373#endif
374 if (io_types[i].i2c_read)
375 codec->hw_read = io_types[i].i2c_read;
376
377 codec->control_data = container_of(codec->dev,
378 struct i2c_client,
379 dev);
380 break; 128 break;
381 129
382 case SND_SOC_SPI: 130 case SND_SOC_SPI:
383#ifdef CONFIG_SPI_MASTER 131 codec->control_data = regmap_init_spi(to_spi_device(codec->dev),
384 codec->hw_write = do_spi_write; 132 &config);
385#endif
386
387 codec->control_data = container_of(codec->dev,
388 struct spi_device,
389 dev);
390 break; 133 break;
134
135 default:
136 return -EINVAL;
391 } 137 }
392 138
139 if (IS_ERR(codec->control_data))
140 return PTR_ERR(codec->control_data);
141
393 return 0; 142 return 0;
394} 143}
395EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); 144EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);