aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-cache.c')
-rw-r--r--sound/soc/soc-cache.c213
1 files changed, 210 insertions, 3 deletions
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index d2505e8b06c9..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
18static 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
27static 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)
57static 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
18static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, 86static 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;
@@ -91,6 +165,11 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
91 if (reg < codec->reg_cache_size) 165 if (reg < codec->reg_cache_size)
92 cache[reg] = value; 166 cache[reg] = value;
93 167
168 if (codec->cache_only) {
169 codec->cache_sync = 1;
170 return 0;
171 }
172
94 if (codec->hw_write(codec->control_data, data, 2) == 2) 173 if (codec->hw_write(codec->control_data, data, 2) == 2)
95 return 0; 174 return 0;
96 else 175 else
@@ -119,6 +198,11 @@ static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
119 if (!snd_soc_codec_volatile_register(codec, reg)) 198 if (!snd_soc_codec_volatile_register(codec, reg))
120 reg_cache[reg] = value; 199 reg_cache[reg] = value;
121 200
201 if (codec->cache_only) {
202 codec->cache_sync = 1;
203 return 0;
204 }
205
122 if (codec->hw_write(codec->control_data, data, 3) == 3) 206 if (codec->hw_write(codec->control_data, data, 3) == 3)
123 return 0; 207 return 0;
124 else 208 else
@@ -131,10 +215,14 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
131 u16 *cache = codec->reg_cache; 215 u16 *cache = codec->reg_cache;
132 216
133 if (reg >= codec->reg_cache_size || 217 if (reg >= codec->reg_cache_size ||
134 snd_soc_codec_volatile_register(codec, reg)) 218 snd_soc_codec_volatile_register(codec, reg)) {
219 if (codec->cache_only)
220 return -EINVAL;
221
135 return codec->hw_read(codec, reg); 222 return codec->hw_read(codec, reg);
136 else 223 } else {
137 return cache[reg]; 224 return cache[reg];
225 }
138} 226}
139 227
140#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) 228#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
@@ -171,6 +259,114 @@ static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec,
171#define snd_soc_8_16_read_i2c NULL 259#define snd_soc_8_16_read_i2c NULL
172#endif 260#endif
173 261
262#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
263static 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 *)&reg;
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
296static 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
307static 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)
339static 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
174static struct { 370static struct {
175 int addr_bits; 371 int addr_bits;
176 int data_bits; 372 int data_bits;
@@ -180,9 +376,14 @@ static struct {
180 unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); 376 unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
181} io_types[] = { 377} io_types[] = {
182 { 378 {
379 .addr_bits = 4, .data_bits = 12,
380 .write = snd_soc_4_12_write, .read = snd_soc_4_12_read,
381 .spi_write = snd_soc_4_12_spi_write,
382 },
383 {
183 .addr_bits = 7, .data_bits = 9, 384 .addr_bits = 7, .data_bits = 9,
184 .write = snd_soc_7_9_write, .read = snd_soc_7_9_read, 385 .write = snd_soc_7_9_write, .read = snd_soc_7_9_read,
185 .spi_write = snd_soc_7_9_spi_write 386 .spi_write = snd_soc_7_9_spi_write,
186 }, 387 },
187 { 388 {
188 .addr_bits = 8, .data_bits = 8, 389 .addr_bits = 8, .data_bits = 8,
@@ -193,6 +394,12 @@ static struct {
193 .write = snd_soc_8_16_write, .read = snd_soc_8_16_read, 394 .write = snd_soc_8_16_write, .read = snd_soc_8_16_read,
194 .i2c_read = snd_soc_8_16_read_i2c, 395 .i2c_read = snd_soc_8_16_read_i2c,
195 }, 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 },
196}; 403};
197 404
198/** 405/**