Linux Audio

Check our new training course

Embedded Linux training

Mar 31-Apr 8, 2025
Register
Loading...
Note: File does not exist in v5.9.
  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	mutex_lock(&component->io_mutex);
 92
 93	ret = snd_soc_component_read(component, reg, &old);
 94	if (ret < 0)
 95		goto out_unlock;
 96
 97	new = (old & ~mask) | (val & mask);
 98	*change = old != new;
 99	if (*change)
100		ret = snd_soc_component_write(component, reg, new);
101out_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;
221
222	return val;
223}
224EXPORT_SYMBOL_GPL(snd_soc_read);
225
226int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg,
227	unsigned int val)
228{
229	return snd_soc_component_write(&codec->component, reg, val);
230}
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 */
244int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned int reg,
245				unsigned int mask, unsigned int value)
246{
247	return snd_soc_component_update_bits(&codec->component, reg, mask,
248		value);
249}
250EXPORT_SYMBOL_GPL(snd_soc_update_bits);
251
252/**
253 * 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 */
264int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
265				unsigned int mask, unsigned int value)
266{
267	return snd_soc_component_test_bits(&codec->component, reg, mask, value);
268}
269EXPORT_SYMBOL_GPL(snd_soc_test_bits);
270
271int snd_soc_platform_read(struct snd_soc_platform *platform,
272					unsigned int reg)
273{
274	unsigned int val;
275	int ret;
276
277	ret = snd_soc_component_read(&platform->component, reg, &val);
278	if (ret < 0)
279		return -1;
280
281	return val;
282}
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{
288	return snd_soc_component_write(&platform->component, reg, val);
289}
290EXPORT_SYMBOL_GPL(snd_soc_platform_write);