]> bbs.cooldavid.org Git - net-next-2.6.git/blame - sound/soc/soc-cache.c
scm: lower SCM_MAX_FD
[net-next-2.6.git] / sound / soc / soc-cache.c
CommitLineData
17a52fd6
MB
1/*
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
7084a42b 14#include <linux/i2c.h>
27ded041 15#include <linux/spi/spi.h>
17a52fd6
MB
16#include <sound/soc.h>
17
63b62ab0
BS
18static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,
19 unsigned int reg)
20{
21 u16 *cache = codec->reg_cache;
db49c146
DP
22
23 if (reg >= codec->driver->reg_cache_size ||
24 snd_soc_codec_volatile_register(codec, reg)) {
25 if (codec->cache_only)
26 return -1;
27
28 return codec->hw_read(codec, reg);
29 }
30
63b62ab0
BS
31 return cache[reg];
32}
33
34static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
35 unsigned int value)
36{
37 u16 *cache = codec->reg_cache;
38 u8 data[2];
39 int ret;
40
63b62ab0
BS
41 data[0] = (reg << 4) | ((value >> 8) & 0x000f);
42 data[1] = value & 0x00ff;
43
db49c146
DP
44 if (!snd_soc_codec_volatile_register(codec, reg) &&
45 reg < codec->driver->reg_cache_size)
46 cache[reg] = value;
8c961bcc 47
a3032b47
MB
48 if (codec->cache_only) {
49 codec->cache_sync = 1;
8c961bcc 50 return 0;
a3032b47 51 }
8c961bcc 52
985d8c4c
MB
53 dev_dbg(codec->dev, "0x%x = 0x%x\n", reg, value);
54
63b62ab0
BS
55 ret = codec->hw_write(codec->control_data, data, 2);
56 if (ret == 2)
57 return 0;
58 if (ret < 0)
59 return ret;
60 else
61 return -EIO;
62}
63
64#if defined(CONFIG_SPI_MASTER)
65static int snd_soc_4_12_spi_write(void *control_data, const char *data,
66 int len)
67{
68 struct spi_device *spi = control_data;
69 struct spi_transfer t;
70 struct spi_message m;
71 u8 msg[2];
72
73 if (len <= 0)
74 return 0;
75
76 msg[0] = data[1];
77 msg[1] = data[0];
78
79 spi_message_init(&m);
80 memset(&t, 0, (sizeof t));
81
82 t.tx_buf = &msg[0];
83 t.len = len;
84
85 spi_message_add_tail(&t, &m);
86 spi_sync(spi, &m);
87
88 return len;
89}
90#else
91#define snd_soc_4_12_spi_write NULL
92#endif
93
17a52fd6
MB
94static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,
95 unsigned int reg)
96{
97 u16 *cache = codec->reg_cache;
db49c146
DP
98
99 if (reg >= codec->driver->reg_cache_size ||
100 snd_soc_codec_volatile_register(codec, reg)) {
101 if (codec->cache_only)
102 return -1;
103
104 return codec->hw_read(codec, reg);
105 }
106
17a52fd6
MB
107 return cache[reg];
108}
109
110static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
111 unsigned int value)
112{
113 u16 *cache = codec->reg_cache;
114 u8 data[2];
115 int ret;
116
17a52fd6
MB
117 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
118 data[1] = value & 0x00ff;
119
db49c146
DP
120 if (!snd_soc_codec_volatile_register(codec, reg) &&
121 reg < codec->driver->reg_cache_size)
122 cache[reg] = value;
8c961bcc 123
a3032b47
MB
124 if (codec->cache_only) {
125 codec->cache_sync = 1;
8c961bcc 126 return 0;
a3032b47 127 }
8c961bcc 128
985d8c4c
MB
129 dev_dbg(codec->dev, "0x%x = 0x%x\n", reg, value);
130
17a52fd6
MB
131 ret = codec->hw_write(codec->control_data, data, 2);
132 if (ret == 2)
133 return 0;
134 if (ret < 0)
135 return ret;
136 else
137 return -EIO;
138}
139
27ded041
MB
140#if defined(CONFIG_SPI_MASTER)
141static int snd_soc_7_9_spi_write(void *control_data, const char *data,
142 int len)
143{
144 struct spi_device *spi = control_data;
145 struct spi_transfer t;
146 struct spi_message m;
147 u8 msg[2];
148
149 if (len <= 0)
150 return 0;
151
152 msg[0] = data[0];
153 msg[1] = data[1];
154
155 spi_message_init(&m);
156 memset(&t, 0, (sizeof t));
157
158 t.tx_buf = &msg[0];
159 t.len = len;
160
161 spi_message_add_tail(&t, &m);
162 spi_sync(spi, &m);
163
164 return len;
165}
166#else
167#define snd_soc_7_9_spi_write NULL
168#endif
169
341c9b84
JS
170static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
171 unsigned int value)
172{
173 u8 *cache = codec->reg_cache;
174 u8 data[2];
175
f4bee1bb
BS
176 reg &= 0xff;
177 data[0] = reg;
341c9b84
JS
178 data[1] = value & 0xff;
179
005d65fb 180 if (!snd_soc_codec_volatile_register(codec, reg) &&
db49c146
DP
181 reg < codec->driver->reg_cache_size)
182 cache[reg] = value;
341c9b84 183
a3032b47
MB
184 if (codec->cache_only) {
185 codec->cache_sync = 1;
8c961bcc 186 return 0;
a3032b47 187 }
8c961bcc 188
985d8c4c
MB
189 dev_dbg(codec->dev, "0x%x = 0x%x\n", reg, value);
190
341c9b84
JS
191 if (codec->hw_write(codec->control_data, data, 2) == 2)
192 return 0;
193 else
194 return -EIO;
195}
196
197static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
198 unsigned int reg)
199{
200 u8 *cache = codec->reg_cache;
db49c146 201
f4bee1bb 202 reg &= 0xff;
db49c146
DP
203 if (reg >= codec->driver->reg_cache_size ||
204 snd_soc_codec_volatile_register(codec, reg)) {
205 if (codec->cache_only)
206 return -1;
207
208 return codec->hw_read(codec, reg);
209 }
210
341c9b84
JS
211 return cache[reg];
212}
213
f479fd93
DP
214#if defined(CONFIG_SPI_MASTER)
215static int snd_soc_8_8_spi_write(void *control_data, const char *data,
216 int len)
217{
218 struct spi_device *spi = control_data;
219 struct spi_transfer t;
220 struct spi_message m;
221 u8 msg[2];
222
223 if (len <= 0)
224 return 0;
225
226 msg[0] = data[0];
227 msg[1] = data[1];
228
229 spi_message_init(&m);
230 memset(&t, 0, (sizeof t));
231
232 t.tx_buf = &msg[0];
233 t.len = len;
234
235 spi_message_add_tail(&t, &m);
236 spi_sync(spi, &m);
237
238 return len;
239}
240#else
241#define snd_soc_8_8_spi_write NULL
242#endif
243
afa2f106
MB
244static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
245 unsigned int value)
246{
247 u16 *reg_cache = codec->reg_cache;
248 u8 data[3];
249
250 data[0] = reg;
251 data[1] = (value >> 8) & 0xff;
252 data[2] = value & 0xff;
253
3e13f65e
TI
254 if (!snd_soc_codec_volatile_register(codec, reg) &&
255 reg < codec->driver->reg_cache_size)
256 reg_cache[reg] = value;
afa2f106 257
a3032b47
MB
258 if (codec->cache_only) {
259 codec->cache_sync = 1;
8c961bcc 260 return 0;
a3032b47 261 }
8c961bcc 262
985d8c4c
MB
263 dev_dbg(codec->dev, "0x%x = 0x%x\n", reg, value);
264
afa2f106
MB
265 if (codec->hw_write(codec->control_data, data, 3) == 3)
266 return 0;
267 else
268 return -EIO;
269}
270
271static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
272 unsigned int reg)
273{
274 u16 *cache = codec->reg_cache;
275
f0fba2ad 276 if (reg >= codec->driver->reg_cache_size ||
8c961bcc
MB
277 snd_soc_codec_volatile_register(codec, reg)) {
278 if (codec->cache_only)
391d8a04 279 return -1;
8c961bcc 280
afa2f106 281 return codec->hw_read(codec, reg);
8c961bcc 282 } else {
afa2f106 283 return cache[reg];
8c961bcc 284 }
afa2f106
MB
285}
286
f479fd93
DP
287#if defined(CONFIG_SPI_MASTER)
288static int snd_soc_8_16_spi_write(void *control_data, const char *data,
289 int len)
290{
291 struct spi_device *spi = control_data;
292 struct spi_transfer t;
293 struct spi_message m;
294 u8 msg[3];
295
296 if (len <= 0)
297 return 0;
298
299 msg[0] = data[0];
300 msg[1] = data[1];
301 msg[2] = data[2];
302
303 spi_message_init(&m);
304 memset(&t, 0, (sizeof t));
305
306 t.tx_buf = &msg[0];
307 t.len = len;
308
309 spi_message_add_tail(&t, &m);
310 spi_sync(spi, &m);
311
312 return len;
313}
314#else
315#define snd_soc_8_16_spi_write NULL
316#endif
317
85dfcdff
CC
318#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
319static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec,
320 unsigned int r)
321{
322 struct i2c_msg xfer[2];
323 u8 reg = r;
324 u8 data;
325 int ret;
326 struct i2c_client *client = codec->control_data;
327
328 /* Write register */
329 xfer[0].addr = client->addr;
330 xfer[0].flags = 0;
331 xfer[0].len = 1;
332 xfer[0].buf = &reg;
333
334 /* Read data */
335 xfer[1].addr = client->addr;
336 xfer[1].flags = I2C_M_RD;
337 xfer[1].len = 1;
338 xfer[1].buf = &data;
339
340 ret = i2c_transfer(client->adapter, xfer, 2);
341 if (ret != 2) {
342 dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
343 return 0;
344 }
345
346 return data;
347}
348#else
349#define snd_soc_8_8_read_i2c NULL
350#endif
351
17244c24 352#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
afa2f106
MB
353static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec,
354 unsigned int r)
355{
356 struct i2c_msg xfer[2];
357 u8 reg = r;
358 u16 data;
359 int ret;
360 struct i2c_client *client = codec->control_data;
361
362 /* Write register */
363 xfer[0].addr = client->addr;
364 xfer[0].flags = 0;
365 xfer[0].len = 1;
366 xfer[0].buf = &reg;
367
368 /* Read data */
369 xfer[1].addr = client->addr;
370 xfer[1].flags = I2C_M_RD;
371 xfer[1].len = 2;
372 xfer[1].buf = (u8 *)&data;
373
374 ret = i2c_transfer(client->adapter, xfer, 2);
375 if (ret != 2) {
376 dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
377 return 0;
378 }
379
380 return (data >> 8) | ((data & 0xff) << 8);
381}
382#else
383#define snd_soc_8_16_read_i2c NULL
384#endif
17a52fd6 385
994dc424
BS
386#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
387static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec,
388 unsigned int r)
389{
390 struct i2c_msg xfer[2];
391 u16 reg = r;
392 u8 data;
393 int ret;
394 struct i2c_client *client = codec->control_data;
395
396 /* Write register */
397 xfer[0].addr = client->addr;
398 xfer[0].flags = 0;
399 xfer[0].len = 2;
400 xfer[0].buf = (u8 *)&reg;
401
402 /* Read data */
403 xfer[1].addr = client->addr;
404 xfer[1].flags = I2C_M_RD;
405 xfer[1].len = 1;
406 xfer[1].buf = &data;
407
408 ret = i2c_transfer(client->adapter, xfer, 2);
409 if (ret != 2) {
410 dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
411 return 0;
412 }
413
414 return data;
415}
416#else
417#define snd_soc_16_8_read_i2c NULL
418#endif
419
420static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec,
421 unsigned int reg)
422{
ac770267 423 u8 *cache = codec->reg_cache;
994dc424
BS
424
425 reg &= 0xff;
db49c146
DP
426 if (reg >= codec->driver->reg_cache_size ||
427 snd_soc_codec_volatile_register(codec, reg)) {
428 if (codec->cache_only)
429 return -1;
430
431 return codec->hw_read(codec, reg);
432 }
433
994dc424
BS
434 return cache[reg];
435}
436
437static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
438 unsigned int value)
439{
ac770267 440 u8 *cache = codec->reg_cache;
994dc424
BS
441 u8 data[3];
442 int ret;
443
994dc424
BS
444 data[0] = (reg >> 8) & 0xff;
445 data[1] = reg & 0xff;
446 data[2] = value;
447
448 reg &= 0xff;
db49c146
DP
449 if (!snd_soc_codec_volatile_register(codec, reg) &&
450 reg < codec->driver->reg_cache_size)
451 cache[reg] = value;
8c961bcc 452
a3032b47
MB
453 if (codec->cache_only) {
454 codec->cache_sync = 1;
8c961bcc 455 return 0;
a3032b47 456 }
8c961bcc 457
985d8c4c
MB
458 dev_dbg(codec->dev, "0x%x = 0x%x\n", reg, value);
459
994dc424
BS
460 ret = codec->hw_write(codec->control_data, data, 3);
461 if (ret == 3)
462 return 0;
463 if (ret < 0)
464 return ret;
465 else
466 return -EIO;
467}
468
469#if defined(CONFIG_SPI_MASTER)
470static int snd_soc_16_8_spi_write(void *control_data, const char *data,
471 int len)
472{
473 struct spi_device *spi = control_data;
474 struct spi_transfer t;
475 struct spi_message m;
476 u8 msg[3];
477
478 if (len <= 0)
479 return 0;
480
481 msg[0] = data[0];
482 msg[1] = data[1];
483 msg[2] = data[2];
484
485 spi_message_init(&m);
486 memset(&t, 0, (sizeof t));
487
488 t.tx_buf = &msg[0];
489 t.len = len;
490
491 spi_message_add_tail(&t, &m);
492 spi_sync(spi, &m);
493
494 return len;
495}
496#else
497#define snd_soc_16_8_spi_write NULL
498#endif
499
bc6552f4
MB
500#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
501static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec,
502 unsigned int r)
503{
504 struct i2c_msg xfer[2];
505 u16 reg = cpu_to_be16(r);
506 u16 data;
507 int ret;
508 struct i2c_client *client = codec->control_data;
509
510 /* Write register */
511 xfer[0].addr = client->addr;
512 xfer[0].flags = 0;
513 xfer[0].len = 2;
514 xfer[0].buf = (u8 *)&reg;
515
516 /* Read data */
517 xfer[1].addr = client->addr;
518 xfer[1].flags = I2C_M_RD;
519 xfer[1].len = 2;
520 xfer[1].buf = (u8 *)&data;
521
522 ret = i2c_transfer(client->adapter, xfer, 2);
523 if (ret != 2) {
524 dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
525 return 0;
526 }
527
528 return be16_to_cpu(data);
529}
530#else
531#define snd_soc_16_16_read_i2c NULL
532#endif
533
534static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec,
535 unsigned int reg)
536{
537 u16 *cache = codec->reg_cache;
538
f0fba2ad 539 if (reg >= codec->driver->reg_cache_size ||
bc6552f4
MB
540 snd_soc_codec_volatile_register(codec, reg)) {
541 if (codec->cache_only)
391d8a04 542 return -1;
bc6552f4
MB
543
544 return codec->hw_read(codec, reg);
545 }
546
547 return cache[reg];
548}
549
550static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
551 unsigned int value)
552{
553 u16 *cache = codec->reg_cache;
554 u8 data[4];
555 int ret;
556
557 data[0] = (reg >> 8) & 0xff;
558 data[1] = reg & 0xff;
559 data[2] = (value >> 8) & 0xff;
560 data[3] = value & 0xff;
561
db49c146
DP
562 if (!snd_soc_codec_volatile_register(codec, reg) &&
563 reg < codec->driver->reg_cache_size)
564 cache[reg] = value;
bc6552f4
MB
565
566 if (codec->cache_only) {
567 codec->cache_sync = 1;
568 return 0;
569 }
570
985d8c4c
MB
571 dev_dbg(codec->dev, "0x%x = 0x%x\n", reg, value);
572
bc6552f4
MB
573 ret = codec->hw_write(codec->control_data, data, 4);
574 if (ret == 4)
575 return 0;
576 if (ret < 0)
577 return ret;
578 else
579 return -EIO;
580}
994dc424 581
f479fd93
DP
582#if defined(CONFIG_SPI_MASTER)
583static int snd_soc_16_16_spi_write(void *control_data, const char *data,
584 int len)
585{
586 struct spi_device *spi = control_data;
587 struct spi_transfer t;
588 struct spi_message m;
589 u8 msg[4];
590
591 if (len <= 0)
592 return 0;
593
594 msg[0] = data[0];
595 msg[1] = data[1];
596 msg[2] = data[2];
597 msg[3] = data[3];
598
599 spi_message_init(&m);
600 memset(&t, 0, (sizeof t));
601
602 t.tx_buf = &msg[0];
603 t.len = len;
604
605 spi_message_add_tail(&t, &m);
606 spi_sync(spi, &m);
607
608 return len;
609}
610#else
611#define snd_soc_16_16_spi_write NULL
612#endif
613
17a52fd6
MB
614static struct {
615 int addr_bits;
616 int data_bits;
afa2f106 617 int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int);
27ded041 618 int (*spi_write)(void *, const char *, int);
17a52fd6 619 unsigned int (*read)(struct snd_soc_codec *, unsigned int);
afa2f106 620 unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
17a52fd6 621} io_types[] = {
63b62ab0
BS
622 {
623 .addr_bits = 4, .data_bits = 12,
624 .write = snd_soc_4_12_write, .read = snd_soc_4_12_read,
625 .spi_write = snd_soc_4_12_spi_write,
626 },
d62ab358
MB
627 {
628 .addr_bits = 7, .data_bits = 9,
629 .write = snd_soc_7_9_write, .read = snd_soc_7_9_read,
8998c899 630 .spi_write = snd_soc_7_9_spi_write,
d62ab358
MB
631 },
632 {
633 .addr_bits = 8, .data_bits = 8,
634 .write = snd_soc_8_8_write, .read = snd_soc_8_8_read,
85dfcdff 635 .i2c_read = snd_soc_8_8_read_i2c,
f479fd93 636 .spi_write = snd_soc_8_8_spi_write,
d62ab358
MB
637 },
638 {
639 .addr_bits = 8, .data_bits = 16,
640 .write = snd_soc_8_16_write, .read = snd_soc_8_16_read,
641 .i2c_read = snd_soc_8_16_read_i2c,
f479fd93 642 .spi_write = snd_soc_8_16_spi_write,
d62ab358 643 },
994dc424
BS
644 {
645 .addr_bits = 16, .data_bits = 8,
646 .write = snd_soc_16_8_write, .read = snd_soc_16_8_read,
647 .i2c_read = snd_soc_16_8_read_i2c,
648 .spi_write = snd_soc_16_8_spi_write,
649 },
bc6552f4
MB
650 {
651 .addr_bits = 16, .data_bits = 16,
652 .write = snd_soc_16_16_write, .read = snd_soc_16_16_read,
653 .i2c_read = snd_soc_16_16_read_i2c,
f479fd93 654 .spi_write = snd_soc_16_16_spi_write,
bc6552f4 655 },
17a52fd6
MB
656};
657
658/**
659 * snd_soc_codec_set_cache_io: Set up standard I/O functions.
660 *
661 * @codec: CODEC to configure.
662 * @type: Type of cache.
663 * @addr_bits: Number of bits of register address data.
664 * @data_bits: Number of bits of data per register.
7084a42b 665 * @control: Control bus used.
17a52fd6
MB
666 *
667 * Register formats are frequently shared between many I2C and SPI
668 * devices. In order to promote code reuse the ASoC core provides
669 * some standard implementations of CODEC read and write operations
670 * which can be set up using this function.
671 *
672 * The caller is responsible for allocating and initialising the
673 * actual cache.
674 *
675 * Note that at present this code cannot be used by CODECs with
676 * volatile registers.
677 */
678int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
7084a42b
MB
679 int addr_bits, int data_bits,
680 enum snd_soc_control_type control)
17a52fd6
MB
681{
682 int i;
683
17a52fd6
MB
684 for (i = 0; i < ARRAY_SIZE(io_types); i++)
685 if (io_types[i].addr_bits == addr_bits &&
686 io_types[i].data_bits == data_bits)
687 break;
688 if (i == ARRAY_SIZE(io_types)) {
689 printk(KERN_ERR
690 "No I/O functions for %d bit address %d bit data\n",
691 addr_bits, data_bits);
692 return -EINVAL;
693 }
694
f0fba2ad
LG
695 codec->driver->write = io_types[i].write;
696 codec->driver->read = io_types[i].read;
17a52fd6 697
7084a42b
MB
698 switch (control) {
699 case SND_SOC_CUSTOM:
700 break;
701
702 case SND_SOC_I2C:
17244c24 703#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
7084a42b
MB
704 codec->hw_write = (hw_write_t)i2c_master_send;
705#endif
afa2f106
MB
706 if (io_types[i].i2c_read)
707 codec->hw_read = io_types[i].i2c_read;
a6d14342
MB
708
709 codec->control_data = container_of(codec->dev,
710 struct i2c_client,
711 dev);
7084a42b
MB
712 break;
713
714 case SND_SOC_SPI:
27ded041
MB
715 if (io_types[i].spi_write)
716 codec->hw_write = io_types[i].spi_write;
a6d14342
MB
717
718 codec->control_data = container_of(codec->dev,
719 struct spi_device,
720 dev);
7084a42b
MB
721 break;
722 }
723
17a52fd6
MB
724 return 0;
725}
726EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);