xref: /openbmc/linux/sound/soc/tegra/tegra210_peq.c (revision 7358a803)
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