| .. | .. |
|---|
| 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 | } |
|---|
| .. | .. |
|---|
| 451 | 444 | .matches = { |
|---|
| 452 | 445 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"), |
|---|
| 453 | 446 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 140 CESIUM"), |
|---|
| 447 | + }, |
|---|
| 448 | + .driver_data = (void *)(BYT_RT5640_IN1_MAP | |
|---|
| 449 | + BYT_RT5640_JD_SRC_JD2_IN4N | |
|---|
| 450 | + BYT_RT5640_OVCD_TH_2000UA | |
|---|
| 451 | + BYT_RT5640_OVCD_SF_0P75 | |
|---|
| 452 | + BYT_RT5640_SSP0_AIF1 | |
|---|
| 453 | + BYT_RT5640_MCLK_EN), |
|---|
| 454 | + }, |
|---|
| 455 | + { |
|---|
| 456 | + .matches = { |
|---|
| 457 | + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
|---|
| 458 | + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"), |
|---|
| 454 | 459 | }, |
|---|
| 455 | 460 | .driver_data = (void *)(BYT_RT5640_IN1_MAP | |
|---|
| 456 | 461 | BYT_RT5640_JD_SRC_JD2_IN4N | |
|---|
| .. | .. |
|---|
| 587 | 592 | .driver_data = (void *)(BYT_RT5640_IN1_MAP | |
|---|
| 588 | 593 | BYT_RT5640_MCLK_EN), |
|---|
| 589 | 594 | }, |
|---|
| 590 | | - { /* HP Pavilion x2 10-n000nd */ |
|---|
| 595 | + { /* HP Pavilion x2 10-k0XX, 10-n0XX */ |
|---|
| 591 | 596 | .matches = { |
|---|
| 592 | | - DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
|---|
| 593 | | - DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), |
|---|
| 597 | + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
|---|
| 598 | + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), |
|---|
| 599 | + }, |
|---|
| 600 | + .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | |
|---|
| 601 | + BYT_RT5640_JD_SRC_JD2_IN4N | |
|---|
| 602 | + BYT_RT5640_OVCD_TH_1500UA | |
|---|
| 603 | + BYT_RT5640_OVCD_SF_0P75 | |
|---|
| 604 | + BYT_RT5640_SSP0_AIF1 | |
|---|
| 605 | + BYT_RT5640_MCLK_EN), |
|---|
| 606 | + }, |
|---|
| 607 | + { /* HP Pavilion x2 10-p0XX */ |
|---|
| 608 | + .matches = { |
|---|
| 609 | + DMI_MATCH(DMI_SYS_VENDOR, "HP"), |
|---|
| 610 | + DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"), |
|---|
| 611 | + }, |
|---|
| 612 | + .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | |
|---|
| 613 | + BYT_RT5640_JD_SRC_JD1_IN4P | |
|---|
| 614 | + BYT_RT5640_OVCD_TH_2000UA | |
|---|
| 615 | + BYT_RT5640_OVCD_SF_0P75 | |
|---|
| 616 | + BYT_RT5640_MCLK_EN), |
|---|
| 617 | + }, |
|---|
| 618 | + { /* HP Pro Tablet 408 */ |
|---|
| 619 | + .matches = { |
|---|
| 620 | + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
|---|
| 621 | + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pro Tablet 408"), |
|---|
| 594 | 622 | }, |
|---|
| 595 | 623 | .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | |
|---|
| 596 | 624 | BYT_RT5640_JD_SRC_JD2_IN4N | |
|---|
| .. | .. |
|---|
| 780 | 808 | BYT_RT5640_SSP0_AIF2 | |
|---|
| 781 | 809 | BYT_RT5640_MCLK_EN), |
|---|
| 782 | 810 | }, |
|---|
| 811 | + { /* Point of View Mobii TAB-P1005W-232 (V2.0) */ |
|---|
| 812 | + .matches = { |
|---|
| 813 | + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "POV"), |
|---|
| 814 | + DMI_EXACT_MATCH(DMI_BOARD_NAME, "I102A"), |
|---|
| 815 | + }, |
|---|
| 816 | + .driver_data = (void *)(BYT_RT5640_IN1_MAP | |
|---|
| 817 | + BYT_RT5640_JD_SRC_JD2_IN4N | |
|---|
| 818 | + BYT_RT5640_OVCD_TH_2000UA | |
|---|
| 819 | + BYT_RT5640_OVCD_SF_0P75 | |
|---|
| 820 | + BYT_RT5640_DIFF_MIC | |
|---|
| 821 | + BYT_RT5640_SSP0_AIF1 | |
|---|
| 822 | + BYT_RT5640_MCLK_EN), |
|---|
| 823 | + }, |
|---|
| 824 | + { |
|---|
| 825 | + /* Prowise PT301 */ |
|---|
| 826 | + .matches = { |
|---|
| 827 | + DMI_MATCH(DMI_SYS_VENDOR, "Prowise"), |
|---|
| 828 | + DMI_MATCH(DMI_PRODUCT_NAME, "PT301"), |
|---|
| 829 | + }, |
|---|
| 830 | + .driver_data = (void *)(BYT_RT5640_IN1_MAP | |
|---|
| 831 | + BYT_RT5640_JD_SRC_JD2_IN4N | |
|---|
| 832 | + BYT_RT5640_OVCD_TH_2000UA | |
|---|
| 833 | + BYT_RT5640_OVCD_SF_0P75 | |
|---|
| 834 | + BYT_RT5640_DIFF_MIC | |
|---|
| 835 | + BYT_RT5640_SSP0_AIF1 | |
|---|
| 836 | + BYT_RT5640_MCLK_EN), |
|---|
| 837 | + }, |
|---|
| 783 | 838 | { |
|---|
| 784 | 839 | /* Teclast X89 */ |
|---|
| 785 | 840 | .matches = { |
|---|
| .. | .. |
|---|
| 917 | 972 | { |
|---|
| 918 | 973 | struct snd_soc_card *card = runtime->card; |
|---|
| 919 | 974 | struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); |
|---|
| 920 | | - struct snd_soc_component *component = runtime->codec_dai->component; |
|---|
| 975 | + struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; |
|---|
| 921 | 976 | const struct snd_soc_dapm_route *custom_map; |
|---|
| 922 | 977 | int num_routes; |
|---|
| 923 | 978 | int ret; |
|---|
| .. | .. |
|---|
| 991 | 1046 | ret = snd_soc_dapm_add_routes(&card->dapm, |
|---|
| 992 | 1047 | byt_rt5640_mono_spk_map, |
|---|
| 993 | 1048 | ARRAY_SIZE(byt_rt5640_mono_spk_map)); |
|---|
| 994 | | - } else { |
|---|
| 1049 | + } else if (!(byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)) { |
|---|
| 995 | 1050 | ret = snd_soc_dapm_add_routes(&card->dapm, |
|---|
| 996 | 1051 | byt_rt5640_stereo_spk_map, |
|---|
| 997 | 1052 | ARRAY_SIZE(byt_rt5640_stereo_spk_map)); |
|---|
| 998 | 1053 | } |
|---|
| 999 | 1054 | if (ret) |
|---|
| 1000 | 1055 | return ret; |
|---|
| 1001 | | - |
|---|
| 1002 | | - snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone"); |
|---|
| 1003 | | - snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); |
|---|
| 1004 | 1056 | |
|---|
| 1005 | 1057 | if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) { |
|---|
| 1006 | 1058 | /* |
|---|
| .. | .. |
|---|
| 1045 | 1097 | return 0; |
|---|
| 1046 | 1098 | } |
|---|
| 1047 | 1099 | |
|---|
| 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 | 1100 | static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd, |
|---|
| 1057 | 1101 | struct snd_pcm_hw_params *params) |
|---|
| 1058 | 1102 | { |
|---|
| .. | .. |
|---|
| 1060 | 1104 | SNDRV_PCM_HW_PARAM_RATE); |
|---|
| 1061 | 1105 | struct snd_interval *channels = hw_param_interval(params, |
|---|
| 1062 | 1106 | SNDRV_PCM_HW_PARAM_CHANNELS); |
|---|
| 1063 | | - int ret; |
|---|
| 1107 | + int ret, bits; |
|---|
| 1064 | 1108 | |
|---|
| 1065 | 1109 | /* The DSP will covert the FE rate to 48k, stereo */ |
|---|
| 1066 | 1110 | rate->min = rate->max = 48000; |
|---|
| 1067 | 1111 | channels->min = channels->max = 2; |
|---|
| 1068 | 1112 | |
|---|
| 1069 | 1113 | if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || |
|---|
| 1070 | | - (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { |
|---|
| 1071 | | - |
|---|
| 1114 | + (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { |
|---|
| 1072 | 1115 | /* set SSP0 to 16-bit */ |
|---|
| 1073 | 1116 | 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 | | - |
|---|
| 1117 | + bits = 16; |
|---|
| 1096 | 1118 | } else { |
|---|
| 1097 | | - |
|---|
| 1098 | 1119 | /* set SSP2 to 24-bit */ |
|---|
| 1099 | 1120 | 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 | | - } |
|---|
| 1121 | + bits = 24; |
|---|
| 1121 | 1122 | } |
|---|
| 1123 | + |
|---|
| 1124 | + /* |
|---|
| 1125 | + * Default mode for SSP configuration is TDM 4 slot, override config |
|---|
| 1126 | + * with explicit setting to I2S 2ch. The word length is set with |
|---|
| 1127 | + * dai_set_tdm_slot() since there is no other API exposed |
|---|
| 1128 | + */ |
|---|
| 1129 | + ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), |
|---|
| 1130 | + SND_SOC_DAIFMT_I2S | |
|---|
| 1131 | + SND_SOC_DAIFMT_NB_NF | |
|---|
| 1132 | + SND_SOC_DAIFMT_CBS_CFS); |
|---|
| 1133 | + if (ret < 0) { |
|---|
| 1134 | + dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); |
|---|
| 1135 | + return ret; |
|---|
| 1136 | + } |
|---|
| 1137 | + |
|---|
| 1138 | + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits); |
|---|
| 1139 | + if (ret < 0) { |
|---|
| 1140 | + dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); |
|---|
| 1141 | + return ret; |
|---|
| 1142 | + } |
|---|
| 1143 | + |
|---|
| 1122 | 1144 | return 0; |
|---|
| 1123 | 1145 | } |
|---|
| 1124 | 1146 | |
|---|
| .. | .. |
|---|
| 1136 | 1158 | .hw_params = byt_rt5640_aif1_hw_params, |
|---|
| 1137 | 1159 | }; |
|---|
| 1138 | 1160 | |
|---|
| 1161 | +SND_SOC_DAILINK_DEF(dummy, |
|---|
| 1162 | + DAILINK_COMP_ARRAY(COMP_DUMMY())); |
|---|
| 1163 | + |
|---|
| 1164 | +SND_SOC_DAILINK_DEF(media, |
|---|
| 1165 | + DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai"))); |
|---|
| 1166 | + |
|---|
| 1167 | +SND_SOC_DAILINK_DEF(deepbuffer, |
|---|
| 1168 | + DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai"))); |
|---|
| 1169 | + |
|---|
| 1170 | +SND_SOC_DAILINK_DEF(ssp2_port, |
|---|
| 1171 | + /* overwritten for ssp0 routing */ |
|---|
| 1172 | + DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port"))); |
|---|
| 1173 | +SND_SOC_DAILINK_DEF(ssp2_codec, |
|---|
| 1174 | + DAILINK_COMP_ARRAY(COMP_CODEC( |
|---|
| 1175 | + /* overwritten with HID */ "i2c-10EC5640:00", |
|---|
| 1176 | + /* changed w/ quirk */ "rt5640-aif1"))); |
|---|
| 1177 | + |
|---|
| 1178 | +SND_SOC_DAILINK_DEF(platform, |
|---|
| 1179 | + DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform"))); |
|---|
| 1180 | + |
|---|
| 1139 | 1181 | static struct snd_soc_dai_link byt_rt5640_dais[] = { |
|---|
| 1140 | 1182 | [MERR_DPCM_AUDIO] = { |
|---|
| 1141 | 1183 | .name = "Baytrail Audio Port", |
|---|
| 1142 | 1184 | .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 | 1185 | .nonatomic = true, |
|---|
| 1148 | 1186 | .dynamic = 1, |
|---|
| 1149 | 1187 | .dpcm_playback = 1, |
|---|
| 1150 | 1188 | .dpcm_capture = 1, |
|---|
| 1151 | 1189 | .ops = &byt_rt5640_aif1_ops, |
|---|
| 1190 | + SND_SOC_DAILINK_REG(media, dummy, platform), |
|---|
| 1152 | 1191 | }, |
|---|
| 1153 | 1192 | [MERR_DPCM_DEEP_BUFFER] = { |
|---|
| 1154 | 1193 | .name = "Deep-Buffer Audio Port", |
|---|
| 1155 | 1194 | .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 | 1195 | .nonatomic = true, |
|---|
| 1161 | 1196 | .dynamic = 1, |
|---|
| 1162 | 1197 | .dpcm_playback = 1, |
|---|
| 1163 | 1198 | .ops = &byt_rt5640_aif1_ops, |
|---|
| 1199 | + SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), |
|---|
| 1164 | 1200 | }, |
|---|
| 1165 | 1201 | /* back ends */ |
|---|
| 1166 | 1202 | { |
|---|
| 1167 | 1203 | .name = "SSP2-Codec", |
|---|
| 1168 | 1204 | .id = 0, |
|---|
| 1169 | | - .cpu_dai_name = "ssp2-port", /* overwritten for ssp0 routing */ |
|---|
| 1170 | | - .platform_name = "sst-mfld-platform", |
|---|
| 1171 | 1205 | .no_pcm = 1, |
|---|
| 1172 | | - .codec_dai_name = "rt5640-aif1", /* changed w/ quirk */ |
|---|
| 1173 | | - .codec_name = "i2c-10EC5640:00", /* overwritten with HID */ |
|---|
| 1174 | 1206 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
|---|
| 1175 | 1207 | | SND_SOC_DAIFMT_CBS_CFS, |
|---|
| 1176 | 1208 | .be_hw_params_fixup = byt_rt5640_codec_fixup, |
|---|
| 1177 | | - .ignore_suspend = 1, |
|---|
| 1178 | 1209 | .nonatomic = true, |
|---|
| 1179 | 1210 | .dpcm_playback = 1, |
|---|
| 1180 | 1211 | .dpcm_capture = 1, |
|---|
| 1181 | 1212 | .init = byt_rt5640_init, |
|---|
| 1182 | 1213 | .ops = &byt_rt5640_be_ssp2_ops, |
|---|
| 1214 | + SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), |
|---|
| 1183 | 1215 | }, |
|---|
| 1184 | 1216 | }; |
|---|
| 1185 | 1217 | |
|---|
| 1186 | 1218 | /* SoC card */ |
|---|
| 1187 | 1219 | 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" */ |
|---|
| 1220 | +#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES) |
|---|
| 1190 | 1221 | static char byt_rt5640_long_name[40]; /* = "bytcr-rt5640-*-spk-*-mic" */ |
|---|
| 1222 | +#endif |
|---|
| 1223 | +static char byt_rt5640_components[32]; /* = "cfg-spk:* cfg-mic:*" */ |
|---|
| 1191 | 1224 | |
|---|
| 1192 | 1225 | static int byt_rt5640_suspend(struct snd_soc_card *card) |
|---|
| 1193 | 1226 | { |
|---|
| .. | .. |
|---|
| 1196 | 1229 | if (!BYT_RT5640_JDSRC(byt_rt5640_quirk)) |
|---|
| 1197 | 1230 | return 0; |
|---|
| 1198 | 1231 | |
|---|
| 1199 | | - list_for_each_entry(component, &card->component_dev_list, card_list) { |
|---|
| 1232 | + for_each_card_components(card, component) { |
|---|
| 1200 | 1233 | if (!strcmp(component->name, byt_rt5640_codec_name)) { |
|---|
| 1201 | 1234 | dev_dbg(component->dev, "disabling jack detect before suspend\n"); |
|---|
| 1202 | 1235 | snd_soc_component_set_jack(component, NULL, NULL); |
|---|
| .. | .. |
|---|
| 1215 | 1248 | if (!BYT_RT5640_JDSRC(byt_rt5640_quirk)) |
|---|
| 1216 | 1249 | return 0; |
|---|
| 1217 | 1250 | |
|---|
| 1218 | | - list_for_each_entry(component, &card->component_dev_list, card_list) { |
|---|
| 1251 | + for_each_card_components(card, component) { |
|---|
| 1219 | 1252 | if (!strcmp(component->name, byt_rt5640_codec_name)) { |
|---|
| 1220 | 1253 | dev_dbg(component->dev, "re-enabling jack detect after resume\n"); |
|---|
| 1221 | 1254 | snd_soc_component_set_jack(component, &priv->jack, NULL); |
|---|
| .. | .. |
|---|
| 1226 | 1259 | return 0; |
|---|
| 1227 | 1260 | } |
|---|
| 1228 | 1261 | |
|---|
| 1262 | +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) |
|---|
| 1263 | +/* use space before codec name to simplify card ID, and simplify driver name */ |
|---|
| 1264 | +#define CARD_NAME "bytcht rt5640" /* card name will be 'sof-bytcht rt5640' */ |
|---|
| 1265 | +#define DRIVER_NAME "SOF" |
|---|
| 1266 | +#else |
|---|
| 1267 | +#define CARD_NAME "bytcr-rt5640" |
|---|
| 1268 | +#define DRIVER_NAME NULL /* card name will be used for driver name */ |
|---|
| 1269 | +#endif |
|---|
| 1270 | + |
|---|
| 1229 | 1271 | static struct snd_soc_card byt_rt5640_card = { |
|---|
| 1230 | | - .name = "bytcr-rt5640", |
|---|
| 1272 | + .name = CARD_NAME, |
|---|
| 1273 | + .driver_name = DRIVER_NAME, |
|---|
| 1231 | 1274 | .owner = THIS_MODULE, |
|---|
| 1232 | 1275 | .dai_link = byt_rt5640_dais, |
|---|
| 1233 | 1276 | .num_links = ARRAY_SIZE(byt_rt5640_dais), |
|---|
| .. | .. |
|---|
| 1240 | 1283 | .resume_post = byt_rt5640_resume, |
|---|
| 1241 | 1284 | }; |
|---|
| 1242 | 1285 | |
|---|
| 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 | 1286 | struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */ |
|---|
| 1256 | 1287 | u64 aif_value; /* 1: AIF1, 2: AIF2 */ |
|---|
| 1257 | 1288 | u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */ |
|---|
| .. | .. |
|---|
| 1259 | 1290 | |
|---|
| 1260 | 1291 | static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) |
|---|
| 1261 | 1292 | { |
|---|
| 1262 | | - const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3" }; |
|---|
| 1293 | + static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3" }; |
|---|
| 1294 | + __maybe_unused const char *spk_type; |
|---|
| 1263 | 1295 | const struct dmi_system_id *dmi_id; |
|---|
| 1264 | 1296 | struct byt_rt5640_private *priv; |
|---|
| 1265 | 1297 | struct snd_soc_acpi_mach *mach; |
|---|
| 1266 | | - const char *i2c_name = NULL; |
|---|
| 1298 | + const char *platform_name; |
|---|
| 1299 | + struct acpi_device *adev; |
|---|
| 1267 | 1300 | int ret_val = 0; |
|---|
| 1268 | 1301 | int dai_index = 0; |
|---|
| 1269 | | - int i; |
|---|
| 1302 | + int i, cfg_spk; |
|---|
| 1270 | 1303 | |
|---|
| 1271 | 1304 | is_bytcr = false; |
|---|
| 1272 | 1305 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 1280 | 1313 | |
|---|
| 1281 | 1314 | /* fix index of codec dai */ |
|---|
| 1282 | 1315 | for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) { |
|---|
| 1283 | | - if (!strcmp(byt_rt5640_dais[i].codec_name, "i2c-10EC5640:00")) { |
|---|
| 1316 | + if (!strcmp(byt_rt5640_dais[i].codecs->name, |
|---|
| 1317 | + "i2c-10EC5640:00")) { |
|---|
| 1284 | 1318 | dai_index = i; |
|---|
| 1285 | 1319 | break; |
|---|
| 1286 | 1320 | } |
|---|
| 1287 | 1321 | } |
|---|
| 1288 | 1322 | |
|---|
| 1289 | 1323 | /* fixup codec name based on HID */ |
|---|
| 1290 | | - i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1); |
|---|
| 1291 | | - if (i2c_name) { |
|---|
| 1324 | + adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1); |
|---|
| 1325 | + if (adev) { |
|---|
| 1292 | 1326 | 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; |
|---|
| 1327 | + "i2c-%s", acpi_dev_name(adev)); |
|---|
| 1328 | + put_device(&adev->dev); |
|---|
| 1329 | + byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name; |
|---|
| 1296 | 1330 | } |
|---|
| 1297 | 1331 | |
|---|
| 1298 | 1332 | /* |
|---|
| 1299 | 1333 | * swap SSP0 if bytcr is detected |
|---|
| 1300 | 1334 | * (will be overridden if DMI quirk is detected) |
|---|
| 1301 | 1335 | */ |
|---|
| 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) |
|---|
| 1336 | + if (soc_intel_is_byt()) { |
|---|
| 1337 | + if (mach->mach_params.acpi_ipc_irq_index == 0) |
|---|
| 1307 | 1338 | is_bytcr = true; |
|---|
| 1308 | 1339 | } |
|---|
| 1309 | 1340 | |
|---|
| .. | .. |
|---|
| 1366 | 1397 | dmi_id = dmi_first_match(byt_rt5640_quirk_table); |
|---|
| 1367 | 1398 | if (dmi_id) |
|---|
| 1368 | 1399 | 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); |
|---|
| 1400 | + if (quirk_override != -1) { |
|---|
| 1401 | + dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n", |
|---|
| 1402 | + byt_rt5640_quirk, quirk_override); |
|---|
| 1372 | 1403 | byt_rt5640_quirk = quirk_override; |
|---|
| 1373 | 1404 | } |
|---|
| 1374 | 1405 | |
|---|
| .. | .. |
|---|
| 1380 | 1411 | log_quirks(&pdev->dev); |
|---|
| 1381 | 1412 | |
|---|
| 1382 | 1413 | 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 | | - } |
|---|
| 1414 | + (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) |
|---|
| 1415 | + byt_rt5640_dais[dai_index].codecs->dai_name = "rt5640-aif2"; |
|---|
| 1393 | 1416 | |
|---|
| 1394 | 1417 | 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 | | - } |
|---|
| 1418 | + (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) |
|---|
| 1419 | + byt_rt5640_dais[dai_index].cpus->dai_name = "ssp0-port"; |
|---|
| 1405 | 1420 | |
|---|
| 1406 | 1421 | if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) { |
|---|
| 1407 | 1422 | priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); |
|---|
| .. | .. |
|---|
| 1423 | 1438 | } |
|---|
| 1424 | 1439 | } |
|---|
| 1425 | 1440 | |
|---|
| 1441 | + if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) { |
|---|
| 1442 | + cfg_spk = 0; |
|---|
| 1443 | + spk_type = "none"; |
|---|
| 1444 | + } else if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) { |
|---|
| 1445 | + cfg_spk = 1; |
|---|
| 1446 | + spk_type = "mono"; |
|---|
| 1447 | + } else { |
|---|
| 1448 | + cfg_spk = 2; |
|---|
| 1449 | + spk_type = "stereo"; |
|---|
| 1450 | + } |
|---|
| 1451 | + |
|---|
| 1452 | + snprintf(byt_rt5640_components, sizeof(byt_rt5640_components), |
|---|
| 1453 | + "cfg-spk:%d cfg-mic:%s", cfg_spk, |
|---|
| 1454 | + map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]); |
|---|
| 1455 | + byt_rt5640_card.components = byt_rt5640_components; |
|---|
| 1456 | +#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES) |
|---|
| 1426 | 1457 | 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", |
|---|
| 1458 | + "bytcr-rt5640-%s-spk-%s-mic", spk_type, |
|---|
| 1430 | 1459 | map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]); |
|---|
| 1431 | 1460 | byt_rt5640_card.long_name = byt_rt5640_long_name; |
|---|
| 1461 | +#endif |
|---|
| 1462 | + |
|---|
| 1463 | + /* override plaform name, if required */ |
|---|
| 1464 | + platform_name = mach->mach_params.platform; |
|---|
| 1465 | + |
|---|
| 1466 | + ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5640_card, |
|---|
| 1467 | + platform_name); |
|---|
| 1468 | + if (ret_val) |
|---|
| 1469 | + return ret_val; |
|---|
| 1432 | 1470 | |
|---|
| 1433 | 1471 | ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card); |
|---|
| 1434 | 1472 | |
|---|
| .. | .. |
|---|
| 1444 | 1482 | static struct platform_driver snd_byt_rt5640_mc_driver = { |
|---|
| 1445 | 1483 | .driver = { |
|---|
| 1446 | 1484 | .name = "bytcr_rt5640", |
|---|
| 1485 | +#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) |
|---|
| 1486 | + .pm = &snd_soc_pm_ops, |
|---|
| 1487 | +#endif |
|---|
| 1447 | 1488 | }, |
|---|
| 1448 | 1489 | .probe = snd_byt_rt5640_mc_probe, |
|---|
| 1449 | 1490 | }; |
|---|