1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // tegra210_peq.c - Tegra210 PEQ driver
4 //
5 // Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
6
7 #include <linux/clk.h>
8 #include <linux/device.h>
9 #include <linux/io.h>
10 #include <linux/module.h>
11 #include <linux/of.h>
12 #include <linux/of_address.h>
13 #include <linux/of_device.h>
14 #include <linux/platform_device.h>
15 #include <linux/pm_runtime.h>
16 #include <linux/regmap.h>
17 #include <sound/core.h>
18 #include <sound/pcm.h>
19 #include <sound/pcm_params.h>
20 #include <sound/soc.h>
21
22 #include "tegra210_ope.h"
23 #include "tegra210_peq.h"
24
25 static const struct reg_default tegra210_peq_reg_defaults[] = {
26 { TEGRA210_PEQ_CFG, 0x00000013},
27 { TEGRA210_PEQ_CFG_RAM_CTRL, 0x00004000},
28 { TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL, 0x00004000},
29 };
30
31 static const u32 biquad_init_gains[TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH] = {
32 1495012349, /* Pre-gain */
33
34 /* Gains : b0, b1, a0, a1, a2 */
35 536870912, -1073741824, 536870912, 2143508246, -1069773768, /* Band-0 */
36 134217728, -265414508, 131766272, 2140402222, -1071252997, /* Band-1 */
37 268435456, -233515765, -33935948, 1839817267, -773826124, /* Band-2 */
38 536870912, -672537913, 139851540, 1886437554, -824433167, /* Band-3 */
39 268435456, -114439279, 173723964, 205743566, 278809729, /* Band-4 */
40 1, 0, 0, 0, 0, /* Band-5 */
41 1, 0, 0, 0, 0, /* Band-6 */
42 1, 0, 0, 0, 0, /* Band-7 */
43 1, 0, 0, 0, 0, /* Band-8 */
44 1, 0, 0, 0, 0, /* Band-9 */
45 1, 0, 0, 0, 0, /* Band-10 */
46 1, 0, 0, 0, 0, /* Band-11 */
47
48 963423114, /* Post-gain */
49 };
50
51 static const u32 biquad_init_shifts[TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH] = {
52 23, /* Pre-shift */
53 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0, /* Shift for bands */
54 28, /* Post-shift */
55 };
56
57 static s32 biquad_coeff_buffer[TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH];
58
tegra210_peq_read_ram(struct regmap * regmap,unsigned int reg_ctrl,unsigned int reg_data,unsigned int ram_offset,unsigned int * data,size_t size)59 static void tegra210_peq_read_ram(struct regmap *regmap, unsigned int reg_ctrl,
60 unsigned int reg_data, unsigned int ram_offset,
61 unsigned int *data, size_t size)
62 {
63 unsigned int val;
64 unsigned int i;
65
66 val = ram_offset & TEGRA210_PEQ_RAM_CTRL_RAM_ADDR_MASK;
67 val |= TEGRA210_PEQ_RAM_CTRL_ADDR_INIT_EN;
68 val |= TEGRA210_PEQ_RAM_CTRL_SEQ_ACCESS_EN;
69 val |= TEGRA210_PEQ_RAM_CTRL_RW_READ;
70
71 regmap_write(regmap, reg_ctrl, val);
72
73 /*
74 * Since all ahub non-io modules work under same ahub clock it is not
75 * necessary to check ahub read busy bit after every read.
76 */
77 for (i = 0; i < size; i++)
78 regmap_read(regmap, reg_data, &data[i]);
79 }
80
tegra210_peq_write_ram(struct regmap * regmap,unsigned int reg_ctrl,unsigned int reg_data,unsigned int ram_offset,unsigned int * data,size_t size)81 static void tegra210_peq_write_ram(struct regmap *regmap, unsigned int reg_ctrl,
82 unsigned int reg_data, unsigned int ram_offset,
83 unsigned int *data, size_t size)
84 {
85 unsigned int val;
86 unsigned int i;
87
88 val = ram_offset & TEGRA210_PEQ_RAM_CTRL_RAM_ADDR_MASK;
89 val |= TEGRA210_PEQ_RAM_CTRL_ADDR_INIT_EN;
90 val |= TEGRA210_PEQ_RAM_CTRL_SEQ_ACCESS_EN;
91 val |= TEGRA210_PEQ_RAM_CTRL_RW_WRITE;
92
93 regmap_write(regmap, reg_ctrl, val);
94
95 for (i = 0; i < size; i++)
96 regmap_write(regmap, reg_data, data[i]);
97 }
98
tegra210_peq_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)99 static int tegra210_peq_get(struct snd_kcontrol *kcontrol,
100 struct snd_ctl_elem_value *ucontrol)
101 {
102 struct soc_mixer_control *mc =
103 (struct soc_mixer_control *)kcontrol->private_value;
104 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
105 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);
106 unsigned int mask = (1 << fls(mc->max)) - 1;
107 unsigned int val;
108
109 regmap_read(ope->peq_regmap, mc->reg, &val);
110
111 ucontrol->value.integer.value[0] = (val >> mc->shift) & mask;
112
113 if (!mc->invert)
114 return 0;
115
116 ucontrol->value.integer.value[0] =
117 mc->max - ucontrol->value.integer.value[0];
118
119 return 0;
120 }
121
tegra210_peq_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)122 static int tegra210_peq_put(struct snd_kcontrol *kcontrol,
123 struct snd_ctl_elem_value *ucontrol)
124 {
125 struct soc_mixer_control *mc =
126 (struct soc_mixer_control *)kcontrol->private_value;
127 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
128 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);
129 unsigned int mask = (1 << fls(mc->max)) - 1;
130 bool change = false;
131 unsigned int val;
132
133 val = (ucontrol->value.integer.value[0] & mask);
134
135 if (mc->invert)
136 val = mc->max - val;
137
138 val = val << mc->shift;
139
140 regmap_update_bits_check(ope->peq_regmap, mc->reg, (mask << mc->shift),
141 val, &change);
142
143 return change ? 1 : 0;
144 }
145
tegra210_peq_ram_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)146 static int tegra210_peq_ram_get(struct snd_kcontrol *kcontrol,
147 struct snd_ctl_elem_value *ucontrol)
148 {
149 struct tegra_soc_bytes *params = (void *)kcontrol->private_value;
150 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
151 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);
152 u32 i, reg_ctrl = params->soc.base;
153 u32 reg_data = reg_ctrl + cmpnt->val_bytes;
154 s32 *data = (s32 *)biquad_coeff_buffer;
155
156 pm_runtime_get_sync(cmpnt->dev);
157
158 tegra210_peq_read_ram(ope->peq_regmap, reg_ctrl, reg_data,
159 params->shift, data, params->soc.num_regs);
160
161 pm_runtime_put_sync(cmpnt->dev);
162
163 for (i = 0; i < params->soc.num_regs; i++)
164 ucontrol->value.integer.value[i] = (long)data[i];
165
166 return 0;
167 }
168
tegra210_peq_ram_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)169 static int tegra210_peq_ram_put(struct snd_kcontrol *kcontrol,
170 struct snd_ctl_elem_value *ucontrol)
171 {
172 struct tegra_soc_bytes *params = (void *)kcontrol->private_value;
173 struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
174 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);
175 u32 i, reg_ctrl = params->soc.base;
176 u32 reg_data = reg_ctrl + cmpnt->val_bytes;
177 s32 *data = (s32 *)biquad_coeff_buffer;
178
179 for (i = 0; i < params->soc.num_regs; i++)
180 data[i] = (s32)ucontrol->value.integer.value[i];
181
182 pm_runtime_get_sync(cmpnt->dev);
183
184 tegra210_peq_write_ram(ope->peq_regmap, reg_ctrl, reg_data,
185 params->shift, data, params->soc.num_regs);
186
187 pm_runtime_put_sync(cmpnt->dev);
188
189 return 1;
190 }
191
tegra210_peq_param_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)192 static int tegra210_peq_param_info(struct snd_kcontrol *kcontrol,
193 struct snd_ctl_elem_info *uinfo)
194 {
195 struct soc_bytes *params = (void *)kcontrol->private_value;
196
197 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
198 uinfo->value.integer.min = INT_MIN;
199 uinfo->value.integer.max = INT_MAX;
200 uinfo->count = params->num_regs;
201
202 return 0;
203 }
204
205 #define TEGRA210_PEQ_GAIN_PARAMS_CTRL(chan) \
206 TEGRA_SOC_BYTES_EXT("PEQ Channel-" #chan " Biquad Gain Params", \
207 TEGRA210_PEQ_CFG_RAM_CTRL, \
208 TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH, \
209 (TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH * chan), 0xffffffff, \
210 tegra210_peq_ram_get, tegra210_peq_ram_put, \
211 tegra210_peq_param_info)
212
213 #define TEGRA210_PEQ_SHIFT_PARAMS_CTRL(chan) \
214 TEGRA_SOC_BYTES_EXT("PEQ Channel-" #chan " Biquad Shift Params", \
215 TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL, \
216 TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH, \
217 (TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH * chan), 0x1f, \
218 tegra210_peq_ram_get, tegra210_peq_ram_put, \
219 tegra210_peq_param_info)
220
221 static const struct snd_kcontrol_new tegra210_peq_controls[] = {
222 SOC_SINGLE_EXT("PEQ Active", TEGRA210_PEQ_CFG,
223 TEGRA210_PEQ_CFG_MODE_SHIFT, 1, 0,
224 tegra210_peq_get, tegra210_peq_put),
225
226 SOC_SINGLE_EXT("PEQ Biquad Stages", TEGRA210_PEQ_CFG,
227 TEGRA210_PEQ_CFG_BIQUAD_STAGES_SHIFT,
228 TEGRA210_PEQ_MAX_BIQUAD_STAGES - 1, 0,
229 tegra210_peq_get, tegra210_peq_put),
230
231 TEGRA210_PEQ_GAIN_PARAMS_CTRL(0),
232 TEGRA210_PEQ_GAIN_PARAMS_CTRL(1),
233 TEGRA210_PEQ_GAIN_PARAMS_CTRL(2),
234 TEGRA210_PEQ_GAIN_PARAMS_CTRL(3),
235 TEGRA210_PEQ_GAIN_PARAMS_CTRL(4),
236 TEGRA210_PEQ_GAIN_PARAMS_CTRL(5),
237 TEGRA210_PEQ_GAIN_PARAMS_CTRL(6),
238 TEGRA210_PEQ_GAIN_PARAMS_CTRL(7),
239
240 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(0),
241 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(1),
242 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(2),
243 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(3),
244 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(4),
245 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(5),
246 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(6),
247 TEGRA210_PEQ_SHIFT_PARAMS_CTRL(7),
248 };
249
tegra210_peq_wr_reg(struct device * dev,unsigned int reg)250 static bool tegra210_peq_wr_reg(struct device *dev, unsigned int reg)
251 {
252 switch (reg) {
253 case TEGRA210_PEQ_SOFT_RESET:
254 case TEGRA210_PEQ_CG:
255 case TEGRA210_PEQ_CFG ... TEGRA210_PEQ_CFG_RAM_SHIFT_DATA:
256 return true;
257 default:
258 return false;
259 }
260 }
261
tegra210_peq_rd_reg(struct device * dev,unsigned int reg)262 static bool tegra210_peq_rd_reg(struct device *dev, unsigned int reg)
263 {
264 if (tegra210_peq_wr_reg(dev, reg))
265 return true;
266
267 switch (reg) {
268 case TEGRA210_PEQ_STATUS:
269 return true;
270 default:
271 return false;
272 }
273 }
274
tegra210_peq_volatile_reg(struct device * dev,unsigned int reg)275 static bool tegra210_peq_volatile_reg(struct device *dev, unsigned int reg)
276 {
277 switch (reg) {
278 case TEGRA210_PEQ_SOFT_RESET:
279 case TEGRA210_PEQ_STATUS:
280 case TEGRA210_PEQ_CFG_RAM_CTRL ... TEGRA210_PEQ_CFG_RAM_SHIFT_DATA:
281 return true;
282 default:
283 return false;
284 }
285 }
286
tegra210_peq_precious_reg(struct device * dev,unsigned int reg)287 static bool tegra210_peq_precious_reg(struct device *dev, unsigned int reg)
288 {
289 switch (reg) {
290 case TEGRA210_PEQ_CFG_RAM_DATA:
291 case TEGRA210_PEQ_CFG_RAM_SHIFT_DATA:
292 return true;
293 default:
294 return false;
295 }
296 }
297
298 static const struct regmap_config tegra210_peq_regmap_config = {
299 .name = "peq",
300 .reg_bits = 32,
301 .reg_stride = 4,
302 .val_bits = 32,
303 .max_register = TEGRA210_PEQ_CFG_RAM_SHIFT_DATA,
304 .writeable_reg = tegra210_peq_wr_reg,
305 .readable_reg = tegra210_peq_rd_reg,
306 .volatile_reg = tegra210_peq_volatile_reg,
307 .precious_reg = tegra210_peq_precious_reg,
308 .reg_defaults = tegra210_peq_reg_defaults,
309 .num_reg_defaults = ARRAY_SIZE(tegra210_peq_reg_defaults),
310 .cache_type = REGCACHE_FLAT,
311 };
312
tegra210_peq_restore(struct regmap * regmap,u32 * biquad_gains,u32 * biquad_shifts)313 void tegra210_peq_restore(struct regmap *regmap, u32 *biquad_gains,
314 u32 *biquad_shifts)
315 {
316 unsigned int i;
317
318 for (i = 0; i < TEGRA210_PEQ_MAX_CHANNELS; i++) {
319 tegra210_peq_write_ram(regmap, TEGRA210_PEQ_CFG_RAM_CTRL,
320 TEGRA210_PEQ_CFG_RAM_DATA,
321 (i * TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH),
322 biquad_gains,
323 TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH);
324
325 tegra210_peq_write_ram(regmap,
326 TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL,
327 TEGRA210_PEQ_CFG_RAM_SHIFT_DATA,
328 (i * TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH),
329 biquad_shifts,
330 TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH);
331
332 }
333 }
334
tegra210_peq_save(struct regmap * regmap,u32 * biquad_gains,u32 * biquad_shifts)335 void tegra210_peq_save(struct regmap *regmap, u32 *biquad_gains,
336 u32 *biquad_shifts)
337 {
338 unsigned int i;
339
340 for (i = 0; i < TEGRA210_PEQ_MAX_CHANNELS; i++) {
341 tegra210_peq_read_ram(regmap,
342 TEGRA210_PEQ_CFG_RAM_CTRL,
343 TEGRA210_PEQ_CFG_RAM_DATA,
344 (i * TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH),
345 biquad_gains,
346 TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH);
347
348 tegra210_peq_read_ram(regmap,
349 TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL,
350 TEGRA210_PEQ_CFG_RAM_SHIFT_DATA,
351 (i * TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH),
352 biquad_shifts,
353 TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH);
354 }
355 }
356
tegra210_peq_component_init(struct snd_soc_component * cmpnt)357 int tegra210_peq_component_init(struct snd_soc_component *cmpnt)
358 {
359 struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);
360 unsigned int i;
361
362 pm_runtime_get_sync(cmpnt->dev);
363 regmap_update_bits(ope->peq_regmap, TEGRA210_PEQ_CFG,
364 TEGRA210_PEQ_CFG_MODE_MASK,
365 0 << TEGRA210_PEQ_CFG_MODE_SHIFT);
366 regmap_update_bits(ope->peq_regmap, TEGRA210_PEQ_CFG,
367 TEGRA210_PEQ_CFG_BIQUAD_STAGES_MASK,
368 (TEGRA210_PEQ_BIQUAD_INIT_STAGE - 1) <<
369 TEGRA210_PEQ_CFG_BIQUAD_STAGES_SHIFT);
370
371 /* Initialize PEQ AHUB RAM with default params */
372 for (i = 0; i < TEGRA210_PEQ_MAX_CHANNELS; i++) {
373
374 /* Set default gain params */
375 tegra210_peq_write_ram(ope->peq_regmap,
376 TEGRA210_PEQ_CFG_RAM_CTRL,
377 TEGRA210_PEQ_CFG_RAM_DATA,
378 (i * TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH),
379 (u32 *)&biquad_init_gains,
380 TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH);
381
382 /* Set default shift params */
383 tegra210_peq_write_ram(ope->peq_regmap,
384 TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL,
385 TEGRA210_PEQ_CFG_RAM_SHIFT_DATA,
386 (i * TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH),
387 (u32 *)&biquad_init_shifts,
388 TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH);
389
390 }
391
392 pm_runtime_put_sync(cmpnt->dev);
393
394 snd_soc_add_component_controls(cmpnt, tegra210_peq_controls,
395 ARRAY_SIZE(tegra210_peq_controls));
396
397 return 0;
398 }
399
tegra210_peq_regmap_init(struct platform_device * pdev)400 int tegra210_peq_regmap_init(struct platform_device *pdev)
401 {
402 struct device *dev = &pdev->dev;
403 struct tegra210_ope *ope = dev_get_drvdata(dev);
404 struct device_node *child;
405 struct resource mem;
406 void __iomem *regs;
407 int err;
408
409 child = of_get_child_by_name(dev->of_node, "equalizer");
410 if (!child)
411 return -ENODEV;
412
413 err = of_address_to_resource(child, 0, &mem);
414 of_node_put(child);
415 if (err < 0) {
416 dev_err(dev, "fail to get PEQ resource\n");
417 return err;
418 }
419
420 mem.flags = IORESOURCE_MEM;
421 regs = devm_ioremap_resource(dev, &mem);
422 if (IS_ERR(regs))
423 return PTR_ERR(regs);
424 ope->peq_regmap = devm_regmap_init_mmio(dev, regs,
425 &tegra210_peq_regmap_config);
426 if (IS_ERR(ope->peq_regmap)) {
427 dev_err(dev, "regmap init failed\n");
428 return PTR_ERR(ope->peq_regmap);
429 }
430
431 regcache_cache_only(ope->peq_regmap, true);
432
433 return 0;
434 }
435