Merge tag 'asoc-fix-v5.4-rc4' of https://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / sound / soc / soc-io.c
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  */
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
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  */
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
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  */
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  */
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  */
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  */
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);