Revert "unicode: Don't special case ignorable code points"
[linux.git] / sound / soc / tegra / tegra_asoc_machine.c
blob775ce433fdbfdbcff4d09d078dbb0e65c0b15b60
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * tegra_asoc_machine.c - Universal ASoC machine driver for NVIDIA Tegra boards.
4 */
6 #include <linux/clk.h>
7 #include <linux/export.h>
8 #include <linux/gpio/consumer.h>
9 #include <linux/module.h>
10 #include <linux/of.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"
22 /* Headphones Jack */
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,
34 .debounce_time = 150,
37 /* Headset Jack */
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,
49 .debounce_time = 150,
52 /* Mic Jack */
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;
62 return 0;
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,
75 .debounce_time = 150,
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));
104 return 0;
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;
144 int err;
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;
149 else
150 jack_name = "Headphones Jack";
152 err = snd_soc_card_jack_new_pins(card, jack_name,
153 SND_JACK_HEADPHONE,
154 &tegra_machine_hp_jack,
155 tegra_machine_hp_jack_pins,
156 ARRAY_SIZE(tegra_machine_hp_jack_pins));
157 if (err) {
158 dev_err(rtd->dev,
159 "Headphones Jack creation failed: %d\n", err);
160 return 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);
167 if (err)
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",
173 SND_JACK_HEADSET,
174 &tegra_machine_headset_jack,
175 tegra_machine_headset_jack_pins,
176 ARRAY_SIZE(tegra_machine_headset_jack_pins));
177 if (err) {
178 dev_err(rtd->dev,
179 "Headset Jack creation failed: %d\n", err);
180 return 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);
187 if (err)
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",
193 SND_JACK_MICROPHONE,
194 &tegra_machine_mic_jack,
195 tegra_machine_mic_jack_pins,
196 ARRAY_SIZE(tegra_machine_mic_jack_pins));
197 if (err) {
198 dev_err(rtd->dev, "Mic Jack creation failed: %d\n", err);
199 return 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);
213 if (err)
214 dev_err(rtd->dev, "Mic GPIOs not added: %d\n", err);
217 return 0;
219 EXPORT_SYMBOL_GPL(tegra_asoc_machine_init);
221 static unsigned int tegra_machine_mclk_rate_128(unsigned int srate)
223 return 128 * srate;
226 static unsigned int tegra_machine_mclk_rate_256(unsigned int srate)
228 return 256 * srate;
231 static unsigned int tegra_machine_mclk_rate_512(unsigned int srate)
233 return 512 * srate;
236 static unsigned int tegra_machine_mclk_rate_12mhz(unsigned int srate)
238 unsigned int mclk;
240 switch (srate) {
241 case 8000:
242 case 16000:
243 case 24000:
244 case 32000:
245 case 48000:
246 case 64000:
247 case 96000:
248 mclk = 12288000;
249 break;
250 case 11025:
251 case 22050:
252 case 44100:
253 case 88200:
254 mclk = 11289600;
255 break;
256 default:
257 mclk = 12000000;
258 break;
261 return mclk;
264 static unsigned int tegra_machine_mclk_rate_6mhz(unsigned int srate)
266 unsigned int mclk;
268 switch (srate) {
269 case 8000:
270 case 16000:
271 case 64000:
272 mclk = 8192000;
273 break;
274 case 11025:
275 case 22050:
276 case 88200:
277 mclk = 11289600;
278 break;
279 case 96000:
280 mclk = 12288000;
281 break;
282 default:
283 mclk = 256 * srate;
284 break;
287 return mclk;
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;
301 int err;
303 switch (srate) {
304 case 11025:
305 case 22050:
306 case 44100:
307 case 88200:
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;
312 else
313 new_baseclock = 282240000;
314 break;
315 case 8000:
316 case 16000:
317 case 32000:
318 case 48000:
319 case 64000:
320 case 96000:
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;
325 else
326 new_baseclock = 368640000;
327 break;
328 default:
329 dev_err(card->dev, "Invalid sound rate: %u\n", srate);
330 return -EINVAL;
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);
341 if (err) {
342 dev_err(card->dev, "Can't set pll_a rate: %d\n", err);
343 return err;
346 err = clk_set_rate(machine->clk_pll_a_out0, mclk);
347 if (err) {
348 dev_err(card->dev, "Can't set pll_a_out0 rate: %d\n", err);
349 return err;
352 /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */
354 err = clk_prepare_enable(machine->clk_cdev1);
355 if (err) {
356 dev_err(card->dev, "Can't enable cdev1: %d\n", err);
357 return 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);
365 if (err < 0) {
366 dev_err(card->dev, "codec_dai clock not set: %d\n", err);
367 return err;
370 return 0;
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;
386 int err;
388 np = of_parse_phandle(dev->of_node, name, 0);
389 if (!np) {
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);
395 if (err)
396 return ERR_PTR(err);
398 return 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;
409 int err;
411 if (!name)
412 return 0;
414 pdev = platform_device_register_simple(name, -1, NULL, 0);
415 if (IS_ERR(pdev))
416 return PTR_ERR(pdev);
418 err = devm_add_action_or_reset(dev, tegra_machine_unregister_codec,
419 pdev);
420 if (err)
421 return err;
423 return 0;
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;
434 int err;
436 machine = devm_kzalloc(dev, sizeof(*machine), GFP_KERNEL);
437 if (!machine)
438 return -ENOMEM;
440 asoc = of_device_get_match_data(dev);
441 card = asoc->card;
442 card->dev = 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;
451 if (IS_ERR(gpiod))
452 return PTR_ERR(gpiod);
454 gpiod = devm_gpiod_get_optional(dev, "nvidia,hp-det", GPIOD_IN);
455 machine->gpiod_hp_det = gpiod;
456 if (IS_ERR(gpiod))
457 return PTR_ERR(gpiod);
459 gpiod = devm_gpiod_get_optional(dev, "nvidia,mic-det", GPIOD_IN);
460 machine->gpiod_mic_det = gpiod;
461 if (IS_ERR(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;
466 if (IS_ERR(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;
471 if (IS_ERR(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;
476 if (IS_ERR(gpiod))
477 return PTR_ERR(gpiod);
479 err = snd_soc_of_parse_card_name(card, "nvidia,model");
480 if (err)
481 return err;
483 if (!card->dapm_routes) {
484 err = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
485 if (err)
486 return err;
489 if (asoc->set_ac97) {
490 err = tegra_machine_register_codec(dev, asoc->codec_dev_name);
491 if (err)
492 return err;
494 np_ac97 = tegra_machine_parse_phandle(dev, "nvidia,ac97-controller");
495 if (IS_ERR(np_ac97))
496 return PTR_ERR(np_ac97);
498 card->dai_link->cpus->of_node = np_ac97;
499 card->dai_link->platforms->of_node = np_ac97;
500 } else {
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");
506 if (IS_ERR(np_i2s))
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;
527 if (!card->owner)
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);
568 if (err < 0) {
569 dev_err(dev, "Set parent failed for clk extern1\n");
570 return err;
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);
580 if (err < 0) {
581 dev_err(dev, "Set parent failed for pmc_clk_out_1\n");
582 return err;
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);
594 if (err) {
595 dev_err(dev, "Can't set pll_a rate: %d\n", err);
596 return err;
599 err = clk_set_rate(machine->clk_pll_a_out0, 24576000);
600 if (err) {
601 dev_err(dev, "Can't set pll_a_out0 rate: %d\n", err);
602 return 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);
615 if (err) {
616 dev_err(dev, "Can't enable cdev1: %d\n", err);
617 return err;
620 err = devm_snd_soc_register_card(dev, card);
621 if (err)
622 return err;
624 return 0;
626 EXPORT_SYMBOL_GPL(tegra_asoc_machine_probe);
628 /* WM8753 machine */
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 = {
636 .name = "WM8753",
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,
647 .num_links = 1,
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,
658 /* WM9712 machine */
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 = {
671 .name = "AC97 HiFi",
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,
680 .num_links = 1,
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",
688 .set_ac97 = true,
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 = {
699 .name = "max98090",
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,
711 .num_links = 1,
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,
723 .add_hp_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 = {
734 .name = "MAX98088",
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,
746 .num_links = 1,
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,
757 .add_hp_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 = {
768 .name = "sgtl5000",
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,
779 .num_links = 1,
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,
823 .num_links = 1,
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,
837 /* RT5677 machine */
839 static int tegra_rt5677_init(struct snd_soc_pcm_runtime *rtd)
841 struct snd_soc_card *card = rtd->card;
842 int err;
844 err = tegra_asoc_machine_init(rtd);
845 if (err)
846 return err;
848 snd_soc_dapm_force_enable_pin(&card->dapm, "MICBIAS1");
850 return 0;
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 = {
859 .name = "RT5677",
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,
871 .num_links = 1,
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,
882 .add_hp_jack = true,
885 /* RT5640 machine */
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 = {
893 .name = "RT5640",
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,
905 .num_links = 1,
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,
915 .add_hp_jack = true,
918 /* RT5632 machine */
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 = {
926 .name = "ALC5632",
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,
938 .num_links = 1,
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,
951 /* RT5631 machine */
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 = {
959 .name = "RT5631",
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,
971 .num_links = 1,
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,
982 .add_hp_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 = {
1002 .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");