.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * bytcr_rt5651.c - ASoc Machine driver for Intel Byt CR platform |
---|
3 | 4 | * (derived from bytcr_rt5640.c) |
---|
4 | 5 | * |
---|
5 | 6 | * Copyright (C) 2015 Intel Corp |
---|
6 | 7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify |
---|
9 | | - * it under the terms of the GNU General Public License as published by |
---|
10 | | - * the Free Software Foundation; version 2 of the License. |
---|
11 | | - * |
---|
12 | | - * This program is distributed in the hope that it will be useful, but |
---|
13 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
15 | | - * General Public License for more details. |
---|
16 | 8 | * |
---|
17 | 9 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
18 | 10 | */ |
---|
.. | .. |
---|
30 | 22 | #include <linux/gpio/consumer.h> |
---|
31 | 23 | #include <linux/gpio/machine.h> |
---|
32 | 24 | #include <linux/slab.h> |
---|
33 | | -#include <asm/cpu_device_id.h> |
---|
34 | | -#include <asm/intel-family.h> |
---|
35 | | -#include <asm/platform_sst_audio.h> |
---|
36 | 25 | #include <sound/pcm.h> |
---|
37 | 26 | #include <sound/pcm_params.h> |
---|
38 | 27 | #include <sound/soc.h> |
---|
.. | .. |
---|
40 | 29 | #include <sound/soc-acpi.h> |
---|
41 | 30 | #include "../../codecs/rt5651.h" |
---|
42 | 31 | #include "../atom/sst-atom-controls.h" |
---|
| 32 | +#include "../common/soc-intel-quirks.h" |
---|
43 | 33 | |
---|
44 | 34 | enum { |
---|
45 | 35 | BYT_RT5651_DMIC_MAP, |
---|
.. | .. |
---|
80 | 70 | #define BYT_RT5651_SSP0_AIF2 BIT(21) |
---|
81 | 71 | #define BYT_RT5651_HP_LR_SWAPPED BIT(22) |
---|
82 | 72 | #define BYT_RT5651_MONO_SPEAKER BIT(23) |
---|
| 73 | +#define BYT_RT5651_JD_NOT_INV BIT(24) |
---|
83 | 74 | |
---|
84 | 75 | #define BYT_RT5651_DEFAULT_QUIRKS (BYT_RT5651_MCLK_EN | \ |
---|
85 | 76 | BYT_RT5651_JD1_1 | \ |
---|
86 | 77 | BYT_RT5651_OVCD_TH_2000UA | \ |
---|
87 | 78 | BYT_RT5651_OVCD_SF_0P75) |
---|
88 | 79 | |
---|
89 | | -/* jack-detect-source + dmic-en + ovcd-th + -sf + terminating empty entry */ |
---|
90 | | -#define MAX_NO_PROPS 5 |
---|
| 80 | +/* jack-detect-source + inv + dmic-en + ovcd-th + -sf + terminating entry */ |
---|
| 81 | +#define MAX_NO_PROPS 6 |
---|
91 | 82 | |
---|
92 | 83 | struct byt_rt5651_private { |
---|
93 | 84 | struct clk *mclk; |
---|
94 | 85 | struct gpio_desc *ext_amp_gpio; |
---|
| 86 | + struct gpio_desc *hp_detect; |
---|
95 | 87 | struct snd_soc_jack jack; |
---|
96 | 88 | }; |
---|
| 89 | + |
---|
| 90 | +static const struct acpi_gpio_mapping *byt_rt5651_gpios; |
---|
97 | 91 | |
---|
98 | 92 | /* Default: jack-detect on JD1_1, internal mic on in2, headsetmic on in3 */ |
---|
99 | 93 | static unsigned long byt_rt5651_quirk = BYT_RT5651_DEFAULT_QUIRKS | |
---|
100 | 94 | BYT_RT5651_IN2_MAP; |
---|
| 95 | + |
---|
| 96 | +static int quirk_override = -1; |
---|
| 97 | +module_param_named(quirk, quirk_override, int, 0444); |
---|
| 98 | +MODULE_PARM_DESC(quirk, "Board-specific quirk override"); |
---|
101 | 99 | |
---|
102 | 100 | static void log_quirks(struct device *dev) |
---|
103 | 101 | { |
---|
.. | .. |
---|
131 | 129 | dev_info(dev, "quirk SSP0_AIF2 enabled\n"); |
---|
132 | 130 | if (byt_rt5651_quirk & BYT_RT5651_MONO_SPEAKER) |
---|
133 | 131 | dev_info(dev, "quirk MONO_SPEAKER enabled\n"); |
---|
| 132 | + if (byt_rt5651_quirk & BYT_RT5651_JD_NOT_INV) |
---|
| 133 | + dev_info(dev, "quirk JD_NOT_INV enabled\n"); |
---|
134 | 134 | } |
---|
135 | 135 | |
---|
136 | 136 | #define BYT_CODEC_DAI1 "rt5651-aif1" |
---|
.. | .. |
---|
347 | 347 | static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream, |
---|
348 | 348 | struct snd_pcm_hw_params *params) |
---|
349 | 349 | { |
---|
350 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
---|
351 | | - struct snd_soc_dai *codec_dai = rtd->codec_dai; |
---|
| 350 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
---|
| 351 | + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); |
---|
352 | 352 | snd_pcm_format_t format = params_format(params); |
---|
353 | 353 | int rate = params_rate(params); |
---|
354 | 354 | int bclk_ratio; |
---|
.. | .. |
---|
359 | 359 | bclk_ratio = 50; |
---|
360 | 360 | |
---|
361 | 361 | return byt_rt5651_prepare_and_enable_pll1(codec_dai, rate, bclk_ratio); |
---|
| 362 | +} |
---|
| 363 | + |
---|
| 364 | +static const struct acpi_gpio_params pov_p1006w_hp_detect = { 1, 0, false }; |
---|
| 365 | +static const struct acpi_gpio_params pov_p1006w_ext_amp_en = { 2, 0, true }; |
---|
| 366 | + |
---|
| 367 | +static const struct acpi_gpio_mapping byt_rt5651_pov_p1006w_gpios[] = { |
---|
| 368 | + { "hp-detect-gpios", &pov_p1006w_hp_detect, 1, }, |
---|
| 369 | + { "ext-amp-enable-gpios", &pov_p1006w_ext_amp_en, 1, }, |
---|
| 370 | + { }, |
---|
| 371 | +}; |
---|
| 372 | + |
---|
| 373 | +static int byt_rt5651_pov_p1006w_quirk_cb(const struct dmi_system_id *id) |
---|
| 374 | +{ |
---|
| 375 | + byt_rt5651_quirk = (unsigned long)id->driver_data; |
---|
| 376 | + byt_rt5651_gpios = byt_rt5651_pov_p1006w_gpios; |
---|
| 377 | + return 1; |
---|
362 | 378 | } |
---|
363 | 379 | |
---|
364 | 380 | static int byt_rt5651_quirk_cb(const struct dmi_system_id *id) |
---|
.. | .. |
---|
393 | 409 | BYT_RT5651_MONO_SPEAKER), |
---|
394 | 410 | }, |
---|
395 | 411 | { |
---|
| 412 | + /* Complet Electro Serv MY8307 */ |
---|
| 413 | + .callback = byt_rt5651_quirk_cb, |
---|
| 414 | + .matches = { |
---|
| 415 | + DMI_MATCH(DMI_SYS_VENDOR, "Complet Electro Serv"), |
---|
| 416 | + DMI_MATCH(DMI_PRODUCT_NAME, "MY8307"), |
---|
| 417 | + }, |
---|
| 418 | + .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS | |
---|
| 419 | + BYT_RT5651_IN2_MAP | |
---|
| 420 | + BYT_RT5651_MONO_SPEAKER | |
---|
| 421 | + BYT_RT5651_JD_NOT_INV), |
---|
| 422 | + }, |
---|
| 423 | + { |
---|
396 | 424 | /* I.T.Works TW701, Ployer Momo7w and Trekstor ST70416-6 |
---|
397 | 425 | * (these all use the same mainboard) */ |
---|
398 | 426 | .callback = byt_rt5651_quirk_cb, |
---|
.. | .. |
---|
406 | 434 | BYT_RT5651_IN2_MAP | |
---|
407 | 435 | BYT_RT5651_SSP0_AIF1 | |
---|
408 | 436 | BYT_RT5651_MONO_SPEAKER), |
---|
| 437 | + }, |
---|
| 438 | + { |
---|
| 439 | + /* Jumper EZpad 7 */ |
---|
| 440 | + .callback = byt_rt5651_quirk_cb, |
---|
| 441 | + .matches = { |
---|
| 442 | + DMI_MATCH(DMI_SYS_VENDOR, "Jumper"), |
---|
| 443 | + DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"), |
---|
| 444 | + /* Jumper12x.WJ2012.bsBKRCP05 with the version dropped */ |
---|
| 445 | + DMI_MATCH(DMI_BIOS_VERSION, "Jumper12x.WJ2012.bsBKRCP"), |
---|
| 446 | + }, |
---|
| 447 | + .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS | |
---|
| 448 | + BYT_RT5651_IN2_MAP | |
---|
| 449 | + BYT_RT5651_JD_NOT_INV), |
---|
409 | 450 | }, |
---|
410 | 451 | { |
---|
411 | 452 | /* KIANO SlimNote 14.2 */ |
---|
.. | .. |
---|
435 | 476 | }, |
---|
436 | 477 | .driver_data = (void *)(BYT_RT5651_MCLK_EN | |
---|
437 | 478 | BYT_RT5651_IN1_MAP), |
---|
| 479 | + }, |
---|
| 480 | + { |
---|
| 481 | + /* Point of View mobii wintab p1006w (v1.0) */ |
---|
| 482 | + .callback = byt_rt5651_pov_p1006w_quirk_cb, |
---|
| 483 | + .matches = { |
---|
| 484 | + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"), |
---|
| 485 | + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "BayTrail"), |
---|
| 486 | + /* Note 105b is Foxcon's USB/PCI vendor id */ |
---|
| 487 | + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "105B"), |
---|
| 488 | + DMI_EXACT_MATCH(DMI_BOARD_NAME, "0E57"), |
---|
| 489 | + }, |
---|
| 490 | + .driver_data = (void *)(BYT_RT5651_DMIC_MAP | |
---|
| 491 | + BYT_RT5651_OVCD_TH_2000UA | |
---|
| 492 | + BYT_RT5651_OVCD_SF_0P75 | |
---|
| 493 | + BYT_RT5651_DMIC_EN | |
---|
| 494 | + BYT_RT5651_MCLK_EN | |
---|
| 495 | + BYT_RT5651_SSP0_AIF1), |
---|
438 | 496 | }, |
---|
439 | 497 | { |
---|
440 | 498 | /* VIOS LTH17 */ |
---|
.. | .. |
---|
486 | 544 | if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN) |
---|
487 | 545 | props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,dmic-en"); |
---|
488 | 546 | |
---|
| 547 | + if (byt_rt5651_quirk & BYT_RT5651_JD_NOT_INV) |
---|
| 548 | + props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted"); |
---|
| 549 | + |
---|
489 | 550 | return device_add_properties(i2c_dev, props); |
---|
490 | 551 | } |
---|
491 | 552 | |
---|
492 | 553 | static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime) |
---|
493 | 554 | { |
---|
494 | 555 | struct snd_soc_card *card = runtime->card; |
---|
495 | | - struct snd_soc_component *codec = runtime->codec_dai->component; |
---|
| 556 | + struct snd_soc_component *codec = asoc_rtd_to_codec(runtime, 0)->component; |
---|
496 | 557 | struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card); |
---|
497 | 558 | const struct snd_soc_dapm_route *custom_map; |
---|
498 | 559 | int num_routes; |
---|
| 560 | + int report; |
---|
499 | 561 | int ret; |
---|
500 | 562 | |
---|
501 | 563 | card->dapm.idle_bias_off = true; |
---|
.. | .. |
---|
552 | 614 | dev_err(card->dev, "unable to add card controls\n"); |
---|
553 | 615 | return ret; |
---|
554 | 616 | } |
---|
555 | | - snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone"); |
---|
556 | | - snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); |
---|
557 | 617 | |
---|
558 | 618 | if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) { |
---|
559 | 619 | /* |
---|
.. | .. |
---|
579 | 639 | dev_err(card->dev, "unable to set MCLK rate\n"); |
---|
580 | 640 | } |
---|
581 | 641 | |
---|
582 | | - if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) { |
---|
| 642 | + report = 0; |
---|
| 643 | + if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) |
---|
| 644 | + report = SND_JACK_HEADSET | SND_JACK_BTN_0; |
---|
| 645 | + else if (priv->hp_detect) |
---|
| 646 | + report = SND_JACK_HEADSET; |
---|
| 647 | + |
---|
| 648 | + if (report) { |
---|
583 | 649 | ret = snd_soc_card_jack_new(runtime->card, "Headset", |
---|
584 | | - SND_JACK_HEADSET | SND_JACK_BTN_0, |
---|
585 | | - &priv->jack, bytcr_jack_pins, |
---|
| 650 | + report, &priv->jack, bytcr_jack_pins, |
---|
586 | 651 | ARRAY_SIZE(bytcr_jack_pins)); |
---|
587 | 652 | if (ret) { |
---|
588 | 653 | dev_err(runtime->dev, "jack creation failed %d\n", ret); |
---|
589 | 654 | return ret; |
---|
590 | 655 | } |
---|
591 | 656 | |
---|
592 | | - snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, |
---|
593 | | - KEY_PLAYPAUSE); |
---|
| 657 | + if (report & SND_JACK_BTN_0) |
---|
| 658 | + snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, |
---|
| 659 | + KEY_PLAYPAUSE); |
---|
594 | 660 | |
---|
595 | | - ret = snd_soc_component_set_jack(codec, &priv->jack, NULL); |
---|
| 661 | + ret = snd_soc_component_set_jack(codec, &priv->jack, |
---|
| 662 | + priv->hp_detect); |
---|
596 | 663 | if (ret) |
---|
597 | 664 | return ret; |
---|
598 | 665 | } |
---|
599 | 666 | |
---|
600 | 667 | return 0; |
---|
601 | 668 | } |
---|
602 | | - |
---|
603 | | -static const struct snd_soc_pcm_stream byt_rt5651_dai_params = { |
---|
604 | | - .formats = SNDRV_PCM_FMTBIT_S24_LE, |
---|
605 | | - .rate_min = 48000, |
---|
606 | | - .rate_max = 48000, |
---|
607 | | - .channels_min = 2, |
---|
608 | | - .channels_max = 2, |
---|
609 | | -}; |
---|
610 | 669 | |
---|
611 | 670 | static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd, |
---|
612 | 671 | struct snd_pcm_hw_params *params) |
---|
.. | .. |
---|
637 | 696 | * with explicit setting to I2S 2ch. The word length is set with |
---|
638 | 697 | * dai_set_tdm_slot() since there is no other API exposed |
---|
639 | 698 | */ |
---|
640 | | - ret = snd_soc_dai_set_fmt(rtd->cpu_dai, |
---|
| 699 | + ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), |
---|
641 | 700 | SND_SOC_DAIFMT_I2S | |
---|
642 | 701 | SND_SOC_DAIFMT_NB_NF | |
---|
643 | 702 | SND_SOC_DAIFMT_CBS_CFS |
---|
.. | .. |
---|
648 | 707 | return ret; |
---|
649 | 708 | } |
---|
650 | 709 | |
---|
651 | | - ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, bits); |
---|
| 710 | + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits); |
---|
652 | 711 | if (ret < 0) { |
---|
653 | 712 | dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); |
---|
654 | 713 | return ret; |
---|
.. | .. |
---|
681 | 740 | .hw_params = byt_rt5651_aif1_hw_params, |
---|
682 | 741 | }; |
---|
683 | 742 | |
---|
| 743 | +SND_SOC_DAILINK_DEF(dummy, |
---|
| 744 | + DAILINK_COMP_ARRAY(COMP_DUMMY())); |
---|
| 745 | + |
---|
| 746 | +SND_SOC_DAILINK_DEF(media, |
---|
| 747 | + DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai"))); |
---|
| 748 | + |
---|
| 749 | +SND_SOC_DAILINK_DEF(deepbuffer, |
---|
| 750 | + DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai"))); |
---|
| 751 | + |
---|
| 752 | +SND_SOC_DAILINK_DEF(ssp2_port, |
---|
| 753 | + DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port"))); |
---|
| 754 | +SND_SOC_DAILINK_DEF(ssp2_codec, |
---|
| 755 | + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5651:00", "rt5651-aif1"))); |
---|
| 756 | + |
---|
| 757 | +SND_SOC_DAILINK_DEF(platform, |
---|
| 758 | + DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform"))); |
---|
| 759 | + |
---|
684 | 760 | static struct snd_soc_dai_link byt_rt5651_dais[] = { |
---|
685 | 761 | [MERR_DPCM_AUDIO] = { |
---|
686 | 762 | .name = "Audio Port", |
---|
687 | 763 | .stream_name = "Audio", |
---|
688 | | - .cpu_dai_name = "media-cpu-dai", |
---|
689 | | - .codec_dai_name = "snd-soc-dummy-dai", |
---|
690 | | - .codec_name = "snd-soc-dummy", |
---|
691 | | - .platform_name = "sst-mfld-platform", |
---|
692 | 764 | .nonatomic = true, |
---|
693 | 765 | .dynamic = 1, |
---|
694 | 766 | .dpcm_playback = 1, |
---|
695 | 767 | .dpcm_capture = 1, |
---|
696 | 768 | .ops = &byt_rt5651_aif1_ops, |
---|
| 769 | + SND_SOC_DAILINK_REG(media, dummy, platform), |
---|
697 | 770 | }, |
---|
698 | 771 | [MERR_DPCM_DEEP_BUFFER] = { |
---|
699 | 772 | .name = "Deep-Buffer Audio Port", |
---|
700 | 773 | .stream_name = "Deep-Buffer Audio", |
---|
701 | | - .cpu_dai_name = "deepbuffer-cpu-dai", |
---|
702 | | - .codec_dai_name = "snd-soc-dummy-dai", |
---|
703 | | - .codec_name = "snd-soc-dummy", |
---|
704 | | - .platform_name = "sst-mfld-platform", |
---|
705 | 774 | .nonatomic = true, |
---|
706 | 775 | .dynamic = 1, |
---|
707 | 776 | .dpcm_playback = 1, |
---|
708 | 777 | .ops = &byt_rt5651_aif1_ops, |
---|
| 778 | + SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), |
---|
709 | 779 | }, |
---|
710 | 780 | /* CODEC<->CODEC link */ |
---|
711 | 781 | /* back ends */ |
---|
712 | 782 | { |
---|
713 | 783 | .name = "SSP2-Codec", |
---|
714 | 784 | .id = 0, |
---|
715 | | - .cpu_dai_name = "ssp2-port", |
---|
716 | | - .platform_name = "sst-mfld-platform", |
---|
717 | 785 | .no_pcm = 1, |
---|
718 | | - .codec_dai_name = "rt5651-aif1", |
---|
719 | | - .codec_name = "i2c-10EC5651:00", |
---|
720 | 786 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
---|
721 | 787 | | SND_SOC_DAIFMT_CBS_CFS, |
---|
722 | 788 | .be_hw_params_fixup = byt_rt5651_codec_fixup, |
---|
723 | | - .ignore_suspend = 1, |
---|
724 | 789 | .nonatomic = true, |
---|
725 | 790 | .dpcm_playback = 1, |
---|
726 | 791 | .dpcm_capture = 1, |
---|
727 | 792 | .init = byt_rt5651_init, |
---|
728 | 793 | .ops = &byt_rt5651_be_ssp2_ops, |
---|
| 794 | + SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), |
---|
729 | 795 | }, |
---|
730 | 796 | }; |
---|
731 | 797 | |
---|
732 | 798 | /* SoC card */ |
---|
733 | 799 | static char byt_rt5651_codec_name[SND_ACPI_I2C_ID_LEN]; |
---|
734 | | -static char byt_rt5651_codec_aif_name[12]; /* = "rt5651-aif[1|2]" */ |
---|
735 | | -static char byt_rt5651_cpu_dai_name[10]; /* = "ssp[0|2]-port" */ |
---|
| 800 | +#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES) |
---|
736 | 801 | static char byt_rt5651_long_name[50]; /* = "bytcr-rt5651-*-spk-*-mic[-swapped-hp]" */ |
---|
| 802 | +#endif |
---|
| 803 | +static char byt_rt5651_components[50]; /* = "cfg-spk:* cfg-mic:*" */ |
---|
737 | 804 | |
---|
738 | 805 | static int byt_rt5651_suspend(struct snd_soc_card *card) |
---|
739 | 806 | { |
---|
.. | .. |
---|
742 | 809 | if (!BYT_RT5651_JDSRC(byt_rt5651_quirk)) |
---|
743 | 810 | return 0; |
---|
744 | 811 | |
---|
745 | | - list_for_each_entry(component, &card->component_dev_list, card_list) { |
---|
| 812 | + for_each_card_components(card, component) { |
---|
746 | 813 | if (!strcmp(component->name, byt_rt5651_codec_name)) { |
---|
747 | 814 | dev_dbg(component->dev, "disabling jack detect before suspend\n"); |
---|
748 | 815 | snd_soc_component_set_jack(component, NULL, NULL); |
---|
.. | .. |
---|
761 | 828 | if (!BYT_RT5651_JDSRC(byt_rt5651_quirk)) |
---|
762 | 829 | return 0; |
---|
763 | 830 | |
---|
764 | | - list_for_each_entry(component, &card->component_dev_list, card_list) { |
---|
| 831 | + for_each_card_components(card, component) { |
---|
765 | 832 | if (!strcmp(component->name, byt_rt5651_codec_name)) { |
---|
766 | 833 | dev_dbg(component->dev, "re-enabling jack detect after resume\n"); |
---|
767 | | - snd_soc_component_set_jack(component, &priv->jack, NULL); |
---|
| 834 | + snd_soc_component_set_jack(component, &priv->jack, |
---|
| 835 | + priv->hp_detect); |
---|
768 | 836 | break; |
---|
769 | 837 | } |
---|
770 | 838 | } |
---|
.. | .. |
---|
772 | 840 | return 0; |
---|
773 | 841 | } |
---|
774 | 842 | |
---|
| 843 | +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) |
---|
| 844 | +/* use space before codec name to simplify card ID, and simplify driver name */ |
---|
| 845 | +#define CARD_NAME "bytcht rt5651" /* card name will be 'sof-bytcht rt5651' */ |
---|
| 846 | +#define DRIVER_NAME "SOF" |
---|
| 847 | +#else |
---|
| 848 | +#define CARD_NAME "bytcr-rt5651" |
---|
| 849 | +#define DRIVER_NAME NULL /* card name will be used for driver name */ |
---|
| 850 | +#endif |
---|
| 851 | + |
---|
775 | 852 | static struct snd_soc_card byt_rt5651_card = { |
---|
776 | | - .name = "bytcr-rt5651", |
---|
| 853 | + .name = CARD_NAME, |
---|
| 854 | + .driver_name = DRIVER_NAME, |
---|
777 | 855 | .owner = THIS_MODULE, |
---|
778 | 856 | .dai_link = byt_rt5651_dais, |
---|
779 | 857 | .num_links = ARRAY_SIZE(byt_rt5651_dais), |
---|
.. | .. |
---|
786 | 864 | .resume_post = byt_rt5651_resume, |
---|
787 | 865 | }; |
---|
788 | 866 | |
---|
789 | | -static const struct x86_cpu_id baytrail_cpu_ids[] = { |
---|
790 | | - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT }, /* Valleyview */ |
---|
791 | | - {} |
---|
792 | | -}; |
---|
| 867 | +static const struct acpi_gpio_params ext_amp_enable_gpios = { 0, 0, false }; |
---|
793 | 868 | |
---|
794 | | -static const struct x86_cpu_id cherrytrail_cpu_ids[] = { |
---|
795 | | - { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT }, /* Braswell */ |
---|
796 | | - {} |
---|
797 | | -}; |
---|
798 | | - |
---|
799 | | -static const struct acpi_gpio_params first_gpio = { 0, 0, false }; |
---|
800 | | -static const struct acpi_gpio_params second_gpio = { 1, 0, false }; |
---|
801 | | - |
---|
802 | | -static const struct acpi_gpio_mapping byt_rt5651_amp_en_first[] = { |
---|
803 | | - { "ext-amp-enable-gpios", &first_gpio, 1 }, |
---|
| 869 | +static const struct acpi_gpio_mapping cht_rt5651_gpios[] = { |
---|
| 870 | + /* |
---|
| 871 | + * Some boards have I2cSerialBusV2, GpioIo, GpioInt as ACPI resources, |
---|
| 872 | + * other boards may have I2cSerialBusV2, GpioInt, GpioIo instead. |
---|
| 873 | + * We want the GpioIo one for the ext-amp-enable-gpio. |
---|
| 874 | + */ |
---|
| 875 | + { "ext-amp-enable-gpios", &ext_amp_enable_gpios, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO }, |
---|
804 | 876 | { }, |
---|
805 | 877 | }; |
---|
806 | | - |
---|
807 | | -static const struct acpi_gpio_mapping byt_rt5651_amp_en_second[] = { |
---|
808 | | - { "ext-amp-enable-gpios", &second_gpio, 1 }, |
---|
809 | | - { }, |
---|
810 | | -}; |
---|
811 | | - |
---|
812 | | -/* |
---|
813 | | - * Some boards have I2cSerialBusV2, GpioIo, GpioInt as ACPI resources, other |
---|
814 | | - * boards may have I2cSerialBusV2, GpioInt, GpioIo instead. We want the |
---|
815 | | - * GpioIo one for the ext-amp-enable-gpio and both count for the index in |
---|
816 | | - * acpi_gpio_params index. So we have 2 different mappings and the code |
---|
817 | | - * below figures out which one to use. |
---|
818 | | - */ |
---|
819 | | -struct byt_rt5651_acpi_resource_data { |
---|
820 | | - int gpio_count; |
---|
821 | | - int gpio_int_idx; |
---|
822 | | -}; |
---|
823 | | - |
---|
824 | | -static int snd_byt_rt5651_acpi_resource(struct acpi_resource *ares, void *arg) |
---|
825 | | -{ |
---|
826 | | - struct byt_rt5651_acpi_resource_data *data = arg; |
---|
827 | | - |
---|
828 | | - if (ares->type != ACPI_RESOURCE_TYPE_GPIO) |
---|
829 | | - return 0; |
---|
830 | | - |
---|
831 | | - if (ares->data.gpio.connection_type == ACPI_RESOURCE_GPIO_TYPE_INT) |
---|
832 | | - data->gpio_int_idx = data->gpio_count; |
---|
833 | | - |
---|
834 | | - data->gpio_count++; |
---|
835 | | - return 0; |
---|
836 | | -} |
---|
837 | | - |
---|
838 | | -static void snd_byt_rt5651_mc_add_amp_en_gpio_mapping(struct device *codec) |
---|
839 | | -{ |
---|
840 | | - struct byt_rt5651_acpi_resource_data data = { 0, -1 }; |
---|
841 | | - LIST_HEAD(resources); |
---|
842 | | - int ret; |
---|
843 | | - |
---|
844 | | - ret = acpi_dev_get_resources(ACPI_COMPANION(codec), &resources, |
---|
845 | | - snd_byt_rt5651_acpi_resource, &data); |
---|
846 | | - if (ret < 0) { |
---|
847 | | - dev_warn(codec, "Failed to get ACPI resources, not adding external amplifier GPIO mapping\n"); |
---|
848 | | - return; |
---|
849 | | - } |
---|
850 | | - |
---|
851 | | - /* All info we need is gathered during the walk */ |
---|
852 | | - acpi_dev_free_resource_list(&resources); |
---|
853 | | - |
---|
854 | | - switch (data.gpio_int_idx) { |
---|
855 | | - case 0: |
---|
856 | | - devm_acpi_dev_add_driver_gpios(codec, byt_rt5651_amp_en_second); |
---|
857 | | - break; |
---|
858 | | - case 1: |
---|
859 | | - devm_acpi_dev_add_driver_gpios(codec, byt_rt5651_amp_en_first); |
---|
860 | | - break; |
---|
861 | | - default: |
---|
862 | | - dev_warn(codec, "Unknown GpioInt index %d, not adding external amplifier GPIO mapping\n", |
---|
863 | | - data.gpio_int_idx); |
---|
864 | | - } |
---|
865 | | -} |
---|
866 | 878 | |
---|
867 | 879 | struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */ |
---|
868 | 880 | u64 aif_value; /* 1: AIF1, 2: AIF2 */ |
---|
.. | .. |
---|
871 | 883 | |
---|
872 | 884 | static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) |
---|
873 | 885 | { |
---|
874 | | - const char * const mic_name[] = { "dmic", "in1", "in2", "in12" }; |
---|
| 886 | + static const char * const mic_name[] = { "dmic", "in1", "in2", "in12" }; |
---|
875 | 887 | struct byt_rt5651_private *priv; |
---|
876 | 888 | struct snd_soc_acpi_mach *mach; |
---|
| 889 | + const char *platform_name; |
---|
| 890 | + struct acpi_device *adev; |
---|
877 | 891 | struct device *codec_dev; |
---|
878 | | - const char *i2c_name = NULL; |
---|
879 | | - const char *hp_swapped; |
---|
880 | 892 | bool is_bytcr = false; |
---|
881 | 893 | int ret_val = 0; |
---|
882 | 894 | int dai_index = 0; |
---|
.. | .. |
---|
894 | 906 | |
---|
895 | 907 | /* fix index of codec dai */ |
---|
896 | 908 | for (i = 0; i < ARRAY_SIZE(byt_rt5651_dais); i++) { |
---|
897 | | - if (!strcmp(byt_rt5651_dais[i].codec_name, "i2c-10EC5651:00")) { |
---|
| 909 | + if (!strcmp(byt_rt5651_dais[i].codecs->name, |
---|
| 910 | + "i2c-10EC5651:00")) { |
---|
898 | 911 | dai_index = i; |
---|
899 | 912 | break; |
---|
900 | 913 | } |
---|
901 | 914 | } |
---|
902 | 915 | |
---|
903 | 916 | /* fixup codec name based on HID */ |
---|
904 | | - i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1); |
---|
905 | | - if (!i2c_name) { |
---|
| 917 | + adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1); |
---|
| 918 | + if (adev) { |
---|
| 919 | + snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name), |
---|
| 920 | + "i2c-%s", acpi_dev_name(adev)); |
---|
| 921 | + put_device(&adev->dev); |
---|
| 922 | + byt_rt5651_dais[dai_index].codecs->name = byt_rt5651_codec_name; |
---|
| 923 | + } else { |
---|
906 | 924 | dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id); |
---|
907 | 925 | return -ENODEV; |
---|
908 | 926 | } |
---|
909 | | - snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name), |
---|
910 | | - "%s%s", "i2c-", i2c_name); |
---|
911 | | - byt_rt5651_dais[dai_index].codec_name = byt_rt5651_codec_name; |
---|
912 | 927 | |
---|
913 | 928 | codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, |
---|
914 | 929 | byt_rt5651_codec_name); |
---|
.. | .. |
---|
919 | 934 | * swap SSP0 if bytcr is detected |
---|
920 | 935 | * (will be overridden if DMI quirk is detected) |
---|
921 | 936 | */ |
---|
922 | | - if (x86_match_cpu(baytrail_cpu_ids)) { |
---|
923 | | - struct sst_platform_info *p_info = mach->pdata; |
---|
924 | | - const struct sst_res_info *res_info = p_info->res_info; |
---|
925 | | - |
---|
926 | | - if (res_info->acpi_ipc_irq_index == 0) |
---|
| 937 | + if (soc_intel_is_byt()) { |
---|
| 938 | + if (mach->mach_params.acpi_ipc_irq_index == 0) |
---|
927 | 939 | is_bytcr = true; |
---|
928 | 940 | } |
---|
929 | 941 | |
---|
.. | .. |
---|
977 | 989 | /* check quirks before creating card */ |
---|
978 | 990 | dmi_check_system(byt_rt5651_quirk_table); |
---|
979 | 991 | |
---|
| 992 | + if (quirk_override != -1) { |
---|
| 993 | + dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n", |
---|
| 994 | + byt_rt5651_quirk, quirk_override); |
---|
| 995 | + byt_rt5651_quirk = quirk_override; |
---|
| 996 | + } |
---|
| 997 | + |
---|
980 | 998 | /* Must be called before register_card, also see declaration comment. */ |
---|
981 | 999 | ret_val = byt_rt5651_add_codec_device_props(codec_dev); |
---|
982 | 1000 | if (ret_val) { |
---|
.. | .. |
---|
985 | 1003 | } |
---|
986 | 1004 | |
---|
987 | 1005 | /* Cherry Trail devices use an external amplifier enable gpio */ |
---|
988 | | - if (x86_match_cpu(cherrytrail_cpu_ids)) { |
---|
989 | | - snd_byt_rt5651_mc_add_amp_en_gpio_mapping(codec_dev); |
---|
990 | | - priv->ext_amp_gpio = devm_fwnode_get_index_gpiod_from_child( |
---|
991 | | - &pdev->dev, "ext-amp-enable", 0, |
---|
992 | | - codec_dev->fwnode, |
---|
993 | | - GPIOD_OUT_LOW, "speaker-amp"); |
---|
| 1006 | + if (soc_intel_is_cht() && !byt_rt5651_gpios) |
---|
| 1007 | + byt_rt5651_gpios = cht_rt5651_gpios; |
---|
| 1008 | + |
---|
| 1009 | + if (byt_rt5651_gpios) { |
---|
| 1010 | + devm_acpi_dev_add_driver_gpios(codec_dev, byt_rt5651_gpios); |
---|
| 1011 | + priv->ext_amp_gpio = devm_fwnode_gpiod_get(&pdev->dev, |
---|
| 1012 | + codec_dev->fwnode, |
---|
| 1013 | + "ext-amp-enable", |
---|
| 1014 | + GPIOD_OUT_LOW, |
---|
| 1015 | + "speaker-amp"); |
---|
994 | 1016 | if (IS_ERR(priv->ext_amp_gpio)) { |
---|
995 | 1017 | ret_val = PTR_ERR(priv->ext_amp_gpio); |
---|
996 | 1018 | switch (ret_val) { |
---|
.. | .. |
---|
1000 | 1022 | default: |
---|
1001 | 1023 | dev_err(&pdev->dev, "Failed to get ext-amp-enable GPIO: %d\n", |
---|
1002 | 1024 | ret_val); |
---|
1003 | | - /* fall through */ |
---|
| 1025 | + fallthrough; |
---|
| 1026 | + case -EPROBE_DEFER: |
---|
| 1027 | + put_device(codec_dev); |
---|
| 1028 | + return ret_val; |
---|
| 1029 | + } |
---|
| 1030 | + } |
---|
| 1031 | + priv->hp_detect = devm_fwnode_gpiod_get(&pdev->dev, |
---|
| 1032 | + codec_dev->fwnode, |
---|
| 1033 | + "hp-detect", |
---|
| 1034 | + GPIOD_IN, |
---|
| 1035 | + "hp-detect"); |
---|
| 1036 | + if (IS_ERR(priv->hp_detect)) { |
---|
| 1037 | + ret_val = PTR_ERR(priv->hp_detect); |
---|
| 1038 | + switch (ret_val) { |
---|
| 1039 | + case -ENOENT: |
---|
| 1040 | + priv->hp_detect = NULL; |
---|
| 1041 | + break; |
---|
| 1042 | + default: |
---|
| 1043 | + dev_err(&pdev->dev, "Failed to get hp-detect GPIO: %d\n", |
---|
| 1044 | + ret_val); |
---|
| 1045 | + fallthrough; |
---|
1004 | 1046 | case -EPROBE_DEFER: |
---|
1005 | 1047 | put_device(codec_dev); |
---|
1006 | 1048 | return ret_val; |
---|
.. | .. |
---|
1013 | 1055 | log_quirks(&pdev->dev); |
---|
1014 | 1056 | |
---|
1015 | 1057 | if ((byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) || |
---|
1016 | | - (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) { |
---|
1017 | | - /* fixup codec aif name */ |
---|
1018 | | - snprintf(byt_rt5651_codec_aif_name, |
---|
1019 | | - sizeof(byt_rt5651_codec_aif_name), |
---|
1020 | | - "%s", "rt5651-aif2"); |
---|
1021 | | - |
---|
1022 | | - byt_rt5651_dais[dai_index].codec_dai_name = |
---|
1023 | | - byt_rt5651_codec_aif_name; |
---|
1024 | | - } |
---|
| 1058 | + (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) |
---|
| 1059 | + byt_rt5651_dais[dai_index].codecs->dai_name = "rt5651-aif2"; |
---|
1025 | 1060 | |
---|
1026 | 1061 | if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) || |
---|
1027 | | - (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) { |
---|
1028 | | - /* fixup cpu dai name name */ |
---|
1029 | | - snprintf(byt_rt5651_cpu_dai_name, |
---|
1030 | | - sizeof(byt_rt5651_cpu_dai_name), |
---|
1031 | | - "%s", "ssp0-port"); |
---|
1032 | | - |
---|
1033 | | - byt_rt5651_dais[dai_index].cpu_dai_name = |
---|
1034 | | - byt_rt5651_cpu_dai_name; |
---|
1035 | | - } |
---|
| 1062 | + (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) |
---|
| 1063 | + byt_rt5651_dais[dai_index].cpus->dai_name = "ssp0-port"; |
---|
1036 | 1064 | |
---|
1037 | 1065 | if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) { |
---|
1038 | 1066 | priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); |
---|
.. | .. |
---|
1052 | 1080 | } |
---|
1053 | 1081 | } |
---|
1054 | 1082 | |
---|
1055 | | - if (byt_rt5651_quirk & BYT_RT5651_HP_LR_SWAPPED) |
---|
1056 | | - hp_swapped = "-hp-swapped"; |
---|
1057 | | - else |
---|
1058 | | - hp_swapped = ""; |
---|
1059 | | - |
---|
| 1083 | + snprintf(byt_rt5651_components, sizeof(byt_rt5651_components), |
---|
| 1084 | + "cfg-spk:%s cfg-mic:%s%s", |
---|
| 1085 | + (byt_rt5651_quirk & BYT_RT5651_MONO_SPEAKER) ? "1" : "2", |
---|
| 1086 | + mic_name[BYT_RT5651_MAP(byt_rt5651_quirk)], |
---|
| 1087 | + (byt_rt5651_quirk & BYT_RT5651_HP_LR_SWAPPED) ? |
---|
| 1088 | + " cfg-hp:lrswap" : ""); |
---|
| 1089 | + byt_rt5651_card.components = byt_rt5651_components; |
---|
| 1090 | +#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES) |
---|
1060 | 1091 | snprintf(byt_rt5651_long_name, sizeof(byt_rt5651_long_name), |
---|
1061 | 1092 | "bytcr-rt5651-%s-spk-%s-mic%s", |
---|
1062 | 1093 | (byt_rt5651_quirk & BYT_RT5651_MONO_SPEAKER) ? |
---|
1063 | 1094 | "mono" : "stereo", |
---|
1064 | | - mic_name[BYT_RT5651_MAP(byt_rt5651_quirk)], hp_swapped); |
---|
| 1095 | + mic_name[BYT_RT5651_MAP(byt_rt5651_quirk)], |
---|
| 1096 | + (byt_rt5651_quirk & BYT_RT5651_HP_LR_SWAPPED) ? |
---|
| 1097 | + "-hp-swapped" : ""); |
---|
1065 | 1098 | byt_rt5651_card.long_name = byt_rt5651_long_name; |
---|
| 1099 | +#endif |
---|
| 1100 | + |
---|
| 1101 | + /* override plaform name, if required */ |
---|
| 1102 | + platform_name = mach->mach_params.platform; |
---|
| 1103 | + |
---|
| 1104 | + ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5651_card, |
---|
| 1105 | + platform_name); |
---|
| 1106 | + if (ret_val) |
---|
| 1107 | + return ret_val; |
---|
1066 | 1108 | |
---|
1067 | 1109 | ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5651_card); |
---|
1068 | 1110 | |
---|
.. | .. |
---|
1078 | 1120 | static struct platform_driver snd_byt_rt5651_mc_driver = { |
---|
1079 | 1121 | .driver = { |
---|
1080 | 1122 | .name = "bytcr_rt5651", |
---|
| 1123 | +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) |
---|
| 1124 | + .pm = &snd_soc_pm_ops, |
---|
| 1125 | +#endif |
---|
1081 | 1126 | }, |
---|
1082 | 1127 | .probe = snd_byt_rt5651_mc_probe, |
---|
1083 | 1128 | }; |
---|