1 // SPDX-License-Identifier: GPL-2.0-only
3 * tegra_asoc_machine.c - Universal ASoC machine driver for NVIDIA Tegra boards.
7 #include <linux/export.h>
8 #include <linux/gpio/consumer.h>
9 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/slab.h>
14 #include <sound/core.h>
15 #include <sound/jack.h>
16 #include <sound/pcm.h>
17 #include <sound/pcm_params.h>
18 #include <sound/soc.h>
20 #include "tegra_asoc_machine.h"
24 static struct snd_soc_jack tegra_machine_hp_jack
;
26 static struct snd_soc_jack_pin tegra_machine_hp_jack_pins
[] = {
27 { .pin
= "Headphone", .mask
= SND_JACK_HEADPHONE
},
28 { .pin
= "Headphones", .mask
= SND_JACK_HEADPHONE
},
31 static struct snd_soc_jack_gpio tegra_machine_hp_jack_gpio
= {
32 .name
= "Headphones detection",
33 .report
= SND_JACK_HEADPHONE
,
39 static struct snd_soc_jack tegra_machine_headset_jack
;
41 static struct snd_soc_jack_pin tegra_machine_headset_jack_pins
[] = {
42 { .pin
= "Headset Mic", .mask
= SND_JACK_MICROPHONE
},
43 { .pin
= "Headset Stereophone", .mask
= SND_JACK_HEADPHONE
},
46 static struct snd_soc_jack_gpio tegra_machine_headset_jack_gpio
= {
47 .name
= "Headset detection",
48 .report
= SND_JACK_HEADSET
,
53 static int coupled_mic_hp_check(void *data
)
55 struct tegra_machine
*machine
= (struct tegra_machine
*)data
;
57 /* Detect mic insertion only if 3.5 jack is in */
58 if (gpiod_get_value_cansleep(machine
->gpiod_hp_det
) &&
59 gpiod_get_value_cansleep(machine
->gpiod_mic_det
))
60 return SND_JACK_MICROPHONE
;
65 static struct snd_soc_jack tegra_machine_mic_jack
;
67 static struct snd_soc_jack_pin tegra_machine_mic_jack_pins
[] = {
68 { .pin
= "Mic Jack", .mask
= SND_JACK_MICROPHONE
},
69 { .pin
= "Headset Mic", .mask
= SND_JACK_MICROPHONE
},
72 static struct snd_soc_jack_gpio tegra_machine_mic_jack_gpio
= {
73 .name
= "Mic detection",
74 .report
= SND_JACK_MICROPHONE
,
78 static int tegra_machine_event(struct snd_soc_dapm_widget
*w
,
79 struct snd_kcontrol
*k
, int event
)
81 struct snd_soc_dapm_context
*dapm
= w
->dapm
;
82 struct tegra_machine
*machine
= snd_soc_card_get_drvdata(dapm
->card
);
84 if (!snd_soc_dapm_widget_name_cmp(w
, "Int Spk") ||
85 !snd_soc_dapm_widget_name_cmp(w
, "Speakers"))
86 gpiod_set_value_cansleep(machine
->gpiod_spkr_en
,
87 SND_SOC_DAPM_EVENT_ON(event
));
89 if (!snd_soc_dapm_widget_name_cmp(w
, "Mic Jack") ||
90 !snd_soc_dapm_widget_name_cmp(w
, "Headset Mic"))
91 gpiod_set_value_cansleep(machine
->gpiod_ext_mic_en
,
92 SND_SOC_DAPM_EVENT_ON(event
));
94 if (!snd_soc_dapm_widget_name_cmp(w
, "Int Mic") ||
95 !snd_soc_dapm_widget_name_cmp(w
, "Internal Mic 2"))
96 gpiod_set_value_cansleep(machine
->gpiod_int_mic_en
,
97 SND_SOC_DAPM_EVENT_ON(event
));
99 if (!snd_soc_dapm_widget_name_cmp(w
, "Headphone") ||
100 !snd_soc_dapm_widget_name_cmp(w
, "Headphone Jack"))
101 gpiod_set_value_cansleep(machine
->gpiod_hp_mute
,
102 !SND_SOC_DAPM_EVENT_ON(event
));
107 static const struct snd_soc_dapm_widget tegra_machine_dapm_widgets
[] = {
108 SND_SOC_DAPM_HP("Headphone Jack", tegra_machine_event
),
109 SND_SOC_DAPM_HP("Headphone", tegra_machine_event
),
110 SND_SOC_DAPM_HP("Headset Stereophone", NULL
),
111 SND_SOC_DAPM_HP("Headphones", NULL
),
112 SND_SOC_DAPM_SPK("Speakers", tegra_machine_event
),
113 SND_SOC_DAPM_SPK("Int Spk", tegra_machine_event
),
114 SND_SOC_DAPM_SPK("Earpiece", NULL
),
115 SND_SOC_DAPM_MIC("Int Mic", tegra_machine_event
),
116 SND_SOC_DAPM_MIC("Mic Jack", tegra_machine_event
),
117 SND_SOC_DAPM_MIC("Internal Mic 1", NULL
),
118 SND_SOC_DAPM_MIC("Internal Mic 2", tegra_machine_event
),
119 SND_SOC_DAPM_MIC("Headset Mic", tegra_machine_event
),
120 SND_SOC_DAPM_MIC("Digital Mic", NULL
),
121 SND_SOC_DAPM_MIC("Mic", NULL
),
122 SND_SOC_DAPM_LINE("Line In Jack", NULL
),
123 SND_SOC_DAPM_LINE("Line In", NULL
),
124 SND_SOC_DAPM_LINE("LineIn", NULL
),
127 static const struct snd_kcontrol_new tegra_machine_controls
[] = {
128 SOC_DAPM_PIN_SWITCH("Speakers"),
129 SOC_DAPM_PIN_SWITCH("Int Spk"),
130 SOC_DAPM_PIN_SWITCH("Earpiece"),
131 SOC_DAPM_PIN_SWITCH("Int Mic"),
132 SOC_DAPM_PIN_SWITCH("Headset Mic"),
133 SOC_DAPM_PIN_SWITCH("Internal Mic 1"),
134 SOC_DAPM_PIN_SWITCH("Internal Mic 2"),
135 SOC_DAPM_PIN_SWITCH("Headphones"),
136 SOC_DAPM_PIN_SWITCH("Mic Jack"),
139 int tegra_asoc_machine_init(struct snd_soc_pcm_runtime
*rtd
)
141 struct snd_soc_card
*card
= rtd
->card
;
142 struct tegra_machine
*machine
= snd_soc_card_get_drvdata(card
);
143 const char *jack_name
;
146 if (machine
->gpiod_hp_det
&& machine
->asoc
->add_hp_jack
) {
147 if (machine
->asoc
->hp_jack_name
)
148 jack_name
= machine
->asoc
->hp_jack_name
;
150 jack_name
= "Headphones Jack";
152 err
= snd_soc_card_jack_new_pins(card
, jack_name
,
154 &tegra_machine_hp_jack
,
155 tegra_machine_hp_jack_pins
,
156 ARRAY_SIZE(tegra_machine_hp_jack_pins
));
159 "Headphones Jack creation failed: %d\n", err
);
163 tegra_machine_hp_jack_gpio
.desc
= machine
->gpiod_hp_det
;
165 err
= snd_soc_jack_add_gpios(&tegra_machine_hp_jack
, 1,
166 &tegra_machine_hp_jack_gpio
);
168 dev_err(rtd
->dev
, "HP GPIOs not added: %d\n", err
);
171 if (machine
->gpiod_hp_det
&& machine
->asoc
->add_headset_jack
) {
172 err
= snd_soc_card_jack_new_pins(card
, "Headset Jack",
174 &tegra_machine_headset_jack
,
175 tegra_machine_headset_jack_pins
,
176 ARRAY_SIZE(tegra_machine_headset_jack_pins
));
179 "Headset Jack creation failed: %d\n", err
);
183 tegra_machine_headset_jack_gpio
.desc
= machine
->gpiod_hp_det
;
185 err
= snd_soc_jack_add_gpios(&tegra_machine_headset_jack
, 1,
186 &tegra_machine_headset_jack_gpio
);
188 dev_err(rtd
->dev
, "Headset GPIOs not added: %d\n", err
);
191 if (machine
->gpiod_mic_det
&& machine
->asoc
->add_mic_jack
) {
192 err
= snd_soc_card_jack_new_pins(rtd
->card
, "Mic Jack",
194 &tegra_machine_mic_jack
,
195 tegra_machine_mic_jack_pins
,
196 ARRAY_SIZE(tegra_machine_mic_jack_pins
));
198 dev_err(rtd
->dev
, "Mic Jack creation failed: %d\n", err
);
202 tegra_machine_mic_jack_gpio
.data
= machine
;
203 tegra_machine_mic_jack_gpio
.desc
= machine
->gpiod_mic_det
;
205 if (of_property_read_bool(card
->dev
->of_node
,
206 "nvidia,coupled-mic-hp-det")) {
207 tegra_machine_mic_jack_gpio
.desc
= machine
->gpiod_hp_det
;
208 tegra_machine_mic_jack_gpio
.jack_status_check
= coupled_mic_hp_check
;
211 err
= snd_soc_jack_add_gpios(&tegra_machine_mic_jack
, 1,
212 &tegra_machine_mic_jack_gpio
);
214 dev_err(rtd
->dev
, "Mic GPIOs not added: %d\n", err
);
219 EXPORT_SYMBOL_GPL(tegra_asoc_machine_init
);
221 static unsigned int tegra_machine_mclk_rate_128(unsigned int srate
)
226 static unsigned int tegra_machine_mclk_rate_256(unsigned int srate
)
231 static unsigned int tegra_machine_mclk_rate_512(unsigned int srate
)
236 static unsigned int tegra_machine_mclk_rate_12mhz(unsigned int srate
)
264 static unsigned int tegra_machine_mclk_rate_6mhz(unsigned int srate
)
290 static int tegra_machine_hw_params(struct snd_pcm_substream
*substream
,
291 struct snd_pcm_hw_params
*params
)
293 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
294 struct snd_soc_dai
*codec_dai
= snd_soc_rtd_to_codec(rtd
, 0);
295 struct snd_soc_card
*card
= rtd
->card
;
296 struct tegra_machine
*machine
= snd_soc_card_get_drvdata(card
);
297 unsigned int srate
= params_rate(params
);
298 unsigned int mclk
= machine
->asoc
->mclk_rate(srate
);
299 unsigned int clk_id
= machine
->asoc
->mclk_id
;
300 unsigned int new_baseclock
;
308 if (of_machine_is_compatible("nvidia,tegra20"))
309 new_baseclock
= 56448000;
310 else if (of_machine_is_compatible("nvidia,tegra30"))
311 new_baseclock
= 564480000;
313 new_baseclock
= 282240000;
321 if (of_machine_is_compatible("nvidia,tegra20"))
322 new_baseclock
= 73728000;
323 else if (of_machine_is_compatible("nvidia,tegra30"))
324 new_baseclock
= 552960000;
326 new_baseclock
= 368640000;
329 dev_err(card
->dev
, "Invalid sound rate: %u\n", srate
);
333 if (new_baseclock
!= machine
->set_baseclock
||
334 mclk
!= machine
->set_mclk
) {
335 machine
->set_baseclock
= 0;
336 machine
->set_mclk
= 0;
338 clk_disable_unprepare(machine
->clk_cdev1
);
340 err
= clk_set_rate(machine
->clk_pll_a
, new_baseclock
);
342 dev_err(card
->dev
, "Can't set pll_a rate: %d\n", err
);
346 err
= clk_set_rate(machine
->clk_pll_a_out0
, mclk
);
348 dev_err(card
->dev
, "Can't set pll_a_out0 rate: %d\n", err
);
352 /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */
354 err
= clk_prepare_enable(machine
->clk_cdev1
);
356 dev_err(card
->dev
, "Can't enable cdev1: %d\n", err
);
360 machine
->set_baseclock
= new_baseclock
;
361 machine
->set_mclk
= mclk
;
364 err
= snd_soc_dai_set_sysclk(codec_dai
, clk_id
, mclk
, SND_SOC_CLOCK_IN
);
366 dev_err(card
->dev
, "codec_dai clock not set: %d\n", err
);
373 static const struct snd_soc_ops tegra_machine_snd_ops
= {
374 .hw_params
= tegra_machine_hw_params
,
377 static void tegra_machine_node_release(void *of_node
)
379 of_node_put(of_node
);
382 static struct device_node
*
383 tegra_machine_parse_phandle(struct device
*dev
, const char *name
)
385 struct device_node
*np
;
388 np
= of_parse_phandle(dev
->of_node
, name
, 0);
390 dev_err(dev
, "Property '%s' missing or invalid\n", name
);
391 return ERR_PTR(-EINVAL
);
394 err
= devm_add_action_or_reset(dev
, tegra_machine_node_release
, np
);
401 static void tegra_machine_unregister_codec(void *pdev
)
403 platform_device_unregister(pdev
);
406 static int tegra_machine_register_codec(struct device
*dev
, const char *name
)
408 struct platform_device
*pdev
;
414 pdev
= platform_device_register_simple(name
, -1, NULL
, 0);
416 return PTR_ERR(pdev
);
418 err
= devm_add_action_or_reset(dev
, tegra_machine_unregister_codec
,
426 int tegra_asoc_machine_probe(struct platform_device
*pdev
)
428 struct device_node
*np_codec
, *np_i2s
, *np_ac97
;
429 const struct tegra_asoc_data
*asoc
;
430 struct device
*dev
= &pdev
->dev
;
431 struct tegra_machine
*machine
;
432 struct snd_soc_card
*card
;
433 struct gpio_desc
*gpiod
;
436 machine
= devm_kzalloc(dev
, sizeof(*machine
), GFP_KERNEL
);
440 asoc
= of_device_get_match_data(dev
);
444 machine
->asoc
= asoc
;
445 machine
->mic_jack
= &tegra_machine_mic_jack
;
446 machine
->hp_jack_gpio
= &tegra_machine_hp_jack_gpio
;
447 snd_soc_card_set_drvdata(card
, machine
);
449 gpiod
= devm_gpiod_get_optional(dev
, "nvidia,hp-mute", GPIOD_OUT_HIGH
);
450 machine
->gpiod_hp_mute
= gpiod
;
452 return PTR_ERR(gpiod
);
454 gpiod
= devm_gpiod_get_optional(dev
, "nvidia,hp-det", GPIOD_IN
);
455 machine
->gpiod_hp_det
= gpiod
;
457 return PTR_ERR(gpiod
);
459 gpiod
= devm_gpiod_get_optional(dev
, "nvidia,mic-det", GPIOD_IN
);
460 machine
->gpiod_mic_det
= gpiod
;
462 return PTR_ERR(gpiod
);
464 gpiod
= devm_gpiod_get_optional(dev
, "nvidia,spkr-en", GPIOD_OUT_LOW
);
465 machine
->gpiod_spkr_en
= gpiod
;
467 return PTR_ERR(gpiod
);
469 gpiod
= devm_gpiod_get_optional(dev
, "nvidia,int-mic-en", GPIOD_OUT_LOW
);
470 machine
->gpiod_int_mic_en
= gpiod
;
472 return PTR_ERR(gpiod
);
474 gpiod
= devm_gpiod_get_optional(dev
, "nvidia,ext-mic-en", GPIOD_OUT_LOW
);
475 machine
->gpiod_ext_mic_en
= gpiod
;
477 return PTR_ERR(gpiod
);
479 err
= snd_soc_of_parse_card_name(card
, "nvidia,model");
483 if (!card
->dapm_routes
) {
484 err
= snd_soc_of_parse_audio_routing(card
, "nvidia,audio-routing");
489 if (asoc
->set_ac97
) {
490 err
= tegra_machine_register_codec(dev
, asoc
->codec_dev_name
);
494 np_ac97
= tegra_machine_parse_phandle(dev
, "nvidia,ac97-controller");
496 return PTR_ERR(np_ac97
);
498 card
->dai_link
->cpus
->of_node
= np_ac97
;
499 card
->dai_link
->platforms
->of_node
= np_ac97
;
501 np_codec
= tegra_machine_parse_phandle(dev
, "nvidia,audio-codec");
502 if (IS_ERR(np_codec
))
503 return PTR_ERR(np_codec
);
505 np_i2s
= tegra_machine_parse_phandle(dev
, "nvidia,i2s-controller");
507 return PTR_ERR(np_i2s
);
509 card
->dai_link
->cpus
->of_node
= np_i2s
;
510 card
->dai_link
->codecs
->of_node
= np_codec
;
511 card
->dai_link
->platforms
->of_node
= np_i2s
;
514 if (asoc
->add_common_controls
) {
515 card
->controls
= tegra_machine_controls
;
516 card
->num_controls
= ARRAY_SIZE(tegra_machine_controls
);
519 if (asoc
->add_common_dapm_widgets
) {
520 card
->dapm_widgets
= tegra_machine_dapm_widgets
;
521 card
->num_dapm_widgets
= ARRAY_SIZE(tegra_machine_dapm_widgets
);
524 if (asoc
->add_common_snd_ops
)
525 card
->dai_link
->ops
= &tegra_machine_snd_ops
;
528 card
->owner
= THIS_MODULE
;
529 if (!card
->driver_name
)
530 card
->driver_name
= "tegra";
532 machine
->clk_pll_a
= devm_clk_get(dev
, "pll_a");
533 if (IS_ERR(machine
->clk_pll_a
)) {
534 dev_err(dev
, "Can't retrieve clk pll_a\n");
535 return PTR_ERR(machine
->clk_pll_a
);
538 machine
->clk_pll_a_out0
= devm_clk_get(dev
, "pll_a_out0");
539 if (IS_ERR(machine
->clk_pll_a_out0
)) {
540 dev_err(dev
, "Can't retrieve clk pll_a_out0\n");
541 return PTR_ERR(machine
->clk_pll_a_out0
);
544 machine
->clk_cdev1
= devm_clk_get(dev
, "mclk");
545 if (IS_ERR(machine
->clk_cdev1
)) {
546 dev_err(dev
, "Can't retrieve clk cdev1\n");
547 return PTR_ERR(machine
->clk_cdev1
);
551 * If clock parents are not set in DT, configure here to use clk_out_1
552 * as mclk and extern1 as parent for Tegra30 and higher.
554 if (!of_property_present(dev
->of_node
, "assigned-clock-parents") &&
555 !of_machine_is_compatible("nvidia,tegra20")) {
556 struct clk
*clk_out_1
, *clk_extern1
;
558 dev_warn(dev
, "Configuring clocks for a legacy device-tree\n");
559 dev_warn(dev
, "Please update DT to use assigned-clock-parents\n");
561 clk_extern1
= devm_clk_get(dev
, "extern1");
562 if (IS_ERR(clk_extern1
)) {
563 dev_err(dev
, "Can't retrieve clk extern1\n");
564 return PTR_ERR(clk_extern1
);
567 err
= clk_set_parent(clk_extern1
, machine
->clk_pll_a_out0
);
569 dev_err(dev
, "Set parent failed for clk extern1\n");
573 clk_out_1
= devm_clk_get(dev
, "pmc_clk_out_1");
574 if (IS_ERR(clk_out_1
)) {
575 dev_err(dev
, "Can't retrieve pmc_clk_out_1\n");
576 return PTR_ERR(clk_out_1
);
579 err
= clk_set_parent(clk_out_1
, clk_extern1
);
581 dev_err(dev
, "Set parent failed for pmc_clk_out_1\n");
585 machine
->clk_cdev1
= clk_out_1
;
588 if (asoc
->set_ac97
) {
590 * AC97 rate is fixed at 24.576MHz and is used for both the
591 * host controller and the external codec
593 err
= clk_set_rate(machine
->clk_pll_a
, 73728000);
595 dev_err(dev
, "Can't set pll_a rate: %d\n", err
);
599 err
= clk_set_rate(machine
->clk_pll_a_out0
, 24576000);
601 dev_err(dev
, "Can't set pll_a_out0 rate: %d\n", err
);
605 machine
->set_baseclock
= 73728000;
606 machine
->set_mclk
= 24576000;
610 * FIXME: There is some unknown dependency between audio MCLK disable
611 * and suspend-resume functionality on Tegra30, although audio MCLK is
612 * only needed for audio.
614 err
= clk_prepare_enable(machine
->clk_cdev1
);
616 dev_err(dev
, "Can't enable cdev1: %d\n", err
);
620 err
= devm_snd_soc_register_card(dev
, card
);
626 EXPORT_SYMBOL_GPL(tegra_asoc_machine_probe
);
630 SND_SOC_DAILINK_DEFS(wm8753_hifi
,
631 DAILINK_COMP_ARRAY(COMP_EMPTY()),
632 DAILINK_COMP_ARRAY(COMP_CODEC(NULL
, "wm8753-hifi")),
633 DAILINK_COMP_ARRAY(COMP_EMPTY()));
635 static struct snd_soc_dai_link tegra_wm8753_dai
= {
637 .stream_name
= "WM8753 PCM",
638 .dai_fmt
= SND_SOC_DAIFMT_I2S
|
639 SND_SOC_DAIFMT_NB_NF
|
640 SND_SOC_DAIFMT_CBS_CFS
,
641 SND_SOC_DAILINK_REG(wm8753_hifi
),
644 static struct snd_soc_card snd_soc_tegra_wm8753
= {
645 .components
= "codec:wm8753",
646 .dai_link
= &tegra_wm8753_dai
,
648 .fully_routed
= true,
651 static const struct tegra_asoc_data tegra_wm8753_data
= {
652 .mclk_rate
= tegra_machine_mclk_rate_12mhz
,
653 .card
= &snd_soc_tegra_wm8753
,
654 .add_common_dapm_widgets
= true,
655 .add_common_snd_ops
= true,
660 static int tegra_wm9712_init(struct snd_soc_pcm_runtime
*rtd
)
662 return snd_soc_dapm_force_enable_pin(&rtd
->card
->dapm
, "Mic Bias");
665 SND_SOC_DAILINK_DEFS(wm9712_hifi
,
666 DAILINK_COMP_ARRAY(COMP_EMPTY()),
667 DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")),
668 DAILINK_COMP_ARRAY(COMP_EMPTY()));
670 static struct snd_soc_dai_link tegra_wm9712_dai
= {
672 .stream_name
= "AC97 HiFi",
673 .init
= tegra_wm9712_init
,
674 SND_SOC_DAILINK_REG(wm9712_hifi
),
677 static struct snd_soc_card snd_soc_tegra_wm9712
= {
678 .components
= "codec:wm9712",
679 .dai_link
= &tegra_wm9712_dai
,
681 .fully_routed
= true,
684 static const struct tegra_asoc_data tegra_wm9712_data
= {
685 .card
= &snd_soc_tegra_wm9712
,
686 .add_common_dapm_widgets
= true,
687 .codec_dev_name
= "wm9712-codec",
691 /* MAX98090 machine */
693 SND_SOC_DAILINK_DEFS(max98090_hifi
,
694 DAILINK_COMP_ARRAY(COMP_EMPTY()),
695 DAILINK_COMP_ARRAY(COMP_CODEC(NULL
, "HiFi")),
696 DAILINK_COMP_ARRAY(COMP_EMPTY()));
698 static struct snd_soc_dai_link tegra_max98090_dai
= {
700 .stream_name
= "max98090 PCM",
701 .init
= tegra_asoc_machine_init
,
702 .dai_fmt
= SND_SOC_DAIFMT_I2S
|
703 SND_SOC_DAIFMT_NB_NF
|
704 SND_SOC_DAIFMT_CBS_CFS
,
705 SND_SOC_DAILINK_REG(max98090_hifi
),
708 static struct snd_soc_card snd_soc_tegra_max98090
= {
709 .components
= "codec:max98090",
710 .dai_link
= &tegra_max98090_dai
,
712 .fully_routed
= true,
715 static const struct tegra_asoc_data tegra_max98090_data
= {
716 .mclk_rate
= tegra_machine_mclk_rate_12mhz
,
717 .card
= &snd_soc_tegra_max98090
,
718 .hp_jack_name
= "Headphones",
719 .add_common_dapm_widgets
= true,
720 .add_common_controls
= true,
721 .add_common_snd_ops
= true,
722 .add_mic_jack
= true,
726 /* MAX98088 machine */
728 SND_SOC_DAILINK_DEFS(max98088_hifi
,
729 DAILINK_COMP_ARRAY(COMP_EMPTY()),
730 DAILINK_COMP_ARRAY(COMP_CODEC(NULL
, "HiFi")),
731 DAILINK_COMP_ARRAY(COMP_EMPTY()));
733 static struct snd_soc_dai_link tegra_max98088_dai
= {
735 .stream_name
= "MAX98088 PCM",
736 .init
= tegra_asoc_machine_init
,
737 .dai_fmt
= SND_SOC_DAIFMT_I2S
|
738 SND_SOC_DAIFMT_NB_NF
|
739 SND_SOC_DAIFMT_CBS_CFS
,
740 SND_SOC_DAILINK_REG(max98088_hifi
),
743 static struct snd_soc_card snd_soc_tegra_max98088
= {
744 .components
= "codec:max98088",
745 .dai_link
= &tegra_max98088_dai
,
747 .fully_routed
= true,
750 static const struct tegra_asoc_data tegra_max98088_data
= {
751 .mclk_rate
= tegra_machine_mclk_rate_12mhz
,
752 .card
= &snd_soc_tegra_max98088
,
753 .add_common_dapm_widgets
= true,
754 .add_common_controls
= true,
755 .add_common_snd_ops
= true,
756 .add_mic_jack
= true,
760 /* SGTL5000 machine */
762 SND_SOC_DAILINK_DEFS(sgtl5000_hifi
,
763 DAILINK_COMP_ARRAY(COMP_EMPTY()),
764 DAILINK_COMP_ARRAY(COMP_CODEC(NULL
, "sgtl5000")),
765 DAILINK_COMP_ARRAY(COMP_EMPTY()));
767 static struct snd_soc_dai_link tegra_sgtl5000_dai
= {
769 .stream_name
= "HiFi",
770 .dai_fmt
= SND_SOC_DAIFMT_I2S
|
771 SND_SOC_DAIFMT_NB_NF
|
772 SND_SOC_DAIFMT_CBS_CFS
,
773 SND_SOC_DAILINK_REG(sgtl5000_hifi
),
776 static struct snd_soc_card snd_soc_tegra_sgtl5000
= {
777 .components
= "codec:sgtl5000",
778 .dai_link
= &tegra_sgtl5000_dai
,
780 .fully_routed
= true,
783 static const struct tegra_asoc_data tegra_sgtl5000_data
= {
784 .mclk_rate
= tegra_machine_mclk_rate_12mhz
,
785 .card
= &snd_soc_tegra_sgtl5000
,
786 .add_common_dapm_widgets
= true,
787 .add_common_snd_ops
= true,
790 /* TLV320AIC23 machine */
792 static const struct snd_soc_dapm_widget trimslice_dapm_widgets
[] = {
793 SND_SOC_DAPM_HP("Line Out", NULL
),
794 SND_SOC_DAPM_LINE("Line In", NULL
),
797 static const struct snd_soc_dapm_route trimslice_audio_map
[] = {
798 {"Line Out", NULL
, "LOUT"},
799 {"Line Out", NULL
, "ROUT"},
801 {"LLINEIN", NULL
, "Line In"},
802 {"RLINEIN", NULL
, "Line In"},
805 SND_SOC_DAILINK_DEFS(tlv320aic23_hifi
,
806 DAILINK_COMP_ARRAY(COMP_EMPTY()),
807 DAILINK_COMP_ARRAY(COMP_CODEC(NULL
, "tlv320aic23-hifi")),
808 DAILINK_COMP_ARRAY(COMP_EMPTY()));
810 static struct snd_soc_dai_link tegra_tlv320aic23_dai
= {
811 .name
= "TLV320AIC23",
812 .stream_name
= "AIC23",
813 .dai_fmt
= SND_SOC_DAIFMT_I2S
|
814 SND_SOC_DAIFMT_NB_NF
|
815 SND_SOC_DAIFMT_CBS_CFS
,
816 SND_SOC_DAILINK_REG(tlv320aic23_hifi
),
819 static struct snd_soc_card snd_soc_tegra_trimslice
= {
820 .name
= "tegra-trimslice",
821 .components
= "codec:tlv320aic23",
822 .dai_link
= &tegra_tlv320aic23_dai
,
824 .dapm_widgets
= trimslice_dapm_widgets
,
825 .num_dapm_widgets
= ARRAY_SIZE(trimslice_dapm_widgets
),
826 .dapm_routes
= trimslice_audio_map
,
827 .num_dapm_routes
= ARRAY_SIZE(trimslice_audio_map
),
828 .fully_routed
= true,
831 static const struct tegra_asoc_data tegra_trimslice_data
= {
832 .mclk_rate
= tegra_machine_mclk_rate_128
,
833 .card
= &snd_soc_tegra_trimslice
,
834 .add_common_snd_ops
= true,
839 static int tegra_rt5677_init(struct snd_soc_pcm_runtime
*rtd
)
841 struct snd_soc_card
*card
= rtd
->card
;
844 err
= tegra_asoc_machine_init(rtd
);
848 snd_soc_dapm_force_enable_pin(&card
->dapm
, "MICBIAS1");
853 SND_SOC_DAILINK_DEFS(rt5677_aif1
,
854 DAILINK_COMP_ARRAY(COMP_EMPTY()),
855 DAILINK_COMP_ARRAY(COMP_CODEC(NULL
, "rt5677-aif1")),
856 DAILINK_COMP_ARRAY(COMP_EMPTY()));
858 static struct snd_soc_dai_link tegra_rt5677_dai
= {
860 .stream_name
= "RT5677 PCM",
861 .init
= tegra_rt5677_init
,
862 .dai_fmt
= SND_SOC_DAIFMT_I2S
|
863 SND_SOC_DAIFMT_NB_NF
|
864 SND_SOC_DAIFMT_CBS_CFS
,
865 SND_SOC_DAILINK_REG(rt5677_aif1
),
868 static struct snd_soc_card snd_soc_tegra_rt5677
= {
869 .components
= "codec:rt5677",
870 .dai_link
= &tegra_rt5677_dai
,
872 .fully_routed
= true,
875 static const struct tegra_asoc_data tegra_rt5677_data
= {
876 .mclk_rate
= tegra_machine_mclk_rate_256
,
877 .card
= &snd_soc_tegra_rt5677
,
878 .add_common_dapm_widgets
= true,
879 .add_common_controls
= true,
880 .add_common_snd_ops
= true,
881 .add_mic_jack
= true,
887 SND_SOC_DAILINK_DEFS(rt5640_aif1
,
888 DAILINK_COMP_ARRAY(COMP_EMPTY()),
889 DAILINK_COMP_ARRAY(COMP_CODEC(NULL
, "rt5640-aif1")),
890 DAILINK_COMP_ARRAY(COMP_EMPTY()));
892 static struct snd_soc_dai_link tegra_rt5640_dai
= {
894 .stream_name
= "RT5640 PCM",
895 .init
= tegra_asoc_machine_init
,
896 .dai_fmt
= SND_SOC_DAIFMT_I2S
|
897 SND_SOC_DAIFMT_NB_NF
|
898 SND_SOC_DAIFMT_CBS_CFS
,
899 SND_SOC_DAILINK_REG(rt5640_aif1
),
902 static struct snd_soc_card snd_soc_tegra_rt5640
= {
903 .components
= "codec:rt5640",
904 .dai_link
= &tegra_rt5640_dai
,
906 .fully_routed
= true,
909 static const struct tegra_asoc_data tegra_rt5640_data
= {
910 .mclk_rate
= tegra_machine_mclk_rate_256
,
911 .card
= &snd_soc_tegra_rt5640
,
912 .add_common_dapm_widgets
= true,
913 .add_common_controls
= true,
914 .add_common_snd_ops
= true,
920 SND_SOC_DAILINK_DEFS(rt5632_hifi
,
921 DAILINK_COMP_ARRAY(COMP_EMPTY()),
922 DAILINK_COMP_ARRAY(COMP_CODEC(NULL
, "alc5632-hifi")),
923 DAILINK_COMP_ARRAY(COMP_EMPTY()));
925 static struct snd_soc_dai_link tegra_rt5632_dai
= {
927 .stream_name
= "ALC5632 PCM",
928 .init
= tegra_rt5677_init
,
929 .dai_fmt
= SND_SOC_DAIFMT_I2S
|
930 SND_SOC_DAIFMT_NB_NF
|
931 SND_SOC_DAIFMT_CBS_CFS
,
932 SND_SOC_DAILINK_REG(rt5632_hifi
),
935 static struct snd_soc_card snd_soc_tegra_rt5632
= {
936 .components
= "codec:rt5632",
937 .dai_link
= &tegra_rt5632_dai
,
939 .fully_routed
= true,
942 static const struct tegra_asoc_data tegra_rt5632_data
= {
943 .mclk_rate
= tegra_machine_mclk_rate_512
,
944 .card
= &snd_soc_tegra_rt5632
,
945 .add_common_dapm_widgets
= true,
946 .add_common_controls
= true,
947 .add_common_snd_ops
= true,
948 .add_headset_jack
= true,
953 SND_SOC_DAILINK_DEFS(rt5631_hifi
,
954 DAILINK_COMP_ARRAY(COMP_EMPTY()),
955 DAILINK_COMP_ARRAY(COMP_CODEC(NULL
, "rt5631-hifi")),
956 DAILINK_COMP_ARRAY(COMP_EMPTY()));
958 static struct snd_soc_dai_link tegra_rt5631_dai
= {
960 .stream_name
= "RT5631 PCM",
961 .init
= tegra_asoc_machine_init
,
962 .dai_fmt
= SND_SOC_DAIFMT_I2S
|
963 SND_SOC_DAIFMT_NB_NF
|
964 SND_SOC_DAIFMT_CBS_CFS
,
965 SND_SOC_DAILINK_REG(rt5631_hifi
),
968 static struct snd_soc_card snd_soc_tegra_rt5631
= {
969 .components
= "codec:rt5631",
970 .dai_link
= &tegra_rt5631_dai
,
972 .fully_routed
= true,
975 static const struct tegra_asoc_data tegra_rt5631_data
= {
976 .mclk_rate
= tegra_machine_mclk_rate_6mhz
,
977 .card
= &snd_soc_tegra_rt5631
,
978 .add_common_dapm_widgets
= true,
979 .add_common_controls
= true,
980 .add_common_snd_ops
= true,
981 .add_mic_jack
= true,
985 static const struct of_device_id tegra_machine_of_match
[] = {
986 { .compatible
= "nvidia,tegra-audio-trimslice", .data
= &tegra_trimslice_data
},
987 { .compatible
= "nvidia,tegra-audio-max98090", .data
= &tegra_max98090_data
},
988 { .compatible
= "nvidia,tegra-audio-max98088", .data
= &tegra_max98088_data
},
989 { .compatible
= "nvidia,tegra-audio-max98089", .data
= &tegra_max98088_data
},
990 { .compatible
= "nvidia,tegra-audio-sgtl5000", .data
= &tegra_sgtl5000_data
},
991 { .compatible
= "nvidia,tegra-audio-wm9712", .data
= &tegra_wm9712_data
},
992 { .compatible
= "nvidia,tegra-audio-wm8753", .data
= &tegra_wm8753_data
},
993 { .compatible
= "nvidia,tegra-audio-rt5677", .data
= &tegra_rt5677_data
},
994 { .compatible
= "nvidia,tegra-audio-rt5640", .data
= &tegra_rt5640_data
},
995 { .compatible
= "nvidia,tegra-audio-alc5632", .data
= &tegra_rt5632_data
},
996 { .compatible
= "nvidia,tegra-audio-rt5631", .data
= &tegra_rt5631_data
},
999 MODULE_DEVICE_TABLE(of
, tegra_machine_of_match
);
1001 static struct platform_driver tegra_asoc_machine_driver
= {
1003 .name
= "tegra-audio",
1004 .of_match_table
= tegra_machine_of_match
,
1005 .pm
= &snd_soc_pm_ops
,
1007 .probe
= tegra_asoc_machine_probe
,
1009 module_platform_driver(tegra_asoc_machine_driver
);
1011 MODULE_AUTHOR("Anatol Pomozov <anatol@google.com>");
1012 MODULE_AUTHOR("Andrey Danin <danindrey@mail.ru>");
1013 MODULE_AUTHOR("Dmitry Osipenko <digetx@gmail.com>");
1014 MODULE_AUTHOR("Ion Agorria <ion@agorria.com>");
1015 MODULE_AUTHOR("Leon Romanovsky <leon@leon.nu>");
1016 MODULE_AUTHOR("Lucas Stach <dev@lynxeye.de>");
1017 MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>");
1018 MODULE_AUTHOR("Marcel Ziswiler <marcel@ziswiler.com>");
1019 MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
1020 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
1021 MODULE_AUTHOR("Svyatoslav Ryhel <clamor95@gmail.com>");
1022 MODULE_DESCRIPTION("Tegra machine ASoC driver");
1023 MODULE_LICENSE("GPL");