diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-07-05 12:24:50 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-07-05 12:24:50 -0400 |
commit | 17a52fd60a0a0e617ed94aadb1b19751a8fa219e (patch) | |
tree | 2c2fd4526ae219ec9435a0a4b0fc281a5ca62b7c /sound/soc/soc-cache.c | |
parent | 5420f30723122012c7bb868a55ff21c7d383b68e (diff) |
ASoC: Begin to factor out register cache I/O functions
A lot of CODECs share the same register data formats and therefore
replicate the code to manage access to and caching of the register
map. In order to reduce code duplication centralised versions of
this code will be introduced with drivers able to configure the use
of the common code by calling the new snd_soc_codec_set_cache_io()
API call during startup.
As an initial user the 7 bit address/9 bit data format used by many
Wolfson devices is supported for write only CODECs and the drivers
with straightforward register cache implementations are converted to
use it.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-cache.c')
-rw-r--r-- | sound/soc/soc-cache.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c new file mode 100644 index 000000000000..4eb4333a0efb --- /dev/null +++ b/sound/soc/soc-cache.c | |||
@@ -0,0 +1,105 @@ | |||
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 | |||
14 | #include <sound/soc.h> | ||
15 | |||
16 | static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, | ||
17 | unsigned int reg) | ||
18 | { | ||
19 | u16 *cache = codec->reg_cache; | ||
20 | if (reg >= codec->reg_cache_size) | ||
21 | return -1; | ||
22 | return cache[reg]; | ||
23 | } | ||
24 | |||
25 | static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg, | ||
26 | unsigned int value) | ||
27 | { | ||
28 | u16 *cache = codec->reg_cache; | ||
29 | u8 data[2]; | ||
30 | int ret; | ||
31 | |||
32 | BUG_ON(codec->volatile_register); | ||
33 | |||
34 | data[0] = (reg << 1) | ((value >> 8) & 0x0001); | ||
35 | data[1] = value & 0x00ff; | ||
36 | |||
37 | if (reg < codec->reg_cache_size) | ||
38 | cache[reg] = value; | ||
39 | ret = codec->hw_write(codec->control_data, data, 2); | ||
40 | if (ret == 2) | ||
41 | return 0; | ||
42 | if (ret < 0) | ||
43 | return ret; | ||
44 | else | ||
45 | return -EIO; | ||
46 | } | ||
47 | |||
48 | |||
49 | static struct { | ||
50 | int addr_bits; | ||
51 | int data_bits; | ||
52 | int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); | ||
53 | unsigned int (*read)(struct snd_soc_codec *, unsigned int); | ||
54 | } io_types[] = { | ||
55 | { 7, 9, snd_soc_7_9_write, snd_soc_7_9_read }, | ||
56 | }; | ||
57 | |||
58 | /** | ||
59 | * snd_soc_codec_set_cache_io: Set up standard I/O functions. | ||
60 | * | ||
61 | * @codec: CODEC to configure. | ||
62 | * @type: Type of cache. | ||
63 | * @addr_bits: Number of bits of register address data. | ||
64 | * @data_bits: Number of bits of data per register. | ||
65 | * | ||
66 | * Register formats are frequently shared between many I2C and SPI | ||
67 | * devices. In order to promote code reuse the ASoC core provides | ||
68 | * some standard implementations of CODEC read and write operations | ||
69 | * which can be set up using this function. | ||
70 | * | ||
71 | * The caller is responsible for allocating and initialising the | ||
72 | * actual cache. | ||
73 | * | ||
74 | * Note that at present this code cannot be used by CODECs with | ||
75 | * volatile registers. | ||
76 | */ | ||
77 | int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, | ||
78 | int addr_bits, int data_bits) | ||
79 | { | ||
80 | int i; | ||
81 | |||
82 | /* We don't support volatile registers yet - refactoring of | ||
83 | * the hw_read operation will be required to do so. */ | ||
84 | if (codec->volatile_register) { | ||
85 | printk(KERN_ERR "Volatile registers not yet supported\n"); | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | |||
89 | for (i = 0; i < ARRAY_SIZE(io_types); i++) | ||
90 | if (io_types[i].addr_bits == addr_bits && | ||
91 | io_types[i].data_bits == data_bits) | ||
92 | break; | ||
93 | if (i == ARRAY_SIZE(io_types)) { | ||
94 | printk(KERN_ERR | ||
95 | "No I/O functions for %d bit address %d bit data\n", | ||
96 | addr_bits, data_bits); | ||
97 | return -EINVAL; | ||
98 | } | ||
99 | |||
100 | codec->write = io_types[i].write; | ||
101 | codec->read = io_types[i].read; | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); | ||