File Index
Files and directories
Sign in
FILE

sdca_regmap.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/sdca/sdca_regmap.c C
  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
 20static struct sdca_entity *
 21function_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
 32static struct sdca_control *
 33entity_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
 45static struct sdca_control *
 46function_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 */
 64bool 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}
 93EXPORT_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 */
102bool 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}
130EXPORT_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 */
139bool 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	return control->is_volatile;
151}
152EXPORT_SYMBOL_NS(sdca_regmap_volatile, "SND_SOC_SDCA");
153
154/**
155 * sdca_regmap_deferrable - return if a given SDCA Control is deferrable
156 * @function: Pointer to the Function information.
157 * @reg: Register address/Control to be processed.
158 *
159 * Return: Returns true if the register is deferrable.
160 */
161bool sdca_regmap_deferrable(struct sdca_function_data *function, unsigned int reg)
162{
163	struct sdca_control *control;
164
165	if (!SDW_SDCA_VALID_CTL(reg))
166		return false;
167
168	control = function_find_control(function, reg);
169	if (!control)
170		return false;
171
172	return control->deferrable;
173}
174EXPORT_SYMBOL_NS(sdca_regmap_deferrable, "SND_SOC_SDCA");
175
176/**
177 * sdca_regmap_mbq_size - return size in bytes of a given SDCA Control
178 * @function: Pointer to the Function information.
179 * @reg: Register address/Control to be processed.
180 *
181 * Return: Returns the size in bytes of the Control.
182 */
183int sdca_regmap_mbq_size(struct sdca_function_data *function, unsigned int reg)
184{
185	struct sdca_control *control;
186
187	if (!SDW_SDCA_VALID_CTL(reg))
188		return -EINVAL;
189
190	control = function_find_control(function, reg);
191	if (!control)
192		return -EINVAL;
193
194	return clamp_val(control->nbits / BITS_PER_BYTE, sizeof(u8), sizeof(u32));
195}
196EXPORT_SYMBOL_NS(sdca_regmap_mbq_size, "SND_SOC_SDCA");
197
198/**
199 * sdca_regmap_count_constants - count the number of DisCo constant Controls
200 * @dev: Pointer to the device.
201 * @function: Pointer to the Function information, to be parsed.
202 *
203 * This function returns the number of DisCo constant Controls present
204 * in a function. Typically this information will be used to populate
205 * the regmap defaults array, allowing drivers to access the values of
206 * DisCo constants as any other physical register.
207 *
208 * Return: Returns number of DisCo constant controls, or a negative error
209 * code on failure.
210 */
211int sdca_regmap_count_constants(struct device *dev,
212				struct sdca_function_data *function)
213{
214	int nconsts = 0;
215	int i, j;
216
217	for (i = 0; i < function->num_entities; i++) {
218		struct sdca_entity *entity = &function->entities[i];
219
220		for (j = 0; j < entity->num_controls; j++) {
221			if (entity->controls[j].mode == SDCA_ACCESS_MODE_DC)
222				nconsts += hweight64(entity->controls[j].cn_list);
223		}
224	}
225
226	return nconsts;
227}
228EXPORT_SYMBOL_NS(sdca_regmap_count_constants, "SND_SOC_SDCA");
229
230/**
231 * sdca_regmap_populate_constants - fill an array with DisCo constant values
232 * @dev: Pointer to the device.
233 * @function: Pointer to the Function information, to be parsed.
234 * @consts: Pointer to the array which should be filled with the DisCo
235 * constant values.
236 *
237 * This function will populate a regmap struct reg_default array with
238 * the values of the DisCo constants for a given Function. This
239 * allows to access the values of DisCo constants the same as any
240 * other physical register.
241 *
242 * Return: Returns the number of constants populated on success, a negative
243 * error code on failure.
244 */
245int sdca_regmap_populate_constants(struct device *dev,
246				   struct sdca_function_data *function,
247				   struct reg_default *consts)
248{
249	int i, j, k, l;
250
251	for (i = 0, k = 0; i < function->num_entities; i++) {
252		struct sdca_entity *entity = &function->entities[i];
253
254		for (j = 0; j < entity->num_controls; j++) {
255			struct sdca_control *control = &entity->controls[j];
256			int cn;
257
258			if (control->mode != SDCA_ACCESS_MODE_DC)
259				continue;
260
261			l = 0;
262			for_each_set_bit(cn, (unsigned long *)&control->cn_list,
263					 BITS_PER_TYPE(control->cn_list)) {
264				consts[k].reg = SDW_SDCA_CTL(function->desc->adr,
265							     entity->id,
266							     control->sel, cn);
267				consts[k].def = control->values[l];
268				k++;
269				l++;
270			}
271		}
272	}
273
274	return k;
275}
276EXPORT_SYMBOL_NS(sdca_regmap_populate_constants, "SND_SOC_SDCA");
277
278static int populate_control_defaults(struct device *dev, struct regmap *regmap,
279				     struct sdca_function_data *function,
280				     struct sdca_entity *entity,
281				     struct sdca_control *control)
282{
283	int i, ret;
284	int cn;
285
286	if (control->mode == SDCA_ACCESS_MODE_DC)
287		return 0;
288
289	if (control->layers & SDCA_ACCESS_LAYER_DEVICE)
290		return 0;
291
292	i = 0;
293	for_each_set_bit(cn, (unsigned long *)&control->cn_list,
294			 BITS_PER_TYPE(control->cn_list)) {
295		unsigned int reg, val;
296
297		reg = SDW_SDCA_CTL(function->desc->adr, entity->id, control->sel, cn);
298
299		if (control->has_default || control->has_fixed) {
300			ret = regmap_write(regmap, reg, control->values[i]);
301			if (ret) {
302				dev_err(dev, "Failed to write default %#x: %d\n",
303					reg, ret);
304				return ret;
305			}
306
307			i++;
308		} else if (!control->is_volatile) {
309			ret = regmap_read(regmap, reg, &val);
310			if (ret) {
311				dev_err(dev, "Failed to read initial %#x: %d\n",
312					reg, ret);
313				return ret;
314			}
315		}
316	}
317
318	return 0;
319}
320
321/**
322 * sdca_regmap_write_defaults - write out DisCo defaults to device
323 * @dev: Pointer to the device.
324 * @regmap: Pointer to the Function register map.
325 * @function: Pointer to the Function information, to be parsed.
326 *
327 * This function will write out to the hardware all the DisCo default and
328 * fixed value controls. This will cause them to be populated into the cache,
329 * and subsequent handling can be done through a cache sync. It will also
330 * read any non-volatile registers that don't have defaults/fixed values to
331 * populate those into the cache, this ensures they are available for reads
332 * even when the device is runtime suspended.
333 *
334 * Return: Returns zero on success, and a negative error code on failure.
335 */
336int sdca_regmap_write_defaults(struct device *dev, struct regmap *regmap,
337			       struct sdca_function_data *function)
338{
339	int i, j;
340	int ret;
341
342	for (i = 0; i < function->num_entities; i++) {
343		struct sdca_entity *entity = &function->entities[i];
344
345		for (j = 0; j < entity->num_controls; j++) {
346			struct sdca_control *control = &entity->controls[j];
347
348			ret = populate_control_defaults(dev, regmap, function,
349							entity, control);
350			if (ret)
351				return ret;
352		}
353	}
354
355	return 0;
356}
357EXPORT_SYMBOL_NS(sdca_regmap_write_defaults, "SND_SOC_SDCA");
358
359int sdca_regmap_write_init(struct device *dev, struct regmap *regmap,
360			   struct sdca_function_data *function)
361{
362	struct sdca_init_write *init = function->init_table;
363	int ret, i;
364
365	for (i = 0; i < function->num_init_table; i++) {
366		ret = regmap_write(regmap, init[i].addr, init[i].val);
367		if (ret)
368			return ret;
369	}
370
371	return 0;
372}
373EXPORT_SYMBOL_NS(sdca_regmap_write_init, "SND_SOC_SDCA");
~/ Read-only file preview.