1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | // |
3 | // tegra210_mbdrc.c - Tegra210 MBDRC driver |
4 | // |
5 | // Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. |
6 | |
7 | #include <linux/device.h> |
8 | #include <linux/io.h> |
9 | #include <linux/module.h> |
10 | #include <linux/of_address.h> |
11 | #include <linux/pm_runtime.h> |
12 | #include <linux/regmap.h> |
13 | #include <sound/core.h> |
14 | #include <sound/soc.h> |
15 | #include <sound/tlv.h> |
16 | |
17 | #include "tegra210_mbdrc.h" |
18 | #include "tegra210_ope.h" |
19 | |
20 | #define MBDRC_FILTER_REG(reg, id) \ |
21 | ((reg) + ((id) * TEGRA210_MBDRC_FILTER_PARAM_STRIDE)) |
22 | |
23 | #define MBDRC_FILTER_REG_DEFAULTS(id) \ |
24 | { MBDRC_FILTER_REG(TEGRA210_MBDRC_IIR_CFG, id), 0x00000005}, \ |
25 | { MBDRC_FILTER_REG(TEGRA210_MBDRC_IN_ATTACK, id), 0x3e48590c}, \ |
26 | { MBDRC_FILTER_REG(TEGRA210_MBDRC_IN_RELEASE, id), 0x08414e9f}, \ |
27 | { MBDRC_FILTER_REG(TEGRA210_MBDRC_FAST_ATTACK, id), 0x7fffffff}, \ |
28 | { MBDRC_FILTER_REG(TEGRA210_MBDRC_IN_THRESHOLD, id), 0x06145082}, \ |
29 | { MBDRC_FILTER_REG(TEGRA210_MBDRC_OUT_THRESHOLD, id), 0x060d379b}, \ |
30 | { MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_1ST, id), 0x0000a000}, \ |
31 | { MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_2ND, id), 0x00002000}, \ |
32 | { MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_3RD, id), 0x00000b33}, \ |
33 | { MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_4TH, id), 0x00000800}, \ |
34 | { MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_5TH, id), 0x0000019a}, \ |
35 | { MBDRC_FILTER_REG(TEGRA210_MBDRC_MAKEUP_GAIN, id), 0x00000002}, \ |
36 | { MBDRC_FILTER_REG(TEGRA210_MBDRC_INIT_GAIN, id), 0x00066666}, \ |
37 | { MBDRC_FILTER_REG(TEGRA210_MBDRC_GAIN_ATTACK, id), 0x00d9ba0e}, \ |
38 | { MBDRC_FILTER_REG(TEGRA210_MBDRC_GAIN_RELEASE, id), 0x3e48590c}, \ |
39 | { MBDRC_FILTER_REG(TEGRA210_MBDRC_FAST_RELEASE, id), 0x7ffff26a}, \ |
40 | { MBDRC_FILTER_REG(TEGRA210_MBDRC_CFG_RAM_CTRL, id), 0x4000} |
41 | |
42 | static const struct reg_default tegra210_mbdrc_reg_defaults[] = { |
43 | { TEGRA210_MBDRC_CFG, 0x0030de51}, |
44 | { TEGRA210_MBDRC_CHANNEL_MASK, 0x00000003}, |
45 | { TEGRA210_MBDRC_FAST_FACTOR, 0x30000800}, |
46 | |
47 | MBDRC_FILTER_REG_DEFAULTS(0), |
48 | MBDRC_FILTER_REG_DEFAULTS(1), |
49 | MBDRC_FILTER_REG_DEFAULTS(2), |
50 | }; |
51 | |
52 | /* Default MBDRC parameters */ |
53 | static const struct tegra210_mbdrc_config mbdrc_init_config = { |
54 | .mode = 0, /* Bypass */ |
55 | .rms_off = 48, |
56 | .peak_rms_mode = 1, /* PEAK */ |
57 | .filter_structure = 0, /* All-pass tree */ |
58 | .shift_ctrl = 30, |
59 | .frame_size = 32, |
60 | .channel_mask = 0x3, |
61 | .fa_factor = 2048, |
62 | .fr_factor = 14747, |
63 | |
64 | .band_params[MBDRC_LOW_BAND] = { |
65 | .band = MBDRC_LOW_BAND, |
66 | .iir_stages = 5, |
67 | .in_attack_tc = 1044928780, |
68 | .in_release_tc = 138497695, |
69 | .fast_attack_tc = 2147483647, |
70 | .in_threshold = {130, 80, 20, 6}, |
71 | .out_threshold = {155, 55, 13, 6}, |
72 | .ratio = {40960, 8192, 2867, 2048, 410}, |
73 | .makeup_gain = 4, |
74 | .gain_init = 419430, |
75 | .gain_attack_tc = 14268942, |
76 | .gain_release_tc = 1440547090, |
77 | .fast_release_tc = 2147480170, |
78 | |
79 | .biquad_params = { |
80 | /* |
81 | * Gains: |
82 | * |
83 | * b0, b1, a0, |
84 | * a1, a2, |
85 | */ |
86 | |
87 | /* Band-0 */ |
88 | 961046798, -2030431983, 1073741824, |
89 | 2030431983, -961046798, |
90 | /* Band-1 */ |
91 | 1030244425, -2099481453, 1073741824, |
92 | 2099481453, -1030244425, |
93 | /* Band-2 */ |
94 | 1067169294, -2136327263, 1073741824, |
95 | 2136327263, -1067169294, |
96 | /* Band-3 */ |
97 | 434951949, -1306567134, 1073741824, |
98 | 1306567134, -434951949, |
99 | /* Band-4 */ |
100 | 780656019, -1605955641, 1073741824, |
101 | 1605955641, -780656019, |
102 | /* Band-5 */ |
103 | 1024497031, -1817128152, 1073741824, |
104 | 1817128152, -1024497031, |
105 | /* Band-6 */ |
106 | 1073741824, 0, 0, |
107 | 0, 0, |
108 | /* Band-7 */ |
109 | 1073741824, 0, 0, |
110 | 0, 0, |
111 | } |
112 | }, |
113 | |
114 | .band_params[MBDRC_MID_BAND] = { |
115 | .band = MBDRC_MID_BAND, |
116 | .iir_stages = 5, |
117 | .in_attack_tc = 1581413104, |
118 | .in_release_tc = 35494783, |
119 | .fast_attack_tc = 2147483647, |
120 | .in_threshold = {130, 50, 30, 6}, |
121 | .out_threshold = {106, 50, 30, 13}, |
122 | .ratio = {40960, 2867, 4096, 2867, 410}, |
123 | .makeup_gain = 6, |
124 | .gain_init = 419430, |
125 | .gain_attack_tc = 4766887, |
126 | .gain_release_tc = 1044928780, |
127 | .fast_release_tc = 2147480170, |
128 | |
129 | .biquad_params = { |
130 | /* |
131 | * Gains: |
132 | * |
133 | * b0, b1, a0, |
134 | * a1, a2, |
135 | */ |
136 | |
137 | /* Band-0 */ |
138 | -1005668963, 1073741824, 0, |
139 | 1005668963, 0, |
140 | /* Band-1 */ |
141 | 998437058, -2067742187, 1073741824, |
142 | 2067742187, -998437058, |
143 | /* Band-2 */ |
144 | 1051963422, -2121153948, 1073741824, |
145 | 2121153948, -1051963422, |
146 | /* Band-3 */ |
147 | 434951949, -1306567134, 1073741824, |
148 | 1306567134, -434951949, |
149 | /* Band-4 */ |
150 | 780656019, -1605955641, 1073741824, |
151 | 1605955641, -780656019, |
152 | /* Band-5 */ |
153 | 1024497031, -1817128152, 1073741824, |
154 | 1817128152, -1024497031, |
155 | /* Band-6 */ |
156 | 1073741824, 0, 0, |
157 | 0, 0, |
158 | /* Band-7 */ |
159 | 1073741824, 0, 0, |
160 | 0, 0, |
161 | } |
162 | }, |
163 | |
164 | .band_params[MBDRC_HIGH_BAND] = { |
165 | .band = MBDRC_HIGH_BAND, |
166 | .iir_stages = 5, |
167 | .in_attack_tc = 2144750688, |
168 | .in_release_tc = 70402888, |
169 | .fast_attack_tc = 2147483647, |
170 | .in_threshold = {130, 50, 30, 6}, |
171 | .out_threshold = {106, 50, 30, 13}, |
172 | .ratio = {40960, 2867, 4096, 2867, 410}, |
173 | .makeup_gain = 6, |
174 | .gain_init = 419430, |
175 | .gain_attack_tc = 4766887, |
176 | .gain_release_tc = 1044928780, |
177 | .fast_release_tc = 2147480170, |
178 | |
179 | .biquad_params = { |
180 | /* |
181 | * Gains: |
182 | * |
183 | * b0, b1, a0, |
184 | * a1, a2, |
185 | */ |
186 | |
187 | /* Band-0 */ |
188 | 1073741824, 0, 0, |
189 | 0, 0, |
190 | /* Band-1 */ |
191 | 1073741824, 0, 0, |
192 | 0, 0, |
193 | /* Band-2 */ |
194 | 1073741824, 0, 0, |
195 | 0, 0, |
196 | /* Band-3 */ |
197 | -619925131, 1073741824, 0, |
198 | 619925131, 0, |
199 | /* Band-4 */ |
200 | 606839335, -1455425976, 1073741824, |
201 | 1455425976, -606839335, |
202 | /* Band-5 */ |
203 | 917759617, -1724690840, 1073741824, |
204 | 1724690840, -917759617, |
205 | /* Band-6 */ |
206 | 1073741824, 0, 0, |
207 | 0, 0, |
208 | /* Band-7 */ |
209 | 1073741824, 0, 0, |
210 | 0, 0, |
211 | } |
212 | } |
213 | }; |
214 | |
215 | static void tegra210_mbdrc_write_ram(struct regmap *regmap, unsigned int reg_ctrl, |
216 | unsigned int reg_data, unsigned int ram_offset, |
217 | unsigned int *data, size_t size) |
218 | { |
219 | unsigned int val; |
220 | unsigned int i; |
221 | |
222 | val = ram_offset & TEGRA210_MBDRC_RAM_CTRL_RAM_ADDR_MASK; |
223 | val |= TEGRA210_MBDRC_RAM_CTRL_ADDR_INIT_EN; |
224 | val |= TEGRA210_MBDRC_RAM_CTRL_SEQ_ACCESS_EN; |
225 | val |= TEGRA210_MBDRC_RAM_CTRL_RW_WRITE; |
226 | |
227 | regmap_write(map: regmap, reg: reg_ctrl, val); |
228 | |
229 | for (i = 0; i < size; i++) |
230 | regmap_write(map: regmap, reg: reg_data, val: data[i]); |
231 | } |
232 | |
233 | static int tegra210_mbdrc_get(struct snd_kcontrol *kcontrol, |
234 | struct snd_ctl_elem_value *ucontrol) |
235 | { |
236 | struct soc_mixer_control *mc = |
237 | (struct soc_mixer_control *)kcontrol->private_value; |
238 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
239 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
240 | unsigned int val; |
241 | |
242 | regmap_read(map: ope->mbdrc_regmap, reg: mc->reg, val: &val); |
243 | |
244 | ucontrol->value.integer.value[0] = (val >> mc->shift) & mc->max; |
245 | |
246 | return 0; |
247 | } |
248 | |
249 | static int tegra210_mbdrc_put(struct snd_kcontrol *kcontrol, |
250 | struct snd_ctl_elem_value *ucontrol) |
251 | { |
252 | struct soc_mixer_control *mc = |
253 | (struct soc_mixer_control *)kcontrol->private_value; |
254 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
255 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
256 | unsigned int val = ucontrol->value.integer.value[0]; |
257 | bool change = false; |
258 | |
259 | val = val << mc->shift; |
260 | |
261 | regmap_update_bits_check(map: ope->mbdrc_regmap, reg: mc->reg, |
262 | mask: (mc->max << mc->shift), val, change: &change); |
263 | |
264 | return change ? 1 : 0; |
265 | } |
266 | |
267 | static int tegra210_mbdrc_get_enum(struct snd_kcontrol *kcontrol, |
268 | struct snd_ctl_elem_value *ucontrol) |
269 | { |
270 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
271 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
272 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
273 | unsigned int val; |
274 | |
275 | regmap_read(map: ope->mbdrc_regmap, reg: e->reg, val: &val); |
276 | |
277 | ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask; |
278 | |
279 | return 0; |
280 | } |
281 | |
282 | static int tegra210_mbdrc_put_enum(struct snd_kcontrol *kcontrol, |
283 | struct snd_ctl_elem_value *ucontrol) |
284 | { |
285 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
286 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
287 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
288 | bool change = false; |
289 | unsigned int val; |
290 | unsigned int mask; |
291 | |
292 | if (ucontrol->value.enumerated.item[0] > e->items - 1) |
293 | return -EINVAL; |
294 | |
295 | val = ucontrol->value.enumerated.item[0] << e->shift_l; |
296 | mask = e->mask << e->shift_l; |
297 | |
298 | regmap_update_bits_check(map: ope->mbdrc_regmap, reg: e->reg, mask, val, |
299 | change: &change); |
300 | |
301 | return change ? 1 : 0; |
302 | } |
303 | |
304 | static int tegra210_mbdrc_band_params_get(struct snd_kcontrol *kcontrol, |
305 | struct snd_ctl_elem_value *ucontrol) |
306 | { |
307 | struct tegra_soc_bytes *params = (void *)kcontrol->private_value; |
308 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
309 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
310 | u32 *data = (u32 *)ucontrol->value.bytes.data; |
311 | u32 regs = params->soc.base; |
312 | u32 mask = params->soc.mask; |
313 | u32 shift = params->shift; |
314 | unsigned int i; |
315 | |
316 | for (i = 0; i < params->soc.num_regs; i++, regs += cmpnt->val_bytes) { |
317 | regmap_read(map: ope->mbdrc_regmap, reg: regs, val: &data[i]); |
318 | |
319 | data[i] = ((data[i] & mask) >> shift); |
320 | } |
321 | |
322 | return 0; |
323 | } |
324 | |
325 | static int tegra210_mbdrc_band_params_put(struct snd_kcontrol *kcontrol, |
326 | struct snd_ctl_elem_value *ucontrol) |
327 | { |
328 | struct tegra_soc_bytes *params = (void *)kcontrol->private_value; |
329 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
330 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
331 | u32 *data = (u32 *)ucontrol->value.bytes.data; |
332 | u32 regs = params->soc.base; |
333 | u32 mask = params->soc.mask; |
334 | u32 shift = params->shift; |
335 | bool change = false; |
336 | unsigned int i; |
337 | |
338 | for (i = 0; i < params->soc.num_regs; i++, regs += cmpnt->val_bytes) { |
339 | bool update = false; |
340 | |
341 | regmap_update_bits_check(map: ope->mbdrc_regmap, reg: regs, mask, |
342 | val: data[i] << shift, change: &update); |
343 | |
344 | change |= update; |
345 | } |
346 | |
347 | return change ? 1 : 0; |
348 | } |
349 | |
350 | static int tegra210_mbdrc_threshold_get(struct snd_kcontrol *kcontrol, |
351 | struct snd_ctl_elem_value *ucontrol) |
352 | { |
353 | struct tegra_soc_bytes *params = (void *)kcontrol->private_value; |
354 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
355 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
356 | u32 *data = (u32 *)ucontrol->value.bytes.data; |
357 | u32 regs = params->soc.base; |
358 | u32 num_regs = params->soc.num_regs; |
359 | u32 val; |
360 | unsigned int i; |
361 | |
362 | for (i = 0; i < num_regs; i += 4, regs += cmpnt->val_bytes) { |
363 | regmap_read(map: ope->mbdrc_regmap, reg: regs, val: &val); |
364 | |
365 | data[i] = (val & TEGRA210_MBDRC_THRESH_1ST_MASK) >> |
366 | TEGRA210_MBDRC_THRESH_1ST_SHIFT; |
367 | data[i + 1] = (val & TEGRA210_MBDRC_THRESH_2ND_MASK) >> |
368 | TEGRA210_MBDRC_THRESH_2ND_SHIFT; |
369 | data[i + 2] = (val & TEGRA210_MBDRC_THRESH_3RD_MASK) >> |
370 | TEGRA210_MBDRC_THRESH_3RD_SHIFT; |
371 | data[i + 3] = (val & TEGRA210_MBDRC_THRESH_4TH_MASK) >> |
372 | TEGRA210_MBDRC_THRESH_4TH_SHIFT; |
373 | } |
374 | |
375 | return 0; |
376 | } |
377 | |
378 | static int tegra210_mbdrc_threshold_put(struct snd_kcontrol *kcontrol, |
379 | struct snd_ctl_elem_value *ucontrol) |
380 | { |
381 | struct tegra_soc_bytes *params = (void *)kcontrol->private_value; |
382 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
383 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
384 | u32 *data = (u32 *)ucontrol->value.bytes.data; |
385 | u32 regs = params->soc.base; |
386 | u32 num_regs = params->soc.num_regs; |
387 | bool change = false; |
388 | unsigned int i; |
389 | |
390 | for (i = 0; i < num_regs; i += 4, regs += cmpnt->val_bytes) { |
391 | bool update = false; |
392 | |
393 | data[i] = (((data[i] >> TEGRA210_MBDRC_THRESH_1ST_SHIFT) & |
394 | TEGRA210_MBDRC_THRESH_1ST_MASK) | |
395 | ((data[i + 1] >> TEGRA210_MBDRC_THRESH_2ND_SHIFT) & |
396 | TEGRA210_MBDRC_THRESH_2ND_MASK) | |
397 | ((data[i + 2] >> TEGRA210_MBDRC_THRESH_3RD_SHIFT) & |
398 | TEGRA210_MBDRC_THRESH_3RD_MASK) | |
399 | ((data[i + 3] >> TEGRA210_MBDRC_THRESH_4TH_SHIFT) & |
400 | TEGRA210_MBDRC_THRESH_4TH_MASK)); |
401 | |
402 | regmap_update_bits_check(map: ope->mbdrc_regmap, reg: regs, mask: 0xffffffff, |
403 | val: data[i], change: &update); |
404 | |
405 | change |= update; |
406 | } |
407 | |
408 | return change ? 1 : 0; |
409 | } |
410 | |
411 | static int tegra210_mbdrc_biquad_coeffs_get(struct snd_kcontrol *kcontrol, |
412 | struct snd_ctl_elem_value *ucontrol) |
413 | { |
414 | struct tegra_soc_bytes *params = (void *)kcontrol->private_value; |
415 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
416 | u32 *data = (u32 *)ucontrol->value.bytes.data; |
417 | |
418 | memset(data, 0, params->soc.num_regs * cmpnt->val_bytes); |
419 | |
420 | return 0; |
421 | } |
422 | |
423 | static int tegra210_mbdrc_biquad_coeffs_put(struct snd_kcontrol *kcontrol, |
424 | struct snd_ctl_elem_value *ucontrol) |
425 | { |
426 | struct tegra_soc_bytes *params = (void *)kcontrol->private_value; |
427 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
428 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
429 | u32 reg_ctrl = params->soc.base; |
430 | u32 reg_data = reg_ctrl + cmpnt->val_bytes; |
431 | u32 *data = (u32 *)ucontrol->value.bytes.data; |
432 | |
433 | tegra210_mbdrc_write_ram(regmap: ope->mbdrc_regmap, reg_ctrl, reg_data, |
434 | ram_offset: params->shift, data, size: params->soc.num_regs); |
435 | |
436 | return 1; |
437 | } |
438 | |
439 | static int tegra210_mbdrc_param_info(struct snd_kcontrol *kcontrol, |
440 | struct snd_ctl_elem_info *uinfo) |
441 | { |
442 | struct soc_bytes *params = (void *)kcontrol->private_value; |
443 | |
444 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; |
445 | uinfo->count = params->num_regs * sizeof(u32); |
446 | |
447 | return 0; |
448 | } |
449 | |
450 | static int tegra210_mbdrc_vol_get(struct snd_kcontrol *kcontrol, |
451 | struct snd_ctl_elem_value *ucontrol) |
452 | { |
453 | struct soc_mixer_control *mc = |
454 | (struct soc_mixer_control *)kcontrol->private_value; |
455 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
456 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
457 | int val; |
458 | |
459 | regmap_read(map: ope->mbdrc_regmap, reg: mc->reg, val: &val); |
460 | |
461 | ucontrol->value.integer.value[0] = |
462 | ((val >> mc->shift) - TEGRA210_MBDRC_MASTER_VOL_MIN); |
463 | |
464 | return 0; |
465 | } |
466 | |
467 | static int tegra210_mbdrc_vol_put(struct snd_kcontrol *kcontrol, |
468 | struct snd_ctl_elem_value *ucontrol) |
469 | { |
470 | struct soc_mixer_control *mc = |
471 | (struct soc_mixer_control *)kcontrol->private_value; |
472 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
473 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
474 | int val = ucontrol->value.integer.value[0]; |
475 | bool change = false; |
476 | |
477 | val += TEGRA210_MBDRC_MASTER_VOL_MIN; |
478 | |
479 | regmap_update_bits_check(map: ope->mbdrc_regmap, reg: mc->reg, |
480 | mask: mc->max << mc->shift, val: val << mc->shift, |
481 | change: &change); |
482 | |
483 | regmap_read(map: ope->mbdrc_regmap, reg: mc->reg, val: &val); |
484 | |
485 | return change ? 1 : 0; |
486 | } |
487 | |
488 | static const char * const tegra210_mbdrc_mode_text[] = { |
489 | "Bypass" , "Fullband" , "Dualband" , "Multiband" |
490 | }; |
491 | |
492 | static const struct soc_enum tegra210_mbdrc_mode_enum = |
493 | SOC_ENUM_SINGLE(TEGRA210_MBDRC_CFG, TEGRA210_MBDRC_CFG_MBDRC_MODE_SHIFT, |
494 | 4, tegra210_mbdrc_mode_text); |
495 | |
496 | static const char * const tegra210_mbdrc_peak_rms_text[] = { |
497 | "Peak" , "RMS" |
498 | }; |
499 | |
500 | static const struct soc_enum tegra210_mbdrc_peak_rms_enum = |
501 | SOC_ENUM_SINGLE(TEGRA210_MBDRC_CFG, TEGRA210_MBDRC_CFG_PEAK_RMS_SHIFT, |
502 | 2, tegra210_mbdrc_peak_rms_text); |
503 | |
504 | static const char * const tegra210_mbdrc_filter_structure_text[] = { |
505 | "All-pass-tree" , "Flexible" |
506 | }; |
507 | |
508 | static const struct soc_enum tegra210_mbdrc_filter_structure_enum = |
509 | SOC_ENUM_SINGLE(TEGRA210_MBDRC_CFG, |
510 | TEGRA210_MBDRC_CFG_FILTER_STRUCTURE_SHIFT, 2, |
511 | tegra210_mbdrc_filter_structure_text); |
512 | |
513 | static const char * const tegra210_mbdrc_frame_size_text[] = { |
514 | "N1" , "N2" , "N4" , "N8" , "N16" , "N32" , "N64" |
515 | }; |
516 | |
517 | static const struct soc_enum tegra210_mbdrc_frame_size_enum = |
518 | SOC_ENUM_SINGLE(TEGRA210_MBDRC_CFG, TEGRA210_MBDRC_CFG_FRAME_SIZE_SHIFT, |
519 | 7, tegra210_mbdrc_frame_size_text); |
520 | |
521 | #define TEGRA_MBDRC_BYTES_EXT(xname, xbase, xregs, xshift, xmask, xinfo) \ |
522 | TEGRA_SOC_BYTES_EXT(xname, xbase, xregs, xshift, xmask, \ |
523 | tegra210_mbdrc_band_params_get, \ |
524 | tegra210_mbdrc_band_params_put, \ |
525 | tegra210_mbdrc_param_info) |
526 | |
527 | #define TEGRA_MBDRC_BAND_BYTES_EXT(xname, xbase, xshift, xmask, xinfo) \ |
528 | TEGRA_MBDRC_BYTES_EXT(xname, xbase, TEGRA210_MBDRC_FILTER_COUNT, \ |
529 | xshift, xmask, xinfo) |
530 | |
531 | static const DECLARE_TLV_DB_MINMAX(mdbrc_vol_tlv, -25600, 25500); |
532 | |
533 | static const struct snd_kcontrol_new tegra210_mbdrc_controls[] = { |
534 | SOC_ENUM_EXT("MBDRC Peak RMS Mode" , tegra210_mbdrc_peak_rms_enum, |
535 | tegra210_mbdrc_get_enum, tegra210_mbdrc_put_enum), |
536 | |
537 | SOC_ENUM_EXT("MBDRC Filter Structure" , |
538 | tegra210_mbdrc_filter_structure_enum, |
539 | tegra210_mbdrc_get_enum, tegra210_mbdrc_put_enum), |
540 | |
541 | SOC_ENUM_EXT("MBDRC Frame Size" , tegra210_mbdrc_frame_size_enum, |
542 | tegra210_mbdrc_get_enum, tegra210_mbdrc_put_enum), |
543 | |
544 | SOC_ENUM_EXT("MBDRC Mode" , tegra210_mbdrc_mode_enum, |
545 | tegra210_mbdrc_get_enum, tegra210_mbdrc_put_enum), |
546 | |
547 | SOC_SINGLE_EXT("MBDRC RMS Offset" , TEGRA210_MBDRC_CFG, |
548 | TEGRA210_MBDRC_CFG_RMS_OFFSET_SHIFT, 0x1ff, 0, |
549 | tegra210_mbdrc_get, tegra210_mbdrc_put), |
550 | |
551 | SOC_SINGLE_EXT("MBDRC Shift Control" , TEGRA210_MBDRC_CFG, |
552 | TEGRA210_MBDRC_CFG_SHIFT_CTRL_SHIFT, 0x1f, 0, |
553 | tegra210_mbdrc_get, tegra210_mbdrc_put), |
554 | |
555 | SOC_SINGLE_EXT("MBDRC Fast Attack Factor" , TEGRA210_MBDRC_FAST_FACTOR, |
556 | TEGRA210_MBDRC_FAST_FACTOR_ATTACK_SHIFT, 0xffff, 0, |
557 | tegra210_mbdrc_get, tegra210_mbdrc_put), |
558 | |
559 | SOC_SINGLE_EXT("MBDRC Fast Release Factor" , TEGRA210_MBDRC_FAST_FACTOR, |
560 | TEGRA210_MBDRC_FAST_FACTOR_RELEASE_SHIFT, 0xffff, 0, |
561 | tegra210_mbdrc_get, tegra210_mbdrc_put), |
562 | |
563 | SOC_SINGLE_RANGE_EXT_TLV("MBDRC Master Volume" , |
564 | TEGRA210_MBDRC_MASTER_VOL, |
565 | TEGRA210_MBDRC_MASTER_VOL_SHIFT, |
566 | 0, 0x1ff, 0, |
567 | tegra210_mbdrc_vol_get, tegra210_mbdrc_vol_put, |
568 | mdbrc_vol_tlv), |
569 | |
570 | TEGRA_SOC_BYTES_EXT("MBDRC IIR Stages" , TEGRA210_MBDRC_IIR_CFG, |
571 | TEGRA210_MBDRC_FILTER_COUNT, |
572 | TEGRA210_MBDRC_IIR_CFG_NUM_STAGES_SHIFT, |
573 | TEGRA210_MBDRC_IIR_CFG_NUM_STAGES_MASK, |
574 | tegra210_mbdrc_band_params_get, |
575 | tegra210_mbdrc_band_params_put, |
576 | tegra210_mbdrc_param_info), |
577 | |
578 | TEGRA_SOC_BYTES_EXT("MBDRC In Attack Time Const" , TEGRA210_MBDRC_IN_ATTACK, |
579 | TEGRA210_MBDRC_FILTER_COUNT, |
580 | TEGRA210_MBDRC_IN_ATTACK_TC_SHIFT, |
581 | TEGRA210_MBDRC_IN_ATTACK_TC_MASK, |
582 | tegra210_mbdrc_band_params_get, |
583 | tegra210_mbdrc_band_params_put, |
584 | tegra210_mbdrc_param_info), |
585 | |
586 | TEGRA_SOC_BYTES_EXT("MBDRC In Release Time Const" , TEGRA210_MBDRC_IN_RELEASE, |
587 | TEGRA210_MBDRC_FILTER_COUNT, |
588 | TEGRA210_MBDRC_IN_RELEASE_TC_SHIFT, |
589 | TEGRA210_MBDRC_IN_RELEASE_TC_MASK, |
590 | tegra210_mbdrc_band_params_get, |
591 | tegra210_mbdrc_band_params_put, |
592 | tegra210_mbdrc_param_info), |
593 | |
594 | TEGRA_SOC_BYTES_EXT("MBDRC Fast Attack Time Const" , TEGRA210_MBDRC_FAST_ATTACK, |
595 | TEGRA210_MBDRC_FILTER_COUNT, |
596 | TEGRA210_MBDRC_FAST_ATTACK_TC_SHIFT, |
597 | TEGRA210_MBDRC_FAST_ATTACK_TC_MASK, |
598 | tegra210_mbdrc_band_params_get, |
599 | tegra210_mbdrc_band_params_put, |
600 | tegra210_mbdrc_param_info), |
601 | |
602 | TEGRA_SOC_BYTES_EXT("MBDRC In Threshold" , TEGRA210_MBDRC_IN_THRESHOLD, |
603 | TEGRA210_MBDRC_FILTER_COUNT * 4, 0, 0xffffffff, |
604 | tegra210_mbdrc_threshold_get, |
605 | tegra210_mbdrc_threshold_put, |
606 | tegra210_mbdrc_param_info), |
607 | |
608 | TEGRA_SOC_BYTES_EXT("MBDRC Out Threshold" , TEGRA210_MBDRC_OUT_THRESHOLD, |
609 | TEGRA210_MBDRC_FILTER_COUNT * 4, 0, 0xffffffff, |
610 | tegra210_mbdrc_threshold_get, |
611 | tegra210_mbdrc_threshold_put, |
612 | tegra210_mbdrc_param_info), |
613 | |
614 | TEGRA_SOC_BYTES_EXT("MBDRC Ratio" , TEGRA210_MBDRC_RATIO_1ST, |
615 | TEGRA210_MBDRC_FILTER_COUNT * 5, |
616 | TEGRA210_MBDRC_RATIO_1ST_SHIFT, TEGRA210_MBDRC_RATIO_1ST_MASK, |
617 | tegra210_mbdrc_band_params_get, |
618 | tegra210_mbdrc_band_params_put, |
619 | tegra210_mbdrc_param_info), |
620 | |
621 | TEGRA_SOC_BYTES_EXT("MBDRC Makeup Gain" , TEGRA210_MBDRC_MAKEUP_GAIN, |
622 | TEGRA210_MBDRC_FILTER_COUNT, |
623 | TEGRA210_MBDRC_MAKEUP_GAIN_SHIFT, |
624 | TEGRA210_MBDRC_MAKEUP_GAIN_MASK, |
625 | tegra210_mbdrc_band_params_get, |
626 | tegra210_mbdrc_band_params_put, |
627 | tegra210_mbdrc_param_info), |
628 | |
629 | TEGRA_SOC_BYTES_EXT("MBDRC Init Gain" , TEGRA210_MBDRC_INIT_GAIN, |
630 | TEGRA210_MBDRC_FILTER_COUNT, |
631 | TEGRA210_MBDRC_INIT_GAIN_SHIFT, |
632 | TEGRA210_MBDRC_INIT_GAIN_MASK, |
633 | tegra210_mbdrc_band_params_get, |
634 | tegra210_mbdrc_band_params_put, |
635 | tegra210_mbdrc_param_info), |
636 | |
637 | TEGRA_SOC_BYTES_EXT("MBDRC Attack Gain" , TEGRA210_MBDRC_GAIN_ATTACK, |
638 | TEGRA210_MBDRC_FILTER_COUNT, |
639 | TEGRA210_MBDRC_GAIN_ATTACK_SHIFT, |
640 | TEGRA210_MBDRC_GAIN_ATTACK_MASK, |
641 | tegra210_mbdrc_band_params_get, |
642 | tegra210_mbdrc_band_params_put, |
643 | tegra210_mbdrc_param_info), |
644 | |
645 | TEGRA_SOC_BYTES_EXT("MBDRC Release Gain" , TEGRA210_MBDRC_GAIN_RELEASE, |
646 | TEGRA210_MBDRC_FILTER_COUNT, |
647 | TEGRA210_MBDRC_GAIN_RELEASE_SHIFT, |
648 | TEGRA210_MBDRC_GAIN_RELEASE_MASK, |
649 | tegra210_mbdrc_band_params_get, |
650 | tegra210_mbdrc_band_params_put, |
651 | tegra210_mbdrc_param_info), |
652 | |
653 | TEGRA_SOC_BYTES_EXT("MBDRC Fast Release Gain" , |
654 | TEGRA210_MBDRC_FAST_RELEASE, |
655 | TEGRA210_MBDRC_FILTER_COUNT, |
656 | TEGRA210_MBDRC_FAST_RELEASE_SHIFT, |
657 | TEGRA210_MBDRC_FAST_RELEASE_MASK, |
658 | tegra210_mbdrc_band_params_get, |
659 | tegra210_mbdrc_band_params_put, |
660 | tegra210_mbdrc_param_info), |
661 | |
662 | TEGRA_SOC_BYTES_EXT("MBDRC Low Band Biquad Coeffs" , |
663 | TEGRA210_MBDRC_CFG_RAM_CTRL, |
664 | TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5, 0, 0xffffffff, |
665 | tegra210_mbdrc_biquad_coeffs_get, |
666 | tegra210_mbdrc_biquad_coeffs_put, |
667 | tegra210_mbdrc_param_info), |
668 | |
669 | TEGRA_SOC_BYTES_EXT("MBDRC Mid Band Biquad Coeffs" , |
670 | TEGRA210_MBDRC_CFG_RAM_CTRL + |
671 | TEGRA210_MBDRC_FILTER_PARAM_STRIDE, |
672 | TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5, 0, 0xffffffff, |
673 | tegra210_mbdrc_biquad_coeffs_get, |
674 | tegra210_mbdrc_biquad_coeffs_put, |
675 | tegra210_mbdrc_param_info), |
676 | |
677 | TEGRA_SOC_BYTES_EXT("MBDRC High Band Biquad Coeffs" , |
678 | TEGRA210_MBDRC_CFG_RAM_CTRL + |
679 | (TEGRA210_MBDRC_FILTER_PARAM_STRIDE * 2), |
680 | TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5, 0, 0xffffffff, |
681 | tegra210_mbdrc_biquad_coeffs_get, |
682 | tegra210_mbdrc_biquad_coeffs_put, |
683 | tegra210_mbdrc_param_info), |
684 | }; |
685 | |
686 | static bool tegra210_mbdrc_wr_reg(struct device *dev, unsigned int reg) |
687 | { |
688 | if (reg >= TEGRA210_MBDRC_IIR_CFG) |
689 | reg -= ((reg - TEGRA210_MBDRC_IIR_CFG) % |
690 | (TEGRA210_MBDRC_FILTER_PARAM_STRIDE * |
691 | TEGRA210_MBDRC_FILTER_COUNT)); |
692 | |
693 | switch (reg) { |
694 | case TEGRA210_MBDRC_SOFT_RESET: |
695 | case TEGRA210_MBDRC_CG: |
696 | case TEGRA210_MBDRC_CFG ... TEGRA210_MBDRC_CFG_RAM_DATA: |
697 | return true; |
698 | default: |
699 | return false; |
700 | } |
701 | } |
702 | |
703 | static bool tegra210_mbdrc_rd_reg(struct device *dev, unsigned int reg) |
704 | { |
705 | if (tegra210_mbdrc_wr_reg(dev, reg)) |
706 | return true; |
707 | |
708 | if (reg >= TEGRA210_MBDRC_IIR_CFG) |
709 | reg -= ((reg - TEGRA210_MBDRC_IIR_CFG) % |
710 | (TEGRA210_MBDRC_FILTER_PARAM_STRIDE * |
711 | TEGRA210_MBDRC_FILTER_COUNT)); |
712 | |
713 | switch (reg) { |
714 | case TEGRA210_MBDRC_STATUS: |
715 | return true; |
716 | default: |
717 | return false; |
718 | } |
719 | } |
720 | |
721 | static bool tegra210_mbdrc_volatile_reg(struct device *dev, unsigned int reg) |
722 | { |
723 | if (reg >= TEGRA210_MBDRC_IIR_CFG) |
724 | reg -= ((reg - TEGRA210_MBDRC_IIR_CFG) % |
725 | (TEGRA210_MBDRC_FILTER_PARAM_STRIDE * |
726 | TEGRA210_MBDRC_FILTER_COUNT)); |
727 | |
728 | switch (reg) { |
729 | case TEGRA210_MBDRC_SOFT_RESET: |
730 | case TEGRA210_MBDRC_STATUS: |
731 | case TEGRA210_MBDRC_CFG_RAM_CTRL: |
732 | case TEGRA210_MBDRC_CFG_RAM_DATA: |
733 | return true; |
734 | default: |
735 | return false; |
736 | } |
737 | } |
738 | |
739 | static bool tegra210_mbdrc_precious_reg(struct device *dev, unsigned int reg) |
740 | { |
741 | if (reg >= TEGRA210_MBDRC_IIR_CFG) |
742 | reg -= ((reg - TEGRA210_MBDRC_IIR_CFG) % |
743 | (TEGRA210_MBDRC_FILTER_PARAM_STRIDE * |
744 | TEGRA210_MBDRC_FILTER_COUNT)); |
745 | |
746 | switch (reg) { |
747 | case TEGRA210_MBDRC_CFG_RAM_DATA: |
748 | return true; |
749 | default: |
750 | return false; |
751 | } |
752 | } |
753 | |
754 | static const struct regmap_config tegra210_mbdrc_regmap_cfg = { |
755 | .name = "mbdrc" , |
756 | .reg_bits = 32, |
757 | .reg_stride = 4, |
758 | .val_bits = 32, |
759 | .max_register = TEGRA210_MBDRC_MAX_REG, |
760 | .writeable_reg = tegra210_mbdrc_wr_reg, |
761 | .readable_reg = tegra210_mbdrc_rd_reg, |
762 | .volatile_reg = tegra210_mbdrc_volatile_reg, |
763 | .precious_reg = tegra210_mbdrc_precious_reg, |
764 | .reg_defaults = tegra210_mbdrc_reg_defaults, |
765 | .num_reg_defaults = ARRAY_SIZE(tegra210_mbdrc_reg_defaults), |
766 | .cache_type = REGCACHE_FLAT, |
767 | }; |
768 | |
769 | int tegra210_mbdrc_hw_params(struct snd_soc_component *cmpnt) |
770 | { |
771 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
772 | const struct tegra210_mbdrc_config *conf = &mbdrc_init_config; |
773 | u32 val = 0; |
774 | unsigned int i; |
775 | |
776 | regmap_read(map: ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, val: &val); |
777 | |
778 | val &= TEGRA210_MBDRC_CFG_MBDRC_MODE_MASK; |
779 | |
780 | if (val == TEGRA210_MBDRC_CFG_MBDRC_MODE_BYPASS) |
781 | return 0; |
782 | |
783 | for (i = 0; i < MBDRC_NUM_BAND; i++) { |
784 | const struct tegra210_mbdrc_band_params *params = |
785 | &conf->band_params[i]; |
786 | |
787 | u32 reg_off = i * TEGRA210_MBDRC_FILTER_PARAM_STRIDE; |
788 | |
789 | tegra210_mbdrc_write_ram(regmap: ope->mbdrc_regmap, |
790 | reg_ctrl: reg_off + TEGRA210_MBDRC_CFG_RAM_CTRL, |
791 | reg_data: reg_off + TEGRA210_MBDRC_CFG_RAM_DATA, |
792 | ram_offset: 0, data: (u32 *)¶ms->biquad_params[0], |
793 | TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5); |
794 | } |
795 | return 0; |
796 | } |
797 | |
798 | int tegra210_mbdrc_component_init(struct snd_soc_component *cmpnt) |
799 | { |
800 | struct tegra210_ope *ope = snd_soc_component_get_drvdata(c: cmpnt); |
801 | const struct tegra210_mbdrc_config *conf = &mbdrc_init_config; |
802 | unsigned int i; |
803 | u32 val; |
804 | |
805 | pm_runtime_get_sync(dev: cmpnt->dev); |
806 | |
807 | /* Initialize MBDRC registers and AHUB RAM with default params */ |
808 | regmap_update_bits(map: ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, |
809 | TEGRA210_MBDRC_CFG_MBDRC_MODE_MASK, |
810 | val: conf->mode << TEGRA210_MBDRC_CFG_MBDRC_MODE_SHIFT); |
811 | |
812 | regmap_update_bits(map: ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, |
813 | TEGRA210_MBDRC_CFG_RMS_OFFSET_MASK, |
814 | val: conf->rms_off << TEGRA210_MBDRC_CFG_RMS_OFFSET_SHIFT); |
815 | |
816 | regmap_update_bits(map: ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, |
817 | TEGRA210_MBDRC_CFG_PEAK_RMS_MASK, |
818 | val: conf->peak_rms_mode << TEGRA210_MBDRC_CFG_PEAK_RMS_SHIFT); |
819 | |
820 | regmap_update_bits(map: ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, |
821 | TEGRA210_MBDRC_CFG_FILTER_STRUCTURE_MASK, |
822 | val: conf->filter_structure << |
823 | TEGRA210_MBDRC_CFG_FILTER_STRUCTURE_SHIFT); |
824 | |
825 | regmap_update_bits(map: ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, |
826 | TEGRA210_MBDRC_CFG_SHIFT_CTRL_MASK, |
827 | val: conf->shift_ctrl << TEGRA210_MBDRC_CFG_SHIFT_CTRL_SHIFT); |
828 | |
829 | regmap_update_bits(map: ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, |
830 | TEGRA210_MBDRC_CFG_FRAME_SIZE_MASK, |
831 | __ffs(conf->frame_size) << |
832 | TEGRA210_MBDRC_CFG_FRAME_SIZE_SHIFT); |
833 | |
834 | regmap_update_bits(map: ope->mbdrc_regmap, TEGRA210_MBDRC_CHANNEL_MASK, |
835 | TEGRA210_MBDRC_CHANNEL_MASK_MASK, |
836 | val: conf->channel_mask << TEGRA210_MBDRC_CHANNEL_MASK_SHIFT); |
837 | |
838 | regmap_update_bits(map: ope->mbdrc_regmap, TEGRA210_MBDRC_FAST_FACTOR, |
839 | TEGRA210_MBDRC_FAST_FACTOR_ATTACK_MASK, |
840 | val: conf->fa_factor << TEGRA210_MBDRC_FAST_FACTOR_ATTACK_SHIFT); |
841 | |
842 | regmap_update_bits(map: ope->mbdrc_regmap, TEGRA210_MBDRC_FAST_FACTOR, |
843 | TEGRA210_MBDRC_FAST_FACTOR_ATTACK_MASK, |
844 | val: conf->fr_factor << TEGRA210_MBDRC_FAST_FACTOR_ATTACK_SHIFT); |
845 | |
846 | for (i = 0; i < MBDRC_NUM_BAND; i++) { |
847 | const struct tegra210_mbdrc_band_params *params = |
848 | &conf->band_params[i]; |
849 | u32 reg_off = i * TEGRA210_MBDRC_FILTER_PARAM_STRIDE; |
850 | |
851 | regmap_update_bits(map: ope->mbdrc_regmap, |
852 | reg: reg_off + TEGRA210_MBDRC_IIR_CFG, |
853 | TEGRA210_MBDRC_IIR_CFG_NUM_STAGES_MASK, |
854 | val: params->iir_stages << |
855 | TEGRA210_MBDRC_IIR_CFG_NUM_STAGES_SHIFT); |
856 | |
857 | regmap_update_bits(map: ope->mbdrc_regmap, |
858 | reg: reg_off + TEGRA210_MBDRC_IN_ATTACK, |
859 | TEGRA210_MBDRC_IN_ATTACK_TC_MASK, |
860 | val: params->in_attack_tc << |
861 | TEGRA210_MBDRC_IN_ATTACK_TC_SHIFT); |
862 | |
863 | regmap_update_bits(map: ope->mbdrc_regmap, |
864 | reg: reg_off + TEGRA210_MBDRC_IN_RELEASE, |
865 | TEGRA210_MBDRC_IN_RELEASE_TC_MASK, |
866 | val: params->in_release_tc << |
867 | TEGRA210_MBDRC_IN_RELEASE_TC_SHIFT); |
868 | |
869 | regmap_update_bits(map: ope->mbdrc_regmap, |
870 | reg: reg_off + TEGRA210_MBDRC_FAST_ATTACK, |
871 | TEGRA210_MBDRC_FAST_ATTACK_TC_MASK, |
872 | val: params->fast_attack_tc << |
873 | TEGRA210_MBDRC_FAST_ATTACK_TC_SHIFT); |
874 | |
875 | val = (((params->in_threshold[0] >> |
876 | TEGRA210_MBDRC_THRESH_1ST_SHIFT) & |
877 | TEGRA210_MBDRC_THRESH_1ST_MASK) | |
878 | ((params->in_threshold[1] >> |
879 | TEGRA210_MBDRC_THRESH_2ND_SHIFT) & |
880 | TEGRA210_MBDRC_THRESH_2ND_MASK) | |
881 | ((params->in_threshold[2] >> |
882 | TEGRA210_MBDRC_THRESH_3RD_SHIFT) & |
883 | TEGRA210_MBDRC_THRESH_3RD_MASK) | |
884 | ((params->in_threshold[3] >> |
885 | TEGRA210_MBDRC_THRESH_4TH_SHIFT) & |
886 | TEGRA210_MBDRC_THRESH_4TH_MASK)); |
887 | |
888 | regmap_update_bits(map: ope->mbdrc_regmap, |
889 | reg: reg_off + TEGRA210_MBDRC_IN_THRESHOLD, |
890 | mask: 0xffffffff, val); |
891 | |
892 | val = (((params->out_threshold[0] >> |
893 | TEGRA210_MBDRC_THRESH_1ST_SHIFT) & |
894 | TEGRA210_MBDRC_THRESH_1ST_MASK) | |
895 | ((params->out_threshold[1] >> |
896 | TEGRA210_MBDRC_THRESH_2ND_SHIFT) & |
897 | TEGRA210_MBDRC_THRESH_2ND_MASK) | |
898 | ((params->out_threshold[2] >> |
899 | TEGRA210_MBDRC_THRESH_3RD_SHIFT) & |
900 | TEGRA210_MBDRC_THRESH_3RD_MASK) | |
901 | ((params->out_threshold[3] >> |
902 | TEGRA210_MBDRC_THRESH_4TH_SHIFT) & |
903 | TEGRA210_MBDRC_THRESH_4TH_MASK)); |
904 | |
905 | regmap_update_bits(map: ope->mbdrc_regmap, |
906 | reg: reg_off + TEGRA210_MBDRC_OUT_THRESHOLD, |
907 | mask: 0xffffffff, val); |
908 | |
909 | regmap_update_bits(map: ope->mbdrc_regmap, |
910 | reg: reg_off + TEGRA210_MBDRC_RATIO_1ST, |
911 | TEGRA210_MBDRC_RATIO_1ST_MASK, |
912 | val: params->ratio[0] << TEGRA210_MBDRC_RATIO_1ST_SHIFT); |
913 | |
914 | regmap_update_bits(map: ope->mbdrc_regmap, |
915 | reg: reg_off + TEGRA210_MBDRC_RATIO_2ND, |
916 | TEGRA210_MBDRC_RATIO_2ND_MASK, |
917 | val: params->ratio[1] << TEGRA210_MBDRC_RATIO_2ND_SHIFT); |
918 | |
919 | regmap_update_bits(map: ope->mbdrc_regmap, |
920 | reg: reg_off + TEGRA210_MBDRC_RATIO_3RD, |
921 | TEGRA210_MBDRC_RATIO_3RD_MASK, |
922 | val: params->ratio[2] << TEGRA210_MBDRC_RATIO_3RD_SHIFT); |
923 | |
924 | regmap_update_bits(map: ope->mbdrc_regmap, |
925 | reg: reg_off + TEGRA210_MBDRC_RATIO_4TH, |
926 | TEGRA210_MBDRC_RATIO_4TH_MASK, |
927 | val: params->ratio[3] << TEGRA210_MBDRC_RATIO_4TH_SHIFT); |
928 | |
929 | regmap_update_bits(map: ope->mbdrc_regmap, |
930 | reg: reg_off + TEGRA210_MBDRC_RATIO_5TH, |
931 | TEGRA210_MBDRC_RATIO_5TH_MASK, |
932 | val: params->ratio[4] << TEGRA210_MBDRC_RATIO_5TH_SHIFT); |
933 | |
934 | regmap_update_bits(map: ope->mbdrc_regmap, |
935 | reg: reg_off + TEGRA210_MBDRC_MAKEUP_GAIN, |
936 | TEGRA210_MBDRC_MAKEUP_GAIN_MASK, |
937 | val: params->makeup_gain << |
938 | TEGRA210_MBDRC_MAKEUP_GAIN_SHIFT); |
939 | |
940 | regmap_update_bits(map: ope->mbdrc_regmap, |
941 | reg: reg_off + TEGRA210_MBDRC_INIT_GAIN, |
942 | TEGRA210_MBDRC_INIT_GAIN_MASK, |
943 | val: params->gain_init << |
944 | TEGRA210_MBDRC_INIT_GAIN_SHIFT); |
945 | |
946 | regmap_update_bits(map: ope->mbdrc_regmap, |
947 | reg: reg_off + TEGRA210_MBDRC_GAIN_ATTACK, |
948 | TEGRA210_MBDRC_GAIN_ATTACK_MASK, |
949 | val: params->gain_attack_tc << |
950 | TEGRA210_MBDRC_GAIN_ATTACK_SHIFT); |
951 | |
952 | regmap_update_bits(map: ope->mbdrc_regmap, |
953 | reg: reg_off + TEGRA210_MBDRC_GAIN_RELEASE, |
954 | TEGRA210_MBDRC_GAIN_RELEASE_MASK, |
955 | val: params->gain_release_tc << |
956 | TEGRA210_MBDRC_GAIN_RELEASE_SHIFT); |
957 | |
958 | regmap_update_bits(map: ope->mbdrc_regmap, |
959 | reg: reg_off + TEGRA210_MBDRC_FAST_RELEASE, |
960 | TEGRA210_MBDRC_FAST_RELEASE_MASK, |
961 | val: params->fast_release_tc << |
962 | TEGRA210_MBDRC_FAST_RELEASE_SHIFT); |
963 | |
964 | tegra210_mbdrc_write_ram(regmap: ope->mbdrc_regmap, |
965 | reg_ctrl: reg_off + TEGRA210_MBDRC_CFG_RAM_CTRL, |
966 | reg_data: reg_off + TEGRA210_MBDRC_CFG_RAM_DATA, ram_offset: 0, |
967 | data: (u32 *)¶ms->biquad_params[0], |
968 | TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5); |
969 | } |
970 | |
971 | pm_runtime_put_sync(dev: cmpnt->dev); |
972 | |
973 | snd_soc_add_component_controls(component: cmpnt, controls: tegra210_mbdrc_controls, |
974 | ARRAY_SIZE(tegra210_mbdrc_controls)); |
975 | |
976 | return 0; |
977 | } |
978 | |
979 | int tegra210_mbdrc_regmap_init(struct platform_device *pdev) |
980 | { |
981 | struct device *dev = &pdev->dev; |
982 | struct tegra210_ope *ope = dev_get_drvdata(dev); |
983 | struct device_node *child; |
984 | struct resource mem; |
985 | void __iomem *regs; |
986 | int err; |
987 | |
988 | child = of_get_child_by_name(node: dev->of_node, name: "dynamic-range-compressor" ); |
989 | if (!child) |
990 | return -ENODEV; |
991 | |
992 | err = of_address_to_resource(dev: child, index: 0, r: &mem); |
993 | of_node_put(node: child); |
994 | if (err < 0) { |
995 | dev_err(dev, "fail to get MBDRC resource\n" ); |
996 | return err; |
997 | } |
998 | |
999 | mem.flags = IORESOURCE_MEM; |
1000 | regs = devm_ioremap_resource(dev, res: &mem); |
1001 | if (IS_ERR(ptr: regs)) |
1002 | return PTR_ERR(ptr: regs); |
1003 | |
1004 | ope->mbdrc_regmap = devm_regmap_init_mmio(dev, regs, |
1005 | &tegra210_mbdrc_regmap_cfg); |
1006 | if (IS_ERR(ptr: ope->mbdrc_regmap)) { |
1007 | dev_err(dev, "regmap init failed\n" ); |
1008 | return PTR_ERR(ptr: ope->mbdrc_regmap); |
1009 | } |
1010 | |
1011 | regcache_cache_only(map: ope->mbdrc_regmap, enable: true); |
1012 | |
1013 | return 0; |
1014 | } |
1015 | |