blob: 4ee473d6057abae81938a2fd88a05974d927da86 [file] [log] [blame]
Mark Brown17a52fd2009-07-05 17:24:50 +01001/*
2 * soc-cache.c -- ASoC register cache helpers
3 *
4 * Copyright 2009 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
Mark Brown7084a422009-07-10 22:24:27 +010014#include <linux/i2c.h>
Mark Brown27ded042009-07-10 23:28:16 +010015#include <linux/spi/spi.h>
Mark Brown17a52fd2009-07-05 17:24:50 +010016#include <sound/soc.h>
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +000017#include <linux/lzo.h>
18#include <linux/bitmap.h>
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +000019#include <linux/rbtree.h>
Mark Brown17a52fd2009-07-05 17:24:50 +010020
Dimitris Papastamosc358e642011-01-21 15:29:02 +000021#include <trace/events/asoc.h>
22
Dimitris Papastamos26e99842011-03-22 10:36:58 +000023static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg,
24 unsigned int value, const void *data, int len)
25{
26 int ret;
27
28 if (!snd_soc_codec_volatile_register(codec, reg) &&
29 reg < codec->driver->reg_cache_size &&
30 !codec->cache_bypass) {
31 ret = snd_soc_cache_write(codec, reg, value);
32 if (ret < 0)
33 return -1;
34 }
35
36 if (codec->cache_only) {
37 codec->cache_sync = 1;
38 return 0;
39 }
40
41 ret = codec->hw_write(codec->control_data, data, len);
42 if (ret == len)
43 return 0;
44 if (ret < 0)
45 return ret;
46 else
47 return -EIO;
48}
49
Barry Song63b62ab2010-01-27 11:46:17 +080050static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,
51 unsigned int reg)
52{
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +000053 int ret;
54 unsigned int val;
Dimitris Papastamosdb49c142010-09-22 13:25:47 +010055
56 if (reg >= codec->driver->reg_cache_size ||
Dimitris Papastamosdad8e7a2011-01-19 14:53:36 +000057 snd_soc_codec_volatile_register(codec, reg) ||
58 codec->cache_bypass) {
Dimitris Papastamosdb49c142010-09-22 13:25:47 +010059 if (codec->cache_only)
60 return -1;
61
Dimitris Papastamos5aaa0622010-11-08 15:37:07 +000062 BUG_ON(!codec->hw_read);
Dimitris Papastamosdb49c142010-09-22 13:25:47 +010063 return codec->hw_read(codec, reg);
64 }
65
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +000066 ret = snd_soc_cache_read(codec, reg, &val);
67 if (ret < 0)
68 return -1;
69 return val;
Barry Song63b62ab2010-01-27 11:46:17 +080070}
71
72static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
73 unsigned int value)
74{
Barry Song63b62ab2010-01-27 11:46:17 +080075 u8 data[2];
Barry Song63b62ab2010-01-27 11:46:17 +080076
Barry Song63b62ab2010-01-27 11:46:17 +080077 data[0] = (reg << 4) | ((value >> 8) & 0x000f);
78 data[1] = value & 0x00ff;
79
Dimitris Papastamos26e99842011-03-22 10:36:58 +000080 return do_hw_write(codec, reg, value, data, 2);
Barry Song63b62ab2010-01-27 11:46:17 +080081}
82
83#if defined(CONFIG_SPI_MASTER)
84static int snd_soc_4_12_spi_write(void *control_data, const char *data,
85 int len)
86{
87 struct spi_device *spi = control_data;
88 struct spi_transfer t;
89 struct spi_message m;
90 u8 msg[2];
91
92 if (len <= 0)
93 return 0;
94
95 msg[0] = data[1];
96 msg[1] = data[0];
97
98 spi_message_init(&m);
Dimitris Papastamos465d7fc2010-12-14 15:15:36 +000099 memset(&t, 0, sizeof t);
Barry Song63b62ab2010-01-27 11:46:17 +0800100
101 t.tx_buf = &msg[0];
102 t.len = len;
103
104 spi_message_add_tail(&t, &m);
105 spi_sync(spi, &m);
106
107 return len;
108}
109#else
110#define snd_soc_4_12_spi_write NULL
111#endif
112
Mark Brown17a52fd2009-07-05 17:24:50 +0100113static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,
114 unsigned int reg)
115{
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +0000116 int ret;
117 unsigned int val;
Dimitris Papastamosdb49c142010-09-22 13:25:47 +0100118
119 if (reg >= codec->driver->reg_cache_size ||
Dimitris Papastamosdad8e7a2011-01-19 14:53:36 +0000120 snd_soc_codec_volatile_register(codec, reg) ||
121 codec->cache_bypass) {
Dimitris Papastamosdb49c142010-09-22 13:25:47 +0100122 if (codec->cache_only)
123 return -1;
124
Dimitris Papastamos5aaa0622010-11-08 15:37:07 +0000125 BUG_ON(!codec->hw_read);
Dimitris Papastamosdb49c142010-09-22 13:25:47 +0100126 return codec->hw_read(codec, reg);
127 }
128
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +0000129 ret = snd_soc_cache_read(codec, reg, &val);
130 if (ret < 0)
131 return -1;
132 return val;
Mark Brown17a52fd2009-07-05 17:24:50 +0100133}
134
135static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
136 unsigned int value)
137{
Mark Brown17a52fd2009-07-05 17:24:50 +0100138 u8 data[2];
Mark Brown17a52fd2009-07-05 17:24:50 +0100139
Mark Brown17a52fd2009-07-05 17:24:50 +0100140 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
141 data[1] = value & 0x00ff;
142
Dimitris Papastamos26e99842011-03-22 10:36:58 +0000143 return do_hw_write(codec, reg, value, data, 2);
Mark Brown17a52fd2009-07-05 17:24:50 +0100144}
145
Mark Brown27ded042009-07-10 23:28:16 +0100146#if defined(CONFIG_SPI_MASTER)
147static int snd_soc_7_9_spi_write(void *control_data, const char *data,
148 int len)
149{
150 struct spi_device *spi = control_data;
151 struct spi_transfer t;
152 struct spi_message m;
153 u8 msg[2];
154
155 if (len <= 0)
156 return 0;
157
158 msg[0] = data[0];
159 msg[1] = data[1];
160
161 spi_message_init(&m);
Dimitris Papastamos465d7fc2010-12-14 15:15:36 +0000162 memset(&t, 0, sizeof t);
Mark Brown27ded042009-07-10 23:28:16 +0100163
164 t.tx_buf = &msg[0];
165 t.len = len;
166
167 spi_message_add_tail(&t, &m);
168 spi_sync(spi, &m);
169
170 return len;
171}
172#else
173#define snd_soc_7_9_spi_write NULL
174#endif
175
Joonyoung Shim341c9b82009-09-07 12:04:37 +0900176static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
177 unsigned int value)
178{
Joonyoung Shim341c9b82009-09-07 12:04:37 +0900179 u8 data[2];
180
Barry Songf4bee1b2010-03-18 16:17:01 +0800181 reg &= 0xff;
182 data[0] = reg;
Joonyoung Shim341c9b82009-09-07 12:04:37 +0900183 data[1] = value & 0xff;
184
Dimitris Papastamos26e99842011-03-22 10:36:58 +0000185 return do_hw_write(codec, reg, value, data, 2);
Joonyoung Shim341c9b82009-09-07 12:04:37 +0900186}
187
188static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
189 unsigned int reg)
190{
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +0000191 int ret;
192 unsigned int val;
Dimitris Papastamosdb49c142010-09-22 13:25:47 +0100193
Barry Songf4bee1b2010-03-18 16:17:01 +0800194 reg &= 0xff;
Dimitris Papastamosdb49c142010-09-22 13:25:47 +0100195 if (reg >= codec->driver->reg_cache_size ||
Dimitris Papastamosdad8e7a2011-01-19 14:53:36 +0000196 snd_soc_codec_volatile_register(codec, reg) ||
197 codec->cache_bypass) {
Dimitris Papastamosdb49c142010-09-22 13:25:47 +0100198 if (codec->cache_only)
199 return -1;
200
Dimitris Papastamos5aaa0622010-11-08 15:37:07 +0000201 BUG_ON(!codec->hw_read);
Dimitris Papastamosdb49c142010-09-22 13:25:47 +0100202 return codec->hw_read(codec, reg);
203 }
204
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +0000205 ret = snd_soc_cache_read(codec, reg, &val);
206 if (ret < 0)
207 return -1;
208 return val;
Joonyoung Shim341c9b82009-09-07 12:04:37 +0900209}
210
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100211#if defined(CONFIG_SPI_MASTER)
212static int snd_soc_8_8_spi_write(void *control_data, const char *data,
213 int len)
214{
215 struct spi_device *spi = control_data;
216 struct spi_transfer t;
217 struct spi_message m;
218 u8 msg[2];
219
220 if (len <= 0)
221 return 0;
222
223 msg[0] = data[0];
224 msg[1] = data[1];
225
226 spi_message_init(&m);
Dimitris Papastamos465d7fc2010-12-14 15:15:36 +0000227 memset(&t, 0, sizeof t);
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100228
229 t.tx_buf = &msg[0];
230 t.len = len;
231
232 spi_message_add_tail(&t, &m);
233 spi_sync(spi, &m);
234
235 return len;
236}
237#else
238#define snd_soc_8_8_spi_write NULL
239#endif
240
Mark Brownafa2f102009-07-10 23:11:24 +0100241static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
242 unsigned int value)
243{
Mark Brownafa2f102009-07-10 23:11:24 +0100244 u8 data[3];
245
246 data[0] = reg;
247 data[1] = (value >> 8) & 0xff;
248 data[2] = value & 0xff;
249
Dimitris Papastamos26e99842011-03-22 10:36:58 +0000250 return do_hw_write(codec, reg, value, data, 3);
Mark Brownafa2f102009-07-10 23:11:24 +0100251}
252
253static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
254 unsigned int reg)
255{
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +0000256 int ret;
257 unsigned int val;
Mark Brownafa2f102009-07-10 23:11:24 +0100258
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000259 if (reg >= codec->driver->reg_cache_size ||
Dimitris Papastamosdad8e7a2011-01-19 14:53:36 +0000260 snd_soc_codec_volatile_register(codec, reg) ||
261 codec->cache_bypass) {
Mark Brown8c961bc2010-02-01 18:46:10 +0000262 if (codec->cache_only)
Dimitris Papastamos391d8a02010-09-21 17:04:07 +0100263 return -1;
Mark Brown8c961bc2010-02-01 18:46:10 +0000264
Dimitris Papastamos5aaa0622010-11-08 15:37:07 +0000265 BUG_ON(!codec->hw_read);
Mark Brownafa2f102009-07-10 23:11:24 +0100266 return codec->hw_read(codec, reg);
Mark Brown8c961bc2010-02-01 18:46:10 +0000267 }
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +0000268
269 ret = snd_soc_cache_read(codec, reg, &val);
270 if (ret < 0)
271 return -1;
272 return val;
Mark Brownafa2f102009-07-10 23:11:24 +0100273}
274
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100275#if defined(CONFIG_SPI_MASTER)
276static int snd_soc_8_16_spi_write(void *control_data, const char *data,
277 int len)
278{
279 struct spi_device *spi = control_data;
280 struct spi_transfer t;
281 struct spi_message m;
282 u8 msg[3];
283
284 if (len <= 0)
285 return 0;
286
287 msg[0] = data[0];
288 msg[1] = data[1];
289 msg[2] = data[2];
290
291 spi_message_init(&m);
Dimitris Papastamos465d7fc2010-12-14 15:15:36 +0000292 memset(&t, 0, sizeof t);
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100293
294 t.tx_buf = &msg[0];
295 t.len = len;
296
297 spi_message_add_tail(&t, &m);
298 spi_sync(spi, &m);
299
300 return len;
301}
302#else
303#define snd_soc_8_16_spi_write NULL
304#endif
305
Randy Dunlap17244c22009-08-10 16:04:39 -0700306#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000307static unsigned int do_i2c_read(struct snd_soc_codec *codec,
308 void *reg, int reglen,
309 void *data, int datalen)
Cliff Cai85dfcdf2010-03-18 16:17:00 +0800310{
311 struct i2c_msg xfer[2];
Cliff Cai85dfcdf2010-03-18 16:17:00 +0800312 int ret;
313 struct i2c_client *client = codec->control_data;
314
315 /* Write register */
316 xfer[0].addr = client->addr;
317 xfer[0].flags = 0;
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000318 xfer[0].len = reglen;
319 xfer[0].buf = reg;
Cliff Cai85dfcdf2010-03-18 16:17:00 +0800320
321 /* Read data */
322 xfer[1].addr = client->addr;
323 xfer[1].flags = I2C_M_RD;
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000324 xfer[1].len = datalen;
325 xfer[1].buf = data;
Cliff Cai85dfcdf2010-03-18 16:17:00 +0800326
327 ret = i2c_transfer(client->adapter, xfer, 2);
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000328 dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
329 if (ret == 2)
Cliff Cai85dfcdf2010-03-18 16:17:00 +0800330 return 0;
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000331 else if (ret < 0)
332 return ret;
333 else
334 return -EIO;
335}
336#endif
Cliff Cai85dfcdf2010-03-18 16:17:00 +0800337
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000338#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
339static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec,
340 unsigned int r)
341{
342 u8 reg = r;
343 u8 data;
344 int ret;
345
346 ret = do_i2c_read(codec, &reg, 1, &data, 1);
347 if (ret < 0)
348 return 0;
Cliff Cai85dfcdf2010-03-18 16:17:00 +0800349 return data;
350}
351#else
352#define snd_soc_8_8_read_i2c NULL
353#endif
354
355#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
Mark Brownafa2f102009-07-10 23:11:24 +0100356static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec,
357 unsigned int r)
358{
Mark Brownafa2f102009-07-10 23:11:24 +0100359 u8 reg = r;
360 u16 data;
361 int ret;
Mark Brownafa2f102009-07-10 23:11:24 +0100362
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000363 ret = do_i2c_read(codec, &reg, 1, &data, 2);
364 if (ret < 0)
Mark Brownafa2f102009-07-10 23:11:24 +0100365 return 0;
Mark Brownafa2f102009-07-10 23:11:24 +0100366 return (data >> 8) | ((data & 0xff) << 8);
367}
368#else
369#define snd_soc_8_16_read_i2c NULL
370#endif
Mark Brown17a52fd2009-07-05 17:24:50 +0100371
Barry Song994dc422010-01-27 11:46:18 +0800372#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
373static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec,
374 unsigned int r)
375{
Barry Song994dc422010-01-27 11:46:18 +0800376 u16 reg = r;
377 u8 data;
378 int ret;
Barry Song994dc422010-01-27 11:46:18 +0800379
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000380 ret = do_i2c_read(codec, &reg, 2, &data, 1);
381 if (ret < 0)
Barry Song994dc422010-01-27 11:46:18 +0800382 return 0;
Barry Song994dc422010-01-27 11:46:18 +0800383 return data;
384}
385#else
386#define snd_soc_16_8_read_i2c NULL
387#endif
388
389static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec,
390 unsigned int reg)
391{
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +0000392 int ret;
393 unsigned int val;
Barry Song994dc422010-01-27 11:46:18 +0800394
395 reg &= 0xff;
Dimitris Papastamosdb49c142010-09-22 13:25:47 +0100396 if (reg >= codec->driver->reg_cache_size ||
Dimitris Papastamosdad8e7a2011-01-19 14:53:36 +0000397 snd_soc_codec_volatile_register(codec, reg) ||
398 codec->cache_bypass) {
Dimitris Papastamosdb49c142010-09-22 13:25:47 +0100399 if (codec->cache_only)
400 return -1;
401
Dimitris Papastamos5aaa0622010-11-08 15:37:07 +0000402 BUG_ON(!codec->hw_read);
Dimitris Papastamosdb49c142010-09-22 13:25:47 +0100403 return codec->hw_read(codec, reg);
404 }
405
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +0000406 ret = snd_soc_cache_read(codec, reg, &val);
407 if (ret < 0)
408 return -1;
409 return val;
Barry Song994dc422010-01-27 11:46:18 +0800410}
411
412static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
413 unsigned int value)
414{
Barry Song994dc422010-01-27 11:46:18 +0800415 u8 data[3];
Barry Song994dc422010-01-27 11:46:18 +0800416
Barry Song994dc422010-01-27 11:46:18 +0800417 data[0] = (reg >> 8) & 0xff;
418 data[1] = reg & 0xff;
419 data[2] = value;
Barry Song994dc422010-01-27 11:46:18 +0800420 reg &= 0xff;
Mark Brown8c961bc2010-02-01 18:46:10 +0000421
Dimitris Papastamos26e99842011-03-22 10:36:58 +0000422 return do_hw_write(codec, reg, value, data, 3);
Barry Song994dc422010-01-27 11:46:18 +0800423}
424
425#if defined(CONFIG_SPI_MASTER)
426static int snd_soc_16_8_spi_write(void *control_data, const char *data,
427 int len)
428{
429 struct spi_device *spi = control_data;
430 struct spi_transfer t;
431 struct spi_message m;
432 u8 msg[3];
433
434 if (len <= 0)
435 return 0;
436
437 msg[0] = data[0];
438 msg[1] = data[1];
439 msg[2] = data[2];
440
441 spi_message_init(&m);
Dimitris Papastamos465d7fc2010-12-14 15:15:36 +0000442 memset(&t, 0, sizeof t);
Barry Song994dc422010-01-27 11:46:18 +0800443
444 t.tx_buf = &msg[0];
445 t.len = len;
446
447 spi_message_add_tail(&t, &m);
448 spi_sync(spi, &m);
449
450 return len;
451}
452#else
453#define snd_soc_16_8_spi_write NULL
454#endif
455
Mark Brownbc6552f2010-03-05 16:27:15 +0000456#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
457static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec,
458 unsigned int r)
459{
Mark Brownbc6552f2010-03-05 16:27:15 +0000460 u16 reg = cpu_to_be16(r);
461 u16 data;
462 int ret;
Mark Brownbc6552f2010-03-05 16:27:15 +0000463
Dimitris Papastamosf3594f52011-03-22 10:37:01 +0000464 ret = do_i2c_read(codec, &reg, 2, &data, 2);
465 if (ret < 0)
Mark Brownbc6552f2010-03-05 16:27:15 +0000466 return 0;
Mark Brownbc6552f2010-03-05 16:27:15 +0000467 return be16_to_cpu(data);
468}
469#else
470#define snd_soc_16_16_read_i2c NULL
471#endif
472
473static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec,
474 unsigned int reg)
475{
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +0000476 int ret;
477 unsigned int val;
Mark Brownbc6552f2010-03-05 16:27:15 +0000478
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000479 if (reg >= codec->driver->reg_cache_size ||
Dimitris Papastamosdad8e7a2011-01-19 14:53:36 +0000480 snd_soc_codec_volatile_register(codec, reg) ||
481 codec->cache_bypass) {
Mark Brownbc6552f2010-03-05 16:27:15 +0000482 if (codec->cache_only)
Dimitris Papastamos391d8a02010-09-21 17:04:07 +0100483 return -1;
Mark Brownbc6552f2010-03-05 16:27:15 +0000484
Dimitris Papastamos5aaa0622010-11-08 15:37:07 +0000485 BUG_ON(!codec->hw_read);
Mark Brownbc6552f2010-03-05 16:27:15 +0000486 return codec->hw_read(codec, reg);
487 }
488
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +0000489 ret = snd_soc_cache_read(codec, reg, &val);
490 if (ret < 0)
491 return -1;
492
493 return val;
Mark Brownbc6552f2010-03-05 16:27:15 +0000494}
495
496static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
497 unsigned int value)
498{
Mark Brownbc6552f2010-03-05 16:27:15 +0000499 u8 data[4];
Mark Brownbc6552f2010-03-05 16:27:15 +0000500
501 data[0] = (reg >> 8) & 0xff;
502 data[1] = reg & 0xff;
503 data[2] = (value >> 8) & 0xff;
504 data[3] = value & 0xff;
505
Dimitris Papastamos26e99842011-03-22 10:36:58 +0000506 return do_hw_write(codec, reg, value, data, 4);
Mark Brownbc6552f2010-03-05 16:27:15 +0000507}
Barry Song994dc422010-01-27 11:46:18 +0800508
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100509#if defined(CONFIG_SPI_MASTER)
510static int snd_soc_16_16_spi_write(void *control_data, const char *data,
511 int len)
512{
513 struct spi_device *spi = control_data;
514 struct spi_transfer t;
515 struct spi_message m;
516 u8 msg[4];
517
518 if (len <= 0)
519 return 0;
520
521 msg[0] = data[0];
522 msg[1] = data[1];
523 msg[2] = data[2];
524 msg[3] = data[3];
525
526 spi_message_init(&m);
Dimitris Papastamos465d7fc2010-12-14 15:15:36 +0000527 memset(&t, 0, sizeof t);
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100528
529 t.tx_buf = &msg[0];
530 t.len = len;
531
532 spi_message_add_tail(&t, &m);
533 spi_sync(spi, &m);
534
535 return len;
536}
537#else
538#define snd_soc_16_16_spi_write NULL
539#endif
540
Dimitris Papastamos5fb609d2011-03-22 10:37:03 +0000541/* Primitive bulk write support for soc-cache. The data pointed to by `data' needs
542 * to already be in the form the hardware expects including any leading register specific
543 * data. Any data written through this function will not go through the cache as it
544 * only handles writing to volatile or out of bounds registers.
545 */
546static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int reg,
547 const void *data, size_t len)
548{
549 int ret;
550
551 /* Ensure that the base register is volatile. Subsequently
552 * any other register that is touched by this routine should be
553 * volatile as well to ensure that we don't get out of sync with
554 * the cache.
555 */
556 if (!snd_soc_codec_volatile_register(codec, reg)
557 && reg < codec->driver->reg_cache_size)
558 return -EINVAL;
559
560 switch (codec->control_type) {
561 case SND_SOC_I2C:
562 ret = i2c_master_send(codec->control_data, data, len);
563 break;
564 case SND_SOC_SPI:
565 ret = do_spi_write(codec->control_data, data, len);
566 break;
567 default:
568 BUG();
569 }
570
571 if (ret == len)
572 return 0;
573 if (ret < 0)
574 return ret;
575 else
576 return -EIO;
577}
578
Mark Brown17a52fd2009-07-05 17:24:50 +0100579static struct {
580 int addr_bits;
581 int data_bits;
Mark Brownafa2f102009-07-10 23:11:24 +0100582 int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int);
Mark Brown27ded042009-07-10 23:28:16 +0100583 int (*spi_write)(void *, const char *, int);
Mark Brown17a52fd2009-07-05 17:24:50 +0100584 unsigned int (*read)(struct snd_soc_codec *, unsigned int);
Mark Brownafa2f102009-07-10 23:11:24 +0100585 unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
Mark Brown17a52fd2009-07-05 17:24:50 +0100586} io_types[] = {
Mark Brownd62ab352009-09-21 04:21:47 -0700587 {
Barry Song63b62ab2010-01-27 11:46:17 +0800588 .addr_bits = 4, .data_bits = 12,
589 .write = snd_soc_4_12_write, .read = snd_soc_4_12_read,
590 .spi_write = snd_soc_4_12_spi_write,
591 },
592 {
Mark Brownd62ab352009-09-21 04:21:47 -0700593 .addr_bits = 7, .data_bits = 9,
594 .write = snd_soc_7_9_write, .read = snd_soc_7_9_read,
Barry Song8998c892009-12-31 10:30:34 +0800595 .spi_write = snd_soc_7_9_spi_write,
Mark Brownd62ab352009-09-21 04:21:47 -0700596 },
597 {
598 .addr_bits = 8, .data_bits = 8,
599 .write = snd_soc_8_8_write, .read = snd_soc_8_8_read,
Cliff Cai85dfcdf2010-03-18 16:17:00 +0800600 .i2c_read = snd_soc_8_8_read_i2c,
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100601 .spi_write = snd_soc_8_8_spi_write,
Mark Brownd62ab352009-09-21 04:21:47 -0700602 },
603 {
604 .addr_bits = 8, .data_bits = 16,
605 .write = snd_soc_8_16_write, .read = snd_soc_8_16_read,
606 .i2c_read = snd_soc_8_16_read_i2c,
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100607 .spi_write = snd_soc_8_16_spi_write,
Mark Brownd62ab352009-09-21 04:21:47 -0700608 },
Barry Song994dc422010-01-27 11:46:18 +0800609 {
610 .addr_bits = 16, .data_bits = 8,
611 .write = snd_soc_16_8_write, .read = snd_soc_16_8_read,
612 .i2c_read = snd_soc_16_8_read_i2c,
613 .spi_write = snd_soc_16_8_spi_write,
614 },
Mark Brownbc6552f2010-03-05 16:27:15 +0000615 {
616 .addr_bits = 16, .data_bits = 16,
617 .write = snd_soc_16_16_write, .read = snd_soc_16_16_read,
618 .i2c_read = snd_soc_16_16_read_i2c,
Dimitris Papastamosf479fd92010-10-04 11:25:13 +0100619 .spi_write = snd_soc_16_16_spi_write,
Mark Brownbc6552f2010-03-05 16:27:15 +0000620 },
Mark Brown17a52fd2009-07-05 17:24:50 +0100621};
622
623/**
624 * snd_soc_codec_set_cache_io: Set up standard I/O functions.
625 *
626 * @codec: CODEC to configure.
627 * @type: Type of cache.
628 * @addr_bits: Number of bits of register address data.
629 * @data_bits: Number of bits of data per register.
Mark Brown7084a422009-07-10 22:24:27 +0100630 * @control: Control bus used.
Mark Brown17a52fd2009-07-05 17:24:50 +0100631 *
632 * Register formats are frequently shared between many I2C and SPI
633 * devices. In order to promote code reuse the ASoC core provides
634 * some standard implementations of CODEC read and write operations
635 * which can be set up using this function.
636 *
637 * The caller is responsible for allocating and initialising the
638 * actual cache.
639 *
640 * Note that at present this code cannot be used by CODECs with
641 * volatile registers.
642 */
643int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
Mark Brown7084a422009-07-10 22:24:27 +0100644 int addr_bits, int data_bits,
645 enum snd_soc_control_type control)
Mark Brown17a52fd2009-07-05 17:24:50 +0100646{
647 int i;
648
Mark Brown17a52fd2009-07-05 17:24:50 +0100649 for (i = 0; i < ARRAY_SIZE(io_types); i++)
650 if (io_types[i].addr_bits == addr_bits &&
651 io_types[i].data_bits == data_bits)
652 break;
653 if (i == ARRAY_SIZE(io_types)) {
654 printk(KERN_ERR
655 "No I/O functions for %d bit address %d bit data\n",
656 addr_bits, data_bits);
657 return -EINVAL;
658 }
659
Mark Brownc3acec22010-12-02 16:15:29 +0000660 codec->write = io_types[i].write;
661 codec->read = io_types[i].read;
Dimitris Papastamos5fb609d2011-03-22 10:37:03 +0000662 codec->bulk_write_raw = snd_soc_hw_bulk_write_raw;
Mark Brown17a52fd2009-07-05 17:24:50 +0100663
Mark Brown7084a422009-07-10 22:24:27 +0100664 switch (control) {
665 case SND_SOC_CUSTOM:
666 break;
667
668 case SND_SOC_I2C:
Randy Dunlap17244c22009-08-10 16:04:39 -0700669#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
Mark Brown7084a422009-07-10 22:24:27 +0100670 codec->hw_write = (hw_write_t)i2c_master_send;
671#endif
Mark Brownafa2f102009-07-10 23:11:24 +0100672 if (io_types[i].i2c_read)
673 codec->hw_read = io_types[i].i2c_read;
Mark Browna6d14342010-08-12 10:59:15 +0100674
675 codec->control_data = container_of(codec->dev,
676 struct i2c_client,
677 dev);
Mark Brown7084a422009-07-10 22:24:27 +0100678 break;
679
680 case SND_SOC_SPI:
Mark Brown27ded042009-07-10 23:28:16 +0100681 if (io_types[i].spi_write)
682 codec->hw_write = io_types[i].spi_write;
Mark Browna6d14342010-08-12 10:59:15 +0100683
684 codec->control_data = container_of(codec->dev,
685 struct spi_device,
686 dev);
Mark Brown7084a422009-07-10 22:24:27 +0100687 break;
688 }
689
Mark Brown17a52fd2009-07-05 17:24:50 +0100690 return 0;
691}
692EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +0000693
Dimitris Papastamos1321e882011-01-11 11:29:49 +0000694static bool snd_soc_set_cache_val(void *base, unsigned int idx,
695 unsigned int val, unsigned int word_size)
696{
697 switch (word_size) {
698 case 1: {
699 u8 *cache = base;
700 if (cache[idx] == val)
701 return true;
702 cache[idx] = val;
703 break;
704 }
705 case 2: {
706 u16 *cache = base;
707 if (cache[idx] == val)
708 return true;
709 cache[idx] = val;
710 break;
711 }
712 default:
713 BUG();
714 }
715 return false;
716}
717
718static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx,
719 unsigned int word_size)
720{
721 switch (word_size) {
722 case 1: {
723 const u8 *cache = base;
724 return cache[idx];
725 }
726 case 2: {
727 const u16 *cache = base;
728 return cache[idx];
729 }
730 default:
731 BUG();
732 }
733 /* unreachable */
734 return -1;
735}
736
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +0000737struct snd_soc_rbtree_node {
738 struct rb_node node;
739 unsigned int reg;
740 unsigned int value;
741 unsigned int defval;
742} __attribute__ ((packed));
743
744struct snd_soc_rbtree_ctx {
745 struct rb_root root;
746};
747
748static struct snd_soc_rbtree_node *snd_soc_rbtree_lookup(
749 struct rb_root *root, unsigned int reg)
750{
751 struct rb_node *node;
752 struct snd_soc_rbtree_node *rbnode;
753
754 node = root->rb_node;
755 while (node) {
756 rbnode = container_of(node, struct snd_soc_rbtree_node, node);
757 if (rbnode->reg < reg)
758 node = node->rb_left;
759 else if (rbnode->reg > reg)
760 node = node->rb_right;
761 else
762 return rbnode;
763 }
764
765 return NULL;
766}
767
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +0000768static int snd_soc_rbtree_insert(struct rb_root *root,
769 struct snd_soc_rbtree_node *rbnode)
770{
771 struct rb_node **new, *parent;
772 struct snd_soc_rbtree_node *rbnode_tmp;
773
774 parent = NULL;
775 new = &root->rb_node;
776 while (*new) {
777 rbnode_tmp = container_of(*new, struct snd_soc_rbtree_node,
778 node);
779 parent = *new;
780 if (rbnode_tmp->reg < rbnode->reg)
781 new = &((*new)->rb_left);
782 else if (rbnode_tmp->reg > rbnode->reg)
783 new = &((*new)->rb_right);
784 else
785 return 0;
786 }
787
788 /* insert the node into the rbtree */
789 rb_link_node(&rbnode->node, parent, new);
790 rb_insert_color(&rbnode->node, root);
791
792 return 1;
793}
794
795static int snd_soc_rbtree_cache_sync(struct snd_soc_codec *codec)
796{
797 struct snd_soc_rbtree_ctx *rbtree_ctx;
798 struct rb_node *node;
799 struct snd_soc_rbtree_node *rbnode;
800 unsigned int val;
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +0000801 int ret;
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +0000802
803 rbtree_ctx = codec->reg_cache;
804 for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) {
805 rbnode = rb_entry(node, struct snd_soc_rbtree_node, node);
806 if (rbnode->value == rbnode->defval)
807 continue;
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +0000808 ret = snd_soc_cache_read(codec, rbnode->reg, &val);
809 if (ret)
810 return ret;
Dimitris Papastamos99780072011-01-19 14:53:37 +0000811 codec->cache_bypass = 1;
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +0000812 ret = snd_soc_write(codec, rbnode->reg, val);
Dimitris Papastamos99780072011-01-19 14:53:37 +0000813 codec->cache_bypass = 0;
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +0000814 if (ret)
815 return ret;
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +0000816 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
817 rbnode->reg, val);
818 }
819
820 return 0;
821}
822
823static int snd_soc_rbtree_cache_write(struct snd_soc_codec *codec,
824 unsigned int reg, unsigned int value)
825{
826 struct snd_soc_rbtree_ctx *rbtree_ctx;
827 struct snd_soc_rbtree_node *rbnode;
828
829 rbtree_ctx = codec->reg_cache;
830 rbnode = snd_soc_rbtree_lookup(&rbtree_ctx->root, reg);
831 if (rbnode) {
832 if (rbnode->value == value)
833 return 0;
834 rbnode->value = value;
835 } else {
836 /* bail out early, no need to create the rbnode yet */
837 if (!value)
838 return 0;
839 /*
840 * for uninitialized registers whose value is changed
841 * from the default zero, create an rbnode and insert
842 * it into the tree.
843 */
844 rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL);
845 if (!rbnode)
846 return -ENOMEM;
847 rbnode->reg = reg;
848 rbnode->value = value;
849 snd_soc_rbtree_insert(&rbtree_ctx->root, rbnode);
850 }
851
852 return 0;
853}
854
855static int snd_soc_rbtree_cache_read(struct snd_soc_codec *codec,
856 unsigned int reg, unsigned int *value)
857{
858 struct snd_soc_rbtree_ctx *rbtree_ctx;
859 struct snd_soc_rbtree_node *rbnode;
860
861 rbtree_ctx = codec->reg_cache;
862 rbnode = snd_soc_rbtree_lookup(&rbtree_ctx->root, reg);
863 if (rbnode) {
864 *value = rbnode->value;
865 } else {
866 /* uninitialized registers default to 0 */
867 *value = 0;
868 }
869
870 return 0;
871}
872
873static int snd_soc_rbtree_cache_exit(struct snd_soc_codec *codec)
874{
875 struct rb_node *next;
876 struct snd_soc_rbtree_ctx *rbtree_ctx;
877 struct snd_soc_rbtree_node *rbtree_node;
878
879 /* if we've already been called then just return */
880 rbtree_ctx = codec->reg_cache;
881 if (!rbtree_ctx)
882 return 0;
883
884 /* free up the rbtree */
885 next = rb_first(&rbtree_ctx->root);
886 while (next) {
887 rbtree_node = rb_entry(next, struct snd_soc_rbtree_node, node);
888 next = rb_next(&rbtree_node->node);
889 rb_erase(&rbtree_node->node, &rbtree_ctx->root);
890 kfree(rbtree_node);
891 }
892
893 /* release the resources */
894 kfree(codec->reg_cache);
895 codec->reg_cache = NULL;
896
897 return 0;
898}
899
900static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
901{
Dimitris Papastamos1321e882011-01-11 11:29:49 +0000902 struct snd_soc_rbtree_node *rbtree_node;
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +0000903 struct snd_soc_rbtree_ctx *rbtree_ctx;
Dimitris Papastamos1321e882011-01-11 11:29:49 +0000904 unsigned int val;
905 unsigned int word_size;
906 int i;
907 int ret;
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +0000908
909 codec->reg_cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL);
910 if (!codec->reg_cache)
911 return -ENOMEM;
912
913 rbtree_ctx = codec->reg_cache;
914 rbtree_ctx->root = RB_ROOT;
915
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +0000916 if (!codec->reg_def_copy)
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +0000917 return 0;
918
Dimitris Papastamos1321e882011-01-11 11:29:49 +0000919 /*
920 * populate the rbtree with the initialized registers. All other
921 * registers will be inserted when they are first modified.
922 */
923 word_size = codec->driver->reg_word_size;
924 for (i = 0; i < codec->driver->reg_cache_size; ++i) {
925 val = snd_soc_get_cache_val(codec->reg_def_copy, i, word_size);
926 if (!val)
927 continue;
928 rbtree_node = kzalloc(sizeof *rbtree_node, GFP_KERNEL);
929 if (!rbtree_node) {
930 ret = -ENOMEM;
931 snd_soc_cache_exit(codec);
932 break;
933 }
934 rbtree_node->reg = i;
935 rbtree_node->value = val;
936 rbtree_node->defval = val;
937 snd_soc_rbtree_insert(&rbtree_ctx->root, rbtree_node);
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +0000938 }
939
940 return 0;
941}
942
Mark Brown68d44ee2010-12-21 17:19:56 +0000943#ifdef CONFIG_SND_SOC_CACHE_LZO
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +0000944struct snd_soc_lzo_ctx {
945 void *wmem;
946 void *dst;
947 const void *src;
948 size_t src_len;
949 size_t dst_len;
950 size_t decompressed_size;
951 unsigned long *sync_bmp;
952 int sync_bmp_nbits;
953};
954
955#define LZO_BLOCK_NUM 8
956static int snd_soc_lzo_block_count(void)
957{
958 return LZO_BLOCK_NUM;
959}
960
961static int snd_soc_lzo_prepare(struct snd_soc_lzo_ctx *lzo_ctx)
962{
963 lzo_ctx->wmem = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
964 if (!lzo_ctx->wmem)
965 return -ENOMEM;
966 return 0;
967}
968
969static int snd_soc_lzo_compress(struct snd_soc_lzo_ctx *lzo_ctx)
970{
971 size_t compress_size;
972 int ret;
973
974 ret = lzo1x_1_compress(lzo_ctx->src, lzo_ctx->src_len,
975 lzo_ctx->dst, &compress_size, lzo_ctx->wmem);
976 if (ret != LZO_E_OK || compress_size > lzo_ctx->dst_len)
977 return -EINVAL;
978 lzo_ctx->dst_len = compress_size;
979 return 0;
980}
981
982static int snd_soc_lzo_decompress(struct snd_soc_lzo_ctx *lzo_ctx)
983{
984 size_t dst_len;
985 int ret;
986
987 dst_len = lzo_ctx->dst_len;
988 ret = lzo1x_decompress_safe(lzo_ctx->src, lzo_ctx->src_len,
989 lzo_ctx->dst, &dst_len);
990 if (ret != LZO_E_OK || dst_len != lzo_ctx->dst_len)
991 return -EINVAL;
992 return 0;
993}
994
995static int snd_soc_lzo_compress_cache_block(struct snd_soc_codec *codec,
996 struct snd_soc_lzo_ctx *lzo_ctx)
997{
998 int ret;
999
1000 lzo_ctx->dst_len = lzo1x_worst_compress(PAGE_SIZE);
1001 lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
1002 if (!lzo_ctx->dst) {
1003 lzo_ctx->dst_len = 0;
1004 return -ENOMEM;
1005 }
1006
1007 ret = snd_soc_lzo_compress(lzo_ctx);
1008 if (ret < 0)
1009 return ret;
1010 return 0;
1011}
1012
1013static int snd_soc_lzo_decompress_cache_block(struct snd_soc_codec *codec,
1014 struct snd_soc_lzo_ctx *lzo_ctx)
1015{
1016 int ret;
1017
1018 lzo_ctx->dst_len = lzo_ctx->decompressed_size;
1019 lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
1020 if (!lzo_ctx->dst) {
1021 lzo_ctx->dst_len = 0;
1022 return -ENOMEM;
1023 }
1024
1025 ret = snd_soc_lzo_decompress(lzo_ctx);
1026 if (ret < 0)
1027 return ret;
1028 return 0;
1029}
1030
1031static inline int snd_soc_lzo_get_blkindex(struct snd_soc_codec *codec,
1032 unsigned int reg)
1033{
Mark Brown001ae4c2010-12-02 16:21:08 +00001034 const struct snd_soc_codec_driver *codec_drv;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001035
1036 codec_drv = codec->driver;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001037 return (reg * codec_drv->reg_word_size) /
Dimitris Papastamosaea170a2011-01-12 10:38:58 +00001038 DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001039}
1040
1041static inline int snd_soc_lzo_get_blkpos(struct snd_soc_codec *codec,
1042 unsigned int reg)
1043{
Mark Brown001ae4c2010-12-02 16:21:08 +00001044 const struct snd_soc_codec_driver *codec_drv;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001045
1046 codec_drv = codec->driver;
Dimitris Papastamosaea170a2011-01-12 10:38:58 +00001047 return reg % (DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count()) /
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001048 codec_drv->reg_word_size);
1049}
1050
1051static inline int snd_soc_lzo_get_blksize(struct snd_soc_codec *codec)
1052{
Mark Brown001ae4c2010-12-02 16:21:08 +00001053 const struct snd_soc_codec_driver *codec_drv;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001054
1055 codec_drv = codec->driver;
Dimitris Papastamosaea170a2011-01-12 10:38:58 +00001056 return DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001057}
1058
1059static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec)
1060{
1061 struct snd_soc_lzo_ctx **lzo_blocks;
1062 unsigned int val;
1063 int i;
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +00001064 int ret;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001065
1066 lzo_blocks = codec->reg_cache;
1067 for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) {
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +00001068 ret = snd_soc_cache_read(codec, i, &val);
1069 if (ret)
1070 return ret;
Dimitris Papastamos99780072011-01-19 14:53:37 +00001071 codec->cache_bypass = 1;
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +00001072 ret = snd_soc_write(codec, i, val);
Dimitris Papastamos99780072011-01-19 14:53:37 +00001073 codec->cache_bypass = 0;
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +00001074 if (ret)
1075 return ret;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001076 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
1077 i, val);
1078 }
1079
1080 return 0;
1081}
1082
1083static int snd_soc_lzo_cache_write(struct snd_soc_codec *codec,
1084 unsigned int reg, unsigned int value)
1085{
1086 struct snd_soc_lzo_ctx *lzo_block, **lzo_blocks;
1087 int ret, blkindex, blkpos;
1088 size_t blksize, tmp_dst_len;
1089 void *tmp_dst;
1090
1091 /* index of the compressed lzo block */
1092 blkindex = snd_soc_lzo_get_blkindex(codec, reg);
1093 /* register index within the decompressed block */
1094 blkpos = snd_soc_lzo_get_blkpos(codec, reg);
1095 /* size of the compressed block */
1096 blksize = snd_soc_lzo_get_blksize(codec);
1097 lzo_blocks = codec->reg_cache;
1098 lzo_block = lzo_blocks[blkindex];
1099
1100 /* save the pointer and length of the compressed block */
1101 tmp_dst = lzo_block->dst;
1102 tmp_dst_len = lzo_block->dst_len;
1103
1104 /* prepare the source to be the compressed block */
1105 lzo_block->src = lzo_block->dst;
1106 lzo_block->src_len = lzo_block->dst_len;
1107
1108 /* decompress the block */
1109 ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
1110 if (ret < 0) {
1111 kfree(lzo_block->dst);
1112 goto out;
1113 }
1114
1115 /* write the new value to the cache */
Dimitris Papastamos1321e882011-01-11 11:29:49 +00001116 if (snd_soc_set_cache_val(lzo_block->dst, blkpos, value,
1117 codec->driver->reg_word_size)) {
1118 kfree(lzo_block->dst);
1119 goto out;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001120 }
1121
1122 /* prepare the source to be the decompressed block */
1123 lzo_block->src = lzo_block->dst;
1124 lzo_block->src_len = lzo_block->dst_len;
1125
1126 /* compress the block */
1127 ret = snd_soc_lzo_compress_cache_block(codec, lzo_block);
1128 if (ret < 0) {
1129 kfree(lzo_block->dst);
1130 kfree(lzo_block->src);
1131 goto out;
1132 }
1133
1134 /* set the bit so we know we have to sync this register */
1135 set_bit(reg, lzo_block->sync_bmp);
1136 kfree(tmp_dst);
1137 kfree(lzo_block->src);
1138 return 0;
1139out:
1140 lzo_block->dst = tmp_dst;
1141 lzo_block->dst_len = tmp_dst_len;
1142 return ret;
1143}
1144
1145static int snd_soc_lzo_cache_read(struct snd_soc_codec *codec,
1146 unsigned int reg, unsigned int *value)
1147{
1148 struct snd_soc_lzo_ctx *lzo_block, **lzo_blocks;
1149 int ret, blkindex, blkpos;
1150 size_t blksize, tmp_dst_len;
1151 void *tmp_dst;
1152
1153 *value = 0;
1154 /* index of the compressed lzo block */
1155 blkindex = snd_soc_lzo_get_blkindex(codec, reg);
1156 /* register index within the decompressed block */
1157 blkpos = snd_soc_lzo_get_blkpos(codec, reg);
1158 /* size of the compressed block */
1159 blksize = snd_soc_lzo_get_blksize(codec);
1160 lzo_blocks = codec->reg_cache;
1161 lzo_block = lzo_blocks[blkindex];
1162
1163 /* save the pointer and length of the compressed block */
1164 tmp_dst = lzo_block->dst;
1165 tmp_dst_len = lzo_block->dst_len;
1166
1167 /* prepare the source to be the compressed block */
1168 lzo_block->src = lzo_block->dst;
1169 lzo_block->src_len = lzo_block->dst_len;
1170
1171 /* decompress the block */
1172 ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
Dimitris Papastamos1321e882011-01-11 11:29:49 +00001173 if (ret >= 0)
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001174 /* fetch the value from the cache */
Dimitris Papastamos1321e882011-01-11 11:29:49 +00001175 *value = snd_soc_get_cache_val(lzo_block->dst, blkpos,
1176 codec->driver->reg_word_size);
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001177
1178 kfree(lzo_block->dst);
1179 /* restore the pointer and length of the compressed block */
1180 lzo_block->dst = tmp_dst;
1181 lzo_block->dst_len = tmp_dst_len;
1182 return 0;
1183}
1184
1185static int snd_soc_lzo_cache_exit(struct snd_soc_codec *codec)
1186{
1187 struct snd_soc_lzo_ctx **lzo_blocks;
1188 int i, blkcount;
1189
1190 lzo_blocks = codec->reg_cache;
1191 if (!lzo_blocks)
1192 return 0;
1193
1194 blkcount = snd_soc_lzo_block_count();
1195 /*
1196 * the pointer to the bitmap used for syncing the cache
1197 * is shared amongst all lzo_blocks. Ensure it is freed
1198 * only once.
1199 */
1200 if (lzo_blocks[0])
1201 kfree(lzo_blocks[0]->sync_bmp);
1202 for (i = 0; i < blkcount; ++i) {
1203 if (lzo_blocks[i]) {
1204 kfree(lzo_blocks[i]->wmem);
1205 kfree(lzo_blocks[i]->dst);
1206 }
1207 /* each lzo_block is a pointer returned by kmalloc or NULL */
1208 kfree(lzo_blocks[i]);
1209 }
1210 kfree(lzo_blocks);
1211 codec->reg_cache = NULL;
1212 return 0;
1213}
1214
1215static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
1216{
1217 struct snd_soc_lzo_ctx **lzo_blocks;
Dimitris Papastamosaea170a2011-01-12 10:38:58 +00001218 size_t bmp_size;
Mark Brown001ae4c2010-12-02 16:21:08 +00001219 const struct snd_soc_codec_driver *codec_drv;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001220 int ret, tofree, i, blksize, blkcount;
1221 const char *p, *end;
1222 unsigned long *sync_bmp;
1223
1224 ret = 0;
1225 codec_drv = codec->driver;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001226
1227 /*
1228 * If we have not been given a default register cache
1229 * then allocate a dummy zero-ed out region, compress it
1230 * and remember to free it afterwards.
1231 */
1232 tofree = 0;
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +00001233 if (!codec->reg_def_copy)
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001234 tofree = 1;
1235
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +00001236 if (!codec->reg_def_copy) {
Dimitris Papastamosaea170a2011-01-12 10:38:58 +00001237 codec->reg_def_copy = kzalloc(codec->reg_size, GFP_KERNEL);
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +00001238 if (!codec->reg_def_copy)
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001239 return -ENOMEM;
1240 }
1241
1242 blkcount = snd_soc_lzo_block_count();
1243 codec->reg_cache = kzalloc(blkcount * sizeof *lzo_blocks,
1244 GFP_KERNEL);
1245 if (!codec->reg_cache) {
1246 ret = -ENOMEM;
1247 goto err_tofree;
1248 }
1249 lzo_blocks = codec->reg_cache;
1250
1251 /*
1252 * allocate a bitmap to be used when syncing the cache with
1253 * the hardware. Each time a register is modified, the corresponding
1254 * bit is set in the bitmap, so we know that we have to sync
1255 * that register.
1256 */
1257 bmp_size = codec_drv->reg_cache_size;
Dimitris Papastamos465d7fc2010-12-14 15:15:36 +00001258 sync_bmp = kmalloc(BITS_TO_LONGS(bmp_size) * sizeof(long),
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001259 GFP_KERNEL);
1260 if (!sync_bmp) {
1261 ret = -ENOMEM;
1262 goto err;
1263 }
Dimitris Papastamos09c74a92010-11-29 11:43:33 +00001264 bitmap_zero(sync_bmp, bmp_size);
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001265
1266 /* allocate the lzo blocks and initialize them */
1267 for (i = 0; i < blkcount; ++i) {
1268 lzo_blocks[i] = kzalloc(sizeof **lzo_blocks,
1269 GFP_KERNEL);
1270 if (!lzo_blocks[i]) {
1271 kfree(sync_bmp);
1272 ret = -ENOMEM;
1273 goto err;
1274 }
1275 lzo_blocks[i]->sync_bmp = sync_bmp;
Dimitris Papastamos04f8fd12011-01-11 11:24:02 +00001276 lzo_blocks[i]->sync_bmp_nbits = bmp_size;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001277 /* alloc the working space for the compressed block */
1278 ret = snd_soc_lzo_prepare(lzo_blocks[i]);
1279 if (ret < 0)
1280 goto err;
1281 }
1282
1283 blksize = snd_soc_lzo_get_blksize(codec);
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +00001284 p = codec->reg_def_copy;
Dimitris Papastamosaea170a2011-01-12 10:38:58 +00001285 end = codec->reg_def_copy + codec->reg_size;
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001286 /* compress the register map and fill the lzo blocks */
1287 for (i = 0; i < blkcount; ++i, p += blksize) {
1288 lzo_blocks[i]->src = p;
1289 if (p + blksize > end)
1290 lzo_blocks[i]->src_len = end - p;
1291 else
1292 lzo_blocks[i]->src_len = blksize;
1293 ret = snd_soc_lzo_compress_cache_block(codec,
1294 lzo_blocks[i]);
1295 if (ret < 0)
1296 goto err;
1297 lzo_blocks[i]->decompressed_size =
1298 lzo_blocks[i]->src_len;
1299 }
1300
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +00001301 if (tofree) {
1302 kfree(codec->reg_def_copy);
1303 codec->reg_def_copy = NULL;
1304 }
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001305 return 0;
1306err:
1307 snd_soc_cache_exit(codec);
1308err_tofree:
Dimitris Papastamos3335ddc2010-12-02 16:11:05 +00001309 if (tofree) {
1310 kfree(codec->reg_def_copy);
1311 codec->reg_def_copy = NULL;
1312 }
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001313 return ret;
1314}
Mark Brown68d44ee2010-12-21 17:19:56 +00001315#endif
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001316
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001317static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
1318{
1319 int i;
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +00001320 int ret;
Mark Brown001ae4c2010-12-02 16:21:08 +00001321 const struct snd_soc_codec_driver *codec_drv;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001322 unsigned int val;
1323
1324 codec_drv = codec->driver;
1325 for (i = 0; i < codec_drv->reg_cache_size; ++i) {
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +00001326 ret = snd_soc_cache_read(codec, i, &val);
1327 if (ret)
1328 return ret;
Dimitris Papastamosd779fce2011-01-12 10:22:28 +00001329 if (codec->reg_def_copy)
1330 if (snd_soc_get_cache_val(codec->reg_def_copy,
Dimitris Papastamos1321e882011-01-11 11:29:49 +00001331 i, codec_drv->reg_word_size) == val)
1332 continue;
Dimitris Papastamos7a33d4c2010-11-29 10:24:54 +00001333 ret = snd_soc_write(codec, i, val);
1334 if (ret)
1335 return ret;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001336 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
1337 i, val);
1338 }
1339 return 0;
1340}
1341
1342static int snd_soc_flat_cache_write(struct snd_soc_codec *codec,
1343 unsigned int reg, unsigned int value)
1344{
Dimitris Papastamos1321e882011-01-11 11:29:49 +00001345 snd_soc_set_cache_val(codec->reg_cache, reg, value,
1346 codec->driver->reg_word_size);
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001347 return 0;
1348}
1349
1350static int snd_soc_flat_cache_read(struct snd_soc_codec *codec,
1351 unsigned int reg, unsigned int *value)
1352{
Dimitris Papastamos1321e882011-01-11 11:29:49 +00001353 *value = snd_soc_get_cache_val(codec->reg_cache, reg,
1354 codec->driver->reg_word_size);
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001355 return 0;
1356}
1357
1358static int snd_soc_flat_cache_exit(struct snd_soc_codec *codec)
1359{
1360 if (!codec->reg_cache)
1361 return 0;
1362 kfree(codec->reg_cache);
1363 codec->reg_cache = NULL;
1364 return 0;
1365}
1366
1367static int snd_soc_flat_cache_init(struct snd_soc_codec *codec)
1368{
Mark Brown001ae4c2010-12-02 16:21:08 +00001369 const struct snd_soc_codec_driver *codec_drv;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001370
1371 codec_drv = codec->driver;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001372
Dimitris Papastamosd779fce2011-01-12 10:22:28 +00001373 if (codec->reg_def_copy)
1374 codec->reg_cache = kmemdup(codec->reg_def_copy,
Dimitris Papastamosaea170a2011-01-12 10:38:58 +00001375 codec->reg_size, GFP_KERNEL);
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001376 else
Dimitris Papastamosaea170a2011-01-12 10:38:58 +00001377 codec->reg_cache = kzalloc(codec->reg_size, GFP_KERNEL);
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001378 if (!codec->reg_cache)
1379 return -ENOMEM;
1380
1381 return 0;
1382}
1383
1384/* an array of all supported compression types */
1385static const struct snd_soc_cache_ops cache_types[] = {
Mark Brownbe4fcdd2010-12-21 17:09:48 +00001386 /* Flat *must* be the first entry for fallback */
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001387 {
Dimitris Papastamosdf0701b2010-11-29 10:54:28 +00001388 .id = SND_SOC_FLAT_COMPRESSION,
Dimitris Papastamos0d735ea2010-12-06 09:51:57 +00001389 .name = "flat",
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001390 .init = snd_soc_flat_cache_init,
1391 .exit = snd_soc_flat_cache_exit,
1392 .read = snd_soc_flat_cache_read,
1393 .write = snd_soc_flat_cache_write,
1394 .sync = snd_soc_flat_cache_sync
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001395 },
Mark Brown68d44ee2010-12-21 17:19:56 +00001396#ifdef CONFIG_SND_SOC_CACHE_LZO
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001397 {
1398 .id = SND_SOC_LZO_COMPRESSION,
Dimitris Papastamos0d735ea2010-12-06 09:51:57 +00001399 .name = "LZO",
Dimitris Papastamoscc28fb82010-11-11 10:04:58 +00001400 .init = snd_soc_lzo_cache_init,
1401 .exit = snd_soc_lzo_cache_exit,
1402 .read = snd_soc_lzo_cache_read,
1403 .write = snd_soc_lzo_cache_write,
1404 .sync = snd_soc_lzo_cache_sync
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +00001405 },
Mark Brown68d44ee2010-12-21 17:19:56 +00001406#endif
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +00001407 {
1408 .id = SND_SOC_RBTREE_COMPRESSION,
Dimitris Papastamos0d735ea2010-12-06 09:51:57 +00001409 .name = "rbtree",
Dimitris Papastamosa7f387d2010-11-11 10:04:59 +00001410 .init = snd_soc_rbtree_cache_init,
1411 .exit = snd_soc_rbtree_cache_exit,
1412 .read = snd_soc_rbtree_cache_read,
1413 .write = snd_soc_rbtree_cache_write,
1414 .sync = snd_soc_rbtree_cache_sync
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001415 }
1416};
1417
1418int snd_soc_cache_init(struct snd_soc_codec *codec)
1419{
1420 int i;
1421
1422 for (i = 0; i < ARRAY_SIZE(cache_types); ++i)
Dimitris Papastamos23bbce32010-12-02 14:53:01 +00001423 if (cache_types[i].id == codec->compress_type)
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001424 break;
Mark Brownbe4fcdd2010-12-21 17:09:48 +00001425
1426 /* Fall back to flat compression */
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001427 if (i == ARRAY_SIZE(cache_types)) {
Mark Brownbe4fcdd2010-12-21 17:09:48 +00001428 dev_warn(codec->dev, "Could not match compress type: %d\n",
1429 codec->compress_type);
1430 i = 0;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001431 }
1432
1433 mutex_init(&codec->cache_rw_mutex);
1434 codec->cache_ops = &cache_types[i];
1435
Dimitris Papastamos0d735ea2010-12-06 09:51:57 +00001436 if (codec->cache_ops->init) {
1437 if (codec->cache_ops->name)
1438 dev_dbg(codec->dev, "Initializing %s cache for %s codec\n",
1439 codec->cache_ops->name, codec->name);
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001440 return codec->cache_ops->init(codec);
Dimitris Papastamos0d735ea2010-12-06 09:51:57 +00001441 }
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001442 return -EINVAL;
1443}
1444
1445/*
1446 * NOTE: keep in mind that this function might be called
1447 * multiple times.
1448 */
1449int snd_soc_cache_exit(struct snd_soc_codec *codec)
1450{
Dimitris Papastamos0d735ea2010-12-06 09:51:57 +00001451 if (codec->cache_ops && codec->cache_ops->exit) {
1452 if (codec->cache_ops->name)
1453 dev_dbg(codec->dev, "Destroying %s cache for %s codec\n",
1454 codec->cache_ops->name, codec->name);
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001455 return codec->cache_ops->exit(codec);
Dimitris Papastamos0d735ea2010-12-06 09:51:57 +00001456 }
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001457 return -EINVAL;
1458}
1459
1460/**
1461 * snd_soc_cache_read: Fetch the value of a given register from the cache.
1462 *
1463 * @codec: CODEC to configure.
1464 * @reg: The register index.
1465 * @value: The value to be returned.
1466 */
1467int snd_soc_cache_read(struct snd_soc_codec *codec,
1468 unsigned int reg, unsigned int *value)
1469{
1470 int ret;
1471
1472 mutex_lock(&codec->cache_rw_mutex);
1473
1474 if (value && codec->cache_ops && codec->cache_ops->read) {
1475 ret = codec->cache_ops->read(codec, reg, value);
1476 mutex_unlock(&codec->cache_rw_mutex);
1477 return ret;
1478 }
1479
1480 mutex_unlock(&codec->cache_rw_mutex);
1481 return -EINVAL;
1482}
1483EXPORT_SYMBOL_GPL(snd_soc_cache_read);
1484
1485/**
1486 * snd_soc_cache_write: Set the value of a given register in the cache.
1487 *
1488 * @codec: CODEC to configure.
1489 * @reg: The register index.
1490 * @value: The new register value.
1491 */
1492int snd_soc_cache_write(struct snd_soc_codec *codec,
1493 unsigned int reg, unsigned int value)
1494{
1495 int ret;
1496
1497 mutex_lock(&codec->cache_rw_mutex);
1498
1499 if (codec->cache_ops && codec->cache_ops->write) {
1500 ret = codec->cache_ops->write(codec, reg, value);
1501 mutex_unlock(&codec->cache_rw_mutex);
1502 return ret;
1503 }
1504
1505 mutex_unlock(&codec->cache_rw_mutex);
1506 return -EINVAL;
1507}
1508EXPORT_SYMBOL_GPL(snd_soc_cache_write);
1509
1510/**
1511 * snd_soc_cache_sync: Sync the register cache with the hardware.
1512 *
1513 * @codec: CODEC to configure.
1514 *
1515 * Any registers that should not be synced should be marked as
1516 * volatile. In general drivers can choose not to use the provided
1517 * syncing functionality if they so require.
1518 */
1519int snd_soc_cache_sync(struct snd_soc_codec *codec)
1520{
1521 int ret;
Dimitris Papastamosc358e642011-01-21 15:29:02 +00001522 const char *name;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001523
1524 if (!codec->cache_sync) {
1525 return 0;
1526 }
1527
Dan Carpenter46fdaa32011-02-07 22:01:41 +03001528 if (!codec->cache_ops || !codec->cache_ops->sync)
1529 return -EINVAL;
1530
Dimitris Papastamosc358e642011-01-21 15:29:02 +00001531 if (codec->cache_ops->name)
1532 name = codec->cache_ops->name;
1533 else
1534 name = "unknown";
1535
Dan Carpenter46fdaa32011-02-07 22:01:41 +03001536 if (codec->cache_ops->name)
1537 dev_dbg(codec->dev, "Syncing %s cache for %s codec\n",
1538 codec->cache_ops->name, codec->name);
1539 trace_snd_soc_cache_sync(codec, name, "start");
1540 ret = codec->cache_ops->sync(codec);
1541 if (!ret)
1542 codec->cache_sync = 0;
1543 trace_snd_soc_cache_sync(codec, name, "end");
1544 return ret;
Dimitris Papastamos7a30a3d2010-11-11 10:04:57 +00001545}
1546EXPORT_SYMBOL_GPL(snd_soc_cache_sync);
Dimitris Papastamos066d16c2011-01-13 12:20:36 +00001547
1548static int snd_soc_get_reg_access_index(struct snd_soc_codec *codec,
1549 unsigned int reg)
1550{
1551 const struct snd_soc_codec_driver *codec_drv;
1552 unsigned int min, max, index;
1553
1554 codec_drv = codec->driver;
1555 min = 0;
1556 max = codec_drv->reg_access_size - 1;
1557 do {
1558 index = (min + max) / 2;
1559 if (codec_drv->reg_access_default[index].reg == reg)
1560 return index;
1561 if (codec_drv->reg_access_default[index].reg < reg)
1562 min = index + 1;
1563 else
1564 max = index;
1565 } while (min <= max);
1566 return -1;
1567}
1568
1569int snd_soc_default_volatile_register(struct snd_soc_codec *codec,
1570 unsigned int reg)
1571{
1572 int index;
1573
1574 if (reg >= codec->driver->reg_cache_size)
1575 return 1;
1576 index = snd_soc_get_reg_access_index(codec, reg);
1577 if (index < 0)
1578 return 0;
1579 return codec->driver->reg_access_default[index].vol;
1580}
1581EXPORT_SYMBOL_GPL(snd_soc_default_volatile_register);
1582
1583int snd_soc_default_readable_register(struct snd_soc_codec *codec,
1584 unsigned int reg)
1585{
1586 int index;
1587
1588 if (reg >= codec->driver->reg_cache_size)
1589 return 1;
1590 index = snd_soc_get_reg_access_index(codec, reg);
1591 if (index < 0)
1592 return 0;
1593 return codec->driver->reg_access_default[index].read;
1594}
1595EXPORT_SYMBOL_GPL(snd_soc_default_readable_register);