xref: /linux/sound/soc/tegra/tegra210_peq.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
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/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>
20 
21 #include "tegra210_ope.h"
22 #include "tegra210_peq.h"
23 
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},
28 };
29 
30 static const u32 biquad_init_gains[TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH] = {
31 	1495012349, /* Pre-gain */
32 
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 */
46 
47 	963423114, /* Post-gain */
48 };
49 
50 static const u32 biquad_init_shifts[TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH] = {
51 	23, /* Pre-shift */
52 	30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0, /* Shift for bands */
53 	28, /* Post-shift */
54 };
55 
56 static s32 biquad_coeff_buffer[TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH];
57 
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)
61 {
62 	unsigned int val;
63 	unsigned int i;
64 
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;
69 
70 	regmap_write(regmap, reg_ctrl, val);
71 
72 	/*
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.
75 	 */
76 	for (i = 0; i < size; i++)
77 		regmap_read(regmap, reg_data, &data[i]);
78 }
79 
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)
83 {
84 	unsigned int val;
85 	unsigned int i;
86 
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;
91 
92 	regmap_write(regmap, reg_ctrl, val);
93 
94 	for (i = 0; i < size; i++)
95 		regmap_write(regmap, reg_data, data[i]);
96 }
97 
98 static int tegra210_peq_get(struct snd_kcontrol *kcontrol,
99 			    struct snd_ctl_elem_value *ucontrol)
100 {
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;
106 	unsigned int val;
107 
108 	regmap_read(ope->peq_regmap, mc->reg, &val);
109 
110 	ucontrol->value.integer.value[0] = (val >> mc->shift) & mask;
111 
112 	if (!mc->invert)
113 		return 0;
114 
115 	ucontrol->value.integer.value[0] =
116 		mc->max - ucontrol->value.integer.value[0];
117 
118 	return 0;
119 }
120 
121 static int tegra210_peq_put(struct snd_kcontrol *kcontrol,
122 			    struct snd_ctl_elem_value *ucontrol)
123 {
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;
129 	bool change = false;
130 	unsigned int val;
131 
132 	val = (ucontrol->value.integer.value[0] & mask);
133 
134 	if (mc->invert)
135 		val = mc->max - val;
136 
137 	val = val << mc->shift;
138 
139 	regmap_update_bits_check(ope->peq_regmap, mc->reg, (mask << mc->shift),
140 				 val, &change);
141 
142 	return change ? 1 : 0;
143 }
144 
145 static int tegra210_peq_ram_get(struct snd_kcontrol *kcontrol,
146 				struct snd_ctl_elem_value *ucontrol)
147 {
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;
154 
155 	pm_runtime_get_sync(cmpnt->dev);
156 
157 	tegra210_peq_read_ram(ope->peq_regmap, reg_ctrl, reg_data,
158 			      params->shift, data, params->soc.num_regs);
159 
160 	pm_runtime_put_sync(cmpnt->dev);
161 
162 	for (i = 0; i < params->soc.num_regs; i++)
163 		ucontrol->value.integer.value[i] = (long)data[i];
164 
165 	return 0;
166 }
167 
168 static int tegra210_peq_ram_put(struct snd_kcontrol *kcontrol,
169 				     struct snd_ctl_elem_value *ucontrol)
170 {
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;
177 
178 	for (i = 0; i < params->soc.num_regs; i++)
179 		data[i] = (s32)ucontrol->value.integer.value[i];
180 
181 	pm_runtime_get_sync(cmpnt->dev);
182 
183 	tegra210_peq_write_ram(ope->peq_regmap, reg_ctrl, reg_data,
184 			       params->shift, data, params->soc.num_regs);
185 
186 	pm_runtime_put_sync(cmpnt->dev);
187 
188 	return 1;
189 }
190 
191 static int tegra210_peq_param_info(struct snd_kcontrol *kcontrol,
192 				   struct snd_ctl_elem_info *uinfo)
193 {
194 	struct soc_bytes *params = (void *)kcontrol->private_value;
195 
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;
200 
201 	return 0;
202 }
203 
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)
211 
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)
219 
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),
224 
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),
229 
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),
238 
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),
247 };
248 
249 static bool tegra210_peq_wr_reg(struct device *dev, unsigned int reg)
250 {
251 	switch (reg) {
252 	case TEGRA210_PEQ_SOFT_RESET:
253 	case TEGRA210_PEQ_CG:
254 	case TEGRA210_PEQ_CFG ... TEGRA210_PEQ_CFG_RAM_SHIFT_DATA:
255 		return true;
256 	default:
257 		return false;
258 	}
259 }
260 
261 static bool tegra210_peq_rd_reg(struct device *dev, unsigned int reg)
262 {
263 	if (tegra210_peq_wr_reg(dev, reg))
264 		return true;
265 
266 	switch (reg) {
267 	case TEGRA210_PEQ_STATUS:
268 		return true;
269 	default:
270 		return false;
271 	}
272 }
273 
274 static bool tegra210_peq_volatile_reg(struct device *dev, unsigned int reg)
275 {
276 	switch (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:
280 		return true;
281 	default:
282 		return false;
283 	}
284 }
285 
286 static bool tegra210_peq_precious_reg(struct device *dev, unsigned int reg)
287 {
288 	switch (reg) {
289 	case TEGRA210_PEQ_CFG_RAM_DATA:
290 	case TEGRA210_PEQ_CFG_RAM_SHIFT_DATA:
291 		return true;
292 	default:
293 		return false;
294 	}
295 }
296 
297 static const struct regmap_config tegra210_peq_regmap_config = {
298 	.name			= "peq",
299 	.reg_bits		= 32,
300 	.reg_stride		= 4,
301 	.val_bits		= 32,
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,
310 };
311 
312 void tegra210_peq_restore(struct regmap *regmap, u32 *biquad_gains,
313 			  u32 *biquad_shifts)
314 {
315 	unsigned int i;
316 
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),
321 			biquad_gains,
322 			TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH);
323 
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),
328 			biquad_shifts,
329 			TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH);
330 
331 	}
332 }
333 
334 void tegra210_peq_save(struct regmap *regmap, u32 *biquad_gains,
335 		       u32 *biquad_shifts)
336 {
337 	unsigned int i;
338 
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),
344 			biquad_gains,
345 			TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH);
346 
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),
351 			biquad_shifts,
352 			TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH);
353 	}
354 }
355 
356 int tegra210_peq_component_init(struct snd_soc_component *cmpnt)
357 {
358 	struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt);
359 	unsigned int i;
360 
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);
369 
370 	/* Initialize PEQ AHUB RAM with default params */
371 	for (i = 0; i < TEGRA210_PEQ_MAX_CHANNELS; i++) {
372 
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);
380 
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);
388 
389 	}
390 
391 	pm_runtime_put_sync(cmpnt->dev);
392 
393 	snd_soc_add_component_controls(cmpnt, tegra210_peq_controls,
394 				       ARRAY_SIZE(tegra210_peq_controls));
395 
396 	return 0;
397 }
398 
399 int tegra210_peq_regmap_init(struct platform_device *pdev)
400 {
401 	struct device *dev = &pdev->dev;
402 	struct tegra210_ope *ope = dev_get_drvdata(dev);
403 	struct device_node *child;
404 	struct resource mem;
405 	void __iomem *regs;
406 	int err;
407 
408 	child = of_get_child_by_name(dev->of_node, "equalizer");
409 	if (!child)
410 		return -ENODEV;
411 
412 	err = of_address_to_resource(child, 0, &mem);
413 	of_node_put(child);
414 	if (err < 0) {
415 		dev_err(dev, "fail to get PEQ resource\n");
416 		return err;
417 	}
418 
419 	mem.flags = IORESOURCE_MEM;
420 	regs = devm_ioremap_resource(dev, &mem);
421 	if (IS_ERR(regs))
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);
428 	}
429 
430 	regcache_cache_only(ope->peq_regmap, true);
431 
432 	return 0;
433 }
434