1 // SPDX-License-Identifier: GPL-2.0-only
3 // tegra210_peq.c - Tegra210 PEQ driver
5 // Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
8 #include <linux/device.h>
10 #include <linux/module.h>
12 #include <linux/of_address.h>
13 #include <linux/platform_device.h>
14 #include <linux/pm_runtime.h>
15 #include <linux/regmap.h>
16 #include <sound/core.h>
17 #include <sound/pcm.h>
18 #include <sound/pcm_params.h>
19 #include <sound/soc.h>
21 #include "tegra210_ope.h"
22 #include "tegra210_peq.h"
24 static const struct reg_default tegra210_peq_reg_defaults
[] = {
25 { TEGRA210_PEQ_CFG
, 0x00000013},
26 { TEGRA210_PEQ_CFG_RAM_CTRL
, 0x00004000},
27 { TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL
, 0x00004000},
30 static const u32 biquad_init_gains
[TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH
] = {
31 1495012349, /* Pre-gain */
33 /* Gains : b0, b1, a0, a1, a2 */
34 536870912, -1073741824, 536870912, 2143508246, -1069773768, /* Band-0 */
35 134217728, -265414508, 131766272, 2140402222, -1071252997, /* Band-1 */
36 268435456, -233515765, -33935948, 1839817267, -773826124, /* Band-2 */
37 536870912, -672537913, 139851540, 1886437554, -824433167, /* Band-3 */
38 268435456, -114439279, 173723964, 205743566, 278809729, /* Band-4 */
39 1, 0, 0, 0, 0, /* Band-5 */
40 1, 0, 0, 0, 0, /* Band-6 */
41 1, 0, 0, 0, 0, /* Band-7 */
42 1, 0, 0, 0, 0, /* Band-8 */
43 1, 0, 0, 0, 0, /* Band-9 */
44 1, 0, 0, 0, 0, /* Band-10 */
45 1, 0, 0, 0, 0, /* Band-11 */
47 963423114, /* Post-gain */
50 static const u32 biquad_init_shifts
[TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH
] = {
52 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0, /* Shift for bands */
56 static s32 biquad_coeff_buffer
[TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH
];
58 static void tegra210_peq_read_ram(struct regmap
*regmap
, unsigned int reg_ctrl
,
59 unsigned int reg_data
, unsigned int ram_offset
,
60 unsigned int *data
, size_t size
)
65 val
= ram_offset
& TEGRA210_PEQ_RAM_CTRL_RAM_ADDR_MASK
;
66 val
|= TEGRA210_PEQ_RAM_CTRL_ADDR_INIT_EN
;
67 val
|= TEGRA210_PEQ_RAM_CTRL_SEQ_ACCESS_EN
;
68 val
|= TEGRA210_PEQ_RAM_CTRL_RW_READ
;
70 regmap_write(regmap
, reg_ctrl
, val
);
73 * Since all ahub non-io modules work under same ahub clock it is not
74 * necessary to check ahub read busy bit after every read.
76 for (i
= 0; i
< size
; i
++)
77 regmap_read(regmap
, reg_data
, &data
[i
]);
80 static void tegra210_peq_write_ram(struct regmap
*regmap
, unsigned int reg_ctrl
,
81 unsigned int reg_data
, unsigned int ram_offset
,
82 unsigned int *data
, size_t size
)
87 val
= ram_offset
& TEGRA210_PEQ_RAM_CTRL_RAM_ADDR_MASK
;
88 val
|= TEGRA210_PEQ_RAM_CTRL_ADDR_INIT_EN
;
89 val
|= TEGRA210_PEQ_RAM_CTRL_SEQ_ACCESS_EN
;
90 val
|= TEGRA210_PEQ_RAM_CTRL_RW_WRITE
;
92 regmap_write(regmap
, reg_ctrl
, val
);
94 for (i
= 0; i
< size
; i
++)
95 regmap_write(regmap
, reg_data
, data
[i
]);
98 static int tegra210_peq_get(struct snd_kcontrol
*kcontrol
,
99 struct snd_ctl_elem_value
*ucontrol
)
101 struct soc_mixer_control
*mc
=
102 (struct soc_mixer_control
*)kcontrol
->private_value
;
103 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
104 struct tegra210_ope
*ope
= snd_soc_component_get_drvdata(cmpnt
);
105 unsigned int mask
= (1 << fls(mc
->max
)) - 1;
108 regmap_read(ope
->peq_regmap
, mc
->reg
, &val
);
110 ucontrol
->value
.integer
.value
[0] = (val
>> mc
->shift
) & mask
;
115 ucontrol
->value
.integer
.value
[0] =
116 mc
->max
- ucontrol
->value
.integer
.value
[0];
121 static int tegra210_peq_put(struct snd_kcontrol
*kcontrol
,
122 struct snd_ctl_elem_value
*ucontrol
)
124 struct soc_mixer_control
*mc
=
125 (struct soc_mixer_control
*)kcontrol
->private_value
;
126 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
127 struct tegra210_ope
*ope
= snd_soc_component_get_drvdata(cmpnt
);
128 unsigned int mask
= (1 << fls(mc
->max
)) - 1;
132 val
= (ucontrol
->value
.integer
.value
[0] & mask
);
137 val
= val
<< mc
->shift
;
139 regmap_update_bits_check(ope
->peq_regmap
, mc
->reg
, (mask
<< mc
->shift
),
142 return change
? 1 : 0;
145 static int tegra210_peq_ram_get(struct snd_kcontrol
*kcontrol
,
146 struct snd_ctl_elem_value
*ucontrol
)
148 struct tegra_soc_bytes
*params
= (void *)kcontrol
->private_value
;
149 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
150 struct tegra210_ope
*ope
= snd_soc_component_get_drvdata(cmpnt
);
151 u32 i
, reg_ctrl
= params
->soc
.base
;
152 u32 reg_data
= reg_ctrl
+ cmpnt
->val_bytes
;
153 s32
*data
= (s32
*)biquad_coeff_buffer
;
155 pm_runtime_get_sync(cmpnt
->dev
);
157 tegra210_peq_read_ram(ope
->peq_regmap
, reg_ctrl
, reg_data
,
158 params
->shift
, data
, params
->soc
.num_regs
);
160 pm_runtime_put_sync(cmpnt
->dev
);
162 for (i
= 0; i
< params
->soc
.num_regs
; i
++)
163 ucontrol
->value
.integer
.value
[i
] = (long)data
[i
];
168 static int tegra210_peq_ram_put(struct snd_kcontrol
*kcontrol
,
169 struct snd_ctl_elem_value
*ucontrol
)
171 struct tegra_soc_bytes
*params
= (void *)kcontrol
->private_value
;
172 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
173 struct tegra210_ope
*ope
= snd_soc_component_get_drvdata(cmpnt
);
174 u32 i
, reg_ctrl
= params
->soc
.base
;
175 u32 reg_data
= reg_ctrl
+ cmpnt
->val_bytes
;
176 s32
*data
= (s32
*)biquad_coeff_buffer
;
178 for (i
= 0; i
< params
->soc
.num_regs
; i
++)
179 data
[i
] = (s32
)ucontrol
->value
.integer
.value
[i
];
181 pm_runtime_get_sync(cmpnt
->dev
);
183 tegra210_peq_write_ram(ope
->peq_regmap
, reg_ctrl
, reg_data
,
184 params
->shift
, data
, params
->soc
.num_regs
);
186 pm_runtime_put_sync(cmpnt
->dev
);
191 static int tegra210_peq_param_info(struct snd_kcontrol
*kcontrol
,
192 struct snd_ctl_elem_info
*uinfo
)
194 struct soc_bytes
*params
= (void *)kcontrol
->private_value
;
196 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
197 uinfo
->value
.integer
.min
= INT_MIN
;
198 uinfo
->value
.integer
.max
= INT_MAX
;
199 uinfo
->count
= params
->num_regs
;
204 #define TEGRA210_PEQ_GAIN_PARAMS_CTRL(chan) \
205 TEGRA_SOC_BYTES_EXT("PEQ Channel-" #chan " Biquad Gain Params", \
206 TEGRA210_PEQ_CFG_RAM_CTRL, \
207 TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH, \
208 (TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH * chan), 0xffffffff, \
209 tegra210_peq_ram_get, tegra210_peq_ram_put, \
210 tegra210_peq_param_info)
212 #define TEGRA210_PEQ_SHIFT_PARAMS_CTRL(chan) \
213 TEGRA_SOC_BYTES_EXT("PEQ Channel-" #chan " Biquad Shift Params", \
214 TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL, \
215 TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH, \
216 (TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH * chan), 0x1f, \
217 tegra210_peq_ram_get, tegra210_peq_ram_put, \
218 tegra210_peq_param_info)
220 static const struct snd_kcontrol_new tegra210_peq_controls
[] = {
221 SOC_SINGLE_EXT("PEQ Active", TEGRA210_PEQ_CFG
,
222 TEGRA210_PEQ_CFG_MODE_SHIFT
, 1, 0,
223 tegra210_peq_get
, tegra210_peq_put
),
225 SOC_SINGLE_EXT("PEQ Biquad Stages", TEGRA210_PEQ_CFG
,
226 TEGRA210_PEQ_CFG_BIQUAD_STAGES_SHIFT
,
227 TEGRA210_PEQ_MAX_BIQUAD_STAGES
- 1, 0,
228 tegra210_peq_get
, tegra210_peq_put
),
230 TEGRA210_PEQ_GAIN_PARAMS_CTRL(0),
231 TEGRA210_PEQ_GAIN_PARAMS_CTRL(1),
232 TEGRA210_PEQ_GAIN_PARAMS_CTRL(2),
233 TEGRA210_PEQ_GAIN_PARAMS_CTRL(3),
234 TEGRA210_PEQ_GAIN_PARAMS_CTRL(4),
235 TEGRA210_PEQ_GAIN_PARAMS_CTRL(5),
236 TEGRA210_PEQ_GAIN_PARAMS_CTRL(6),
237 TEGRA210_PEQ_GAIN_PARAMS_CTRL(7),
239 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(0),
240 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(1),
241 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(2),
242 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(3),
243 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(4),
244 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(5),
245 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(6),
246 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(7),
249 static bool tegra210_peq_wr_reg(struct device
*dev
, unsigned int reg
)
252 case TEGRA210_PEQ_SOFT_RESET
:
253 case TEGRA210_PEQ_CG
:
254 case TEGRA210_PEQ_CFG
... TEGRA210_PEQ_CFG_RAM_SHIFT_DATA
:
261 static bool tegra210_peq_rd_reg(struct device
*dev
, unsigned int reg
)
263 if (tegra210_peq_wr_reg(dev
, reg
))
267 case TEGRA210_PEQ_STATUS
:
274 static bool tegra210_peq_volatile_reg(struct device
*dev
, unsigned int reg
)
277 case TEGRA210_PEQ_SOFT_RESET
:
278 case TEGRA210_PEQ_STATUS
:
279 case TEGRA210_PEQ_CFG_RAM_CTRL
... TEGRA210_PEQ_CFG_RAM_SHIFT_DATA
:
286 static bool tegra210_peq_precious_reg(struct device
*dev
, unsigned int reg
)
289 case TEGRA210_PEQ_CFG_RAM_DATA
:
290 case TEGRA210_PEQ_CFG_RAM_SHIFT_DATA
:
297 static const struct regmap_config tegra210_peq_regmap_config
= {
302 .max_register
= TEGRA210_PEQ_CFG_RAM_SHIFT_DATA
,
303 .writeable_reg
= tegra210_peq_wr_reg
,
304 .readable_reg
= tegra210_peq_rd_reg
,
305 .volatile_reg
= tegra210_peq_volatile_reg
,
306 .precious_reg
= tegra210_peq_precious_reg
,
307 .reg_defaults
= tegra210_peq_reg_defaults
,
308 .num_reg_defaults
= ARRAY_SIZE(tegra210_peq_reg_defaults
),
309 .cache_type
= REGCACHE_FLAT
,
312 void tegra210_peq_restore(struct regmap
*regmap
, u32
*biquad_gains
,
317 for (i
= 0; i
< TEGRA210_PEQ_MAX_CHANNELS
; i
++) {
318 tegra210_peq_write_ram(regmap
, TEGRA210_PEQ_CFG_RAM_CTRL
,
319 TEGRA210_PEQ_CFG_RAM_DATA
,
320 (i
* TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH
),
322 TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH
);
324 tegra210_peq_write_ram(regmap
,
325 TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL
,
326 TEGRA210_PEQ_CFG_RAM_SHIFT_DATA
,
327 (i
* TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH
),
329 TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH
);
334 void tegra210_peq_save(struct regmap
*regmap
, u32
*biquad_gains
,
339 for (i
= 0; i
< TEGRA210_PEQ_MAX_CHANNELS
; i
++) {
340 tegra210_peq_read_ram(regmap
,
341 TEGRA210_PEQ_CFG_RAM_CTRL
,
342 TEGRA210_PEQ_CFG_RAM_DATA
,
343 (i
* TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH
),
345 TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH
);
347 tegra210_peq_read_ram(regmap
,
348 TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL
,
349 TEGRA210_PEQ_CFG_RAM_SHIFT_DATA
,
350 (i
* TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH
),
352 TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH
);
356 int tegra210_peq_component_init(struct snd_soc_component
*cmpnt
)
358 struct tegra210_ope
*ope
= snd_soc_component_get_drvdata(cmpnt
);
361 pm_runtime_get_sync(cmpnt
->dev
);
362 regmap_update_bits(ope
->peq_regmap
, TEGRA210_PEQ_CFG
,
363 TEGRA210_PEQ_CFG_MODE_MASK
,
364 0 << TEGRA210_PEQ_CFG_MODE_SHIFT
);
365 regmap_update_bits(ope
->peq_regmap
, TEGRA210_PEQ_CFG
,
366 TEGRA210_PEQ_CFG_BIQUAD_STAGES_MASK
,
367 (TEGRA210_PEQ_BIQUAD_INIT_STAGE
- 1) <<
368 TEGRA210_PEQ_CFG_BIQUAD_STAGES_SHIFT
);
370 /* Initialize PEQ AHUB RAM with default params */
371 for (i
= 0; i
< TEGRA210_PEQ_MAX_CHANNELS
; i
++) {
373 /* Set default gain params */
374 tegra210_peq_write_ram(ope
->peq_regmap
,
375 TEGRA210_PEQ_CFG_RAM_CTRL
,
376 TEGRA210_PEQ_CFG_RAM_DATA
,
377 (i
* TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH
),
378 (u32
*)&biquad_init_gains
,
379 TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH
);
381 /* Set default shift params */
382 tegra210_peq_write_ram(ope
->peq_regmap
,
383 TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL
,
384 TEGRA210_PEQ_CFG_RAM_SHIFT_DATA
,
385 (i
* TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH
),
386 (u32
*)&biquad_init_shifts
,
387 TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH
);
391 pm_runtime_put_sync(cmpnt
->dev
);
393 snd_soc_add_component_controls(cmpnt
, tegra210_peq_controls
,
394 ARRAY_SIZE(tegra210_peq_controls
));
399 int tegra210_peq_regmap_init(struct platform_device
*pdev
)
401 struct device
*dev
= &pdev
->dev
;
402 struct tegra210_ope
*ope
= dev_get_drvdata(dev
);
403 struct device_node
*child
;
408 child
= of_get_child_by_name(dev
->of_node
, "equalizer");
412 err
= of_address_to_resource(child
, 0, &mem
);
415 dev_err(dev
, "fail to get PEQ resource\n");
419 mem
.flags
= IORESOURCE_MEM
;
420 regs
= devm_ioremap_resource(dev
, &mem
);
422 return PTR_ERR(regs
);
423 ope
->peq_regmap
= devm_regmap_init_mmio(dev
, regs
,
424 &tegra210_peq_regmap_config
);
425 if (IS_ERR(ope
->peq_regmap
)) {
426 dev_err(dev
, "regmap init failed\n");
427 return PTR_ERR(ope
->peq_regmap
);
430 regcache_cache_only(ope
->peq_regmap
, true);