1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2025 Cirrus Logic, Inc. and
3 // Cirrus Logic International Semiconductor Ltd.
4
5 /*
6 * The MIPI SDCA specification is available for public downloads at
7 * https://www.mipi.org/mipi-sdca-v1-0-download
8 */
9
10 #include <linux/bitops.h>
11 #include <linux/minmax.h>
12 #include <linux/module.h>
13 #include <linux/regmap.h>
14 #include <linux/soundwire/sdw_registers.h>
15 #include <linux/types.h>
16 #include <sound/sdca.h>
17 #include <sound/sdca_function.h>
18 #include <sound/sdca_regmap.h>
19
20 static struct sdca_entity *
function_find_entity(struct sdca_function_data * function,unsigned int reg)21 function_find_entity(struct sdca_function_data *function, unsigned int reg)
22 {
23 int i;
24
25 for (i = 0; i < function->num_entities; i++)
26 if (SDW_SDCA_CTL_ENT(reg) == function->entities[i].id)
27 return &function->entities[i];
28
29 return NULL;
30 }
31
32 static struct sdca_control *
entity_find_control(struct sdca_entity * entity,unsigned int reg)33 entity_find_control(struct sdca_entity *entity, unsigned int reg)
34 {
35 int i;
36
37 for (i = 0; i < entity->num_controls; i++) {
38 if (SDW_SDCA_CTL_CSEL(reg) == entity->controls[i].sel)
39 return &entity->controls[i];
40 }
41
42 return NULL;
43 }
44
45 static struct sdca_control *
function_find_control(struct sdca_function_data * function,unsigned int reg)46 function_find_control(struct sdca_function_data *function, unsigned int reg)
47 {
48 struct sdca_entity *entity;
49
50 entity = function_find_entity(function, reg);
51 if (!entity)
52 return NULL;
53
54 return entity_find_control(entity, reg);
55 }
56
57 /**
58 * sdca_regmap_readable - return if a given SDCA Control is readable
59 * @function: Pointer to the Function information.
60 * @reg: Register address/Control to be processed.
61 *
62 * Return: Returns true if the register is readable.
63 */
sdca_regmap_readable(struct sdca_function_data * function,unsigned int reg)64 bool sdca_regmap_readable(struct sdca_function_data *function, unsigned int reg)
65 {
66 struct sdca_control *control;
67
68 if (!SDW_SDCA_VALID_CTL(reg))
69 return false;
70
71 control = function_find_control(function, reg);
72 if (!control)
73 return false;
74
75 if (!(BIT(SDW_SDCA_CTL_CNUM(reg)) & control->cn_list))
76 return false;
77
78 switch (control->mode) {
79 case SDCA_ACCESS_MODE_RW:
80 case SDCA_ACCESS_MODE_RO:
81 case SDCA_ACCESS_MODE_RW1S:
82 case SDCA_ACCESS_MODE_RW1C:
83 if (SDW_SDCA_NEXT_CTL(0) & reg)
84 return false;
85 fallthrough;
86 case SDCA_ACCESS_MODE_DUAL:
87 /* No access to registers marked solely for device use */
88 return control->layers & ~SDCA_ACCESS_LAYER_DEVICE;
89 default:
90 return false;
91 }
92 }
93 EXPORT_SYMBOL_NS(sdca_regmap_readable, "SND_SOC_SDCA");
94
95 /**
96 * sdca_regmap_writeable - return if a given SDCA Control is writeable
97 * @function: Pointer to the Function information.
98 * @reg: Register address/Control to be processed.
99 *
100 * Return: Returns true if the register is writeable.
101 */
sdca_regmap_writeable(struct sdca_function_data * function,unsigned int reg)102 bool sdca_regmap_writeable(struct sdca_function_data *function, unsigned int reg)
103 {
104 struct sdca_control *control;
105
106 if (!SDW_SDCA_VALID_CTL(reg))
107 return false;
108
109 control = function_find_control(function, reg);
110 if (!control)
111 return false;
112
113 if (!(BIT(SDW_SDCA_CTL_CNUM(reg)) & control->cn_list))
114 return false;
115
116 switch (control->mode) {
117 case SDCA_ACCESS_MODE_RW:
118 case SDCA_ACCESS_MODE_RW1S:
119 case SDCA_ACCESS_MODE_RW1C:
120 if (SDW_SDCA_NEXT_CTL(0) & reg)
121 return false;
122 fallthrough;
123 case SDCA_ACCESS_MODE_DUAL:
124 /* No access to registers marked solely for device use */
125 return control->layers & ~SDCA_ACCESS_LAYER_DEVICE;
126 default:
127 return false;
128 }
129 }
130 EXPORT_SYMBOL_NS(sdca_regmap_writeable, "SND_SOC_SDCA");
131
132 /**
133 * sdca_regmap_volatile - return if a given SDCA Control is volatile
134 * @function: Pointer to the Function information.
135 * @reg: Register address/Control to be processed.
136 *
137 * Return: Returns true if the register is volatile.
138 */
sdca_regmap_volatile(struct sdca_function_data * function,unsigned int reg)139 bool sdca_regmap_volatile(struct sdca_function_data *function, unsigned int reg)
140 {
141 struct sdca_control *control;
142
143 if (!SDW_SDCA_VALID_CTL(reg))
144 return false;
145
146 control = function_find_control(function, reg);
147 if (!control)
148 return false;
149
150 switch (control->mode) {
151 case SDCA_ACCESS_MODE_RO:
152 case SDCA_ACCESS_MODE_RW1S:
153 case SDCA_ACCESS_MODE_RW1C:
154 return true;
155 default:
156 return false;
157 }
158 }
159 EXPORT_SYMBOL_NS(sdca_regmap_volatile, "SND_SOC_SDCA");
160
161 /**
162 * sdca_regmap_deferrable - return if a given SDCA Control is deferrable
163 * @function: Pointer to the Function information.
164 * @reg: Register address/Control to be processed.
165 *
166 * Return: Returns true if the register is deferrable.
167 */
sdca_regmap_deferrable(struct sdca_function_data * function,unsigned int reg)168 bool sdca_regmap_deferrable(struct sdca_function_data *function, unsigned int reg)
169 {
170 struct sdca_control *control;
171
172 if (!SDW_SDCA_VALID_CTL(reg))
173 return false;
174
175 control = function_find_control(function, reg);
176 if (!control)
177 return false;
178
179 return control->deferrable;
180 }
181 EXPORT_SYMBOL_NS(sdca_regmap_deferrable, "SND_SOC_SDCA");
182
183 /**
184 * sdca_regmap_mbq_size - return size in bytes of a given SDCA Control
185 * @function: Pointer to the Function information.
186 * @reg: Register address/Control to be processed.
187 *
188 * Return: Returns the size in bytes of the Control.
189 */
sdca_regmap_mbq_size(struct sdca_function_data * function,unsigned int reg)190 int sdca_regmap_mbq_size(struct sdca_function_data *function, unsigned int reg)
191 {
192 struct sdca_control *control;
193
194 if (!SDW_SDCA_VALID_CTL(reg))
195 return -EINVAL;
196
197 control = function_find_control(function, reg);
198 if (!control)
199 return -EINVAL;
200
201 return clamp_val(control->nbits / BITS_PER_BYTE, sizeof(u8), sizeof(u32));
202 }
203 EXPORT_SYMBOL_NS(sdca_regmap_mbq_size, "SND_SOC_SDCA");
204
205 /**
206 * sdca_regmap_count_constants - count the number of DisCo constant Controls
207 * @dev: Pointer to the device.
208 * @function: Pointer to the Function information, to be parsed.
209 *
210 * This function returns the number of DisCo constant Controls present
211 * in a function. Typically this information will be used to populate
212 * the regmap defaults array, allowing drivers to access the values of
213 * DisCo constants as any other physical register.
214 *
215 * Return: Returns number of DisCo constant controls, or a negative error
216 * code on failure.
217 */
sdca_regmap_count_constants(struct device * dev,struct sdca_function_data * function)218 int sdca_regmap_count_constants(struct device *dev,
219 struct sdca_function_data *function)
220 {
221 int nconsts = 0;
222 int i, j;
223
224 for (i = 0; i < function->num_entities; i++) {
225 struct sdca_entity *entity = &function->entities[i];
226
227 for (j = 0; j < entity->num_controls; j++) {
228 if (entity->controls[j].mode == SDCA_ACCESS_MODE_DC)
229 nconsts += hweight64(entity->controls[j].cn_list);
230 }
231 }
232
233 return nconsts;
234 }
235 EXPORT_SYMBOL_NS(sdca_regmap_count_constants, "SND_SOC_SDCA");
236
237 /**
238 * sdca_regmap_populate_constants - fill an array with DisCo constant values
239 * @dev: Pointer to the device.
240 * @function: Pointer to the Function information, to be parsed.
241 * @consts: Pointer to the array which should be filled with the DisCo
242 * constant values.
243 *
244 * This function will populate a regmap struct reg_default array with
245 * the values of the DisCo constants for a given Function. This
246 * allows to access the values of DisCo constants the same as any
247 * other physical register.
248 *
249 * Return: Returns the number of constants populated on success, a negative
250 * error code on failure.
251 */
sdca_regmap_populate_constants(struct device * dev,struct sdca_function_data * function,struct reg_default * consts)252 int sdca_regmap_populate_constants(struct device *dev,
253 struct sdca_function_data *function,
254 struct reg_default *consts)
255 {
256 int i, j, k, l;
257
258 for (i = 0, k = 0; i < function->num_entities; i++) {
259 struct sdca_entity *entity = &function->entities[i];
260
261 for (j = 0; j < entity->num_controls; j++) {
262 struct sdca_control *control = &entity->controls[j];
263 int cn;
264
265 if (control->mode != SDCA_ACCESS_MODE_DC)
266 continue;
267
268 l = 0;
269 for_each_set_bit(cn, (unsigned long *)&control->cn_list,
270 BITS_PER_TYPE(control->cn_list)) {
271 consts[k].reg = SDW_SDCA_CTL(function->desc->adr,
272 entity->id,
273 control->sel, cn);
274 consts[k].def = control->values[l];
275 k++;
276 l++;
277 }
278 }
279 }
280
281 return k;
282 }
283 EXPORT_SYMBOL_NS(sdca_regmap_populate_constants, "SND_SOC_SDCA");
284
285 /**
286 * sdca_regmap_write_defaults - write out DisCo defaults to device
287 * @dev: Pointer to the device.
288 * @regmap: Pointer to the Function register map.
289 * @function: Pointer to the Function information, to be parsed.
290 *
291 * This function will write out to the hardware all the DisCo default and
292 * fixed value controls. This will cause them to be populated into the cache,
293 * and subsequent handling can be done through a cache sync.
294 *
295 * Return: Returns zero on success, and a negative error code on failure.
296 */
sdca_regmap_write_defaults(struct device * dev,struct regmap * regmap,struct sdca_function_data * function)297 int sdca_regmap_write_defaults(struct device *dev, struct regmap *regmap,
298 struct sdca_function_data *function)
299 {
300 int i, j, k;
301 int ret;
302
303 for (i = 0; i < function->num_entities; i++) {
304 struct sdca_entity *entity = &function->entities[i];
305
306 for (j = 0; j < entity->num_controls; j++) {
307 struct sdca_control *control = &entity->controls[j];
308 int cn;
309
310 if (control->mode == SDCA_ACCESS_MODE_DC)
311 continue;
312
313 if (!control->has_default && !control->has_fixed)
314 continue;
315
316 k = 0;
317 for_each_set_bit(cn, (unsigned long *)&control->cn_list,
318 BITS_PER_TYPE(control->cn_list)) {
319 unsigned int reg;
320
321 reg = SDW_SDCA_CTL(function->desc->adr, entity->id,
322 control->sel, cn);
323
324 ret = regmap_write(regmap, reg, control->values[k]);
325 if (ret)
326 return ret;
327
328 k++;
329 }
330 }
331 }
332
333 return 0;
334 }
335 EXPORT_SYMBOL_NS(sdca_regmap_write_defaults, "SND_SOC_SDCA");
336