Root/
1 | /* |
2 | * soc-io.c -- ASoC register I/O helpers |
3 | * |
4 | * Copyright 2009-2011 Wolfson Microelectronics PLC. |
5 | * |
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify it |
9 | * under the terms of the GNU General Public License as published by the |
10 | * Free Software Foundation; either version 2 of the License, or (at your |
11 | * option) any later version. |
12 | */ |
13 | |
14 | #include <linux/i2c.h> |
15 | #include <linux/spi/spi.h> |
16 | #include <sound/soc.h> |
17 | |
18 | #include <trace/events/asoc.h> |
19 | |
20 | #ifdef CONFIG_SPI_MASTER |
21 | static int do_spi_write(void *control, const char *data, int len) |
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 | |
34 | static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg, |
35 | unsigned int value, const void *data, int len) |
36 | { |
37 | int ret; |
38 | |
39 | if (!snd_soc_codec_volatile_register(codec, reg) && |
40 | reg < codec->driver->reg_cache_size && |
41 | !codec->cache_bypass) { |
42 | ret = snd_soc_cache_write(codec, reg, value); |
43 | if (ret < 0) |
44 | return -1; |
45 | } |
46 | |
47 | if (codec->cache_only) { |
48 | codec->cache_sync = 1; |
49 | return 0; |
50 | } |
51 | |
52 | ret = codec->hw_write(codec->control_data, data, len); |
53 | if (ret == len) |
54 | return 0; |
55 | if (ret < 0) |
56 | return ret; |
57 | else |
58 | return -EIO; |
59 | } |
60 | |
61 | static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg) |
62 | { |
63 | int ret; |
64 | unsigned int val; |
65 | |
66 | if (reg >= codec->driver->reg_cache_size || |
67 | snd_soc_codec_volatile_register(codec, reg) || |
68 | codec->cache_bypass) { |
69 | if (codec->cache_only) |
70 | return -1; |
71 | |
72 | BUG_ON(!codec->hw_read); |
73 | return codec->hw_read(codec, reg); |
74 | } |
75 | |
76 | ret = snd_soc_cache_read(codec, reg, &val); |
77 | if (ret < 0) |
78 | return -1; |
79 | return val; |
80 | } |
81 | |
82 | static 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 | |
92 | static 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 | |
102 | static 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 | |
114 | static 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)) |
127 | static 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)) |
158 | static 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, ®, 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)) |
175 | static 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, ®, 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)) |
192 | static 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, ®, 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 | |
208 | #if defined(CONFIG_SPI_MASTER) |
209 | static unsigned int snd_soc_16_8_read_spi(struct snd_soc_codec *codec, |
210 | unsigned int r) |
211 | { |
212 | struct spi_device *spi = codec->control_data; |
213 | |
214 | const u16 reg = cpu_to_be16(r | 0x100); |
215 | u8 data; |
216 | int ret; |
217 | |
218 | ret = spi_write_then_read(spi, ®, 2, &data, 1); |
219 | if (ret < 0) |
220 | return 0; |
221 | return data; |
222 | } |
223 | #else |
224 | #define snd_soc_16_8_read_spi NULL |
225 | #endif |
226 | |
227 | static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, |
228 | unsigned int value) |
229 | { |
230 | u8 data[3]; |
231 | u16 rval = cpu_to_be16(reg); |
232 | |
233 | memcpy(data, &rval, sizeof(rval)); |
234 | data[2] = value; |
235 | |
236 | return do_hw_write(codec, reg, value, data, 3); |
237 | } |
238 | |
239 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) |
240 | static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec, |
241 | unsigned int r) |
242 | { |
243 | u16 reg = cpu_to_be16(r); |
244 | u16 data; |
245 | int ret; |
246 | |
247 | ret = do_i2c_read(codec, ®, 2, &data, 2); |
248 | if (ret < 0) |
249 | return 0; |
250 | return be16_to_cpu(data); |
251 | } |
252 | #else |
253 | #define snd_soc_16_16_read_i2c NULL |
254 | #endif |
255 | |
256 | static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg, |
257 | unsigned int value) |
258 | { |
259 | u16 data[2]; |
260 | |
261 | data[0] = cpu_to_be16(reg); |
262 | data[1] = cpu_to_be16(value); |
263 | |
264 | return do_hw_write(codec, reg, value, data, sizeof(data)); |
265 | } |
266 | |
267 | /* Primitive bulk write support for soc-cache. The data pointed to by |
268 | * `data' needs to already be in the form the hardware expects |
269 | * including any leading register specific data. Any data written |
270 | * through this function will not go through the cache as it only |
271 | * handles writing to volatile or out of bounds registers. |
272 | */ |
273 | static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int reg, |
274 | const void *data, size_t len) |
275 | { |
276 | int ret; |
277 | |
278 | /* To ensure that we don't get out of sync with the cache, check |
279 | * whether the base register is volatile or if we've directly asked |
280 | * to bypass the cache. Out of bounds registers are considered |
281 | * volatile. |
282 | */ |
283 | if (!codec->cache_bypass |
284 | && !snd_soc_codec_volatile_register(codec, reg) |
285 | && reg < codec->driver->reg_cache_size) |
286 | return -EINVAL; |
287 | |
288 | switch (codec->control_type) { |
289 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) |
290 | case SND_SOC_I2C: |
291 | ret = i2c_master_send(to_i2c_client(codec->dev), data, len); |
292 | break; |
293 | #endif |
294 | #if defined(CONFIG_SPI_MASTER) |
295 | case SND_SOC_SPI: |
296 | ret = spi_write(to_spi_device(codec->dev), data, len); |
297 | break; |
298 | #endif |
299 | default: |
300 | BUG(); |
301 | } |
302 | |
303 | if (ret == len) |
304 | return 0; |
305 | if (ret < 0) |
306 | return ret; |
307 | else |
308 | return -EIO; |
309 | } |
310 | |
311 | static struct { |
312 | int addr_bits; |
313 | int data_bits; |
314 | int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int); |
315 | unsigned int (*read)(struct snd_soc_codec *, unsigned int); |
316 | unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); |
317 | unsigned int (*spi_read)(struct snd_soc_codec *, unsigned int); |
318 | } io_types[] = { |
319 | { |
320 | .addr_bits = 4, .data_bits = 12, |
321 | .write = snd_soc_4_12_write, |
322 | }, |
323 | { |
324 | .addr_bits = 7, .data_bits = 9, |
325 | .write = snd_soc_7_9_write, |
326 | }, |
327 | { |
328 | .addr_bits = 8, .data_bits = 8, |
329 | .write = snd_soc_8_8_write, |
330 | .i2c_read = snd_soc_8_8_read_i2c, |
331 | }, |
332 | { |
333 | .addr_bits = 8, .data_bits = 16, |
334 | .write = snd_soc_8_16_write, |
335 | .i2c_read = snd_soc_8_16_read_i2c, |
336 | }, |
337 | { |
338 | .addr_bits = 16, .data_bits = 8, |
339 | .write = snd_soc_16_8_write, |
340 | .i2c_read = snd_soc_16_8_read_i2c, |
341 | .spi_read = snd_soc_16_8_read_spi, |
342 | }, |
343 | { |
344 | .addr_bits = 16, .data_bits = 16, |
345 | .write = snd_soc_16_16_write, |
346 | .i2c_read = snd_soc_16_16_read_i2c, |
347 | }, |
348 | }; |
349 | |
350 | /** |
351 | * snd_soc_codec_set_cache_io: Set up standard I/O functions. |
352 | * |
353 | * @codec: CODEC to configure. |
354 | * @addr_bits: Number of bits of register address data. |
355 | * @data_bits: Number of bits of data per register. |
356 | * @control: Control bus used. |
357 | * |
358 | * Register formats are frequently shared between many I2C and SPI |
359 | * devices. In order to promote code reuse the ASoC core provides |
360 | * some standard implementations of CODEC read and write operations |
361 | * which can be set up using this function. |
362 | * |
363 | * The caller is responsible for allocating and initialising the |
364 | * actual cache. |
365 | * |
366 | * Note that at present this code cannot be used by CODECs with |
367 | * volatile registers. |
368 | */ |
369 | int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, |
370 | int addr_bits, int data_bits, |
371 | enum snd_soc_control_type control) |
372 | { |
373 | int i; |
374 | |
375 | for (i = 0; i < ARRAY_SIZE(io_types); i++) |
376 | if (io_types[i].addr_bits == addr_bits && |
377 | io_types[i].data_bits == data_bits) |
378 | break; |
379 | if (i == ARRAY_SIZE(io_types)) { |
380 | printk(KERN_ERR |
381 | "No I/O functions for %d bit address %d bit data\n", |
382 | addr_bits, data_bits); |
383 | return -EINVAL; |
384 | } |
385 | |
386 | codec->write = io_types[i].write; |
387 | codec->read = hw_read; |
388 | codec->bulk_write_raw = snd_soc_hw_bulk_write_raw; |
389 | |
390 | switch (control) { |
391 | case SND_SOC_I2C: |
392 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) |
393 | codec->hw_write = (hw_write_t)i2c_master_send; |
394 | #endif |
395 | if (io_types[i].i2c_read) |
396 | codec->hw_read = io_types[i].i2c_read; |
397 | |
398 | codec->control_data = container_of(codec->dev, |
399 | struct i2c_client, |
400 | dev); |
401 | break; |
402 | |
403 | case SND_SOC_SPI: |
404 | #ifdef CONFIG_SPI_MASTER |
405 | codec->hw_write = do_spi_write; |
406 | #endif |
407 | if (io_types[i].spi_read) |
408 | codec->hw_read = io_types[i].spi_read; |
409 | |
410 | codec->control_data = container_of(codec->dev, |
411 | struct spi_device, |
412 | dev); |
413 | break; |
414 | } |
415 | |
416 | return 0; |
417 | } |
418 | EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); |
419 | |
420 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9