Linux Audio

Check our new training course

Loading...
v6.2
  1// SPDX-License-Identifier: GPL-2.0-only
 
  2//
  3// tegra186_dspk.c - Tegra186 DSPK driver
  4//
  5// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
  6
  7#include <linux/clk.h>
  8#include <linux/device.h>
 
  9#include <linux/module.h>
 10#include <linux/of.h>
 11#include <linux/of_device.h>
 12#include <linux/platform_device.h>
 13#include <linux/pm_runtime.h>
 14#include <linux/regmap.h>
 15#include <sound/core.h>
 16#include <sound/pcm_params.h>
 17#include <sound/soc.h>
 18#include "tegra186_dspk.h"
 19#include "tegra_cif.h"
 20
 21static const struct reg_default tegra186_dspk_reg_defaults[] = {
 22	{ TEGRA186_DSPK_RX_INT_MASK, 0x00000007 },
 23	{ TEGRA186_DSPK_RX_CIF_CTRL, 0x00007700 },
 24	{ TEGRA186_DSPK_CG,	     0x00000001 },
 25	{ TEGRA186_DSPK_CORE_CTRL,   0x00000310 },
 26	{ TEGRA186_DSPK_CODEC_CTRL,  0x03000000 },
 27};
 28
 29static int tegra186_dspk_get_fifo_th(struct snd_kcontrol *kcontrol,
 30				     struct snd_ctl_elem_value *ucontrol)
 31{
 32	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
 33	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
 34
 35	ucontrol->value.integer.value[0] = dspk->rx_fifo_th;
 36
 37	return 0;
 38}
 39
 40static int tegra186_dspk_put_fifo_th(struct snd_kcontrol *kcontrol,
 41				     struct snd_ctl_elem_value *ucontrol)
 42{
 43	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
 44	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
 45	int value = ucontrol->value.integer.value[0];
 46
 47	if (value == dspk->rx_fifo_th)
 48		return 0;
 49
 50	dspk->rx_fifo_th = value;
 51
 52	return 1;
 53}
 54
 55static int tegra186_dspk_get_osr_val(struct snd_kcontrol *kcontrol,
 56				     struct snd_ctl_elem_value *ucontrol)
 57{
 58	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
 59	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
 60
 61	ucontrol->value.enumerated.item[0] = dspk->osr_val;
 62
 63	return 0;
 64}
 65
 66static int tegra186_dspk_put_osr_val(struct snd_kcontrol *kcontrol,
 67				     struct snd_ctl_elem_value *ucontrol)
 68{
 69	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
 70	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
 71	unsigned int value = ucontrol->value.enumerated.item[0];
 72
 73	if (value == dspk->osr_val)
 74		return 0;
 75
 76	dspk->osr_val = value;
 77
 78	return 1;
 79}
 80
 81static int tegra186_dspk_get_pol_sel(struct snd_kcontrol *kcontrol,
 82				     struct snd_ctl_elem_value *ucontrol)
 83{
 84	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
 85	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
 86
 87	ucontrol->value.enumerated.item[0] = dspk->lrsel;
 88
 89	return 0;
 90}
 91
 92static int tegra186_dspk_put_pol_sel(struct snd_kcontrol *kcontrol,
 93				     struct snd_ctl_elem_value *ucontrol)
 94{
 95	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
 96	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
 97	unsigned int value = ucontrol->value.enumerated.item[0];
 98
 99	if (value == dspk->lrsel)
100		return 0;
101
102	dspk->lrsel = value;
103
104	return 1;
105}
106
107static int tegra186_dspk_get_ch_sel(struct snd_kcontrol *kcontrol,
108				    struct snd_ctl_elem_value *ucontrol)
109{
110	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
111	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
112
113	ucontrol->value.enumerated.item[0] = dspk->ch_sel;
114
115	return 0;
116}
117
118static int tegra186_dspk_put_ch_sel(struct snd_kcontrol *kcontrol,
119				    struct snd_ctl_elem_value *ucontrol)
120{
121	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
122	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
123	unsigned int value = ucontrol->value.enumerated.item[0];
124
125	if (value == dspk->ch_sel)
126		return 0;
127
128	dspk->ch_sel = value;
129
130	return 1;
131}
132
133static int tegra186_dspk_get_mono_to_stereo(struct snd_kcontrol *kcontrol,
134					    struct snd_ctl_elem_value *ucontrol)
135{
136	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
137	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
138
139	ucontrol->value.enumerated.item[0] = dspk->mono_to_stereo;
140
141	return 0;
142}
143
144static int tegra186_dspk_put_mono_to_stereo(struct snd_kcontrol *kcontrol,
145					    struct snd_ctl_elem_value *ucontrol)
146{
147	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
148	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
149	unsigned int value = ucontrol->value.enumerated.item[0];
150
151	if (value == dspk->mono_to_stereo)
152		return 0;
153
154	dspk->mono_to_stereo = value;
155
156	return 1;
157}
158
159static int tegra186_dspk_get_stereo_to_mono(struct snd_kcontrol *kcontrol,
160					    struct snd_ctl_elem_value *ucontrol)
161{
162	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
163	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
164
165	ucontrol->value.enumerated.item[0] = dspk->stereo_to_mono;
166
167	return 0;
168}
169
170static int tegra186_dspk_put_stereo_to_mono(struct snd_kcontrol *kcontrol,
171					    struct snd_ctl_elem_value *ucontrol)
172{
173	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
174	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
175	unsigned int value = ucontrol->value.enumerated.item[0];
176
177	if (value == dspk->stereo_to_mono)
178		return 0;
179
180	dspk->stereo_to_mono = value;
181
182	return 1;
183}
184
185static int __maybe_unused tegra186_dspk_runtime_suspend(struct device *dev)
186{
187	struct tegra186_dspk *dspk = dev_get_drvdata(dev);
188
189	regcache_cache_only(dspk->regmap, true);
190	regcache_mark_dirty(dspk->regmap);
191
192	clk_disable_unprepare(dspk->clk_dspk);
193
194	return 0;
195}
196
197static int __maybe_unused tegra186_dspk_runtime_resume(struct device *dev)
198{
199	struct tegra186_dspk *dspk = dev_get_drvdata(dev);
200	int err;
201
202	err = clk_prepare_enable(dspk->clk_dspk);
203	if (err) {
204		dev_err(dev, "failed to enable DSPK clock, err: %d\n", err);
205		return err;
206	}
207
208	regcache_cache_only(dspk->regmap, false);
209	regcache_sync(dspk->regmap);
210
211	return 0;
212}
213
214static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream,
215				   struct snd_pcm_hw_params *params,
216				   struct snd_soc_dai *dai)
217{
218	struct tegra186_dspk *dspk = snd_soc_dai_get_drvdata(dai);
219	unsigned int channels, srate, dspk_clk;
220	struct device *dev = dai->dev;
221	struct tegra_cif_conf cif_conf;
222	unsigned int max_th;
223	int err;
224
225	memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
226
227	channels = params_channels(params);
228	cif_conf.audio_ch = channels;
229
230	/* Client channel */
231	switch (dspk->ch_sel) {
232	case DSPK_CH_SELECT_LEFT:
233	case DSPK_CH_SELECT_RIGHT:
234		cif_conf.client_ch = 1;
235		break;
236	case DSPK_CH_SELECT_STEREO:
237		cif_conf.client_ch = 2;
238		break;
239	default:
240		dev_err(dev, "Invalid DSPK client channels\n");
241		return -EINVAL;
242	}
243
244	cif_conf.client_bits = TEGRA_ACIF_BITS_24;
245
246	switch (params_format(params)) {
247	case SNDRV_PCM_FORMAT_S16_LE:
248		cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
 
249		break;
250	case SNDRV_PCM_FORMAT_S32_LE:
251		cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
 
252		break;
253	default:
254		dev_err(dev, "unsupported format!\n");
255		return -EOPNOTSUPP;
256	}
257
258	srate = params_rate(params);
259
260	/* RX FIFO threshold in terms of frames */
261	max_th = (TEGRA186_DSPK_RX_FIFO_DEPTH / cif_conf.audio_ch) - 1;
262
263	if (dspk->rx_fifo_th > max_th)
264		dspk->rx_fifo_th = max_th;
265
266	cif_conf.threshold = dspk->rx_fifo_th;
267	cif_conf.mono_conv = dspk->mono_to_stereo;
268	cif_conf.stereo_conv = dspk->stereo_to_mono;
269
270	tegra_set_cif(dspk->regmap, TEGRA186_DSPK_RX_CIF_CTRL,
271		      &cif_conf);
272
273	/*
274	 * DSPK clock and PDM codec clock should be synchronous with 4:1 ratio,
275	 * this is because it takes 4 clock cycles to send out one sample to
276	 * codec by sigma delta modulator. Finally the clock rate is a multiple
277	 * of 'Over Sampling Ratio', 'Sample Rate' and 'Interface Clock Ratio'.
278	 */
279	dspk_clk = (DSPK_OSR_FACTOR << dspk->osr_val) * srate * DSPK_CLK_RATIO;
280
281	err = clk_set_rate(dspk->clk_dspk, dspk_clk);
282	if (err) {
283		dev_err(dev, "can't set DSPK clock rate %u, err: %d\n",
284			dspk_clk, err);
285
286		return err;
287	}
288
289	regmap_update_bits(dspk->regmap,
290			   /* Reg */
291			   TEGRA186_DSPK_CORE_CTRL,
292			   /* Mask */
293			   TEGRA186_DSPK_OSR_MASK |
294			   TEGRA186_DSPK_CHANNEL_SELECT_MASK |
295			   TEGRA186_DSPK_CTRL_LRSEL_POLARITY_MASK,
296			   /* Value */
297			   (dspk->osr_val << DSPK_OSR_SHIFT) |
298			   ((dspk->ch_sel + 1) << CH_SEL_SHIFT) |
299			   (dspk->lrsel << LRSEL_POL_SHIFT));
300
301	return 0;
302}
303
304static const struct snd_soc_dai_ops tegra186_dspk_dai_ops = {
305	.hw_params	= tegra186_dspk_hw_params,
306};
307
308static struct snd_soc_dai_driver tegra186_dspk_dais[] = {
309	{
310	    .name = "DSPK-CIF",
311	    .playback = {
312		.stream_name = "CIF-Playback",
313		.channels_min = 1,
314		.channels_max = 2,
315		.rates = SNDRV_PCM_RATE_8000_48000,
316		.formats = SNDRV_PCM_FMTBIT_S16_LE |
317			   SNDRV_PCM_FMTBIT_S32_LE,
318	    },
319	},
320	{
321	    .name = "DSPK-DAP",
322	    .playback = {
323		.stream_name = "DAP-Playback",
324		.channels_min = 1,
325		.channels_max = 2,
326		.rates = SNDRV_PCM_RATE_8000_48000,
327		.formats = SNDRV_PCM_FMTBIT_S16_LE |
328			   SNDRV_PCM_FMTBIT_S32_LE,
329	    },
330	    .ops = &tegra186_dspk_dai_ops,
331	    .symmetric_rate = 1,
332	},
333};
334
335static const struct snd_soc_dapm_widget tegra186_dspk_widgets[] = {
336	SND_SOC_DAPM_AIF_IN("RX", NULL, 0, TEGRA186_DSPK_ENABLE, 0, 0),
337	SND_SOC_DAPM_SPK("SPK", NULL),
338};
339
340static const struct snd_soc_dapm_route tegra186_dspk_routes[] = {
341	{ "XBAR-Playback",	NULL,	"XBAR-TX" },
342	{ "CIF-Playback",	NULL,	"XBAR-Playback" },
343	{ "RX",			NULL,	"CIF-Playback" },
344	{ "DAP-Playback",	NULL,	"RX" },
345	{ "SPK",		NULL,	"DAP-Playback" },
346};
347
348static const char * const tegra186_dspk_ch_sel_text[] = {
349	"Left", "Right", "Stereo",
350};
351
352static const struct soc_enum tegra186_dspk_ch_sel_enum =
353	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_ch_sel_text),
354			tegra186_dspk_ch_sel_text);
355
356static const char * const tegra186_dspk_osr_text[] = {
357	"OSR_32", "OSR_64", "OSR_128", "OSR_256",
358};
359
360static const struct soc_enum tegra186_dspk_osr_enum =
361	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_osr_text),
362			tegra186_dspk_osr_text);
363
364static const char * const tegra186_dspk_lrsel_text[] = {
365	"Left", "Right",
366};
367
368static const char * const tegra186_dspk_mono_conv_text[] = {
369	"Zero", "Copy",
370};
371
372static const struct soc_enum tegra186_dspk_mono_conv_enum =
373	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
374			ARRAY_SIZE(tegra186_dspk_mono_conv_text),
375			tegra186_dspk_mono_conv_text);
376
377static const char * const tegra186_dspk_stereo_conv_text[] = {
378	"CH0", "CH1", "AVG",
379};
380
381static const struct soc_enum tegra186_dspk_stereo_conv_enum =
382	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
383			ARRAY_SIZE(tegra186_dspk_stereo_conv_text),
384			tegra186_dspk_stereo_conv_text);
385
386static const struct soc_enum tegra186_dspk_lrsel_enum =
387	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_lrsel_text),
388			tegra186_dspk_lrsel_text);
389
390static const struct snd_kcontrol_new tegrat186_dspk_controls[] = {
391	SOC_SINGLE_EXT("FIFO Threshold", SND_SOC_NOPM, 0,
392		       TEGRA186_DSPK_RX_FIFO_DEPTH - 1, 0,
393		       tegra186_dspk_get_fifo_th, tegra186_dspk_put_fifo_th),
394	SOC_ENUM_EXT("OSR Value", tegra186_dspk_osr_enum,
395		     tegra186_dspk_get_osr_val, tegra186_dspk_put_osr_val),
396	SOC_ENUM_EXT("LR Polarity Select", tegra186_dspk_lrsel_enum,
397		     tegra186_dspk_get_pol_sel, tegra186_dspk_put_pol_sel),
398	SOC_ENUM_EXT("Channel Select", tegra186_dspk_ch_sel_enum,
399		     tegra186_dspk_get_ch_sel, tegra186_dspk_put_ch_sel),
400	SOC_ENUM_EXT("Mono To Stereo", tegra186_dspk_mono_conv_enum,
401		     tegra186_dspk_get_mono_to_stereo,
402		     tegra186_dspk_put_mono_to_stereo),
403	SOC_ENUM_EXT("Stereo To Mono", tegra186_dspk_stereo_conv_enum,
404		     tegra186_dspk_get_stereo_to_mono,
405		     tegra186_dspk_put_stereo_to_mono),
406};
407
408static const struct snd_soc_component_driver tegra186_dspk_cmpnt = {
409	.dapm_widgets = tegra186_dspk_widgets,
410	.num_dapm_widgets = ARRAY_SIZE(tegra186_dspk_widgets),
411	.dapm_routes = tegra186_dspk_routes,
412	.num_dapm_routes = ARRAY_SIZE(tegra186_dspk_routes),
413	.controls = tegrat186_dspk_controls,
414	.num_controls = ARRAY_SIZE(tegrat186_dspk_controls),
415};
416
417static bool tegra186_dspk_wr_reg(struct device *dev, unsigned int reg)
418{
419	switch (reg) {
420	case TEGRA186_DSPK_RX_INT_MASK ... TEGRA186_DSPK_RX_CIF_CTRL:
421	case TEGRA186_DSPK_ENABLE ... TEGRA186_DSPK_CG:
422	case TEGRA186_DSPK_CORE_CTRL ... TEGRA186_DSPK_CODEC_CTRL:
423		return true;
424	default:
425		return false;
426	}
427}
428
429static bool tegra186_dspk_rd_reg(struct device *dev, unsigned int reg)
430{
431	if (tegra186_dspk_wr_reg(dev, reg))
432		return true;
433
434	switch (reg) {
435	case TEGRA186_DSPK_RX_STATUS:
436	case TEGRA186_DSPK_RX_INT_STATUS:
437	case TEGRA186_DSPK_STATUS:
438	case TEGRA186_DSPK_INT_STATUS:
439		return true;
440	default:
441		return false;
442	}
443}
444
445static bool tegra186_dspk_volatile_reg(struct device *dev, unsigned int reg)
446{
447	switch (reg) {
448	case TEGRA186_DSPK_RX_STATUS:
449	case TEGRA186_DSPK_RX_INT_STATUS:
450	case TEGRA186_DSPK_STATUS:
451	case TEGRA186_DSPK_INT_STATUS:
452		return true;
453	default:
454		return false;
455	}
456}
457
458static const struct regmap_config tegra186_dspk_regmap = {
459	.reg_bits		= 32,
460	.reg_stride		= 4,
461	.val_bits		= 32,
462	.max_register		= TEGRA186_DSPK_CODEC_CTRL,
463	.writeable_reg		= tegra186_dspk_wr_reg,
464	.readable_reg		= tegra186_dspk_rd_reg,
465	.volatile_reg		= tegra186_dspk_volatile_reg,
466	.reg_defaults		= tegra186_dspk_reg_defaults,
467	.num_reg_defaults	= ARRAY_SIZE(tegra186_dspk_reg_defaults),
468	.cache_type		= REGCACHE_FLAT,
469};
470
471static const struct of_device_id tegra186_dspk_of_match[] = {
472	{ .compatible = "nvidia,tegra186-dspk" },
473	{},
474};
475MODULE_DEVICE_TABLE(of, tegra186_dspk_of_match);
476
477static int tegra186_dspk_platform_probe(struct platform_device *pdev)
478{
479	struct device *dev = &pdev->dev;
480	struct tegra186_dspk *dspk;
481	void __iomem *regs;
482	int err;
483
484	dspk = devm_kzalloc(dev, sizeof(*dspk), GFP_KERNEL);
485	if (!dspk)
486		return -ENOMEM;
487
488	dspk->osr_val = DSPK_OSR_64;
489	dspk->lrsel = DSPK_LRSEL_LEFT;
490	dspk->ch_sel = DSPK_CH_SELECT_STEREO;
491	dspk->mono_to_stereo = 0; /* "Zero" */
492
493	dev_set_drvdata(dev, dspk);
494
495	dspk->clk_dspk = devm_clk_get(dev, "dspk");
496	if (IS_ERR(dspk->clk_dspk)) {
497		dev_err(dev, "can't retrieve DSPK clock\n");
498		return PTR_ERR(dspk->clk_dspk);
499	}
500
501	regs = devm_platform_ioremap_resource(pdev, 0);
502	if (IS_ERR(regs))
503		return PTR_ERR(regs);
504
505	dspk->regmap = devm_regmap_init_mmio(dev, regs, &tegra186_dspk_regmap);
506	if (IS_ERR(dspk->regmap)) {
507		dev_err(dev, "regmap init failed\n");
508		return PTR_ERR(dspk->regmap);
509	}
510
511	regcache_cache_only(dspk->regmap, true);
512
513	err = devm_snd_soc_register_component(dev, &tegra186_dspk_cmpnt,
514					      tegra186_dspk_dais,
515					      ARRAY_SIZE(tegra186_dspk_dais));
516	if (err) {
517		dev_err(dev, "can't register DSPK component, err: %d\n",
518			err);
519		return err;
520	}
521
522	pm_runtime_enable(dev);
523
524	return 0;
525}
526
527static int tegra186_dspk_platform_remove(struct platform_device *pdev)
528{
529	pm_runtime_disable(&pdev->dev);
530
531	return 0;
532}
533
534static const struct dev_pm_ops tegra186_dspk_pm_ops = {
535	SET_RUNTIME_PM_OPS(tegra186_dspk_runtime_suspend,
536			   tegra186_dspk_runtime_resume, NULL)
537	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
538				pm_runtime_force_resume)
539};
540
541static struct platform_driver tegra186_dspk_driver = {
542	.driver = {
543		.name = "tegra186-dspk",
544		.of_match_table = tegra186_dspk_of_match,
545		.pm = &tegra186_dspk_pm_ops,
546	},
547	.probe = tegra186_dspk_platform_probe,
548	.remove = tegra186_dspk_platform_remove,
549};
550module_platform_driver(tegra186_dspk_driver);
551
552MODULE_AUTHOR("Mohan Kumar <mkumard@nvidia.com>");
553MODULE_AUTHOR("Sameer Pujar <spujar@nvidia.com>");
554MODULE_DESCRIPTION("Tegra186 ASoC DSPK driver");
555MODULE_LICENSE("GPL v2");
v6.9.4
  1// SPDX-License-Identifier: GPL-2.0-only
  2// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
  3//
  4// tegra186_dspk.c - Tegra186 DSPK driver
 
 
  5
  6#include <linux/clk.h>
  7#include <linux/device.h>
  8#include <linux/mod_devicetable.h>
  9#include <linux/module.h>
 10#include <linux/of.h>
 
 11#include <linux/platform_device.h>
 12#include <linux/pm_runtime.h>
 13#include <linux/regmap.h>
 14#include <sound/core.h>
 15#include <sound/pcm_params.h>
 16#include <sound/soc.h>
 17#include "tegra186_dspk.h"
 18#include "tegra_cif.h"
 19
 20static const struct reg_default tegra186_dspk_reg_defaults[] = {
 21	{ TEGRA186_DSPK_RX_INT_MASK, 0x00000007 },
 22	{ TEGRA186_DSPK_RX_CIF_CTRL, 0x00007700 },
 23	{ TEGRA186_DSPK_CG,	     0x00000001 },
 24	{ TEGRA186_DSPK_CORE_CTRL,   0x00000310 },
 25	{ TEGRA186_DSPK_CODEC_CTRL,  0x03000000 },
 26};
 27
 28static int tegra186_dspk_get_fifo_th(struct snd_kcontrol *kcontrol,
 29				     struct snd_ctl_elem_value *ucontrol)
 30{
 31	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
 32	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
 33
 34	ucontrol->value.integer.value[0] = dspk->rx_fifo_th;
 35
 36	return 0;
 37}
 38
 39static int tegra186_dspk_put_fifo_th(struct snd_kcontrol *kcontrol,
 40				     struct snd_ctl_elem_value *ucontrol)
 41{
 42	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
 43	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
 44	int value = ucontrol->value.integer.value[0];
 45
 46	if (value == dspk->rx_fifo_th)
 47		return 0;
 48
 49	dspk->rx_fifo_th = value;
 50
 51	return 1;
 52}
 53
 54static int tegra186_dspk_get_osr_val(struct snd_kcontrol *kcontrol,
 55				     struct snd_ctl_elem_value *ucontrol)
 56{
 57	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
 58	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
 59
 60	ucontrol->value.enumerated.item[0] = dspk->osr_val;
 61
 62	return 0;
 63}
 64
 65static int tegra186_dspk_put_osr_val(struct snd_kcontrol *kcontrol,
 66				     struct snd_ctl_elem_value *ucontrol)
 67{
 68	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
 69	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
 70	unsigned int value = ucontrol->value.enumerated.item[0];
 71
 72	if (value == dspk->osr_val)
 73		return 0;
 74
 75	dspk->osr_val = value;
 76
 77	return 1;
 78}
 79
 80static int tegra186_dspk_get_pol_sel(struct snd_kcontrol *kcontrol,
 81				     struct snd_ctl_elem_value *ucontrol)
 82{
 83	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
 84	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
 85
 86	ucontrol->value.enumerated.item[0] = dspk->lrsel;
 87
 88	return 0;
 89}
 90
 91static int tegra186_dspk_put_pol_sel(struct snd_kcontrol *kcontrol,
 92				     struct snd_ctl_elem_value *ucontrol)
 93{
 94	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
 95	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
 96	unsigned int value = ucontrol->value.enumerated.item[0];
 97
 98	if (value == dspk->lrsel)
 99		return 0;
100
101	dspk->lrsel = value;
102
103	return 1;
104}
105
106static int tegra186_dspk_get_ch_sel(struct snd_kcontrol *kcontrol,
107				    struct snd_ctl_elem_value *ucontrol)
108{
109	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
110	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
111
112	ucontrol->value.enumerated.item[0] = dspk->ch_sel;
113
114	return 0;
115}
116
117static int tegra186_dspk_put_ch_sel(struct snd_kcontrol *kcontrol,
118				    struct snd_ctl_elem_value *ucontrol)
119{
120	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
121	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
122	unsigned int value = ucontrol->value.enumerated.item[0];
123
124	if (value == dspk->ch_sel)
125		return 0;
126
127	dspk->ch_sel = value;
128
129	return 1;
130}
131
132static int tegra186_dspk_get_mono_to_stereo(struct snd_kcontrol *kcontrol,
133					    struct snd_ctl_elem_value *ucontrol)
134{
135	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
136	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
137
138	ucontrol->value.enumerated.item[0] = dspk->mono_to_stereo;
139
140	return 0;
141}
142
143static int tegra186_dspk_put_mono_to_stereo(struct snd_kcontrol *kcontrol,
144					    struct snd_ctl_elem_value *ucontrol)
145{
146	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
147	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
148	unsigned int value = ucontrol->value.enumerated.item[0];
149
150	if (value == dspk->mono_to_stereo)
151		return 0;
152
153	dspk->mono_to_stereo = value;
154
155	return 1;
156}
157
158static int tegra186_dspk_get_stereo_to_mono(struct snd_kcontrol *kcontrol,
159					    struct snd_ctl_elem_value *ucontrol)
160{
161	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
162	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
163
164	ucontrol->value.enumerated.item[0] = dspk->stereo_to_mono;
165
166	return 0;
167}
168
169static int tegra186_dspk_put_stereo_to_mono(struct snd_kcontrol *kcontrol,
170					    struct snd_ctl_elem_value *ucontrol)
171{
172	struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
173	struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
174	unsigned int value = ucontrol->value.enumerated.item[0];
175
176	if (value == dspk->stereo_to_mono)
177		return 0;
178
179	dspk->stereo_to_mono = value;
180
181	return 1;
182}
183
184static int __maybe_unused tegra186_dspk_runtime_suspend(struct device *dev)
185{
186	struct tegra186_dspk *dspk = dev_get_drvdata(dev);
187
188	regcache_cache_only(dspk->regmap, true);
189	regcache_mark_dirty(dspk->regmap);
190
191	clk_disable_unprepare(dspk->clk_dspk);
192
193	return 0;
194}
195
196static int __maybe_unused tegra186_dspk_runtime_resume(struct device *dev)
197{
198	struct tegra186_dspk *dspk = dev_get_drvdata(dev);
199	int err;
200
201	err = clk_prepare_enable(dspk->clk_dspk);
202	if (err) {
203		dev_err(dev, "failed to enable DSPK clock, err: %d\n", err);
204		return err;
205	}
206
207	regcache_cache_only(dspk->regmap, false);
208	regcache_sync(dspk->regmap);
209
210	return 0;
211}
212
213static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream,
214				   struct snd_pcm_hw_params *params,
215				   struct snd_soc_dai *dai)
216{
217	struct tegra186_dspk *dspk = snd_soc_dai_get_drvdata(dai);
218	unsigned int channels, srate, dspk_clk;
219	struct device *dev = dai->dev;
220	struct tegra_cif_conf cif_conf;
221	unsigned int max_th;
222	int err;
223
224	memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
225
226	channels = params_channels(params);
227	cif_conf.audio_ch = channels;
228
229	/* Client channel */
230	switch (dspk->ch_sel) {
231	case DSPK_CH_SELECT_LEFT:
232	case DSPK_CH_SELECT_RIGHT:
233		cif_conf.client_ch = 1;
234		break;
235	case DSPK_CH_SELECT_STEREO:
236		cif_conf.client_ch = 2;
237		break;
238	default:
239		dev_err(dev, "Invalid DSPK client channels\n");
240		return -EINVAL;
241	}
242
 
 
243	switch (params_format(params)) {
244	case SNDRV_PCM_FORMAT_S16_LE:
245		cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
246		cif_conf.client_bits = TEGRA_ACIF_BITS_16;
247		break;
248	case SNDRV_PCM_FORMAT_S32_LE:
249		cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
250		cif_conf.client_bits = TEGRA_ACIF_BITS_24;
251		break;
252	default:
253		dev_err(dev, "unsupported format!\n");
254		return -EOPNOTSUPP;
255	}
256
257	srate = params_rate(params);
258
259	/* RX FIFO threshold in terms of frames */
260	max_th = (TEGRA186_DSPK_RX_FIFO_DEPTH / cif_conf.audio_ch) - 1;
261
262	if (dspk->rx_fifo_th > max_th)
263		dspk->rx_fifo_th = max_th;
264
265	cif_conf.threshold = dspk->rx_fifo_th;
266	cif_conf.mono_conv = dspk->mono_to_stereo;
267	cif_conf.stereo_conv = dspk->stereo_to_mono;
268
269	tegra_set_cif(dspk->regmap, TEGRA186_DSPK_RX_CIF_CTRL,
270		      &cif_conf);
271
272	/*
273	 * DSPK clock and PDM codec clock should be synchronous with 4:1 ratio,
274	 * this is because it takes 4 clock cycles to send out one sample to
275	 * codec by sigma delta modulator. Finally the clock rate is a multiple
276	 * of 'Over Sampling Ratio', 'Sample Rate' and 'Interface Clock Ratio'.
277	 */
278	dspk_clk = (DSPK_OSR_FACTOR << dspk->osr_val) * srate * DSPK_CLK_RATIO;
279
280	err = clk_set_rate(dspk->clk_dspk, dspk_clk);
281	if (err) {
282		dev_err(dev, "can't set DSPK clock rate %u, err: %d\n",
283			dspk_clk, err);
284
285		return err;
286	}
287
288	regmap_update_bits(dspk->regmap,
289			   /* Reg */
290			   TEGRA186_DSPK_CORE_CTRL,
291			   /* Mask */
292			   TEGRA186_DSPK_OSR_MASK |
293			   TEGRA186_DSPK_CHANNEL_SELECT_MASK |
294			   TEGRA186_DSPK_CTRL_LRSEL_POLARITY_MASK,
295			   /* Value */
296			   (dspk->osr_val << DSPK_OSR_SHIFT) |
297			   ((dspk->ch_sel + 1) << CH_SEL_SHIFT) |
298			   (dspk->lrsel << LRSEL_POL_SHIFT));
299
300	return 0;
301}
302
303static const struct snd_soc_dai_ops tegra186_dspk_dai_ops = {
304	.hw_params	= tegra186_dspk_hw_params,
305};
306
307static struct snd_soc_dai_driver tegra186_dspk_dais[] = {
308	{
309	    .name = "DSPK-CIF",
310	    .playback = {
311		.stream_name = "CIF-Playback",
312		.channels_min = 1,
313		.channels_max = 2,
314		.rates = SNDRV_PCM_RATE_8000_48000,
315		.formats = SNDRV_PCM_FMTBIT_S16_LE |
316			   SNDRV_PCM_FMTBIT_S32_LE,
317	    },
318	},
319	{
320	    .name = "DSPK-DAP",
321	    .playback = {
322		.stream_name = "DAP-Playback",
323		.channels_min = 1,
324		.channels_max = 2,
325		.rates = SNDRV_PCM_RATE_8000_48000,
326		.formats = SNDRV_PCM_FMTBIT_S16_LE |
327			   SNDRV_PCM_FMTBIT_S32_LE,
328	    },
329	    .ops = &tegra186_dspk_dai_ops,
330	    .symmetric_rate = 1,
331	},
332};
333
334static const struct snd_soc_dapm_widget tegra186_dspk_widgets[] = {
335	SND_SOC_DAPM_AIF_IN("RX", NULL, 0, TEGRA186_DSPK_ENABLE, 0, 0),
336	SND_SOC_DAPM_SPK("SPK", NULL),
337};
338
339static const struct snd_soc_dapm_route tegra186_dspk_routes[] = {
340	{ "XBAR-Playback",	NULL,	"XBAR-TX" },
341	{ "CIF-Playback",	NULL,	"XBAR-Playback" },
342	{ "RX",			NULL,	"CIF-Playback" },
343	{ "DAP-Playback",	NULL,	"RX" },
344	{ "SPK",		NULL,	"DAP-Playback" },
345};
346
347static const char * const tegra186_dspk_ch_sel_text[] = {
348	"Left", "Right", "Stereo",
349};
350
351static const struct soc_enum tegra186_dspk_ch_sel_enum =
352	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_ch_sel_text),
353			tegra186_dspk_ch_sel_text);
354
355static const char * const tegra186_dspk_osr_text[] = {
356	"OSR_32", "OSR_64", "OSR_128", "OSR_256",
357};
358
359static const struct soc_enum tegra186_dspk_osr_enum =
360	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_osr_text),
361			tegra186_dspk_osr_text);
362
363static const char * const tegra186_dspk_lrsel_text[] = {
364	"Left", "Right",
365};
366
367static const char * const tegra186_dspk_mono_conv_text[] = {
368	"Zero", "Copy",
369};
370
371static const struct soc_enum tegra186_dspk_mono_conv_enum =
372	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
373			ARRAY_SIZE(tegra186_dspk_mono_conv_text),
374			tegra186_dspk_mono_conv_text);
375
376static const char * const tegra186_dspk_stereo_conv_text[] = {
377	"CH0", "CH1", "AVG",
378};
379
380static const struct soc_enum tegra186_dspk_stereo_conv_enum =
381	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
382			ARRAY_SIZE(tegra186_dspk_stereo_conv_text),
383			tegra186_dspk_stereo_conv_text);
384
385static const struct soc_enum tegra186_dspk_lrsel_enum =
386	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tegra186_dspk_lrsel_text),
387			tegra186_dspk_lrsel_text);
388
389static const struct snd_kcontrol_new tegrat186_dspk_controls[] = {
390	SOC_SINGLE_EXT("FIFO Threshold", SND_SOC_NOPM, 0,
391		       TEGRA186_DSPK_RX_FIFO_DEPTH - 1, 0,
392		       tegra186_dspk_get_fifo_th, tegra186_dspk_put_fifo_th),
393	SOC_ENUM_EXT("OSR Value", tegra186_dspk_osr_enum,
394		     tegra186_dspk_get_osr_val, tegra186_dspk_put_osr_val),
395	SOC_ENUM_EXT("LR Polarity Select", tegra186_dspk_lrsel_enum,
396		     tegra186_dspk_get_pol_sel, tegra186_dspk_put_pol_sel),
397	SOC_ENUM_EXT("Channel Select", tegra186_dspk_ch_sel_enum,
398		     tegra186_dspk_get_ch_sel, tegra186_dspk_put_ch_sel),
399	SOC_ENUM_EXT("Mono To Stereo", tegra186_dspk_mono_conv_enum,
400		     tegra186_dspk_get_mono_to_stereo,
401		     tegra186_dspk_put_mono_to_stereo),
402	SOC_ENUM_EXT("Stereo To Mono", tegra186_dspk_stereo_conv_enum,
403		     tegra186_dspk_get_stereo_to_mono,
404		     tegra186_dspk_put_stereo_to_mono),
405};
406
407static const struct snd_soc_component_driver tegra186_dspk_cmpnt = {
408	.dapm_widgets = tegra186_dspk_widgets,
409	.num_dapm_widgets = ARRAY_SIZE(tegra186_dspk_widgets),
410	.dapm_routes = tegra186_dspk_routes,
411	.num_dapm_routes = ARRAY_SIZE(tegra186_dspk_routes),
412	.controls = tegrat186_dspk_controls,
413	.num_controls = ARRAY_SIZE(tegrat186_dspk_controls),
414};
415
416static bool tegra186_dspk_wr_reg(struct device *dev, unsigned int reg)
417{
418	switch (reg) {
419	case TEGRA186_DSPK_RX_INT_MASK ... TEGRA186_DSPK_RX_CIF_CTRL:
420	case TEGRA186_DSPK_ENABLE ... TEGRA186_DSPK_CG:
421	case TEGRA186_DSPK_CORE_CTRL ... TEGRA186_DSPK_CODEC_CTRL:
422		return true;
423	default:
424		return false;
425	}
426}
427
428static bool tegra186_dspk_rd_reg(struct device *dev, unsigned int reg)
429{
430	if (tegra186_dspk_wr_reg(dev, reg))
431		return true;
432
433	switch (reg) {
434	case TEGRA186_DSPK_RX_STATUS:
435	case TEGRA186_DSPK_RX_INT_STATUS:
436	case TEGRA186_DSPK_STATUS:
437	case TEGRA186_DSPK_INT_STATUS:
438		return true;
439	default:
440		return false;
441	}
442}
443
444static bool tegra186_dspk_volatile_reg(struct device *dev, unsigned int reg)
445{
446	switch (reg) {
447	case TEGRA186_DSPK_RX_STATUS:
448	case TEGRA186_DSPK_RX_INT_STATUS:
449	case TEGRA186_DSPK_STATUS:
450	case TEGRA186_DSPK_INT_STATUS:
451		return true;
452	default:
453		return false;
454	}
455}
456
457static const struct regmap_config tegra186_dspk_regmap = {
458	.reg_bits		= 32,
459	.reg_stride		= 4,
460	.val_bits		= 32,
461	.max_register		= TEGRA186_DSPK_CODEC_CTRL,
462	.writeable_reg		= tegra186_dspk_wr_reg,
463	.readable_reg		= tegra186_dspk_rd_reg,
464	.volatile_reg		= tegra186_dspk_volatile_reg,
465	.reg_defaults		= tegra186_dspk_reg_defaults,
466	.num_reg_defaults	= ARRAY_SIZE(tegra186_dspk_reg_defaults),
467	.cache_type		= REGCACHE_FLAT,
468};
469
470static const struct of_device_id tegra186_dspk_of_match[] = {
471	{ .compatible = "nvidia,tegra186-dspk" },
472	{},
473};
474MODULE_DEVICE_TABLE(of, tegra186_dspk_of_match);
475
476static int tegra186_dspk_platform_probe(struct platform_device *pdev)
477{
478	struct device *dev = &pdev->dev;
479	struct tegra186_dspk *dspk;
480	void __iomem *regs;
481	int err;
482
483	dspk = devm_kzalloc(dev, sizeof(*dspk), GFP_KERNEL);
484	if (!dspk)
485		return -ENOMEM;
486
487	dspk->osr_val = DSPK_OSR_64;
488	dspk->lrsel = DSPK_LRSEL_LEFT;
489	dspk->ch_sel = DSPK_CH_SELECT_STEREO;
490	dspk->mono_to_stereo = 0; /* "Zero" */
491
492	dev_set_drvdata(dev, dspk);
493
494	dspk->clk_dspk = devm_clk_get(dev, "dspk");
495	if (IS_ERR(dspk->clk_dspk)) {
496		dev_err(dev, "can't retrieve DSPK clock\n");
497		return PTR_ERR(dspk->clk_dspk);
498	}
499
500	regs = devm_platform_ioremap_resource(pdev, 0);
501	if (IS_ERR(regs))
502		return PTR_ERR(regs);
503
504	dspk->regmap = devm_regmap_init_mmio(dev, regs, &tegra186_dspk_regmap);
505	if (IS_ERR(dspk->regmap)) {
506		dev_err(dev, "regmap init failed\n");
507		return PTR_ERR(dspk->regmap);
508	}
509
510	regcache_cache_only(dspk->regmap, true);
511
512	err = devm_snd_soc_register_component(dev, &tegra186_dspk_cmpnt,
513					      tegra186_dspk_dais,
514					      ARRAY_SIZE(tegra186_dspk_dais));
515	if (err) {
516		dev_err(dev, "can't register DSPK component, err: %d\n",
517			err);
518		return err;
519	}
520
521	pm_runtime_enable(dev);
522
523	return 0;
524}
525
526static void tegra186_dspk_platform_remove(struct platform_device *pdev)
527{
528	pm_runtime_disable(&pdev->dev);
 
 
529}
530
531static const struct dev_pm_ops tegra186_dspk_pm_ops = {
532	SET_RUNTIME_PM_OPS(tegra186_dspk_runtime_suspend,
533			   tegra186_dspk_runtime_resume, NULL)
534	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
535				pm_runtime_force_resume)
536};
537
538static struct platform_driver tegra186_dspk_driver = {
539	.driver = {
540		.name = "tegra186-dspk",
541		.of_match_table = tegra186_dspk_of_match,
542		.pm = &tegra186_dspk_pm_ops,
543	},
544	.probe = tegra186_dspk_platform_probe,
545	.remove_new = tegra186_dspk_platform_remove,
546};
547module_platform_driver(tegra186_dspk_driver);
548
549MODULE_AUTHOR("Mohan Kumar <mkumard@nvidia.com>");
550MODULE_AUTHOR("Sameer Pujar <spujar@nvidia.com>");
551MODULE_DESCRIPTION("Tegra186 ASoC DSPK driver");
552MODULE_LICENSE("GPL v2");