1024 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * tegra_asoc_machine.c - Universal ASoC machine driver for NVIDIA Tegra boards.4 */5 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>13 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>19 20#include "tegra_asoc_machine.h"21 22/* Headphones Jack */23 24static struct snd_soc_jack tegra_machine_hp_jack;25 26static struct snd_soc_jack_pin tegra_machine_hp_jack_pins[] = {27 { .pin = "Headphone", .mask = SND_JACK_HEADPHONE },28 { .pin = "Headphones", .mask = SND_JACK_HEADPHONE },29};30 31static struct snd_soc_jack_gpio tegra_machine_hp_jack_gpio = {32 .name = "Headphones detection",33 .report = SND_JACK_HEADPHONE,34 .debounce_time = 150,35};36 37/* Headset Jack */38 39static struct snd_soc_jack tegra_machine_headset_jack;40 41static 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 },44};45 46static struct snd_soc_jack_gpio tegra_machine_headset_jack_gpio = {47 .name = "Headset detection",48 .report = SND_JACK_HEADSET,49 .debounce_time = 150,50};51 52/* Mic Jack */53static int coupled_mic_hp_check(void *data)54{55 struct tegra_machine *machine = (struct tegra_machine *)data;56 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;61 62 return 0;63}64 65static struct snd_soc_jack tegra_machine_mic_jack;66 67static 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 },70};71 72static struct snd_soc_jack_gpio tegra_machine_mic_jack_gpio = {73 .name = "Mic detection",74 .report = SND_JACK_MICROPHONE,75 .debounce_time = 150,76};77 78static int tegra_machine_event(struct snd_soc_dapm_widget *w,79 struct snd_kcontrol *k, int event)80{81 struct snd_soc_dapm_context *dapm = w->dapm;82 struct tegra_machine *machine = snd_soc_card_get_drvdata(dapm->card);83 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));88 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));93 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));98 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));103 104 return 0;105}106 107static 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),125};126 127static 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"),137};138 139int tegra_asoc_machine_init(struct snd_soc_pcm_runtime *rtd)140{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;145 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 else150 jack_name = "Headphones Jack";151 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;161 }162 163 tegra_machine_hp_jack_gpio.desc = machine->gpiod_hp_det;164 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);169 }170 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;181 }182 183 tegra_machine_headset_jack_gpio.desc = machine->gpiod_hp_det;184 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);189 }190 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;200 }201 202 tegra_machine_mic_jack_gpio.data = machine;203 tegra_machine_mic_jack_gpio.desc = machine->gpiod_mic_det;204 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;209 }210 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);215 }216 217 return 0;218}219EXPORT_SYMBOL_GPL(tegra_asoc_machine_init);220 221static unsigned int tegra_machine_mclk_rate_128(unsigned int srate)222{223 return 128 * srate;224}225 226static unsigned int tegra_machine_mclk_rate_256(unsigned int srate)227{228 return 256 * srate;229}230 231static unsigned int tegra_machine_mclk_rate_512(unsigned int srate)232{233 return 512 * srate;234}235 236static unsigned int tegra_machine_mclk_rate_12mhz(unsigned int srate)237{238 unsigned int mclk;239 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;259 }260 261 return mclk;262}263 264static unsigned int tegra_machine_mclk_rate_6mhz(unsigned int srate)265{266 unsigned int mclk;267 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;285 }286 287 return mclk;288}289 290static int tegra_machine_hw_params(struct snd_pcm_substream *substream,291 struct snd_pcm_hw_params *params)292{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;302 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 else313 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 else326 new_baseclock = 368640000;327 break;328 default:329 dev_err(card->dev, "Invalid sound rate: %u\n", srate);330 return -EINVAL;331 }332 333 if (new_baseclock != machine->set_baseclock ||334 mclk != machine->set_mclk) {335 machine->set_baseclock = 0;336 machine->set_mclk = 0;337 338 clk_disable_unprepare(machine->clk_cdev1);339 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;344 }345 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;350 }351 352 /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */353 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;358 }359 360 machine->set_baseclock = new_baseclock;361 machine->set_mclk = mclk;362 }363 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;368 }369 370 return 0;371}372 373static const struct snd_soc_ops tegra_machine_snd_ops = {374 .hw_params = tegra_machine_hw_params,375};376 377static void tegra_machine_node_release(void *of_node)378{379 of_node_put(of_node);380}381 382static struct device_node *383tegra_machine_parse_phandle(struct device *dev, const char *name)384{385 struct device_node *np;386 int err;387 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);392 }393 394 err = devm_add_action_or_reset(dev, tegra_machine_node_release, np);395 if (err)396 return ERR_PTR(err);397 398 return np;399}400 401static void tegra_machine_unregister_codec(void *pdev)402{403 platform_device_unregister(pdev);404}405 406static int tegra_machine_register_codec(struct device *dev, const char *name)407{408 struct platform_device *pdev;409 int err;410 411 if (!name)412 return 0;413 414 pdev = platform_device_register_simple(name, -1, NULL, 0);415 if (IS_ERR(pdev))416 return PTR_ERR(pdev);417 418 err = devm_add_action_or_reset(dev, tegra_machine_unregister_codec,419 pdev);420 if (err)421 return err;422 423 return 0;424}425 426int tegra_asoc_machine_probe(struct platform_device *pdev)427{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;435 436 machine = devm_kzalloc(dev, sizeof(*machine), GFP_KERNEL);437 if (!machine)438 return -ENOMEM;439 440 asoc = of_device_get_match_data(dev);441 card = asoc->card;442 card->dev = dev;443 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);448 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);453 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);458 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);463 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);468 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);473 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);478 479 err = snd_soc_of_parse_card_name(card, "nvidia,model");480 if (err)481 return err;482 483 if (!card->dapm_routes) {484 err = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");485 if (err)486 return err;487 }488 489 if (asoc->set_ac97) {490 err = tegra_machine_register_codec(dev, asoc->codec_dev_name);491 if (err)492 return err;493 494 np_ac97 = tegra_machine_parse_phandle(dev, "nvidia,ac97-controller");495 if (IS_ERR(np_ac97))496 return PTR_ERR(np_ac97);497 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);504 505 np_i2s = tegra_machine_parse_phandle(dev, "nvidia,i2s-controller");506 if (IS_ERR(np_i2s))507 return PTR_ERR(np_i2s);508 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;512 }513 514 if (asoc->add_common_controls) {515 card->controls = tegra_machine_controls;516 card->num_controls = ARRAY_SIZE(tegra_machine_controls);517 }518 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);522 }523 524 if (asoc->add_common_snd_ops)525 card->dai_link->ops = &tegra_machine_snd_ops;526 527 if (!card->owner)528 card->owner = THIS_MODULE;529 if (!card->driver_name)530 card->driver_name = "tegra";531 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);536 }537 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);542 }543 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);548 }549 550 /*551 * If clock parents are not set in DT, configure here to use clk_out_1552 * as mclk and extern1 as parent for Tegra30 and higher.553 */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;557 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");560 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);565 }566 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;571 }572 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);577 }578 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;583 }584 585 machine->clk_cdev1 = clk_out_1;586 }587 588 if (asoc->set_ac97) {589 /*590 * AC97 rate is fixed at 24.576MHz and is used for both the591 * host controller and the external codec592 */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;597 }598 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;603 }604 605 machine->set_baseclock = 73728000;606 machine->set_mclk = 24576000;607 }608 609 /*610 * FIXME: There is some unknown dependency between audio MCLK disable611 * and suspend-resume functionality on Tegra30, although audio MCLK is612 * only needed for audio.613 */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;618 }619 620 err = devm_snd_soc_register_card(dev, card);621 if (err)622 return err;623 624 return 0;625}626EXPORT_SYMBOL_GPL(tegra_asoc_machine_probe);627 628/* WM8753 machine */629 630SND_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()));634 635static 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),642};643 644static 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,649};650 651static 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,656};657 658/* WM9712 machine */659 660static int tegra_wm9712_init(struct snd_soc_pcm_runtime *rtd)661{662 return snd_soc_dapm_force_enable_pin(&rtd->card->dapm, "Mic Bias");663}664 665SND_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()));669 670static 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),675};676 677static 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,682};683 684static 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,689};690 691/* MAX98090 machine */692 693SND_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()));697 698static 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),706};707 708static 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,713};714 715static 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,724};725 726/* MAX98088 machine */727 728SND_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()));732 733static 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),741};742 743static 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,748};749 750static 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,758};759 760/* SGTL5000 machine */761 762SND_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()));766 767static 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),774};775 776static 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,781};782 783static 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,788};789 790/* TLV320AIC23 machine */791 792static 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),795};796 797static const struct snd_soc_dapm_route trimslice_audio_map[] = {798 {"Line Out", NULL, "LOUT"},799 {"Line Out", NULL, "ROUT"},800 801 {"LLINEIN", NULL, "Line In"},802 {"RLINEIN", NULL, "Line In"},803};804 805SND_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()));809 810static 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),817};818 819static 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,829};830 831static 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,835};836 837/* RT5677 machine */838 839static int tegra_rt5677_init(struct snd_soc_pcm_runtime *rtd)840{841 struct snd_soc_card *card = rtd->card;842 int err;843 844 err = tegra_asoc_machine_init(rtd);845 if (err)846 return err;847 848 snd_soc_dapm_force_enable_pin(&card->dapm, "MICBIAS1");849 850 return 0;851}852 853SND_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()));857 858static 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),866};867 868static 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,873};874 875static 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,883};884 885/* RT5640 machine */886 887SND_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()));891 892static 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),900};901 902static 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,907};908 909static 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,916};917 918/* RT5632 machine */919 920SND_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()));924 925static 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),933};934 935static 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,940};941 942static 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,949};950 951/* RT5631 machine */952 953SND_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()));957 958static 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),966};967 968static 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,973};974 975static 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,983};984 985static 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 },997 {},998};999MODULE_DEVICE_TABLE(of, tegra_machine_of_match);1000 1001static 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,1006 },1007 .probe = tegra_asoc_machine_probe,1008};1009module_platform_driver(tegra_asoc_machine_driver);1010 1011MODULE_AUTHOR("Anatol Pomozov <anatol@google.com>");1012MODULE_AUTHOR("Andrey Danin <danindrey@mail.ru>");1013MODULE_AUTHOR("Dmitry Osipenko <digetx@gmail.com>");1014MODULE_AUTHOR("Ion Agorria <ion@agorria.com>");1015MODULE_AUTHOR("Leon Romanovsky <leon@leon.nu>");1016MODULE_AUTHOR("Lucas Stach <dev@lynxeye.de>");1017MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>");1018MODULE_AUTHOR("Marcel Ziswiler <marcel@ziswiler.com>");1019MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");1020MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");1021MODULE_AUTHOR("Svyatoslav Ryhel <clamor95@gmail.com>");1022MODULE_DESCRIPTION("Tegra machine ASoC driver");1023MODULE_LICENSE("GPL");1024