2 * tegra210_sfc_alt.c - Tegra210 SFC driver
4 * Copyright (c) 2014-2017 NVIDIA CORPORATION. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include <linux/clk.h>
19 #include <linux/device.h>
21 #include <linux/module.h>
23 #include <linux/platform_device.h>
24 #include <linux/pm_runtime.h>
25 #include <linux/regmap.h>
26 #include <linux/slab.h>
27 #include <sound/core.h>
28 #include <sound/pcm.h>
29 #include <sound/pcm_params.h>
30 #include <sound/soc.h>
31 #include <linux/pinctrl/consumer.h>
32 #include <linux/of_device.h>
33 #include <linux/delay.h>
35 #include "tegra210_xbar_alt.h"
36 #include "tegra210_sfc_alt.h"
38 #define DRV_NAME "tegra210-sfc"
40 static const struct reg_default tegra210_sfc_reg_defaults[] = {
41 { TEGRA210_SFC_AXBAR_RX_INT_MASK, 0x00000001},
42 { TEGRA210_SFC_AXBAR_RX_CIF_CTRL, 0x00007700},
43 { TEGRA210_SFC_AXBAR_TX_INT_MASK, 0x00000001},
44 { TEGRA210_SFC_AXBAR_TX_CIF_CTRL, 0x00007700},
45 { TEGRA210_SFC_CG, 0x1},
46 { TEGRA210_SFC_AHUBRAMCTL_SFC_CTRL, 0x00004000},
49 static int tegra210_sfc_rates[] = {
50 8000, /* #define TEGRA210_SFC_FS8 0 */
51 11025, /* #define TEGRA210_SFC_FS11_025 1 */
52 16000, /* #define TEGRA210_SFC_FS16 2 */
53 22050, /* #define TEGRA210_SFC_FS22_05 3 */
54 24000, /* #define TEGRA210_SFC_FS24 4 */
55 32000, /* #define TEGRA210_SFC_FS32 5 */
56 44100, /* #define TEGRA210_SFC_FS44_1 6 */
57 48000, /* #define TEGRA210_SFC_FS48 7 */
58 64000, /* #define TEGRA210_SFC_FS64 8 */
59 88200, /* #define TEGRA210_SFC_FS88_2 9 */
60 96000, /* #define TEGRA210_SFC_FS96 10 */
61 176400, /* #define TEGRA210_SFC_FS176_4 11 */
62 192000, /* #define TEGRA210_SFC_FS192 12 */
65 static int tegra210_sfc_runtime_suspend(struct device *dev)
67 struct tegra210_sfc *sfc = dev_get_drvdata(dev);
69 regcache_cache_only(sfc->regmap, true);
70 regcache_mark_dirty(sfc->regmap);
75 static int tegra210_sfc_runtime_resume(struct device *dev)
77 struct tegra210_sfc *sfc = dev_get_drvdata(dev);
79 regcache_cache_only(sfc->regmap, false);
81 if (!sfc->is_shutdown)
82 regcache_sync(sfc->regmap);
87 #ifdef CONFIG_PM_SLEEP
88 static int tegra210_sfc_suspend(struct device *dev)
94 static int tegra210_sfc_set_dai_sysclk(struct snd_soc_dai *dai,
95 int clk_id, unsigned int freq, int dir)
97 struct tegra210_sfc *sfc = snd_soc_dai_get_drvdata(dai);
102 value = TEGRA210_SFC_FS8;
105 value = TEGRA210_SFC_FS11_025;
108 value = TEGRA210_SFC_FS16;
111 value = TEGRA210_SFC_FS22_05;
114 value = TEGRA210_SFC_FS24;
117 value = TEGRA210_SFC_FS32;
120 value = TEGRA210_SFC_FS44_1;
123 value = TEGRA210_SFC_FS48;
126 value = TEGRA210_SFC_FS64;
129 value = TEGRA210_SFC_FS88_2;
132 value = TEGRA210_SFC_FS96;
135 value = TEGRA210_SFC_FS176_4;
138 value = TEGRA210_SFC_FS192;
141 value = TEGRA210_SFC_FS8;
145 if (dir == SND_SOC_CLOCK_OUT)
146 sfc->srate_out = value;
147 else if (dir == SND_SOC_CLOCK_IN)
148 sfc->srate_in = value;
153 static int tegra210_sfc_write_coeff_ram(struct tegra210_sfc *sfc)
155 u32 *coeff_ram = NULL;
157 switch (sfc->srate_in) {
158 case TEGRA210_SFC_FS8:
159 if (sfc->srate_out == TEGRA210_SFC_FS48)
160 coeff_ram = coef_8to48;
161 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
162 coeff_ram = coef_8to44;
163 else if (sfc->srate_out == TEGRA210_SFC_FS24)
164 coeff_ram = coef_8to24;
165 else if (sfc->srate_out == TEGRA210_SFC_FS16)
166 coeff_ram = coef_8to16;
169 case TEGRA210_SFC_FS16:
170 if (sfc->srate_out == TEGRA210_SFC_FS48)
171 coeff_ram = coef_16to48;
172 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
173 coeff_ram = coef_16to44;
174 else if (sfc->srate_out == TEGRA210_SFC_FS24)
175 coeff_ram = coef_16to24;
176 else if (sfc->srate_out == TEGRA210_SFC_FS8)
177 coeff_ram = coef_16to8;
180 case TEGRA210_SFC_FS44_1:
181 if (sfc->srate_out == TEGRA210_SFC_FS8)
182 coeff_ram = coef_44to8;
183 else if (sfc->srate_out == TEGRA210_SFC_FS16)
184 coeff_ram = coef_44to16;
185 else if (sfc->srate_out == TEGRA210_SFC_FS48)
186 coeff_ram = coef_44to48;
189 case TEGRA210_SFC_FS48:
190 if (sfc->srate_out == TEGRA210_SFC_FS8)
191 coeff_ram = coef_48to8;
192 else if (sfc->srate_out == TEGRA210_SFC_FS16)
193 coeff_ram = coef_48to16;
194 else if (sfc->srate_out == TEGRA210_SFC_FS24)
195 coeff_ram = coef_48to24;
196 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
197 coeff_ram = coef_48to44;
198 else if (sfc->srate_out == TEGRA210_SFC_FS96)
199 coeff_ram = coef_48to96;
200 else if (sfc->srate_out == TEGRA210_SFC_FS192)
201 coeff_ram = coef_48to192;
204 case TEGRA210_SFC_FS11_025:
205 if (sfc->srate_out == TEGRA210_SFC_FS48)
206 coeff_ram = coef_11to48;
207 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
208 coeff_ram = coef_11to44;
211 case TEGRA210_SFC_FS22_05:
212 if (sfc->srate_out == TEGRA210_SFC_FS48)
213 coeff_ram = coef_22to48;
214 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
215 coeff_ram = coef_22to44;
218 case TEGRA210_SFC_FS24:
219 if (sfc->srate_out == TEGRA210_SFC_FS48)
220 coeff_ram = coef_24to48;
221 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
222 coeff_ram = coef_24to44;
225 case TEGRA210_SFC_FS32:
226 if (sfc->srate_out == TEGRA210_SFC_FS48)
227 coeff_ram = coef_32to48;
228 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
229 coeff_ram = coef_32to44;
232 case TEGRA210_SFC_FS88_2:
233 if (sfc->srate_out == TEGRA210_SFC_FS48)
234 coeff_ram = coef_88to48;
235 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
236 coeff_ram = coef_88to44;
239 case TEGRA210_SFC_FS96:
240 if (sfc->srate_out == TEGRA210_SFC_FS48)
241 coeff_ram = coef_96to48;
242 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
243 coeff_ram = coef_96to44;
246 case TEGRA210_SFC_FS176_4:
247 if (sfc->srate_out == TEGRA210_SFC_FS48)
248 coeff_ram = coef_176to48;
249 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
250 coeff_ram = coef_176to44;
253 case TEGRA210_SFC_FS192:
254 if (sfc->srate_out == TEGRA210_SFC_FS48)
255 coeff_ram = coef_192to48;
256 else if (sfc->srate_out == TEGRA210_SFC_FS44_1)
257 coeff_ram = coef_192to44;
261 pr_err("SFC input rate not supported: %d\n",
267 tegra210_xbar_write_ahubram(sfc->regmap,
268 TEGRA210_SFC_AHUBRAMCTL_SFC_CTRL,
269 TEGRA210_SFC_AHUBRAMCTL_SFC_DATA,
270 0, coeff_ram, TEGRA210_SFC_COEF_RAM_DEPTH);
272 regmap_update_bits(sfc->regmap,
273 TEGRA210_SFC_COEF_RAM,
274 TEGRA210_SFC_COEF_RAM_COEF_RAM_EN,
275 TEGRA210_SFC_COEF_RAM_COEF_RAM_EN);
281 static const int tegra210_sfc_fmt_values[] = {
283 TEGRA210_AUDIOCIF_BITS_16,
284 TEGRA210_AUDIOCIF_BITS_32,
287 static int tegra210_sfc_set_audio_cif(struct tegra210_sfc *sfc,
288 struct snd_pcm_hw_params *params,
291 int channels, audio_bits;
292 struct tegra210_xbar_cif_conf cif_conf;
294 memset(&cif_conf, 0, sizeof(struct tegra210_xbar_cif_conf));
296 channels = params_channels(params);
298 switch (params_format(params)) {
299 case SNDRV_PCM_FORMAT_S16_LE:
300 audio_bits = TEGRA210_AUDIOCIF_BITS_16;
302 case SNDRV_PCM_FORMAT_S32_LE:
303 audio_bits = TEGRA210_AUDIOCIF_BITS_32;
309 if (sfc->channels_via_control)
310 channels = sfc->channels_via_control;
312 if (sfc->stereo_conv_input > 0 && 2 == channels &&
313 (reg == TEGRA210_SFC_AXBAR_RX_CIF_CTRL)) {
314 cif_conf.stereo_conv = sfc->stereo_conv_input - 1;
315 cif_conf.client_channels = 1;
316 } else if (sfc->mono_conv_output > 0 && 2 == channels &&
317 (reg == TEGRA210_SFC_AXBAR_TX_CIF_CTRL)) {
318 cif_conf.mono_conv = sfc->mono_conv_output - 1;
319 cif_conf.client_channels = 1;
321 cif_conf.client_channels = channels;
324 cif_conf.audio_channels = channels;
325 cif_conf.audio_bits = audio_bits;
326 if (sfc->format_in && (reg == TEGRA210_SFC_AXBAR_RX_CIF_CTRL))
327 cif_conf.audio_bits = tegra210_sfc_fmt_values[sfc->format_in];
328 if (sfc->format_out && (reg == TEGRA210_SFC_AXBAR_TX_CIF_CTRL))
329 cif_conf.audio_bits = tegra210_sfc_fmt_values[sfc->format_out];
330 cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_32;
332 sfc->soc_data->set_audio_cif(sfc->regmap, reg, &cif_conf);
337 static int tegra210_sfc_soft_reset(struct tegra210_sfc *sfc)
343 regmap_update_bits(sfc->regmap,
344 TEGRA210_SFC_SOFT_RESET,
345 TEGRA210_SFC_SOFT_RESET_EN,
349 regmap_read(sfc->regmap, TEGRA210_SFC_SOFT_RESET, &val);
350 } while ((val & TEGRA210_SFC_SOFT_RESET_EN) && cnt--);
356 static int tegra210_sfc_in_hw_params(struct snd_pcm_substream *substream,
357 struct snd_pcm_hw_params *params,
358 struct snd_soc_dai *dai)
360 struct device *dev = dai->dev;
361 struct tegra210_sfc *sfc = snd_soc_dai_get_drvdata(dai);
364 regmap_update_bits(sfc->regmap,
365 TEGRA210_SFC_COEF_RAM,
366 TEGRA210_SFC_COEF_RAM_COEF_RAM_EN,
369 ret = tegra210_sfc_soft_reset(sfc);
371 dev_err(dev, "SOFT_RESET error: %d\n", ret);
375 ret = tegra210_sfc_set_audio_cif(sfc, params,
376 TEGRA210_SFC_AXBAR_RX_CIF_CTRL);
378 dev_err(dev, "Can't set SFC RX CIF: %d\n", ret);
381 memcpy(&sfc->in_hw_params, params, sizeof(struct snd_pcm_hw_params));
383 regmap_write(sfc->regmap, TEGRA210_SFC_AXBAR_RX_FREQ, sfc->srate_in);
385 if (sfc->srate_in != sfc->srate_out)
386 tegra210_sfc_write_coeff_ram(sfc);
391 static int tegra210_sfc_out_hw_params(struct snd_pcm_substream *substream,
392 struct snd_pcm_hw_params *params,
393 struct snd_soc_dai *dai)
395 struct device *dev = dai->dev;
396 struct tegra210_sfc *sfc = snd_soc_dai_get_drvdata(dai);
399 ret = tegra210_sfc_set_audio_cif(sfc, params,
400 TEGRA210_SFC_AXBAR_TX_CIF_CTRL);
402 dev_err(dev, "Can't set SFC TX CIF: %d\n", ret);
405 memcpy(&sfc->out_hw_params, params, sizeof(struct snd_pcm_hw_params));
407 if (sfc->srate_out < 0) {
408 dev_err(dev, "SFC%d output rate not set: %d\n",
413 regmap_write(sfc->regmap, TEGRA210_SFC_AXBAR_TX_FREQ, sfc->srate_out);
417 static int tegra210_sfc_rate_to_index(int rate)
420 for (index = 0; index < ARRAY_SIZE(tegra210_sfc_rates); index++) {
421 if (rate == tegra210_sfc_rates[index])
427 static int tegra210_sfc_get_srate(struct snd_kcontrol *kcontrol,
428 struct snd_ctl_elem_value *ucontrol)
430 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
431 struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
433 /* get the sfc output rate */
434 if (strstr(kcontrol->id.name, "input"))
435 ucontrol->value.integer.value[0] = tegra210_sfc_rates[sfc->srate_in];
436 else if (strstr(kcontrol->id.name, "output"))
437 ucontrol->value.integer.value[0] = tegra210_sfc_rates[sfc->srate_out];
442 static int tegra210_sfc_put_srate(struct snd_kcontrol *kcontrol,
443 struct snd_ctl_elem_value *ucontrol)
445 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
446 struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
447 int srate = tegra210_sfc_rate_to_index(ucontrol->value.integer.value[0]);
449 if ((srate < TEGRA210_SFC_FS8) || (srate > TEGRA210_SFC_FS192))
452 /* Update the SFC input/output rate */
453 if (strstr(kcontrol->id.name, "input"))
454 sfc->srate_in = srate;
455 else if (strstr(kcontrol->id.name, "output"))
456 sfc->srate_out = srate;
461 static int tegra210_sfc_get_format(struct snd_kcontrol *kcontrol,
462 struct snd_ctl_elem_value *ucontrol)
464 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
465 struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
467 /* get the format control flag */
468 if (strstr(kcontrol->id.name, "input"))
469 ucontrol->value.integer.value[0] = sfc->format_in;
470 else if (strstr(kcontrol->id.name, "output"))
471 ucontrol->value.integer.value[0] = sfc->format_out;
472 else if (strstr(kcontrol->id.name, "Channels"))
473 ucontrol->value.integer.value[0] = sfc->channels_via_control;
478 static int tegra210_sfc_put_format(struct snd_kcontrol *kcontrol,
479 struct snd_ctl_elem_value *ucontrol)
481 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
482 struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
483 int value = ucontrol->value.integer.value[0];
485 /* set the format control flag */
486 if (strstr(kcontrol->id.name, "input"))
487 sfc->format_in = value;
488 else if (strstr(kcontrol->id.name, "output"))
489 sfc->format_out = value;
490 else if (strstr(kcontrol->id.name, "Channels")) {
491 if (value > 0 && value <= 2)
492 sfc->channels_via_control = value;
500 static int tegra210_sfc_init_get(struct snd_kcontrol *kcontrol,
501 struct snd_ctl_elem_value *ucontrol)
506 static int tegra210_sfc_init_put(struct snd_kcontrol *kcontrol,
507 struct snd_ctl_elem_value *ucontrol)
509 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
510 struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
511 int init = ucontrol->value.enumerated.item[0];
518 dev_dbg(codec->dev, "%s: inrate %d outrate %d\n",
519 __func__, sfc->srate_in, sfc->srate_out);
521 ret = pm_runtime_get_sync(codec->dev->parent);
523 dev_err(codec->dev, "parent get_sync failed: %d\n", ret);
527 regmap_read(sfc->regmap, TEGRA210_SFC_ENABLE, &is_enabled);
533 regmap_write(sfc->regmap, TEGRA210_SFC_ENABLE, 0);
535 regmap_read(sfc->regmap, TEGRA210_SFC_STATUS, &val);
536 while ((val & 1) && cnt--) {
538 regmap_read(sfc->regmap, TEGRA210_SFC_STATUS, &val);
542 dev_warn(codec->dev, "SFC disable timeout\n");
544 regmap_update_bits(sfc->regmap,
545 TEGRA210_SFC_COEF_RAM,
546 TEGRA210_SFC_COEF_RAM_COEF_RAM_EN,
549 ret = tegra210_sfc_soft_reset(sfc);
551 dev_err(codec->dev, "SOFT_RESET error: %d\n", ret);
555 ret = tegra210_sfc_set_audio_cif(sfc, &sfc->in_hw_params,
556 TEGRA210_SFC_AXBAR_RX_CIF_CTRL);
558 dev_err(codec->dev, "Can't set SFC RX CIF: %d\n", ret);
562 ret = tegra210_sfc_set_audio_cif(sfc, &sfc->out_hw_params,
563 TEGRA210_SFC_AXBAR_TX_CIF_CTRL);
565 dev_err(codec->dev, "Can't set SFC TX CIF: %d\n", ret);
569 regmap_write(sfc->regmap, TEGRA210_SFC_AXBAR_RX_FREQ, sfc->srate_in);
570 regmap_write(sfc->regmap, TEGRA210_SFC_AXBAR_TX_FREQ, sfc->srate_out);
572 if (sfc->srate_in != sfc->srate_out)
573 tegra210_sfc_write_coeff_ram(sfc);
575 regmap_write(sfc->regmap, TEGRA210_SFC_ENABLE, 1);
578 pm_runtime_put(codec->dev->parent);
583 static int tegra210_sfc_get_stereo_conv(struct snd_kcontrol *kcontrol,
584 struct snd_ctl_elem_value *ucontrol)
586 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
587 struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
589 ucontrol->value.integer.value[0] = sfc->stereo_conv_input;
593 static int tegra210_sfc_put_stereo_conv(struct snd_kcontrol *kcontrol,
594 struct snd_ctl_elem_value *ucontrol)
596 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
597 struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
599 sfc->stereo_conv_input = ucontrol->value.integer.value[0];
603 static int tegra210_sfc_get_mono_conv(struct snd_kcontrol *kcontrol,
604 struct snd_ctl_elem_value *ucontrol)
606 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
607 struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
609 ucontrol->value.integer.value[0] = sfc->mono_conv_output;
613 static int tegra210_sfc_put_mono_conv(struct snd_kcontrol *kcontrol,
614 struct snd_ctl_elem_value *ucontrol)
616 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
617 struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
619 sfc->mono_conv_output = ucontrol->value.integer.value[0];
623 static int tegra210_sfc_codec_probe(struct snd_soc_codec *codec)
625 struct tegra210_sfc *sfc = snd_soc_codec_get_drvdata(codec);
627 codec->control_data = sfc->regmap;
632 static struct snd_soc_dai_ops tegra210_sfc_in_dai_ops = {
633 .hw_params = tegra210_sfc_in_hw_params,
634 .set_sysclk = tegra210_sfc_set_dai_sysclk,
637 static struct snd_soc_dai_ops tegra210_sfc_out_dai_ops = {
638 .hw_params = tegra210_sfc_out_hw_params,
641 static struct snd_soc_dai_driver tegra210_sfc_dais[] = {
645 .stream_name = "SFC Receive",
648 .rates = SNDRV_PCM_RATE_8000_96000,
649 .formats = SNDRV_PCM_FMTBIT_S8 |
650 SNDRV_PCM_FMTBIT_S16_LE |
651 SNDRV_PCM_FMTBIT_S24_LE |
652 SNDRV_PCM_FMTBIT_S32_LE,
654 .ops = &tegra210_sfc_in_dai_ops,
659 .stream_name = "SFC Transmit",
662 .rates = SNDRV_PCM_RATE_8000_96000,
663 .formats = SNDRV_PCM_FMTBIT_S8 |
664 SNDRV_PCM_FMTBIT_S16_LE |
665 SNDRV_PCM_FMTBIT_S24_LE |
666 SNDRV_PCM_FMTBIT_S32_LE,
668 .ops = &tegra210_sfc_out_dai_ops,
672 static const struct snd_soc_dapm_widget tegra210_sfc_widgets[] = {
673 SND_SOC_DAPM_AIF_IN("SFC RX", NULL, 0, SND_SOC_NOPM,
675 SND_SOC_DAPM_AIF_OUT("SFC TX", NULL, 0, TEGRA210_SFC_ENABLE,
676 TEGRA210_SFC_EN_SHIFT, 0),
679 static const struct snd_soc_dapm_route tegra210_sfc_routes[] = {
680 { "SFC RX", NULL, "SFC Receive" },
681 { "SFC TX", NULL, "SFC RX" },
682 { "SFC Transmit", NULL, "SFC TX" },
685 static const char * const tegra210_sfc_format_text[] = {
691 static const char * const tegra210_sfc_stereo_conv_text[] = {
692 "None", "CH0", "CH1", "AVG",
695 static const char * const tegra210_sfc_mono_conv_text[] = {
696 "None", "ZERO", "COPY",
699 static const struct soc_enum tegra210_sfc_format_enum =
700 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
701 ARRAY_SIZE(tegra210_sfc_format_text),
702 tegra210_sfc_format_text);
704 static const struct soc_enum tegra210_sfc_stereo_conv_enum =
705 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
706 ARRAY_SIZE(tegra210_sfc_stereo_conv_text),
707 tegra210_sfc_stereo_conv_text);
709 static const struct soc_enum tegra210_sfc_mono_conv_enum =
710 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
711 ARRAY_SIZE(tegra210_sfc_mono_conv_text),
712 tegra210_sfc_mono_conv_text);
714 static const struct snd_kcontrol_new tegra210_sfc_controls[] = {
715 SOC_SINGLE_EXT("input rate", 0, 0, 192000, 0,
716 tegra210_sfc_get_srate, tegra210_sfc_put_srate),
717 SOC_SINGLE_EXT("output rate", 0, 0, 192000, 0,
718 tegra210_sfc_get_srate, tegra210_sfc_put_srate),
719 SOC_ENUM_EXT("input bit format", tegra210_sfc_format_enum,
720 tegra210_sfc_get_format, tegra210_sfc_put_format),
721 SOC_ENUM_EXT("output bit format", tegra210_sfc_format_enum,
722 tegra210_sfc_get_format, tegra210_sfc_put_format),
723 SOC_SINGLE_EXT("Channels", 0, 0, 2, 0,
724 tegra210_sfc_get_format, tegra210_sfc_put_format),
725 SOC_SINGLE_EXT("init", 0, 0, 1, 0,
726 tegra210_sfc_init_get, tegra210_sfc_init_put),
727 SOC_ENUM_EXT("input stereo conv", tegra210_sfc_stereo_conv_enum,
728 tegra210_sfc_get_stereo_conv, tegra210_sfc_put_stereo_conv),
729 SOC_ENUM_EXT("output mono conv", tegra210_sfc_mono_conv_enum,
730 tegra210_sfc_get_mono_conv, tegra210_sfc_put_mono_conv),
733 static struct snd_soc_codec_driver tegra210_sfc_codec = {
734 .probe = tegra210_sfc_codec_probe,
735 .dapm_widgets = tegra210_sfc_widgets,
736 .num_dapm_widgets = ARRAY_SIZE(tegra210_sfc_widgets),
737 .dapm_routes = tegra210_sfc_routes,
738 .num_dapm_routes = ARRAY_SIZE(tegra210_sfc_routes),
739 .controls = tegra210_sfc_controls,
740 .num_controls = ARRAY_SIZE(tegra210_sfc_controls),
744 static bool tegra210_sfc_wr_reg(struct device *dev, unsigned int reg)
747 case TEGRA210_SFC_AXBAR_RX_INT_MASK:
748 case TEGRA210_SFC_AXBAR_RX_INT_SET:
749 case TEGRA210_SFC_AXBAR_RX_INT_CLEAR:
750 case TEGRA210_SFC_AXBAR_RX_CIF_CTRL:
751 case TEGRA210_SFC_AXBAR_RX_FREQ:
753 case TEGRA210_SFC_AXBAR_TX_INT_MASK:
754 case TEGRA210_SFC_AXBAR_TX_INT_SET:
755 case TEGRA210_SFC_AXBAR_TX_INT_CLEAR:
756 case TEGRA210_SFC_AXBAR_TX_CIF_CTRL:
757 case TEGRA210_SFC_AXBAR_TX_FREQ:
759 case TEGRA210_SFC_ENABLE:
760 case TEGRA210_SFC_SOFT_RESET:
761 case TEGRA210_SFC_CG:
762 case TEGRA210_SFC_COEF_RAM:
763 case TEGRA210_SFC_AHUBRAMCTL_SFC_CTRL:
764 case TEGRA210_SFC_AHUBRAMCTL_SFC_DATA:
771 static bool tegra210_sfc_rd_reg(struct device *dev, unsigned int reg)
774 case TEGRA210_SFC_AXBAR_RX_STATUS:
775 case TEGRA210_SFC_AXBAR_RX_INT_STATUS:
776 case TEGRA210_SFC_AXBAR_RX_INT_MASK:
777 case TEGRA210_SFC_AXBAR_RX_INT_SET:
778 case TEGRA210_SFC_AXBAR_RX_INT_CLEAR:
779 case TEGRA210_SFC_AXBAR_RX_CIF_CTRL:
780 case TEGRA210_SFC_AXBAR_RX_FREQ:
782 case TEGRA210_SFC_AXBAR_TX_STATUS:
783 case TEGRA210_SFC_AXBAR_TX_INT_STATUS:
784 case TEGRA210_SFC_AXBAR_TX_INT_MASK:
785 case TEGRA210_SFC_AXBAR_TX_INT_SET:
786 case TEGRA210_SFC_AXBAR_TX_INT_CLEAR:
787 case TEGRA210_SFC_AXBAR_TX_CIF_CTRL:
788 case TEGRA210_SFC_AXBAR_TX_FREQ:
790 case TEGRA210_SFC_ENABLE:
791 case TEGRA210_SFC_SOFT_RESET:
792 case TEGRA210_SFC_CG:
793 case TEGRA210_SFC_STATUS:
794 case TEGRA210_SFC_INT_STATUS:
795 case TEGRA210_SFC_COEF_RAM:
796 case TEGRA210_SFC_AHUBRAMCTL_SFC_CTRL:
797 case TEGRA210_SFC_AHUBRAMCTL_SFC_DATA:
804 static bool tegra210_sfc_volatile_reg(struct device *dev, unsigned int reg)
807 case TEGRA210_SFC_AXBAR_RX_STATUS:
808 case TEGRA210_SFC_AXBAR_RX_INT_STATUS:
809 case TEGRA210_SFC_AXBAR_RX_INT_SET:
811 case TEGRA210_SFC_AXBAR_TX_STATUS:
812 case TEGRA210_SFC_AXBAR_TX_INT_STATUS:
813 case TEGRA210_SFC_AXBAR_TX_INT_SET:
815 case TEGRA210_SFC_SOFT_RESET:
816 case TEGRA210_SFC_STATUS:
817 case TEGRA210_SFC_INT_STATUS:
818 case TEGRA210_SFC_AHUBRAMCTL_SFC_CTRL:
819 case TEGRA210_SFC_AHUBRAMCTL_SFC_DATA:
826 static bool tegra210_sfc_precious_reg(struct device *dev, unsigned int reg)
829 case TEGRA210_SFC_AHUBRAMCTL_SFC_DATA:
836 static const struct regmap_config tegra210_sfc_regmap_config = {
840 .max_register = TEGRA210_SFC_AHUBRAMCTL_SFC_DATA,
841 .writeable_reg = tegra210_sfc_wr_reg,
842 .readable_reg = tegra210_sfc_rd_reg,
843 .volatile_reg = tegra210_sfc_volatile_reg,
844 .precious_reg = tegra210_sfc_precious_reg,
845 .reg_defaults = tegra210_sfc_reg_defaults,
846 .num_reg_defaults = ARRAY_SIZE(tegra210_sfc_reg_defaults),
847 .cache_type = REGCACHE_FLAT,
850 static const struct tegra210_sfc_soc_data soc_data_tegra210 = {
851 .set_audio_cif = tegra210_xbar_set_cif,
854 static const struct of_device_id tegra210_sfc_of_match[] = {
855 { .compatible = "nvidia,tegra210-sfc", .data = &soc_data_tegra210 },
859 static int tegra210_sfc_platform_probe(struct platform_device *pdev)
861 struct tegra210_sfc *sfc;
862 struct resource *mem, *memregion;
865 const struct of_device_id *match;
866 struct tegra210_sfc_soc_data *soc_data;
868 match = of_match_device(tegra210_sfc_of_match, &pdev->dev);
870 dev_err(&pdev->dev, "Error: No device match found\n");
874 soc_data = (struct tegra210_sfc_soc_data *)match->data;
876 sfc = devm_kzalloc(&pdev->dev, sizeof(struct tegra210_sfc), GFP_KERNEL);
878 dev_err(&pdev->dev, "Can't allocate sfc\n");
883 sfc->soc_data = soc_data;
884 sfc->is_shutdown = false;
886 /* initialize default output srate */
887 sfc->srate_out = TEGRA210_SFC_FS48;
889 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
891 dev_err(&pdev->dev, "No memory resource\n");
896 memregion = devm_request_mem_region(&pdev->dev, mem->start,
897 resource_size(mem), pdev->name);
899 dev_err(&pdev->dev, "Memory region already claimed\n");
904 regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
906 dev_err(&pdev->dev, "ioremap failed\n");
911 sfc->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
912 &tegra210_sfc_regmap_config);
913 if (IS_ERR(sfc->regmap)) {
914 dev_err(&pdev->dev, "regmap init failed\n");
915 ret = PTR_ERR(sfc->regmap);
918 regcache_cache_only(sfc->regmap, true);
920 if (of_property_read_u32(pdev->dev.of_node,
921 "nvidia,ahub-sfc-id",
922 &pdev->dev.id) < 0) {
924 "Missing property nvidia,ahub-sfc-id\n");
929 pm_runtime_enable(&pdev->dev);
930 if (!pm_runtime_enabled(&pdev->dev)) {
931 ret = tegra210_sfc_runtime_resume(&pdev->dev);
936 ret = snd_soc_register_codec(&pdev->dev, &tegra210_sfc_codec,
938 ARRAY_SIZE(tegra210_sfc_dais));
940 dev_err(&pdev->dev, "Could not register CODEC: %d\n", ret);
944 dev_set_drvdata(&pdev->dev, sfc);
949 if (!pm_runtime_status_suspended(&pdev->dev))
950 tegra210_sfc_runtime_suspend(&pdev->dev);
952 pm_runtime_disable(&pdev->dev);
957 static void tegra210_sfc_platform_shutdown(struct platform_device *pdev)
959 struct tegra210_sfc *sfc = dev_get_drvdata(&pdev->dev);
961 sfc->is_shutdown = true;
964 static int tegra210_sfc_platform_remove(struct platform_device *pdev)
966 snd_soc_unregister_codec(&pdev->dev);
968 pm_runtime_disable(&pdev->dev);
969 if (!pm_runtime_status_suspended(&pdev->dev))
970 tegra210_sfc_runtime_suspend(&pdev->dev);
975 static const struct dev_pm_ops tegra210_sfc_pm_ops = {
976 SET_RUNTIME_PM_OPS(tegra210_sfc_runtime_suspend,
977 tegra210_sfc_runtime_resume, NULL)
978 SET_SYSTEM_SLEEP_PM_OPS(tegra210_sfc_suspend, NULL)
981 static struct platform_driver tegra210_sfc_driver = {
984 .owner = THIS_MODULE,
985 .of_match_table = tegra210_sfc_of_match,
986 .pm = &tegra210_sfc_pm_ops,
988 .probe = tegra210_sfc_platform_probe,
989 .remove = tegra210_sfc_platform_remove,
990 .shutdown = tegra210_sfc_platform_shutdown,
992 module_platform_driver(tegra210_sfc_driver)
994 MODULE_AUTHOR("Arun Shamanna Lakshmi <aruns@nvidia.com>");
995 MODULE_DESCRIPTION("Tegra210 SFC ASoC driver");
996 MODULE_LICENSE("GPL");
997 MODULE_ALIAS("platform:" DRV_NAME);
998 MODULE_DEVICE_TABLE(of, tegra210_sfc_of_match);