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