blob: d36a192fbece4f8be1124fcb256355149eeef94e [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
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +020091 mutex_lock(&component->io_mutex);
92
Peter Ujfalusidead99e2018-03-12 16:24:23 +020093 ret = snd_soc_component_read(component, reg, &old);
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +020094 if (ret < 0)
95 goto out_unlock;
96
97 new = (old & ~mask) | (val & mask);
98 *change = old != new;
99 if (*change)
Peter Ujfalusidead99e2018-03-12 16:24:23 +0200100 ret = snd_soc_component_write(component, reg, new);
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +0200101out_unlock:
102 mutex_unlock(&component->io_mutex);
103
104 return ret;
105}
106
107/**
108 * snd_soc_component_update_bits() - Perform read/modify/write cycle
109 * @component: Component to update
110 * @reg: Register to update
111 * @mask: Mask that specifies which bits to update
112 * @val: New value for the bits specified by mask
113 *
114 * Return: 1 if the operation was successful and the value of the register
115 * changed, 0 if the operation was successful, but the value did not change.
116 * Returns a negative error code otherwise.
117 */
118int snd_soc_component_update_bits(struct snd_soc_component *component,
119 unsigned int reg, unsigned int mask, unsigned int val)
120{
121 bool change;
122 int ret;
123
124 if (component->regmap)
125 ret = regmap_update_bits_check(component->regmap, reg, mask,
126 val, &change);
127 else
128 ret = snd_soc_component_update_bits_legacy(component, reg,
129 mask, val, &change);
130
131 if (ret < 0)
132 return ret;
133 return change;
134}
135EXPORT_SYMBOL_GPL(snd_soc_component_update_bits);
136
137/**
138 * snd_soc_component_update_bits_async() - Perform asynchronous
139 * read/modify/write cycle
140 * @component: Component to update
141 * @reg: Register to update
142 * @mask: Mask that specifies which bits to update
143 * @val: New value for the bits specified by mask
144 *
145 * This function is similar to snd_soc_component_update_bits(), but the update
146 * operation is scheduled asynchronously. This means it may not be completed
147 * when the function returns. To make sure that all scheduled updates have been
148 * completed snd_soc_component_async_complete() must be called.
149 *
150 * Return: 1 if the operation was successful and the value of the register
151 * changed, 0 if the operation was successful, but the value did not change.
152 * Returns a negative error code otherwise.
153 */
154int snd_soc_component_update_bits_async(struct snd_soc_component *component,
155 unsigned int reg, unsigned int mask, unsigned int val)
156{
157 bool change;
158 int ret;
159
160 if (component->regmap)
161 ret = regmap_update_bits_check_async(component->regmap, reg,
162 mask, val, &change);
163 else
164 ret = snd_soc_component_update_bits_legacy(component, reg,
165 mask, val, &change);
166
167 if (ret < 0)
168 return ret;
169 return change;
170}
171EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async);
172
173/**
174 * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed
175 * @component: Component for which to wait
176 *
177 * This function blocks until all asynchronous I/O which has previously been
178 * scheduled using snd_soc_component_update_bits_async() has completed.
179 */
180void snd_soc_component_async_complete(struct snd_soc_component *component)
181{
182 if (component->regmap)
183 regmap_async_complete(component->regmap);
184}
185EXPORT_SYMBOL_GPL(snd_soc_component_async_complete);
186
187/**
188 * snd_soc_component_test_bits - Test register for change
189 * @component: component
190 * @reg: Register to test
191 * @mask: Mask that specifies which bits to test
192 * @value: Value to test against
193 *
194 * Tests a register with a new value and checks if the new value is
195 * different from the old value.
196 *
197 * Return: 1 for change, otherwise 0.
198 */
199int snd_soc_component_test_bits(struct snd_soc_component *component,
200 unsigned int reg, unsigned int mask, unsigned int value)
201{
202 unsigned int old, new;
203 int ret;
204
205 ret = snd_soc_component_read(component, reg, &old);
206 if (ret < 0)
207 return ret;
208 new = (old & ~mask) | value;
209 return old != new;
210}
211EXPORT_SYMBOL_GPL(snd_soc_component_test_bits);
212
213unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg)
214{
215 unsigned int val;
216 int ret;
217
218 ret = snd_soc_component_read(&codec->component, reg, &val);
219 if (ret < 0)
220 return -1;
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +0200221
222 return val;
223}
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100224EXPORT_SYMBOL_GPL(snd_soc_read);
225
Lars-Peter Clausenab2874a2014-04-19 10:43:57 +0200226int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg,
227 unsigned int val)
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100228{
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +0200229 return snd_soc_component_write(&codec->component, reg, val);
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100230}
231EXPORT_SYMBOL_GPL(snd_soc_write);
232
233/**
234 * snd_soc_update_bits - update codec register bits
235 * @codec: audio codec
236 * @reg: codec register
237 * @mask: register mask
238 * @value: new value
239 *
240 * Writes new register value.
241 *
242 * Returns 1 for change, 0 for no change, or negative error code.
243 */
Mark Brownaa0258a2014-04-14 17:42:28 +0100244int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned int reg,
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100245 unsigned int mask, unsigned int value)
246{
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +0200247 return snd_soc_component_update_bits(&codec->component, reg, mask,
248 value);
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100249}
250EXPORT_SYMBOL_GPL(snd_soc_update_bits);
251
252/**
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100253 * snd_soc_test_bits - test register for change
254 * @codec: audio codec
255 * @reg: codec register
256 * @mask: register mask
257 * @value: new value
258 *
259 * Tests a register with a new value and checks if the new value is
260 * different from the old value.
261 *
262 * Returns 1 for change else 0.
263 */
Mark Brownaa0258a2014-04-14 17:42:28 +0100264int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100265 unsigned int mask, unsigned int value)
266{
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +0200267 return snd_soc_component_test_bits(&codec->component, reg, mask, value);
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100268}
269EXPORT_SYMBOL_GPL(snd_soc_test_bits);
270
271int snd_soc_platform_read(struct snd_soc_platform *platform,
272 unsigned int reg)
273{
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +0200274 unsigned int val;
275 int ret;
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100276
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +0200277 ret = snd_soc_component_read(&platform->component, reg, &val);
278 if (ret < 0)
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100279 return -1;
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100280
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +0200281 return val;
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100282}
283EXPORT_SYMBOL_GPL(snd_soc_platform_read);
284
285int snd_soc_platform_write(struct snd_soc_platform *platform,
286 unsigned int reg, unsigned int val)
287{
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +0200288 return snd_soc_component_write(&platform->component, reg, val);
Lars-Peter Clausen96241c832014-03-18 09:02:07 +0100289}
290EXPORT_SYMBOL_GPL(snd_soc_platform_write);