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