xref: /linux/sound/soc/sdca/sdca_regmap.c (revision 6a137497178720da8f454c81d2e9fcebc3137b51)
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 *
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 *
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 *
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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