Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/sdca/sdca_regmap.c
51073 views
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
return control->is_volatile;
151
}
152
EXPORT_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
*/
161
bool 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
}
174
EXPORT_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
*/
183
int 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
}
196
EXPORT_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
*/
211
int 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
entity->controls[j].has_reset)
223
nconsts += hweight64(entity->controls[j].cn_list);
224
}
225
}
226
227
return nconsts;
228
}
229
EXPORT_SYMBOL_NS(sdca_regmap_count_constants, "SND_SOC_SDCA");
230
231
/**
232
* sdca_regmap_populate_constants - fill an array with DisCo constant values
233
* @dev: Pointer to the device.
234
* @function: Pointer to the Function information, to be parsed.
235
* @consts: Pointer to the array which should be filled with the DisCo
236
* constant values.
237
*
238
* This function will populate a regmap struct reg_default array with
239
* the values of the DisCo constants for a given Function. This
240
* allows to access the values of DisCo constants the same as any
241
* other physical register.
242
*
243
* Return: Returns the number of constants populated on success, a negative
244
* error code on failure.
245
*/
246
int sdca_regmap_populate_constants(struct device *dev,
247
struct sdca_function_data *function,
248
struct reg_default *consts)
249
{
250
int i, j, k, l;
251
252
for (i = 0, k = 0; i < function->num_entities; i++) {
253
struct sdca_entity *entity = &function->entities[i];
254
255
for (j = 0; j < entity->num_controls; j++) {
256
struct sdca_control *control = &entity->controls[j];
257
int cn;
258
259
if (control->mode != SDCA_ACCESS_MODE_DC &&
260
!control->has_reset)
261
continue;
262
263
l = 0;
264
for_each_set_bit(cn, (unsigned long *)&control->cn_list,
265
BITS_PER_TYPE(control->cn_list)) {
266
consts[k].reg = SDW_SDCA_CTL(function->desc->adr,
267
entity->id,
268
control->sel, cn);
269
if (control->mode == SDCA_ACCESS_MODE_DC)
270
consts[k].def = control->values[l];
271
else
272
consts[k].def = control->reset;
273
k++;
274
l++;
275
}
276
}
277
}
278
279
return k;
280
}
281
EXPORT_SYMBOL_NS(sdca_regmap_populate_constants, "SND_SOC_SDCA");
282
283
static int populate_control_defaults(struct device *dev, struct regmap *regmap,
284
struct sdca_function_data *function,
285
struct sdca_entity *entity,
286
struct sdca_control *control)
287
{
288
int i, ret;
289
int cn;
290
291
if (control->mode == SDCA_ACCESS_MODE_DC)
292
return 0;
293
294
if (control->layers & SDCA_ACCESS_LAYER_DEVICE)
295
return 0;
296
297
i = 0;
298
for_each_set_bit(cn, (unsigned long *)&control->cn_list,
299
BITS_PER_TYPE(control->cn_list)) {
300
unsigned int reg, val;
301
302
reg = SDW_SDCA_CTL(function->desc->adr, entity->id, control->sel, cn);
303
304
if (control->has_default || control->has_fixed) {
305
ret = regmap_write(regmap, reg, control->values[i]);
306
if (ret) {
307
dev_err(dev, "Failed to write default %#x: %d\n",
308
reg, ret);
309
return ret;
310
}
311
312
i++;
313
} else if (!control->is_volatile) {
314
if (control->has_reset)
315
regcache_drop_region(regmap, reg, reg);
316
317
ret = regmap_read(regmap, reg, &val);
318
if (ret) {
319
dev_err(dev, "Failed to read initial %#x: %d\n",
320
reg, ret);
321
return ret;
322
}
323
}
324
}
325
326
return 0;
327
}
328
329
/**
330
* sdca_regmap_write_defaults - write out DisCo defaults to device
331
* @dev: Pointer to the device.
332
* @regmap: Pointer to the Function register map.
333
* @function: Pointer to the Function information, to be parsed.
334
*
335
* This function will write out to the hardware all the DisCo default and
336
* fixed value controls. This will cause them to be populated into the cache,
337
* and subsequent handling can be done through a cache sync. It will also
338
* read any non-volatile registers that don't have defaults/fixed values to
339
* populate those into the cache, this ensures they are available for reads
340
* even when the device is runtime suspended.
341
*
342
* Return: Returns zero on success, and a negative error code on failure.
343
*/
344
int sdca_regmap_write_defaults(struct device *dev, struct regmap *regmap,
345
struct sdca_function_data *function)
346
{
347
int i, j;
348
int ret;
349
350
for (i = 0; i < function->num_entities; i++) {
351
struct sdca_entity *entity = &function->entities[i];
352
353
for (j = 0; j < entity->num_controls; j++) {
354
struct sdca_control *control = &entity->controls[j];
355
356
ret = populate_control_defaults(dev, regmap, function,
357
entity, control);
358
if (ret)
359
return ret;
360
}
361
}
362
363
return 0;
364
}
365
EXPORT_SYMBOL_NS(sdca_regmap_write_defaults, "SND_SOC_SDCA");
366
367
int sdca_regmap_write_init(struct device *dev, struct regmap *regmap,
368
struct sdca_function_data *function)
369
{
370
struct sdca_init_write *init = function->init_table;
371
int ret, i;
372
373
for (i = 0; i < function->num_init_table; i++) {
374
ret = regmap_write(regmap, init[i].addr, init[i].val);
375
if (ret)
376
return ret;
377
}
378
379
return 0;
380
}
381
EXPORT_SYMBOL_NS(sdca_regmap_write_init, "SND_SOC_SDCA");
382
383