1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2 // 3 // This file is provided under a dual BSD/GPLv2 license. When using or 4 // redistributing this file, you may do so under either license. 5 // 6 // Copyright(c) 2021 Advanced Micro Devices, Inc. 7 // 8 // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com> 9 // 10 11 /* 12 * Machine Driver Legacy Support for ACP HW block 13 */ 14 15 #include <sound/core.h> 16 #include <sound/pcm_params.h> 17 #include <sound/soc-acpi.h> 18 #include <sound/soc-dapm.h> 19 #include <linux/dmi.h> 20 #include <linux/module.h> 21 22 #include "acp-mach.h" 23 #include "acp3x-es83xx/acp3x-es83xx.h" 24 25 static struct acp_card_drvdata rt5682_rt1019_data = { 26 .hs_cpu_id = I2S_SP, 27 .amp_cpu_id = I2S_SP, 28 .dmic_cpu_id = DMIC, 29 .hs_codec_id = RT5682, 30 .amp_codec_id = RT1019, 31 .dmic_codec_id = DMIC, 32 .tdm_mode = false, 33 }; 34 35 static struct acp_card_drvdata rt5682s_max_data = { 36 .hs_cpu_id = I2S_SP, 37 .amp_cpu_id = I2S_SP, 38 .dmic_cpu_id = DMIC, 39 .hs_codec_id = RT5682S, 40 .amp_codec_id = MAX98360A, 41 .dmic_codec_id = DMIC, 42 .tdm_mode = false, 43 }; 44 45 static struct acp_card_drvdata rt5682s_rt1019_data = { 46 .hs_cpu_id = I2S_SP, 47 .amp_cpu_id = I2S_SP, 48 .dmic_cpu_id = DMIC, 49 .hs_codec_id = RT5682S, 50 .amp_codec_id = RT1019, 51 .dmic_codec_id = DMIC, 52 .tdm_mode = false, 53 }; 54 55 static struct acp_card_drvdata es83xx_rn_data = { 56 .hs_cpu_id = I2S_SP, 57 .dmic_cpu_id = DMIC, 58 .hs_codec_id = ES83XX, 59 .dmic_codec_id = DMIC, 60 .platform = RENOIR, 61 }; 62 63 static struct acp_card_drvdata max_nau8825_data = { 64 .hs_cpu_id = I2S_HS, 65 .amp_cpu_id = I2S_HS, 66 .dmic_cpu_id = DMIC, 67 .hs_codec_id = NAU8825, 68 .amp_codec_id = MAX98360A, 69 .dmic_codec_id = DMIC, 70 .soc_mclk = true, 71 .platform = REMBRANDT, 72 .tdm_mode = false, 73 }; 74 75 static struct acp_card_drvdata rt5682s_rt1019_rmb_data = { 76 .hs_cpu_id = I2S_HS, 77 .amp_cpu_id = I2S_HS, 78 .dmic_cpu_id = DMIC, 79 .hs_codec_id = RT5682S, 80 .amp_codec_id = RT1019, 81 .dmic_codec_id = DMIC, 82 .soc_mclk = true, 83 .platform = REMBRANDT, 84 .tdm_mode = false, 85 }; 86 87 static bool acp_asoc_init_ops(struct acp_card_drvdata *priv) 88 { 89 bool has_ops = false; 90 91 if (priv->hs_codec_id == ES83XX) { 92 has_ops = true; 93 acp3x_es83xx_init_ops(&priv->ops); 94 } 95 return has_ops; 96 } 97 98 static int acp_asoc_suspend_pre(struct snd_soc_card *card) 99 { 100 int ret; 101 102 ret = acp_ops_suspend_pre(card); 103 if (ret == 1) 104 return 0; 105 else 106 return ret; 107 } 108 109 static int acp_asoc_resume_post(struct snd_soc_card *card) 110 { 111 int ret; 112 113 ret = acp_ops_resume_post(card); 114 if (ret == 1) 115 return 0; 116 else 117 return ret; 118 } 119 120 static int acp_asoc_probe(struct platform_device *pdev) 121 { 122 struct snd_soc_card *card = NULL; 123 struct device *dev = &pdev->dev; 124 const struct dmi_system_id *dmi_id; 125 struct acp_card_drvdata *acp_card_drvdata; 126 int ret; 127 128 if (!pdev->id_entry) { 129 ret = -EINVAL; 130 goto out; 131 } 132 133 card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); 134 if (!card) { 135 ret = -ENOMEM; 136 goto out; 137 } 138 139 card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data; 140 acp_card_drvdata = card->drvdata; 141 acp_card_drvdata->acpi_mach = (struct snd_soc_acpi_mach *)pdev->dev.platform_data; 142 card->dev = dev; 143 card->owner = THIS_MODULE; 144 card->name = pdev->id_entry->name; 145 146 acp_asoc_init_ops(card->drvdata); 147 148 /* If widgets and controls are not set in specific callback, 149 * they will be added per-codec in acp-mach-common.c 150 */ 151 ret = acp_ops_configure_widgets(card); 152 if (ret < 0) { 153 dev_err(&pdev->dev, 154 "Cannot configure widgets for card (%s): %d\n", 155 card->name, ret); 156 goto out; 157 } 158 card->suspend_pre = acp_asoc_suspend_pre; 159 card->resume_post = acp_asoc_resume_post; 160 161 ret = acp_ops_probe(card); 162 if (ret < 0) { 163 dev_err(&pdev->dev, 164 "Cannot probe card (%s): %d\n", 165 card->name, ret); 166 goto out; 167 } 168 169 dmi_id = dmi_first_match(acp_quirk_table); 170 if (dmi_id && dmi_id->driver_data) 171 acp_card_drvdata->tdm_mode = dmi_id->driver_data; 172 173 ret = acp_legacy_dai_links_create(card); 174 if (ret) { 175 dev_err(&pdev->dev, 176 "Cannot create dai links for card (%s): %d\n", 177 card->name, ret); 178 goto out; 179 } 180 181 ret = devm_snd_soc_register_card(&pdev->dev, card); 182 if (ret) { 183 dev_err(&pdev->dev, 184 "devm_snd_soc_register_card(%s) failed: %d\n", 185 card->name, ret); 186 goto out; 187 } 188 out: 189 return ret; 190 } 191 192 static const struct platform_device_id board_ids[] = { 193 { 194 .name = "acp3xalc56821019", 195 .driver_data = (kernel_ulong_t)&rt5682_rt1019_data, 196 }, 197 { 198 .name = "acp3xalc5682sm98360", 199 .driver_data = (kernel_ulong_t)&rt5682s_max_data, 200 }, 201 { 202 .name = "acp3xalc5682s1019", 203 .driver_data = (kernel_ulong_t)&rt5682s_rt1019_data, 204 }, 205 { 206 .name = "acp3x-es83xx", 207 .driver_data = (kernel_ulong_t)&es83xx_rn_data, 208 }, 209 { 210 .name = "rmb-nau8825-max", 211 .driver_data = (kernel_ulong_t)&max_nau8825_data, 212 }, 213 { 214 .name = "rmb-rt5682s-rt1019", 215 .driver_data = (kernel_ulong_t)&rt5682s_rt1019_rmb_data, 216 }, 217 { } 218 }; 219 static struct platform_driver acp_asoc_audio = { 220 .driver = { 221 .pm = &snd_soc_pm_ops, 222 .name = "acp_mach", 223 }, 224 .probe = acp_asoc_probe, 225 .id_table = board_ids, 226 }; 227 228 module_platform_driver(acp_asoc_audio); 229 230 MODULE_IMPORT_NS(SND_SOC_AMD_MACH); 231 MODULE_DESCRIPTION("ACP chrome audio support"); 232 MODULE_ALIAS("platform:acp3xalc56821019"); 233 MODULE_ALIAS("platform:acp3xalc5682sm98360"); 234 MODULE_ALIAS("platform:acp3xalc5682s1019"); 235 MODULE_ALIAS("platform:acp3x-es83xx"); 236 MODULE_ALIAS("platform:rmb-nau8825-max"); 237 MODULE_ALIAS("platform:rmb-rt5682s-rt1019"); 238 MODULE_LICENSE("GPL v2"); 239