Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/*
2 * soc-io.c -- ASoC register I/O helpers
3 *
4 * Copyright 2009-2011 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 <linux/i2c.h>
15#include <linux/spi/spi.h>
16#include <linux/regmap.h>
17#include <linux/export.h>
18#include <sound/soc.h>
19
20/**
21 * snd_soc_component_read() - Read register value
22 * @component: Component to read from
23 * @reg: Register to read
24 * @val: Pointer to where the read value is stored
25 *
26 * Return: 0 on success, a negative error code otherwise.
27 */
28int snd_soc_component_read(struct snd_soc_component *component,
29 unsigned int reg, unsigned int *val)
30{
31 int ret;
32
33 if (component->regmap)
34 ret = regmap_read(component->regmap, reg, val);
35 else if (component->read)
36 ret = component->read(component, reg, val);
37 else if (component->driver->read) {
38 *val = component->driver->read(component, reg);
39 ret = 0;
40 }
41 else
42 ret = -EIO;
43
44 return ret;
45}
46EXPORT_SYMBOL_GPL(snd_soc_component_read);
47
48unsigned int snd_soc_component_read32(struct snd_soc_component *component,
49 unsigned int reg)
50{
51 unsigned int val;
52 int ret;
53
54 ret = snd_soc_component_read(component, reg, &val);
55 if (ret < 0)
56 return -1;
57
58 return val;
59}
60EXPORT_SYMBOL_GPL(snd_soc_component_read32);
61
62/**
63 * snd_soc_component_write() - Write register value
64 * @component: Component to write to
65 * @reg: Register to write
66 * @val: Value to write to the register
67 *
68 * Return: 0 on success, a negative error code otherwise.
69 */
70int snd_soc_component_write(struct snd_soc_component *component,
71 unsigned int reg, unsigned int val)
72{
73 if (component->regmap)
74 return regmap_write(component->regmap, reg, val);
75 else if (component->write)
76 return component->write(component, reg, val);
77 else if (component->driver->write)
78 return component->driver->write(component, reg, val);
79 else
80 return -EIO;
81}
82EXPORT_SYMBOL_GPL(snd_soc_component_write);
83
84static int snd_soc_component_update_bits_legacy(
85 struct snd_soc_component *component, unsigned int reg,
86 unsigned int mask, unsigned int val, bool *change)
87{
88 unsigned int old, new;
89 int ret;
90
91 if (!component->read || !component->write)
92 return -EIO;
93
94 mutex_lock(&component->io_mutex);
95
96 ret = component->read(component, reg, &old);
97 if (ret < 0)
98 goto out_unlock;
99
100 new = (old & ~mask) | (val & mask);
101 *change = old != new;
102 if (*change)
103 ret = component->write(component, reg, new);
104out_unlock:
105 mutex_unlock(&component->io_mutex);
106
107 return ret;
108}
109
110/**
111 * snd_soc_component_update_bits() - Perform read/modify/write cycle
112 * @component: Component to update
113 * @reg: Register to update
114 * @mask: Mask that specifies which bits to update
115 * @val: New value for the bits specified by mask
116 *
117 * Return: 1 if the operation was successful and the value of the register
118 * changed, 0 if the operation was successful, but the value did not change.
119 * Returns a negative error code otherwise.
120 */
121int snd_soc_component_update_bits(struct snd_soc_component *component,
122 unsigned int reg, unsigned int mask, unsigned int val)
123{
124 bool change;
125 int ret;
126
127 if (component->regmap)
128 ret = regmap_update_bits_check(component->regmap, reg, mask,
129 val, &change);
130 else
131 ret = snd_soc_component_update_bits_legacy(component, reg,
132 mask, val, &change);
133
134 if (ret < 0)
135 return ret;
136 return change;
137}
138EXPORT_SYMBOL_GPL(snd_soc_component_update_bits);
139
140/**
141 * snd_soc_component_update_bits_async() - Perform asynchronous
142 * read/modify/write cycle
143 * @component: Component to update
144 * @reg: Register to update
145 * @mask: Mask that specifies which bits to update
146 * @val: New value for the bits specified by mask
147 *
148 * This function is similar to snd_soc_component_update_bits(), but the update
149 * operation is scheduled asynchronously. This means it may not be completed
150 * when the function returns. To make sure that all scheduled updates have been
151 * completed snd_soc_component_async_complete() must be called.
152 *
153 * Return: 1 if the operation was successful and the value of the register
154 * changed, 0 if the operation was successful, but the value did not change.
155 * Returns a negative error code otherwise.
156 */
157int snd_soc_component_update_bits_async(struct snd_soc_component *component,
158 unsigned int reg, unsigned int mask, unsigned int val)
159{
160 bool change;
161 int ret;
162
163 if (component->regmap)
164 ret = regmap_update_bits_check_async(component->regmap, reg,
165 mask, val, &change);
166 else
167 ret = snd_soc_component_update_bits_legacy(component, reg,
168 mask, val, &change);
169
170 if (ret < 0)
171 return ret;
172 return change;
173}
174EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async);
175
176/**
177 * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed
178 * @component: Component for which to wait
179 *
180 * This function blocks until all asynchronous I/O which has previously been
181 * scheduled using snd_soc_component_update_bits_async() has completed.
182 */
183void snd_soc_component_async_complete(struct snd_soc_component *component)
184{
185 if (component->regmap)
186 regmap_async_complete(component->regmap);
187}
188EXPORT_SYMBOL_GPL(snd_soc_component_async_complete);
189
190/**
191 * snd_soc_component_test_bits - Test register for change
192 * @component: component
193 * @reg: Register to test
194 * @mask: Mask that specifies which bits to test
195 * @value: Value to test against
196 *
197 * Tests a register with a new value and checks if the new value is
198 * different from the old value.
199 *
200 * Return: 1 for change, otherwise 0.
201 */
202int snd_soc_component_test_bits(struct snd_soc_component *component,
203 unsigned int reg, unsigned int mask, unsigned int value)
204{
205 unsigned int old, new;
206 int ret;
207
208 ret = snd_soc_component_read(component, reg, &old);
209 if (ret < 0)
210 return ret;
211 new = (old & ~mask) | value;
212 return old != new;
213}
214EXPORT_SYMBOL_GPL(snd_soc_component_test_bits);
215
216unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg)
217{
218 unsigned int val;
219 int ret;
220
221 ret = snd_soc_component_read(&codec->component, reg, &val);
222 if (ret < 0)
223 return -1;
224
225 return val;
226}
227EXPORT_SYMBOL_GPL(snd_soc_read);
228
229int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg,
230 unsigned int val)
231{
232 return snd_soc_component_write(&codec->component, reg, val);
233}
234EXPORT_SYMBOL_GPL(snd_soc_write);
235
236/**
237 * snd_soc_update_bits - update codec register bits
238 * @codec: audio codec
239 * @reg: codec register
240 * @mask: register mask
241 * @value: new value
242 *
243 * Writes new register value.
244 *
245 * Returns 1 for change, 0 for no change, or negative error code.
246 */
247int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned int reg,
248 unsigned int mask, unsigned int value)
249{
250 return snd_soc_component_update_bits(&codec->component, reg, mask,
251 value);
252}
253EXPORT_SYMBOL_GPL(snd_soc_update_bits);
254
255/**
256 * snd_soc_test_bits - test register for change
257 * @codec: audio codec
258 * @reg: codec register
259 * @mask: register mask
260 * @value: new value
261 *
262 * Tests a register with a new value and checks if the new value is
263 * different from the old value.
264 *
265 * Returns 1 for change else 0.
266 */
267int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
268 unsigned int mask, unsigned int value)
269{
270 return snd_soc_component_test_bits(&codec->component, reg, mask, value);
271}
272EXPORT_SYMBOL_GPL(snd_soc_test_bits);
273
274int snd_soc_platform_read(struct snd_soc_platform *platform,
275 unsigned int reg)
276{
277 unsigned int val;
278 int ret;
279
280 ret = snd_soc_component_read(&platform->component, reg, &val);
281 if (ret < 0)
282 return -1;
283
284 return val;
285}
286EXPORT_SYMBOL_GPL(snd_soc_platform_read);
287
288int snd_soc_platform_write(struct snd_soc_platform *platform,
289 unsigned int reg, unsigned int val)
290{
291 return snd_soc_component_write(&platform->component, reg, val);
292}
293EXPORT_SYMBOL_GPL(snd_soc_platform_write);