1 // SPDX-License-Identifier: GPL-2.0+
2 //
3 // soc-io.c  --  ASoC register I/O helpers
4 //
5 // Copyright 2009-2011 Wolfson Microelectronics PLC.
6 //
7 // Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8 
9 #include <linux/i2c.h>
10 #include <linux/spi/spi.h>
11 #include <linux/regmap.h>
12 #include <linux/export.h>
13 #include <sound/soc.h>
14 
15 /**
16  * snd_soc_component_read() - Read register value
17  * @component: Component to read from
18  * @reg: Register to read
19  * @val: Pointer to where the read value is stored
20  *
21  * Return: 0 on success, a negative error code otherwise.
22  */
snd_soc_component_read(struct snd_soc_component * component,unsigned int reg,unsigned int * val)23 int snd_soc_component_read(struct snd_soc_component *component,
24 	unsigned int reg, unsigned int *val)
25 {
26 	int ret;
27 
28 	if (component->regmap)
29 		ret = regmap_read(component->regmap, reg, val);
30 	else if (component->driver->read) {
31 		*val = component->driver->read(component, reg);
32 		ret = 0;
33 	}
34 	else
35 		ret = -EIO;
36 
37 	return ret;
38 }
39 EXPORT_SYMBOL_GPL(snd_soc_component_read);
40 
snd_soc_component_read32(struct snd_soc_component * component,unsigned int reg)41 unsigned int snd_soc_component_read32(struct snd_soc_component *component,
42 				      unsigned int reg)
43 {
44 	unsigned int val;
45 	int ret;
46 
47 	ret = snd_soc_component_read(component, reg, &val);
48 	if (ret < 0)
49 		return -1;
50 
51 	return val;
52 }
53 EXPORT_SYMBOL_GPL(snd_soc_component_read32);
54 
55 /**
56  * snd_soc_component_write() - Write register value
57  * @component: Component to write to
58  * @reg: Register to write
59  * @val: Value to write to the register
60  *
61  * Return: 0 on success, a negative error code otherwise.
62  */
snd_soc_component_write(struct snd_soc_component * component,unsigned int reg,unsigned int val)63 int snd_soc_component_write(struct snd_soc_component *component,
64 	unsigned int reg, unsigned int val)
65 {
66 	if (component->regmap)
67 		return regmap_write(component->regmap, reg, val);
68 	else if (component->driver->write)
69 		return component->driver->write(component, reg, val);
70 	else
71 		return -EIO;
72 }
73 EXPORT_SYMBOL_GPL(snd_soc_component_write);
74 
snd_soc_component_update_bits_legacy(struct snd_soc_component * component,unsigned int reg,unsigned int mask,unsigned int val,bool * change)75 static int snd_soc_component_update_bits_legacy(
76 	struct snd_soc_component *component, unsigned int reg,
77 	unsigned int mask, unsigned int val, bool *change)
78 {
79 	unsigned int old, new;
80 	int ret;
81 
82 	mutex_lock(&component->io_mutex);
83 
84 	ret = snd_soc_component_read(component, reg, &old);
85 	if (ret < 0)
86 		goto out_unlock;
87 
88 	new = (old & ~mask) | (val & mask);
89 	*change = old != new;
90 	if (*change)
91 		ret = snd_soc_component_write(component, reg, new);
92 out_unlock:
93 	mutex_unlock(&component->io_mutex);
94 
95 	return ret;
96 }
97 
98 /**
99  * snd_soc_component_update_bits() - Perform read/modify/write cycle
100  * @component: Component to update
101  * @reg: Register to update
102  * @mask: Mask that specifies which bits to update
103  * @val: New value for the bits specified by mask
104  *
105  * Return: 1 if the operation was successful and the value of the register
106  * changed, 0 if the operation was successful, but the value did not change.
107  * Returns a negative error code otherwise.
108  */
snd_soc_component_update_bits(struct snd_soc_component * component,unsigned int reg,unsigned int mask,unsigned int val)109 int snd_soc_component_update_bits(struct snd_soc_component *component,
110 	unsigned int reg, unsigned int mask, unsigned int val)
111 {
112 	bool change;
113 	int ret;
114 
115 	if (component->regmap)
116 		ret = regmap_update_bits_check(component->regmap, reg, mask,
117 			val, &change);
118 	else
119 		ret = snd_soc_component_update_bits_legacy(component, reg,
120 			mask, val, &change);
121 
122 	if (ret < 0)
123 		return ret;
124 	return change;
125 }
126 EXPORT_SYMBOL_GPL(snd_soc_component_update_bits);
127 
128 /**
129  * snd_soc_component_update_bits_async() - Perform asynchronous
130  *  read/modify/write cycle
131  * @component: Component to update
132  * @reg: Register to update
133  * @mask: Mask that specifies which bits to update
134  * @val: New value for the bits specified by mask
135  *
136  * This function is similar to snd_soc_component_update_bits(), but the update
137  * operation is scheduled asynchronously. This means it may not be completed
138  * when the function returns. To make sure that all scheduled updates have been
139  * completed snd_soc_component_async_complete() must be called.
140  *
141  * Return: 1 if the operation was successful and the value of the register
142  * changed, 0 if the operation was successful, but the value did not change.
143  * Returns a negative error code otherwise.
144  */
snd_soc_component_update_bits_async(struct snd_soc_component * component,unsigned int reg,unsigned int mask,unsigned int val)145 int snd_soc_component_update_bits_async(struct snd_soc_component *component,
146 	unsigned int reg, unsigned int mask, unsigned int val)
147 {
148 	bool change;
149 	int ret;
150 
151 	if (component->regmap)
152 		ret = regmap_update_bits_check_async(component->regmap, reg,
153 			mask, val, &change);
154 	else
155 		ret = snd_soc_component_update_bits_legacy(component, reg,
156 			mask, val, &change);
157 
158 	if (ret < 0)
159 		return ret;
160 	return change;
161 }
162 EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async);
163 
164 /**
165  * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed
166  * @component: Component for which to wait
167  *
168  * This function blocks until all asynchronous I/O which has previously been
169  * scheduled using snd_soc_component_update_bits_async() has completed.
170  */
snd_soc_component_async_complete(struct snd_soc_component * component)171 void snd_soc_component_async_complete(struct snd_soc_component *component)
172 {
173 	if (component->regmap)
174 		regmap_async_complete(component->regmap);
175 }
176 EXPORT_SYMBOL_GPL(snd_soc_component_async_complete);
177 
178 /**
179  * snd_soc_component_test_bits - Test register for change
180  * @component: component
181  * @reg: Register to test
182  * @mask: Mask that specifies which bits to test
183  * @value: Value to test against
184  *
185  * Tests a register with a new value and checks if the new value is
186  * different from the old value.
187  *
188  * Return: 1 for change, otherwise 0.
189  */
snd_soc_component_test_bits(struct snd_soc_component * component,unsigned int reg,unsigned int mask,unsigned int value)190 int snd_soc_component_test_bits(struct snd_soc_component *component,
191 	unsigned int reg, unsigned int mask, unsigned int value)
192 {
193 	unsigned int old, new;
194 	int ret;
195 
196 	ret = snd_soc_component_read(component, reg, &old);
197 	if (ret < 0)
198 		return ret;
199 	new = (old & ~mask) | value;
200 	return old != new;
201 }
202 EXPORT_SYMBOL_GPL(snd_soc_component_test_bits);
203