Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/sdca/sdca_regmap.c
26436 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
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 false;
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
337