| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * byt_cr_dpcm_rt5640.c - ASoc Machine driver for Intel Byt CR platform |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2014 Intel Corp |
|---|
| 5 | 6 | * Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com> |
|---|
| 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 | */ |
|---|
| .. | .. |
|---|
| 28 | 20 | #include <linux/dmi.h> |
|---|
| 29 | 21 | #include <linux/input.h> |
|---|
| 30 | 22 | #include <linux/slab.h> |
|---|
| 31 | | -#include <asm/cpu_device_id.h> |
|---|
| 32 | | -#include <asm/platform_sst_audio.h> |
|---|
| 33 | 23 | #include <sound/pcm.h> |
|---|
| 34 | 24 | #include <sound/pcm_params.h> |
|---|
| 35 | 25 | #include <sound/soc.h> |
|---|
| .. | .. |
|---|
| 38 | 28 | #include <dt-bindings/sound/rt5640.h> |
|---|
| 39 | 29 | #include "../../codecs/rt5640.h" |
|---|
| 40 | 30 | #include "../atom/sst-atom-controls.h" |
|---|
| 41 | | -#include "../common/sst-dsp.h" |
|---|
| 31 | +#include "../common/soc-intel-quirks.h" |
|---|
| 42 | 32 | |
|---|
| 43 | 33 | enum { |
|---|
| 44 | 34 | BYT_RT5640_DMIC1_MAP, |
|---|
| .. | .. |
|---|
| 81 | 71 | #define BYT_RT5640_SSP0_AIF2 BIT(21) |
|---|
| 82 | 72 | #define BYT_RT5640_MCLK_EN BIT(22) |
|---|
| 83 | 73 | #define BYT_RT5640_MCLK_25MHZ BIT(23) |
|---|
| 74 | +#define BYT_RT5640_NO_SPEAKERS BIT(24) |
|---|
| 84 | 75 | |
|---|
| 85 | 76 | #define BYTCR_INPUT_DEFAULTS \ |
|---|
| 86 | 77 | (BYT_RT5640_IN3_MAP | \ |
|---|
| .. | .. |
|---|
| 99 | 90 | static bool is_bytcr; |
|---|
| 100 | 91 | |
|---|
| 101 | 92 | static unsigned long byt_rt5640_quirk = BYT_RT5640_MCLK_EN; |
|---|
| 102 | | -static unsigned int quirk_override; |
|---|
| 103 | | -module_param_named(quirk, quirk_override, uint, 0444); |
|---|
| 93 | +static int quirk_override = -1; |
|---|
| 94 | +module_param_named(quirk, quirk_override, int, 0444); |
|---|
| 104 | 95 | MODULE_PARM_DESC(quirk, "Board-specific quirk override"); |
|---|
| 105 | 96 | |
|---|
| 106 | 97 | static void log_quirks(struct device *dev) |
|---|
| .. | .. |
|---|
| 142 | 133 | dev_info(dev, "quirk JD_NOT_INV enabled\n"); |
|---|
| 143 | 134 | if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) |
|---|
| 144 | 135 | dev_info(dev, "quirk MONO_SPEAKER enabled\n"); |
|---|
| 136 | + if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) |
|---|
| 137 | + dev_info(dev, "quirk NO_SPEAKERS enabled\n"); |
|---|
| 145 | 138 | if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) |
|---|
| 146 | 139 | dev_info(dev, "quirk DIFF_MIC enabled\n"); |
|---|
| 147 | 140 | if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) { |
|---|
| .. | .. |
|---|
| 392 | 385 | static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream, |
|---|
| 393 | 386 | struct snd_pcm_hw_params *params) |
|---|
| 394 | 387 | { |
|---|
| 395 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
|---|
| 396 | | - struct snd_soc_dai *dai = rtd->codec_dai; |
|---|
| 388 | + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
|---|
| 389 | + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); |
|---|
| 397 | 390 | |
|---|
| 398 | 391 | return byt_rt5640_prepare_and_enable_pll1(dai, params_rate(params)); |
|---|
| 399 | 392 | } |
|---|
| 400 | 393 | |
|---|
| 401 | 394 | /* Please keep this list alphabetically sorted */ |
|---|
| 402 | 395 | static const struct dmi_system_id byt_rt5640_quirk_table[] = { |
|---|
| 396 | + { /* Acer Iconia One 7 B1-750 */ |
|---|
| 397 | + .matches = { |
|---|
| 398 | + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"), |
|---|
| 399 | + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "VESPA2"), |
|---|
| 400 | + }, |
|---|
| 401 | + .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | |
|---|
| 402 | + BYT_RT5640_JD_SRC_JD1_IN4P | |
|---|
| 403 | + BYT_RT5640_OVCD_TH_1500UA | |
|---|
| 404 | + BYT_RT5640_OVCD_SF_0P75 | |
|---|
| 405 | + BYT_RT5640_SSP0_AIF1 | |
|---|
| 406 | + BYT_RT5640_MCLK_EN), |
|---|
| 407 | + }, |
|---|
| 403 | 408 | { /* Acer Iconia Tab 8 W1-810 */ |
|---|
| 404 | 409 | .matches = { |
|---|
| 405 | 410 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"), |
|---|
| .. | .. |
|---|
| 438 | 443 | BYT_RT5640_MCLK_EN), |
|---|
| 439 | 444 | }, |
|---|
| 440 | 445 | { |
|---|
| 446 | + /* Advantech MICA-071 */ |
|---|
| 447 | + .matches = { |
|---|
| 448 | + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Advantech"), |
|---|
| 449 | + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MICA-071"), |
|---|
| 450 | + }, |
|---|
| 451 | + /* OVCD Th = 1500uA to reliable detect head-phones vs -set */ |
|---|
| 452 | + .driver_data = (void *)(BYT_RT5640_IN3_MAP | |
|---|
| 453 | + BYT_RT5640_JD_SRC_JD2_IN4N | |
|---|
| 454 | + BYT_RT5640_OVCD_TH_1500UA | |
|---|
| 455 | + BYT_RT5640_OVCD_SF_0P75 | |
|---|
| 456 | + BYT_RT5640_MONO_SPEAKER | |
|---|
| 457 | + BYT_RT5640_DIFF_MIC | |
|---|
| 458 | + BYT_RT5640_MCLK_EN), |
|---|
| 459 | + }, |
|---|
| 460 | + { |
|---|
| 441 | 461 | .matches = { |
|---|
| 442 | 462 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"), |
|---|
| 443 | 463 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 80 Cesium"), |
|---|
| .. | .. |
|---|
| 451 | 471 | .matches = { |
|---|
| 452 | 472 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"), |
|---|
| 453 | 473 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 140 CESIUM"), |
|---|
| 474 | + }, |
|---|
| 475 | + .driver_data = (void *)(BYT_RT5640_IN1_MAP | |
|---|
| 476 | + BYT_RT5640_JD_SRC_JD2_IN4N | |
|---|
| 477 | + BYT_RT5640_OVCD_TH_2000UA | |
|---|
| 478 | + BYT_RT5640_OVCD_SF_0P75 | |
|---|
| 479 | + BYT_RT5640_SSP0_AIF1 | |
|---|
| 480 | + BYT_RT5640_MCLK_EN), |
|---|
| 481 | + }, |
|---|
| 482 | + { |
|---|
| 483 | + .matches = { |
|---|
| 484 | + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
|---|
| 485 | + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"), |
|---|
| 454 | 486 | }, |
|---|
| 455 | 487 | .driver_data = (void *)(BYT_RT5640_IN1_MAP | |
|---|
| 456 | 488 | BYT_RT5640_JD_SRC_JD2_IN4N | |
|---|
| .. | .. |
|---|
| 587 | 619 | .driver_data = (void *)(BYT_RT5640_IN1_MAP | |
|---|
| 588 | 620 | BYT_RT5640_MCLK_EN), |
|---|
| 589 | 621 | }, |
|---|
| 590 | | - { /* HP Pavilion x2 10-n000nd */ |
|---|
| 622 | + { /* HP Pavilion x2 10-k0XX, 10-n0XX */ |
|---|
| 591 | 623 | .matches = { |
|---|
| 592 | | - DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
|---|
| 593 | | - DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), |
|---|
| 624 | + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
|---|
| 625 | + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), |
|---|
| 626 | + }, |
|---|
| 627 | + .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | |
|---|
| 628 | + BYT_RT5640_JD_SRC_JD2_IN4N | |
|---|
| 629 | + BYT_RT5640_OVCD_TH_1500UA | |
|---|
| 630 | + BYT_RT5640_OVCD_SF_0P75 | |
|---|
| 631 | + BYT_RT5640_SSP0_AIF1 | |
|---|
| 632 | + BYT_RT5640_MCLK_EN), |
|---|
| 633 | + }, |
|---|
| 634 | + { /* HP Pavilion x2 10-p0XX */ |
|---|
| 635 | + .matches = { |
|---|
| 636 | + DMI_MATCH(DMI_SYS_VENDOR, "HP"), |
|---|
| 637 | + DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"), |
|---|
| 638 | + }, |
|---|
| 639 | + .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | |
|---|
| 640 | + BYT_RT5640_JD_SRC_JD1_IN4P | |
|---|
| 641 | + BYT_RT5640_OVCD_TH_2000UA | |
|---|
| 642 | + BYT_RT5640_OVCD_SF_0P75 | |
|---|
| 643 | + BYT_RT5640_MCLK_EN), |
|---|
| 644 | + }, |
|---|
| 645 | + { /* HP Pro Tablet 408 */ |
|---|
| 646 | + .matches = { |
|---|
| 647 | + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
|---|
| 648 | + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pro Tablet 408"), |
|---|
| 594 | 649 | }, |
|---|
| 595 | 650 | .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | |
|---|
| 596 | 651 | BYT_RT5640_JD_SRC_JD2_IN4N | |
|---|
| .. | .. |
|---|
| 780 | 835 | BYT_RT5640_SSP0_AIF2 | |
|---|
| 781 | 836 | BYT_RT5640_MCLK_EN), |
|---|
| 782 | 837 | }, |
|---|
| 838 | + { /* Point of View Mobii TAB-P1005W-232 (V2.0) */ |
|---|
| 839 | + .matches = { |
|---|
| 840 | + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "POV"), |
|---|
| 841 | + DMI_EXACT_MATCH(DMI_BOARD_NAME, "I102A"), |
|---|
| 842 | + }, |
|---|
| 843 | + .driver_data = (void *)(BYT_RT5640_IN1_MAP | |
|---|
| 844 | + BYT_RT5640_JD_SRC_JD2_IN4N | |
|---|
| 845 | + BYT_RT5640_OVCD_TH_2000UA | |
|---|
| 846 | + BYT_RT5640_OVCD_SF_0P75 | |
|---|
| 847 | + BYT_RT5640_DIFF_MIC | |
|---|
| 848 | + BYT_RT5640_SSP0_AIF1 | |
|---|
| 849 | + BYT_RT5640_MCLK_EN), |
|---|
| 850 | + }, |
|---|
| 851 | + { |
|---|
| 852 | + /* Prowise PT301 */ |
|---|
| 853 | + .matches = { |
|---|
| 854 | + DMI_MATCH(DMI_SYS_VENDOR, "Prowise"), |
|---|
| 855 | + DMI_MATCH(DMI_PRODUCT_NAME, "PT301"), |
|---|
| 856 | + }, |
|---|
| 857 | + .driver_data = (void *)(BYT_RT5640_IN1_MAP | |
|---|
| 858 | + BYT_RT5640_JD_SRC_JD2_IN4N | |
|---|
| 859 | + BYT_RT5640_OVCD_TH_2000UA | |
|---|
| 860 | + BYT_RT5640_OVCD_SF_0P75 | |
|---|
| 861 | + BYT_RT5640_DIFF_MIC | |
|---|
| 862 | + BYT_RT5640_SSP0_AIF1 | |
|---|
| 863 | + BYT_RT5640_MCLK_EN), |
|---|
| 864 | + }, |
|---|
| 783 | 865 | { |
|---|
| 784 | 866 | /* Teclast X89 */ |
|---|
| 785 | 867 | .matches = { |
|---|
| .. | .. |
|---|
| 917 | 999 | { |
|---|
| 918 | 1000 | struct snd_soc_card *card = runtime->card; |
|---|
| 919 | 1001 | struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); |
|---|
| 920 | | - struct snd_soc_component *component = runtime->codec_dai->component; |
|---|
| 1002 | + struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; |
|---|
| 921 | 1003 | const struct snd_soc_dapm_route *custom_map; |
|---|
| 922 | 1004 | int num_routes; |
|---|
| 923 | 1005 | int ret; |
|---|
| .. | .. |
|---|
| 991 | 1073 | ret = snd_soc_dapm_add_routes(&card->dapm, |
|---|
| 992 | 1074 | byt_rt5640_mono_spk_map, |
|---|
| 993 | 1075 | ARRAY_SIZE(byt_rt5640_mono_spk_map)); |
|---|
| 994 | | - } else { |
|---|
| 1076 | + } else if (!(byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)) { |
|---|
| 995 | 1077 | ret = snd_soc_dapm_add_routes(&card->dapm, |
|---|
| 996 | 1078 | byt_rt5640_stereo_spk_map, |
|---|
| 997 | 1079 | ARRAY_SIZE(byt_rt5640_stereo_spk_map)); |
|---|
| 998 | 1080 | } |
|---|
| 999 | 1081 | if (ret) |
|---|
| 1000 | 1082 | return ret; |
|---|
| 1001 | | - |
|---|
| 1002 | | - snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone"); |
|---|
| 1003 | | - snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); |
|---|
| 1004 | 1083 | |
|---|
| 1005 | 1084 | if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) { |
|---|
| 1006 | 1085 | /* |
|---|
| .. | .. |
|---|
| 1045 | 1124 | return 0; |
|---|
| 1046 | 1125 | } |
|---|
| 1047 | 1126 | |
|---|
| 1048 | | -static const struct snd_soc_pcm_stream byt_rt5640_dai_params = { |
|---|
| 1049 | | - .formats = SNDRV_PCM_FMTBIT_S24_LE, |
|---|
| 1050 | | - .rate_min = 48000, |
|---|
| 1051 | | - .rate_max = 48000, |
|---|
| 1052 | | - .channels_min = 2, |
|---|
| 1053 | | - .channels_max = 2, |
|---|
| 1054 | | -}; |
|---|
| 1055 | | - |
|---|
| 1056 | 1127 | static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd, |
|---|
| 1057 | 1128 | struct snd_pcm_hw_params *params) |
|---|
| 1058 | 1129 | { |
|---|
| .. | .. |
|---|
| 1060 | 1131 | SNDRV_PCM_HW_PARAM_RATE); |
|---|
| 1061 | 1132 | struct snd_interval *channels = hw_param_interval(params, |
|---|
| 1062 | 1133 | SNDRV_PCM_HW_PARAM_CHANNELS); |
|---|
| 1063 | | - int ret; |
|---|
| 1134 | + int ret, bits; |
|---|
| 1064 | 1135 | |
|---|
| 1065 | 1136 | /* The DSP will covert the FE rate to 48k, stereo */ |
|---|
| 1066 | 1137 | rate->min = rate->max = 48000; |
|---|
| 1067 | 1138 | channels->min = channels->max = 2; |
|---|
| 1068 | 1139 | |
|---|
| 1069 | 1140 | if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || |
|---|
| 1070 | | - (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { |
|---|
| 1071 | | - |
|---|
| 1141 | + (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { |
|---|
| 1072 | 1142 | /* set SSP0 to 16-bit */ |
|---|
| 1073 | 1143 | params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); |
|---|
| 1074 | | - |
|---|
| 1075 | | - /* |
|---|
| 1076 | | - * Default mode for SSP configuration is TDM 4 slot, override config |
|---|
| 1077 | | - * with explicit setting to I2S 2ch 16-bit. The word length is set with |
|---|
| 1078 | | - * dai_set_tdm_slot() since there is no other API exposed |
|---|
| 1079 | | - */ |
|---|
| 1080 | | - ret = snd_soc_dai_set_fmt(rtd->cpu_dai, |
|---|
| 1081 | | - SND_SOC_DAIFMT_I2S | |
|---|
| 1082 | | - SND_SOC_DAIFMT_NB_NF | |
|---|
| 1083 | | - SND_SOC_DAIFMT_CBS_CFS |
|---|
| 1084 | | - ); |
|---|
| 1085 | | - if (ret < 0) { |
|---|
| 1086 | | - dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); |
|---|
| 1087 | | - return ret; |
|---|
| 1088 | | - } |
|---|
| 1089 | | - |
|---|
| 1090 | | - ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 16); |
|---|
| 1091 | | - if (ret < 0) { |
|---|
| 1092 | | - dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); |
|---|
| 1093 | | - return ret; |
|---|
| 1094 | | - } |
|---|
| 1095 | | - |
|---|
| 1144 | + bits = 16; |
|---|
| 1096 | 1145 | } else { |
|---|
| 1097 | | - |
|---|
| 1098 | 1146 | /* set SSP2 to 24-bit */ |
|---|
| 1099 | 1147 | params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); |
|---|
| 1100 | | - |
|---|
| 1101 | | - /* |
|---|
| 1102 | | - * Default mode for SSP configuration is TDM 4 slot, override config |
|---|
| 1103 | | - * with explicit setting to I2S 2ch 24-bit. The word length is set with |
|---|
| 1104 | | - * dai_set_tdm_slot() since there is no other API exposed |
|---|
| 1105 | | - */ |
|---|
| 1106 | | - ret = snd_soc_dai_set_fmt(rtd->cpu_dai, |
|---|
| 1107 | | - SND_SOC_DAIFMT_I2S | |
|---|
| 1108 | | - SND_SOC_DAIFMT_NB_NF | |
|---|
| 1109 | | - SND_SOC_DAIFMT_CBS_CFS |
|---|
| 1110 | | - ); |
|---|
| 1111 | | - if (ret < 0) { |
|---|
| 1112 | | - dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); |
|---|
| 1113 | | - return ret; |
|---|
| 1114 | | - } |
|---|
| 1115 | | - |
|---|
| 1116 | | - ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24); |
|---|
| 1117 | | - if (ret < 0) { |
|---|
| 1118 | | - dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); |
|---|
| 1119 | | - return ret; |
|---|
| 1120 | | - } |
|---|
| 1148 | + bits = 24; |
|---|
| 1121 | 1149 | } |
|---|
| 1150 | + |
|---|
| 1151 | + /* |
|---|
| 1152 | + * Default mode for SSP configuration is TDM 4 slot, override config |
|---|
| 1153 | + * with explicit setting to I2S 2ch. The word length is set with |
|---|
| 1154 | + * dai_set_tdm_slot() since there is no other API exposed |
|---|
| 1155 | + */ |
|---|
| 1156 | + ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), |
|---|
| 1157 | + SND_SOC_DAIFMT_I2S | |
|---|
| 1158 | + SND_SOC_DAIFMT_NB_NF | |
|---|
| 1159 | + SND_SOC_DAIFMT_CBS_CFS); |
|---|
| 1160 | + if (ret < 0) { |
|---|
| 1161 | + dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); |
|---|
| 1162 | + return ret; |
|---|
| 1163 | + } |
|---|
| 1164 | + |
|---|
| 1165 | + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits); |
|---|
| 1166 | + if (ret < 0) { |
|---|
| 1167 | + dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); |
|---|
| 1168 | + return ret; |
|---|
| 1169 | + } |
|---|
| 1170 | + |
|---|
| 1122 | 1171 | return 0; |
|---|
| 1123 | 1172 | } |
|---|
| 1124 | 1173 | |
|---|
| .. | .. |
|---|
| 1136 | 1185 | .hw_params = byt_rt5640_aif1_hw_params, |
|---|
| 1137 | 1186 | }; |
|---|
| 1138 | 1187 | |
|---|
| 1188 | +SND_SOC_DAILINK_DEF(dummy, |
|---|
| 1189 | + DAILINK_COMP_ARRAY(COMP_DUMMY())); |
|---|
| 1190 | + |
|---|
| 1191 | +SND_SOC_DAILINK_DEF(media, |
|---|
| 1192 | + DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai"))); |
|---|
| 1193 | + |
|---|
| 1194 | +SND_SOC_DAILINK_DEF(deepbuffer, |
|---|
| 1195 | + DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai"))); |
|---|
| 1196 | + |
|---|
| 1197 | +SND_SOC_DAILINK_DEF(ssp2_port, |
|---|
| 1198 | + /* overwritten for ssp0 routing */ |
|---|
| 1199 | + DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port"))); |
|---|
| 1200 | +SND_SOC_DAILINK_DEF(ssp2_codec, |
|---|
| 1201 | + DAILINK_COMP_ARRAY(COMP_CODEC( |
|---|
| 1202 | + /* overwritten with HID */ "i2c-10EC5640:00", |
|---|
| 1203 | + /* changed w/ quirk */ "rt5640-aif1"))); |
|---|
| 1204 | + |
|---|
| 1205 | +SND_SOC_DAILINK_DEF(platform, |
|---|
| 1206 | + DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform"))); |
|---|
| 1207 | + |
|---|
| 1139 | 1208 | static struct snd_soc_dai_link byt_rt5640_dais[] = { |
|---|
| 1140 | 1209 | [MERR_DPCM_AUDIO] = { |
|---|
| 1141 | 1210 | .name = "Baytrail Audio Port", |
|---|
| 1142 | 1211 | .stream_name = "Baytrail Audio", |
|---|
| 1143 | | - .cpu_dai_name = "media-cpu-dai", |
|---|
| 1144 | | - .codec_dai_name = "snd-soc-dummy-dai", |
|---|
| 1145 | | - .codec_name = "snd-soc-dummy", |
|---|
| 1146 | | - .platform_name = "sst-mfld-platform", |
|---|
| 1147 | 1212 | .nonatomic = true, |
|---|
| 1148 | 1213 | .dynamic = 1, |
|---|
| 1149 | 1214 | .dpcm_playback = 1, |
|---|
| 1150 | 1215 | .dpcm_capture = 1, |
|---|
| 1151 | 1216 | .ops = &byt_rt5640_aif1_ops, |
|---|
| 1217 | + SND_SOC_DAILINK_REG(media, dummy, platform), |
|---|
| 1152 | 1218 | }, |
|---|
| 1153 | 1219 | [MERR_DPCM_DEEP_BUFFER] = { |
|---|
| 1154 | 1220 | .name = "Deep-Buffer Audio Port", |
|---|
| 1155 | 1221 | .stream_name = "Deep-Buffer Audio", |
|---|
| 1156 | | - .cpu_dai_name = "deepbuffer-cpu-dai", |
|---|
| 1157 | | - .codec_dai_name = "snd-soc-dummy-dai", |
|---|
| 1158 | | - .codec_name = "snd-soc-dummy", |
|---|
| 1159 | | - .platform_name = "sst-mfld-platform", |
|---|
| 1160 | 1222 | .nonatomic = true, |
|---|
| 1161 | 1223 | .dynamic = 1, |
|---|
| 1162 | 1224 | .dpcm_playback = 1, |
|---|
| 1163 | 1225 | .ops = &byt_rt5640_aif1_ops, |
|---|
| 1226 | + SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), |
|---|
| 1164 | 1227 | }, |
|---|
| 1165 | 1228 | /* back ends */ |
|---|
| 1166 | 1229 | { |
|---|
| 1167 | 1230 | .name = "SSP2-Codec", |
|---|
| 1168 | 1231 | .id = 0, |
|---|
| 1169 | | - .cpu_dai_name = "ssp2-port", /* overwritten for ssp0 routing */ |
|---|
| 1170 | | - .platform_name = "sst-mfld-platform", |
|---|
| 1171 | 1232 | .no_pcm = 1, |
|---|
| 1172 | | - .codec_dai_name = "rt5640-aif1", /* changed w/ quirk */ |
|---|
| 1173 | | - .codec_name = "i2c-10EC5640:00", /* overwritten with HID */ |
|---|
| 1174 | 1233 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
|---|
| 1175 | 1234 | | SND_SOC_DAIFMT_CBS_CFS, |
|---|
| 1176 | 1235 | .be_hw_params_fixup = byt_rt5640_codec_fixup, |
|---|
| 1177 | | - .ignore_suspend = 1, |
|---|
| 1178 | 1236 | .nonatomic = true, |
|---|
| 1179 | 1237 | .dpcm_playback = 1, |
|---|
| 1180 | 1238 | .dpcm_capture = 1, |
|---|
| 1181 | 1239 | .init = byt_rt5640_init, |
|---|
| 1182 | 1240 | .ops = &byt_rt5640_be_ssp2_ops, |
|---|
| 1241 | + SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), |
|---|
| 1183 | 1242 | }, |
|---|
| 1184 | 1243 | }; |
|---|
| 1185 | 1244 | |
|---|
| 1186 | 1245 | /* SoC card */ |
|---|
| 1187 | 1246 | static char byt_rt5640_codec_name[SND_ACPI_I2C_ID_LEN]; |
|---|
| 1188 | | -static char byt_rt5640_codec_aif_name[12]; /* = "rt5640-aif[1|2]" */ |
|---|
| 1189 | | -static char byt_rt5640_cpu_dai_name[10]; /* = "ssp[0|2]-port" */ |
|---|
| 1247 | +#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES) |
|---|
| 1190 | 1248 | static char byt_rt5640_long_name[40]; /* = "bytcr-rt5640-*-spk-*-mic" */ |
|---|
| 1249 | +#endif |
|---|
| 1250 | +static char byt_rt5640_components[32]; /* = "cfg-spk:* cfg-mic:*" */ |
|---|
| 1191 | 1251 | |
|---|
| 1192 | 1252 | static int byt_rt5640_suspend(struct snd_soc_card *card) |
|---|
| 1193 | 1253 | { |
|---|
| .. | .. |
|---|
| 1196 | 1256 | if (!BYT_RT5640_JDSRC(byt_rt5640_quirk)) |
|---|
| 1197 | 1257 | return 0; |
|---|
| 1198 | 1258 | |
|---|
| 1199 | | - list_for_each_entry(component, &card->component_dev_list, card_list) { |
|---|
| 1259 | + for_each_card_components(card, component) { |
|---|
| 1200 | 1260 | if (!strcmp(component->name, byt_rt5640_codec_name)) { |
|---|
| 1201 | 1261 | dev_dbg(component->dev, "disabling jack detect before suspend\n"); |
|---|
| 1202 | 1262 | snd_soc_component_set_jack(component, NULL, NULL); |
|---|
| .. | .. |
|---|
| 1215 | 1275 | if (!BYT_RT5640_JDSRC(byt_rt5640_quirk)) |
|---|
| 1216 | 1276 | return 0; |
|---|
| 1217 | 1277 | |
|---|
| 1218 | | - list_for_each_entry(component, &card->component_dev_list, card_list) { |
|---|
| 1278 | + for_each_card_components(card, component) { |
|---|
| 1219 | 1279 | if (!strcmp(component->name, byt_rt5640_codec_name)) { |
|---|
| 1220 | 1280 | dev_dbg(component->dev, "re-enabling jack detect after resume\n"); |
|---|
| 1221 | 1281 | snd_soc_component_set_jack(component, &priv->jack, NULL); |
|---|
| .. | .. |
|---|
| 1226 | 1286 | return 0; |
|---|
| 1227 | 1287 | } |
|---|
| 1228 | 1288 | |
|---|
| 1289 | +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) |
|---|
| 1290 | +/* use space before codec name to simplify card ID, and simplify driver name */ |
|---|
| 1291 | +#define CARD_NAME "bytcht rt5640" /* card name will be 'sof-bytcht rt5640' */ |
|---|
| 1292 | +#define DRIVER_NAME "SOF" |
|---|
| 1293 | +#else |
|---|
| 1294 | +#define CARD_NAME "bytcr-rt5640" |
|---|
| 1295 | +#define DRIVER_NAME NULL /* card name will be used for driver name */ |
|---|
| 1296 | +#endif |
|---|
| 1297 | + |
|---|
| 1229 | 1298 | static struct snd_soc_card byt_rt5640_card = { |
|---|
| 1230 | | - .name = "bytcr-rt5640", |
|---|
| 1299 | + .name = CARD_NAME, |
|---|
| 1300 | + .driver_name = DRIVER_NAME, |
|---|
| 1231 | 1301 | .owner = THIS_MODULE, |
|---|
| 1232 | 1302 | .dai_link = byt_rt5640_dais, |
|---|
| 1233 | 1303 | .num_links = ARRAY_SIZE(byt_rt5640_dais), |
|---|
| .. | .. |
|---|
| 1240 | 1310 | .resume_post = byt_rt5640_resume, |
|---|
| 1241 | 1311 | }; |
|---|
| 1242 | 1312 | |
|---|
| 1243 | | -static bool is_valleyview(void) |
|---|
| 1244 | | -{ |
|---|
| 1245 | | - static const struct x86_cpu_id cpu_ids[] = { |
|---|
| 1246 | | - { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */ |
|---|
| 1247 | | - {} |
|---|
| 1248 | | - }; |
|---|
| 1249 | | - |
|---|
| 1250 | | - if (!x86_match_cpu(cpu_ids)) |
|---|
| 1251 | | - return false; |
|---|
| 1252 | | - return true; |
|---|
| 1253 | | -} |
|---|
| 1254 | | - |
|---|
| 1255 | 1313 | struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */ |
|---|
| 1256 | 1314 | u64 aif_value; /* 1: AIF1, 2: AIF2 */ |
|---|
| 1257 | 1315 | u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */ |
|---|
| .. | .. |
|---|
| 1259 | 1317 | |
|---|
| 1260 | 1318 | static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) |
|---|
| 1261 | 1319 | { |
|---|
| 1262 | | - const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3" }; |
|---|
| 1320 | + static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3" }; |
|---|
| 1321 | + __maybe_unused const char *spk_type; |
|---|
| 1263 | 1322 | const struct dmi_system_id *dmi_id; |
|---|
| 1264 | 1323 | struct byt_rt5640_private *priv; |
|---|
| 1265 | 1324 | struct snd_soc_acpi_mach *mach; |
|---|
| 1266 | | - const char *i2c_name = NULL; |
|---|
| 1325 | + const char *platform_name; |
|---|
| 1326 | + struct acpi_device *adev; |
|---|
| 1267 | 1327 | int ret_val = 0; |
|---|
| 1268 | 1328 | int dai_index = 0; |
|---|
| 1269 | | - int i; |
|---|
| 1329 | + int i, cfg_spk; |
|---|
| 1270 | 1330 | |
|---|
| 1271 | 1331 | is_bytcr = false; |
|---|
| 1272 | 1332 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 1280 | 1340 | |
|---|
| 1281 | 1341 | /* fix index of codec dai */ |
|---|
| 1282 | 1342 | for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) { |
|---|
| 1283 | | - if (!strcmp(byt_rt5640_dais[i].codec_name, "i2c-10EC5640:00")) { |
|---|
| 1343 | + if (!strcmp(byt_rt5640_dais[i].codecs->name, |
|---|
| 1344 | + "i2c-10EC5640:00")) { |
|---|
| 1284 | 1345 | dai_index = i; |
|---|
| 1285 | 1346 | break; |
|---|
| 1286 | 1347 | } |
|---|
| 1287 | 1348 | } |
|---|
| 1288 | 1349 | |
|---|
| 1289 | 1350 | /* fixup codec name based on HID */ |
|---|
| 1290 | | - i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1); |
|---|
| 1291 | | - if (i2c_name) { |
|---|
| 1351 | + adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1); |
|---|
| 1352 | + if (adev) { |
|---|
| 1292 | 1353 | snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name), |
|---|
| 1293 | | - "%s%s", "i2c-", i2c_name); |
|---|
| 1294 | | - |
|---|
| 1295 | | - byt_rt5640_dais[dai_index].codec_name = byt_rt5640_codec_name; |
|---|
| 1354 | + "i2c-%s", acpi_dev_name(adev)); |
|---|
| 1355 | + put_device(&adev->dev); |
|---|
| 1356 | + byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name; |
|---|
| 1296 | 1357 | } |
|---|
| 1297 | 1358 | |
|---|
| 1298 | 1359 | /* |
|---|
| 1299 | 1360 | * swap SSP0 if bytcr is detected |
|---|
| 1300 | 1361 | * (will be overridden if DMI quirk is detected) |
|---|
| 1301 | 1362 | */ |
|---|
| 1302 | | - if (is_valleyview()) { |
|---|
| 1303 | | - struct sst_platform_info *p_info = mach->pdata; |
|---|
| 1304 | | - const struct sst_res_info *res_info = p_info->res_info; |
|---|
| 1305 | | - |
|---|
| 1306 | | - if (res_info->acpi_ipc_irq_index == 0) |
|---|
| 1363 | + if (soc_intel_is_byt()) { |
|---|
| 1364 | + if (mach->mach_params.acpi_ipc_irq_index == 0) |
|---|
| 1307 | 1365 | is_bytcr = true; |
|---|
| 1308 | 1366 | } |
|---|
| 1309 | 1367 | |
|---|
| .. | .. |
|---|
| 1366 | 1424 | dmi_id = dmi_first_match(byt_rt5640_quirk_table); |
|---|
| 1367 | 1425 | if (dmi_id) |
|---|
| 1368 | 1426 | byt_rt5640_quirk = (unsigned long)dmi_id->driver_data; |
|---|
| 1369 | | - if (quirk_override) { |
|---|
| 1370 | | - dev_info(&pdev->dev, "Overriding quirk 0x%x => 0x%x\n", |
|---|
| 1371 | | - (unsigned int)byt_rt5640_quirk, quirk_override); |
|---|
| 1427 | + if (quirk_override != -1) { |
|---|
| 1428 | + dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n", |
|---|
| 1429 | + byt_rt5640_quirk, quirk_override); |
|---|
| 1372 | 1430 | byt_rt5640_quirk = quirk_override; |
|---|
| 1373 | 1431 | } |
|---|
| 1374 | 1432 | |
|---|
| .. | .. |
|---|
| 1380 | 1438 | log_quirks(&pdev->dev); |
|---|
| 1381 | 1439 | |
|---|
| 1382 | 1440 | if ((byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) || |
|---|
| 1383 | | - (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { |
|---|
| 1384 | | - |
|---|
| 1385 | | - /* fixup codec aif name */ |
|---|
| 1386 | | - snprintf(byt_rt5640_codec_aif_name, |
|---|
| 1387 | | - sizeof(byt_rt5640_codec_aif_name), |
|---|
| 1388 | | - "%s", "rt5640-aif2"); |
|---|
| 1389 | | - |
|---|
| 1390 | | - byt_rt5640_dais[dai_index].codec_dai_name = |
|---|
| 1391 | | - byt_rt5640_codec_aif_name; |
|---|
| 1392 | | - } |
|---|
| 1441 | + (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) |
|---|
| 1442 | + byt_rt5640_dais[dai_index].codecs->dai_name = "rt5640-aif2"; |
|---|
| 1393 | 1443 | |
|---|
| 1394 | 1444 | if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || |
|---|
| 1395 | | - (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { |
|---|
| 1396 | | - |
|---|
| 1397 | | - /* fixup cpu dai name name */ |
|---|
| 1398 | | - snprintf(byt_rt5640_cpu_dai_name, |
|---|
| 1399 | | - sizeof(byt_rt5640_cpu_dai_name), |
|---|
| 1400 | | - "%s", "ssp0-port"); |
|---|
| 1401 | | - |
|---|
| 1402 | | - byt_rt5640_dais[dai_index].cpu_dai_name = |
|---|
| 1403 | | - byt_rt5640_cpu_dai_name; |
|---|
| 1404 | | - } |
|---|
| 1445 | + (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) |
|---|
| 1446 | + byt_rt5640_dais[dai_index].cpus->dai_name = "ssp0-port"; |
|---|
| 1405 | 1447 | |
|---|
| 1406 | 1448 | if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) { |
|---|
| 1407 | 1449 | priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); |
|---|
| .. | .. |
|---|
| 1423 | 1465 | } |
|---|
| 1424 | 1466 | } |
|---|
| 1425 | 1467 | |
|---|
| 1468 | + if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) { |
|---|
| 1469 | + cfg_spk = 0; |
|---|
| 1470 | + spk_type = "none"; |
|---|
| 1471 | + } else if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) { |
|---|
| 1472 | + cfg_spk = 1; |
|---|
| 1473 | + spk_type = "mono"; |
|---|
| 1474 | + } else { |
|---|
| 1475 | + cfg_spk = 2; |
|---|
| 1476 | + spk_type = "stereo"; |
|---|
| 1477 | + } |
|---|
| 1478 | + |
|---|
| 1479 | + snprintf(byt_rt5640_components, sizeof(byt_rt5640_components), |
|---|
| 1480 | + "cfg-spk:%d cfg-mic:%s", cfg_spk, |
|---|
| 1481 | + map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]); |
|---|
| 1482 | + byt_rt5640_card.components = byt_rt5640_components; |
|---|
| 1483 | +#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES) |
|---|
| 1426 | 1484 | snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name), |
|---|
| 1427 | | - "bytcr-rt5640-%s-spk-%s-mic", |
|---|
| 1428 | | - (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) ? |
|---|
| 1429 | | - "mono" : "stereo", |
|---|
| 1485 | + "bytcr-rt5640-%s-spk-%s-mic", spk_type, |
|---|
| 1430 | 1486 | map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]); |
|---|
| 1431 | 1487 | byt_rt5640_card.long_name = byt_rt5640_long_name; |
|---|
| 1488 | +#endif |
|---|
| 1489 | + |
|---|
| 1490 | + /* override plaform name, if required */ |
|---|
| 1491 | + platform_name = mach->mach_params.platform; |
|---|
| 1492 | + |
|---|
| 1493 | + ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5640_card, |
|---|
| 1494 | + platform_name); |
|---|
| 1495 | + if (ret_val) |
|---|
| 1496 | + return ret_val; |
|---|
| 1432 | 1497 | |
|---|
| 1433 | 1498 | ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card); |
|---|
| 1434 | 1499 | |
|---|
| .. | .. |
|---|
| 1444 | 1509 | static struct platform_driver snd_byt_rt5640_mc_driver = { |
|---|
| 1445 | 1510 | .driver = { |
|---|
| 1446 | 1511 | .name = "bytcr_rt5640", |
|---|
| 1512 | +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) |
|---|
| 1513 | + .pm = &snd_soc_pm_ops, |
|---|
| 1514 | +#endif |
|---|
| 1447 | 1515 | }, |
|---|
| 1448 | 1516 | .probe = snd_byt_rt5640_mc_probe, |
|---|
| 1449 | 1517 | }; |
|---|