xref: /linux/sound/soc/sdca/sdca_regmap.c (revision a9e6060bb2a6cae6d43a98ec0794844ad01273d3)
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 	switch (control->mode) {
76 	case SDCA_ACCESS_MODE_RW:
77 	case SDCA_ACCESS_MODE_RO:
78 	case SDCA_ACCESS_MODE_DUAL:
79 	case SDCA_ACCESS_MODE_RW1S:
80 	case SDCA_ACCESS_MODE_RW1C:
81 		/* No access to registers marked solely for device use */
82 		return control->layers & ~SDCA_ACCESS_LAYER_DEVICE;
83 	default:
84 		return false;
85 	}
86 }
87 EXPORT_SYMBOL_NS(sdca_regmap_readable, "SND_SOC_SDCA");
88 
89 /**
90  * sdca_regmap_writeable - return if a given SDCA Control is writeable
91  * @function: Pointer to the Function information.
92  * @reg: Register address/Control to be processed.
93  *
94  * Return: Returns true if the register is writeable.
95  */
sdca_regmap_writeable(struct sdca_function_data * function,unsigned int reg)96 bool sdca_regmap_writeable(struct sdca_function_data *function, unsigned int reg)
97 {
98 	struct sdca_control *control;
99 
100 	if (!SDW_SDCA_VALID_CTL(reg))
101 		return false;
102 
103 	control = function_find_control(function, reg);
104 	if (!control)
105 		return false;
106 
107 	switch (control->mode) {
108 	case SDCA_ACCESS_MODE_RW:
109 	case SDCA_ACCESS_MODE_DUAL:
110 	case SDCA_ACCESS_MODE_RW1S:
111 	case SDCA_ACCESS_MODE_RW1C:
112 		/* No access to registers marked solely for device use */
113 		return control->layers & ~SDCA_ACCESS_LAYER_DEVICE;
114 	default:
115 		return false;
116 	}
117 }
118 EXPORT_SYMBOL_NS(sdca_regmap_writeable, "SND_SOC_SDCA");
119 
120 /**
121  * sdca_regmap_volatile - return if a given SDCA Control is volatile
122  * @function: Pointer to the Function information.
123  * @reg: Register address/Control to be processed.
124  *
125  * Return: Returns true if the register is volatile.
126  */
sdca_regmap_volatile(struct sdca_function_data * function,unsigned int reg)127 bool sdca_regmap_volatile(struct sdca_function_data *function, unsigned int reg)
128 {
129 	struct sdca_control *control;
130 
131 	if (!SDW_SDCA_VALID_CTL(reg))
132 		return false;
133 
134 	control = function_find_control(function, reg);
135 	if (!control)
136 		return false;
137 
138 	switch (control->mode) {
139 	case SDCA_ACCESS_MODE_RO:
140 	case SDCA_ACCESS_MODE_RW1S:
141 	case SDCA_ACCESS_MODE_RW1C:
142 		return true;
143 	default:
144 		return false;
145 	}
146 }
147 EXPORT_SYMBOL_NS(sdca_regmap_volatile, "SND_SOC_SDCA");
148 
149 /**
150  * sdca_regmap_deferrable - return if a given SDCA Control is deferrable
151  * @function: Pointer to the Function information.
152  * @reg: Register address/Control to be processed.
153  *
154  * Return: Returns true if the register is deferrable.
155  */
sdca_regmap_deferrable(struct sdca_function_data * function,unsigned int reg)156 bool sdca_regmap_deferrable(struct sdca_function_data *function, unsigned int reg)
157 {
158 	struct sdca_control *control;
159 
160 	if (!SDW_SDCA_VALID_CTL(reg))
161 		return false;
162 
163 	control = function_find_control(function, reg);
164 	if (!control)
165 		return false;
166 
167 	return control->deferrable;
168 }
169 EXPORT_SYMBOL_NS(sdca_regmap_deferrable, "SND_SOC_SDCA");
170 
171 /**
172  * sdca_regmap_mbq_size - return size in bytes of a given SDCA Control
173  * @function: Pointer to the Function information.
174  * @reg: Register address/Control to be processed.
175  *
176  * Return: Returns the size in bytes of the Control.
177  */
sdca_regmap_mbq_size(struct sdca_function_data * function,unsigned int reg)178 int sdca_regmap_mbq_size(struct sdca_function_data *function, unsigned int reg)
179 {
180 	struct sdca_control *control;
181 
182 	if (!SDW_SDCA_VALID_CTL(reg))
183 		return -EINVAL;
184 
185 	control = function_find_control(function, reg);
186 	if (!control)
187 		return false;
188 
189 	return clamp_val(control->nbits / BITS_PER_BYTE, sizeof(u8), sizeof(u32));
190 }
191 EXPORT_SYMBOL_NS(sdca_regmap_mbq_size, "SND_SOC_SDCA");
192 
193 /**
194  * sdca_regmap_count_constants - count the number of DisCo constant Controls
195  * @dev: Pointer to the device.
196  * @function: Pointer to the Function information, to be parsed.
197  *
198  * This function returns the number of DisCo constant Controls present
199  * in a function. Typically this information will be used to populate
200  * the regmap defaults array, allowing drivers to access the values of
201  * DisCo constants as any other physical register.
202  *
203  * Return: Returns number of DisCo constant controls, or a negative error
204  * code on failure.
205  */
sdca_regmap_count_constants(struct device * dev,struct sdca_function_data * function)206 int sdca_regmap_count_constants(struct device *dev,
207 				struct sdca_function_data *function)
208 {
209 	int nconsts = 0;
210 	int i, j;
211 
212 	for (i = 0; i < function->num_entities; i++) {
213 		struct sdca_entity *entity = &function->entities[i];
214 
215 		for (j = 0; j < entity->num_controls; j++) {
216 			if (entity->controls[j].mode == SDCA_ACCESS_MODE_DC)
217 				nconsts += hweight64(entity->controls[j].cn_list);
218 		}
219 	}
220 
221 	return nconsts;
222 }
223 EXPORT_SYMBOL_NS(sdca_regmap_count_constants, "SND_SOC_SDCA");
224 
225 /**
226  * sdca_regmap_populate_constants - fill an array with DisCo constant values
227  * @dev: Pointer to the device.
228  * @function: Pointer to the Function information, to be parsed.
229  * @consts: Pointer to the array which should be filled with the DisCo
230  * constant values.
231  *
232  * This function will populate a regmap struct reg_default array with
233  * the values of the DisCo constants for a given Function. This
234  * allows to access the values of DisCo constants the same as any
235  * other physical register.
236  *
237  * Return: Returns the number of constants populated on success, a negative
238  * error code on failure.
239  */
sdca_regmap_populate_constants(struct device * dev,struct sdca_function_data * function,struct reg_default * consts)240 int sdca_regmap_populate_constants(struct device *dev,
241 				   struct sdca_function_data *function,
242 				   struct reg_default *consts)
243 {
244 	int i, j, k;
245 
246 	for (i = 0, k = 0; i < function->num_entities; i++) {
247 		struct sdca_entity *entity = &function->entities[i];
248 
249 		for (j = 0; j < entity->num_controls; j++) {
250 			struct sdca_control *control = &entity->controls[j];
251 			int cn;
252 
253 			if (control->mode != SDCA_ACCESS_MODE_DC)
254 				continue;
255 
256 			for_each_set_bit(cn, (unsigned long *)&control->cn_list,
257 					 BITS_PER_TYPE(control->cn_list)) {
258 				consts[k].reg = SDW_SDCA_CTL(function->desc->adr,
259 							     entity->id,
260 							     control->sel, cn);
261 				consts[k].def = control->value;
262 				k++;
263 			}
264 		}
265 	}
266 
267 	return k;
268 }
269 EXPORT_SYMBOL_NS(sdca_regmap_populate_constants, "SND_SOC_SDCA");
270 
271 /**
272  * sdca_regmap_write_defaults - write out DisCo defaults to device
273  * @dev: Pointer to the device.
274  * @regmap: Pointer to the Function register map.
275  * @function: Pointer to the Function information, to be parsed.
276  *
277  * This function will write out to the hardware all the DisCo default and
278  * fixed value controls. This will cause them to be populated into the cache,
279  * and subsequent handling can be done through a cache sync.
280  *
281  * Return: Returns zero on success, and a negative error code on failure.
282  */
sdca_regmap_write_defaults(struct device * dev,struct regmap * regmap,struct sdca_function_data * function)283 int sdca_regmap_write_defaults(struct device *dev, struct regmap *regmap,
284 			       struct sdca_function_data *function)
285 {
286 	int i, j;
287 	int ret;
288 
289 	for (i = 0; i < function->num_entities; i++) {
290 		struct sdca_entity *entity = &function->entities[i];
291 
292 		for (j = 0; j < entity->num_controls; j++) {
293 			struct sdca_control *control = &entity->controls[j];
294 			int cn;
295 
296 			if (control->mode == SDCA_ACCESS_MODE_DC)
297 				continue;
298 
299 			if (!control->has_default && !control->has_fixed)
300 				continue;
301 
302 			for_each_set_bit(cn, (unsigned long *)&control->cn_list,
303 					 BITS_PER_TYPE(control->cn_list)) {
304 				unsigned int reg;
305 
306 				reg = SDW_SDCA_CTL(function->desc->adr, entity->id,
307 						   control->sel, cn);
308 
309 				ret = regmap_write(regmap, reg, control->value);
310 				if (ret)
311 					return ret;
312 			}
313 		}
314 	}
315 
316 	return 0;
317 }
318 EXPORT_SYMBOL_NS(sdca_regmap_write_defaults, "SND_SOC_SDCA");
319