blob: 2bc1c4c17896d6c946baf584656f4fdca2bc25e8 [file] [log] [blame]
Mark Brown5bef44f2011-06-13 17:49:55 +01001/*
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>
Mark Brownbe3ea3b2011-06-13 19:35:29 +010016#include <linux/regmap.h>
Paul Gortmakerd81a6d72011-09-22 09:34:58 -040017#include <linux/export.h>
Mark Brown5bef44f2011-06-13 17:49:55 +010018#include <sound/soc.h>
19
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +020020/**
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)
Lars-Peter Clausen96241c832014-03-18 09:02:07 +010030{
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +020031 int ret;
Lars-Peter Clausen96241c832014-03-18 09:02:07 +010032
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +020033 if (component->regmap)
34 ret = regmap_read(component->regmap, reg, val);
35 else if (component->read)
36 ret = component->read(component, reg, val);
Kuninori Morimotod0ff8ba2018-01-16 02:00:59 +000037 else if (component->driver->read) {
38 *val = component->driver->read(component, reg);
39 ret = 0;
40 }
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +020041 else
42 ret = -EIO;
43
Lars-Peter Clausen96241c832014-03-18 09:02:07 +010044 return ret;
45}
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +020046EXPORT_SYMBOL_GPL(snd_soc_component_read);
47
Kuninori Morimoto738b49e2017-11-06 01:48:19 +000048unsigned 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
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +020062/**
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{
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +020073 if (component->regmap)
74 return regmap_write(component->regmap, reg, val);
75 else if (component->write)
76 return component->write(component, reg, val);
Kuninori Morimotod0ff8ba2018-01-16 02:00:59 +000077 else if (component->driver->write)
78 return component->driver->write(component, reg, val);
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +020079 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;
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +0200224
225 return val;
226}
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100227EXPORT_SYMBOL_GPL(snd_soc_read);
228
Lars-Peter Clausenab2874a2014-04-19 10:43:57 +0200229int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg,
230 unsigned int val)
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100231{
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +0200232 return snd_soc_component_write(&codec->component, reg, val);
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100233}
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 */
Mark Brownaa0258a2014-04-14 17:42:28 +0100247int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned int reg,
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100248 unsigned int mask, unsigned int value)
249{
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +0200250 return snd_soc_component_update_bits(&codec->component, reg, mask,
251 value);
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100252}
253EXPORT_SYMBOL_GPL(snd_soc_update_bits);
254
255/**
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100256 * 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 */
Mark Brownaa0258a2014-04-14 17:42:28 +0100267int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100268 unsigned int mask, unsigned int value)
269{
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +0200270 return snd_soc_component_test_bits(&codec->component, reg, mask, value);
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100271}
272EXPORT_SYMBOL_GPL(snd_soc_test_bits);
273
274int snd_soc_platform_read(struct snd_soc_platform *platform,
275 unsigned int reg)
276{
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +0200277 unsigned int val;
278 int ret;
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100279
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +0200280 ret = snd_soc_component_read(&platform->component, reg, &val);
281 if (ret < 0)
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100282 return -1;
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100283
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +0200284 return val;
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100285}
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{
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +0200291 return snd_soc_component_write(&platform->component, reg, val);
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100292}
293EXPORT_SYMBOL_GPL(snd_soc_platform_write);