.. | .. |
---|
| 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 | }; |
---|