diff options
Diffstat (limited to 'sound/soc/soc-cache.c')
-rw-r--r-- | sound/soc/soc-cache.c | 257 |
1 files changed, 252 insertions, 5 deletions
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index c8ceddc2a26c..5869dc3be781 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c | |||
@@ -15,6 +15,74 @@ | |||
15 | #include <linux/spi/spi.h> | 15 | #include <linux/spi/spi.h> |
16 | #include <sound/soc.h> | 16 | #include <sound/soc.h> |
17 | 17 | ||
18 | static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec, | ||
19 | unsigned int reg) | ||
20 | { | ||
21 | u16 *cache = codec->reg_cache; | ||
22 | if (reg >= codec->reg_cache_size) | ||
23 | return -1; | ||
24 | return cache[reg]; | ||
25 | } | ||
26 | |||
27 | static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg, | ||
28 | unsigned int value) | ||
29 | { | ||
30 | u16 *cache = codec->reg_cache; | ||
31 | u8 data[2]; | ||
32 | int ret; | ||
33 | |||
34 | BUG_ON(codec->volatile_register); | ||
35 | |||
36 | data[0] = (reg << 4) | ((value >> 8) & 0x000f); | ||
37 | data[1] = value & 0x00ff; | ||
38 | |||
39 | if (reg < codec->reg_cache_size) | ||
40 | cache[reg] = value; | ||
41 | |||
42 | if (codec->cache_only) { | ||
43 | codec->cache_sync = 1; | ||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | ret = codec->hw_write(codec->control_data, data, 2); | ||
48 | if (ret == 2) | ||
49 | return 0; | ||
50 | if (ret < 0) | ||
51 | return ret; | ||
52 | else | ||
53 | return -EIO; | ||
54 | } | ||
55 | |||
56 | #if defined(CONFIG_SPI_MASTER) | ||
57 | static int snd_soc_4_12_spi_write(void *control_data, const char *data, | ||
58 | int len) | ||
59 | { | ||
60 | struct spi_device *spi = control_data; | ||
61 | struct spi_transfer t; | ||
62 | struct spi_message m; | ||
63 | u8 msg[2]; | ||
64 | |||
65 | if (len <= 0) | ||
66 | return 0; | ||
67 | |||
68 | msg[0] = data[1]; | ||
69 | msg[1] = data[0]; | ||
70 | |||
71 | spi_message_init(&m); | ||
72 | memset(&t, 0, (sizeof t)); | ||
73 | |||
74 | t.tx_buf = &msg[0]; | ||
75 | t.len = len; | ||
76 | |||
77 | spi_message_add_tail(&t, &m); | ||
78 | spi_sync(spi, &m); | ||
79 | |||
80 | return len; | ||
81 | } | ||
82 | #else | ||
83 | #define snd_soc_4_12_spi_write NULL | ||
84 | #endif | ||
85 | |||
18 | static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, | 86 | static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, |
19 | unsigned int reg) | 87 | unsigned int reg) |
20 | { | 88 | { |
@@ -38,6 +106,12 @@ static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg, | |||
38 | 106 | ||
39 | if (reg < codec->reg_cache_size) | 107 | if (reg < codec->reg_cache_size) |
40 | cache[reg] = value; | 108 | cache[reg] = value; |
109 | |||
110 | if (codec->cache_only) { | ||
111 | codec->cache_sync = 1; | ||
112 | return 0; | ||
113 | } | ||
114 | |||
41 | ret = codec->hw_write(codec->control_data, data, 2); | 115 | ret = codec->hw_write(codec->control_data, data, 2); |
42 | if (ret == 2) | 116 | if (ret == 2) |
43 | return 0; | 117 | return 0; |
@@ -77,6 +151,40 @@ static int snd_soc_7_9_spi_write(void *control_data, const char *data, | |||
77 | #define snd_soc_7_9_spi_write NULL | 151 | #define snd_soc_7_9_spi_write NULL |
78 | #endif | 152 | #endif |
79 | 153 | ||
154 | static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg, | ||
155 | unsigned int value) | ||
156 | { | ||
157 | u8 *cache = codec->reg_cache; | ||
158 | u8 data[2]; | ||
159 | |||
160 | BUG_ON(codec->volatile_register); | ||
161 | |||
162 | data[0] = reg & 0xff; | ||
163 | data[1] = value & 0xff; | ||
164 | |||
165 | if (reg < codec->reg_cache_size) | ||
166 | cache[reg] = value; | ||
167 | |||
168 | if (codec->cache_only) { | ||
169 | codec->cache_sync = 1; | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | if (codec->hw_write(codec->control_data, data, 2) == 2) | ||
174 | return 0; | ||
175 | else | ||
176 | return -EIO; | ||
177 | } | ||
178 | |||
179 | static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec, | ||
180 | unsigned int reg) | ||
181 | { | ||
182 | u8 *cache = codec->reg_cache; | ||
183 | if (reg >= codec->reg_cache_size) | ||
184 | return -1; | ||
185 | return cache[reg]; | ||
186 | } | ||
187 | |||
80 | static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, | 188 | static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, |
81 | unsigned int value) | 189 | unsigned int value) |
82 | { | 190 | { |
@@ -90,6 +198,11 @@ static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, | |||
90 | if (!snd_soc_codec_volatile_register(codec, reg)) | 198 | if (!snd_soc_codec_volatile_register(codec, reg)) |
91 | reg_cache[reg] = value; | 199 | reg_cache[reg] = value; |
92 | 200 | ||
201 | if (codec->cache_only) { | ||
202 | codec->cache_sync = 1; | ||
203 | return 0; | ||
204 | } | ||
205 | |||
93 | if (codec->hw_write(codec->control_data, data, 3) == 3) | 206 | if (codec->hw_write(codec->control_data, data, 3) == 3) |
94 | return 0; | 207 | return 0; |
95 | else | 208 | else |
@@ -102,10 +215,14 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec, | |||
102 | u16 *cache = codec->reg_cache; | 215 | u16 *cache = codec->reg_cache; |
103 | 216 | ||
104 | if (reg >= codec->reg_cache_size || | 217 | if (reg >= codec->reg_cache_size || |
105 | snd_soc_codec_volatile_register(codec, reg)) | 218 | snd_soc_codec_volatile_register(codec, reg)) { |
219 | if (codec->cache_only) | ||
220 | return -EINVAL; | ||
221 | |||
106 | return codec->hw_read(codec, reg); | 222 | return codec->hw_read(codec, reg); |
107 | else | 223 | } else { |
108 | return cache[reg]; | 224 | return cache[reg]; |
225 | } | ||
109 | } | 226 | } |
110 | 227 | ||
111 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | 228 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) |
@@ -142,6 +259,114 @@ static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec, | |||
142 | #define snd_soc_8_16_read_i2c NULL | 259 | #define snd_soc_8_16_read_i2c NULL |
143 | #endif | 260 | #endif |
144 | 261 | ||
262 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | ||
263 | static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec, | ||
264 | unsigned int r) | ||
265 | { | ||
266 | struct i2c_msg xfer[2]; | ||
267 | u16 reg = r; | ||
268 | u8 data; | ||
269 | int ret; | ||
270 | struct i2c_client *client = codec->control_data; | ||
271 | |||
272 | /* Write register */ | ||
273 | xfer[0].addr = client->addr; | ||
274 | xfer[0].flags = 0; | ||
275 | xfer[0].len = 2; | ||
276 | xfer[0].buf = (u8 *)® | ||
277 | |||
278 | /* Read data */ | ||
279 | xfer[1].addr = client->addr; | ||
280 | xfer[1].flags = I2C_M_RD; | ||
281 | xfer[1].len = 1; | ||
282 | xfer[1].buf = &data; | ||
283 | |||
284 | ret = i2c_transfer(client->adapter, xfer, 2); | ||
285 | if (ret != 2) { | ||
286 | dev_err(&client->dev, "i2c_transfer() returned %d\n", ret); | ||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | return data; | ||
291 | } | ||
292 | #else | ||
293 | #define snd_soc_16_8_read_i2c NULL | ||
294 | #endif | ||
295 | |||
296 | static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec, | ||
297 | unsigned int reg) | ||
298 | { | ||
299 | u16 *cache = codec->reg_cache; | ||
300 | |||
301 | reg &= 0xff; | ||
302 | if (reg >= codec->reg_cache_size) | ||
303 | return -1; | ||
304 | return cache[reg]; | ||
305 | } | ||
306 | |||
307 | static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, | ||
308 | unsigned int value) | ||
309 | { | ||
310 | u16 *cache = codec->reg_cache; | ||
311 | u8 data[3]; | ||
312 | int ret; | ||
313 | |||
314 | BUG_ON(codec->volatile_register); | ||
315 | |||
316 | data[0] = (reg >> 8) & 0xff; | ||
317 | data[1] = reg & 0xff; | ||
318 | data[2] = value; | ||
319 | |||
320 | reg &= 0xff; | ||
321 | if (reg < codec->reg_cache_size) | ||
322 | cache[reg] = value; | ||
323 | |||
324 | if (codec->cache_only) { | ||
325 | codec->cache_sync = 1; | ||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | ret = codec->hw_write(codec->control_data, data, 3); | ||
330 | if (ret == 3) | ||
331 | return 0; | ||
332 | if (ret < 0) | ||
333 | return ret; | ||
334 | else | ||
335 | return -EIO; | ||
336 | } | ||
337 | |||
338 | #if defined(CONFIG_SPI_MASTER) | ||
339 | static int snd_soc_16_8_spi_write(void *control_data, const char *data, | ||
340 | int len) | ||
341 | { | ||
342 | struct spi_device *spi = control_data; | ||
343 | struct spi_transfer t; | ||
344 | struct spi_message m; | ||
345 | u8 msg[3]; | ||
346 | |||
347 | if (len <= 0) | ||
348 | return 0; | ||
349 | |||
350 | msg[0] = data[0]; | ||
351 | msg[1] = data[1]; | ||
352 | msg[2] = data[2]; | ||
353 | |||
354 | spi_message_init(&m); | ||
355 | memset(&t, 0, (sizeof t)); | ||
356 | |||
357 | t.tx_buf = &msg[0]; | ||
358 | t.len = len; | ||
359 | |||
360 | spi_message_add_tail(&t, &m); | ||
361 | spi_sync(spi, &m); | ||
362 | |||
363 | return len; | ||
364 | } | ||
365 | #else | ||
366 | #define snd_soc_16_8_spi_write NULL | ||
367 | #endif | ||
368 | |||
369 | |||
145 | static struct { | 370 | static struct { |
146 | int addr_bits; | 371 | int addr_bits; |
147 | int data_bits; | 372 | int data_bits; |
@@ -150,9 +375,31 @@ static struct { | |||
150 | unsigned int (*read)(struct snd_soc_codec *, unsigned int); | 375 | unsigned int (*read)(struct snd_soc_codec *, unsigned int); |
151 | unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); | 376 | unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); |
152 | } io_types[] = { | 377 | } io_types[] = { |
153 | { 7, 9, snd_soc_7_9_write, snd_soc_7_9_spi_write, snd_soc_7_9_read }, | 378 | { |
154 | { 8, 16, snd_soc_8_16_write, NULL, snd_soc_8_16_read, | 379 | .addr_bits = 4, .data_bits = 12, |
155 | snd_soc_8_16_read_i2c }, | 380 | .write = snd_soc_4_12_write, .read = snd_soc_4_12_read, |
381 | .spi_write = snd_soc_4_12_spi_write, | ||
382 | }, | ||
383 | { | ||
384 | .addr_bits = 7, .data_bits = 9, | ||
385 | .write = snd_soc_7_9_write, .read = snd_soc_7_9_read, | ||
386 | .spi_write = snd_soc_7_9_spi_write, | ||
387 | }, | ||
388 | { | ||
389 | .addr_bits = 8, .data_bits = 8, | ||
390 | .write = snd_soc_8_8_write, .read = snd_soc_8_8_read, | ||
391 | }, | ||
392 | { | ||
393 | .addr_bits = 8, .data_bits = 16, | ||
394 | .write = snd_soc_8_16_write, .read = snd_soc_8_16_read, | ||
395 | .i2c_read = snd_soc_8_16_read_i2c, | ||
396 | }, | ||
397 | { | ||
398 | .addr_bits = 16, .data_bits = 8, | ||
399 | .write = snd_soc_16_8_write, .read = snd_soc_16_8_read, | ||
400 | .i2c_read = snd_soc_16_8_read_i2c, | ||
401 | .spi_write = snd_soc_16_8_spi_write, | ||
402 | }, | ||
156 | }; | 403 | }; |
157 | 404 | ||
158 | /** | 405 | /** |