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 * SOF Machine Driver 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 24 static struct acp_card_drvdata sof_rt5682_rt1019_data = { 25 .hs_cpu_id = I2S_SP, 26 .amp_cpu_id = I2S_SP, 27 .dmic_cpu_id = DMIC, 28 .hs_codec_id = RT5682, 29 .amp_codec_id = RT1019, 30 .dmic_codec_id = DMIC, 31 .tdm_mode = false, 32 }; 33 34 static struct acp_card_drvdata sof_rt5682_max_data = { 35 .hs_cpu_id = I2S_SP, 36 .amp_cpu_id = I2S_SP, 37 .dmic_cpu_id = DMIC, 38 .hs_codec_id = RT5682, 39 .amp_codec_id = MAX98360A, 40 .dmic_codec_id = DMIC, 41 .tdm_mode = false, 42 }; 43 44 static struct acp_card_drvdata sof_rt5682s_rt1019_data = { 45 .hs_cpu_id = I2S_SP, 46 .amp_cpu_id = I2S_SP, 47 .dmic_cpu_id = DMIC, 48 .hs_codec_id = RT5682S, 49 .amp_codec_id = RT1019, 50 .dmic_codec_id = DMIC, 51 .tdm_mode = false, 52 }; 53 54 static struct acp_card_drvdata sof_rt5682s_max_data = { 55 .hs_cpu_id = I2S_SP, 56 .amp_cpu_id = I2S_SP, 57 .dmic_cpu_id = DMIC, 58 .hs_codec_id = RT5682S, 59 .amp_codec_id = MAX98360A, 60 .dmic_codec_id = DMIC, 61 .tdm_mode = false, 62 }; 63 64 static struct acp_card_drvdata sof_nau8825_data = { 65 .hs_cpu_id = I2S_HS, 66 .amp_cpu_id = I2S_HS, 67 .dmic_cpu_id = DMIC, 68 .hs_codec_id = NAU8825, 69 .amp_codec_id = MAX98360A, 70 .dmic_codec_id = DMIC, 71 .soc_mclk = true, 72 .tdm_mode = false, 73 }; 74 75 static struct acp_card_drvdata sof_rt5682s_hs_rt1019_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 .tdm_mode = false, 84 }; 85 86 static struct acp_card_drvdata sof_nau8821_max98388_data = { 87 .hs_cpu_id = I2S_SP, 88 .amp_cpu_id = I2S_HS, 89 .dmic_cpu_id = NONE, 90 .hs_codec_id = NAU8821, 91 .amp_codec_id = MAX98388, 92 .dmic_codec_id = NONE, 93 .soc_mclk = true, 94 .tdm_mode = false, 95 }; 96 97 static const struct snd_kcontrol_new acp_controls[] = { 98 SOC_DAPM_PIN_SWITCH("Headphone Jack"), 99 SOC_DAPM_PIN_SWITCH("Headset Mic"), 100 SOC_DAPM_PIN_SWITCH("Spk"), 101 SOC_DAPM_PIN_SWITCH("Left Spk"), 102 SOC_DAPM_PIN_SWITCH("Right Spk"), 103 }; 104 105 static const struct snd_soc_dapm_widget acp_widgets[] = { 106 SND_SOC_DAPM_HP("Headphone Jack", NULL), 107 SND_SOC_DAPM_MIC("Headset Mic", NULL), 108 SND_SOC_DAPM_SPK("Spk", NULL), 109 SND_SOC_DAPM_SPK("Left Spk", NULL), 110 SND_SOC_DAPM_SPK("Right Spk", NULL), 111 }; 112 113 static int acp_sof_probe(struct platform_device *pdev) 114 { 115 struct snd_soc_card *card = NULL; 116 struct device *dev = &pdev->dev; 117 const struct dmi_system_id *dmi_id; 118 struct acp_card_drvdata *acp_card_drvdata; 119 int ret; 120 121 if (!pdev->id_entry) 122 return -EINVAL; 123 124 card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); 125 if (!card) 126 return -ENOMEM; 127 128 card->dev = dev; 129 card->owner = THIS_MODULE; 130 card->name = pdev->id_entry->name; 131 card->dapm_widgets = acp_widgets; 132 card->num_dapm_widgets = ARRAY_SIZE(acp_widgets); 133 card->controls = acp_controls; 134 card->num_controls = ARRAY_SIZE(acp_controls); 135 card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data; 136 137 acp_card_drvdata = card->drvdata; 138 dmi_id = dmi_first_match(acp_quirk_table); 139 if (dmi_id && dmi_id->driver_data) 140 acp_card_drvdata->tdm_mode = dmi_id->driver_data; 141 142 acp_sofdsp_dai_links_create(card); 143 144 ret = devm_snd_soc_register_card(&pdev->dev, card); 145 if (ret) { 146 dev_err(&pdev->dev, 147 "devm_snd_soc_register_card(%s) failed: %d\n", 148 card->name, ret); 149 return ret; 150 } 151 152 return 0; 153 } 154 155 static const struct platform_device_id board_ids[] = { 156 { 157 .name = "rt5682-rt1019", 158 .driver_data = (kernel_ulong_t)&sof_rt5682_rt1019_data 159 }, 160 { 161 .name = "rt5682-max", 162 .driver_data = (kernel_ulong_t)&sof_rt5682_max_data 163 }, 164 { 165 .name = "rt5682s-max", 166 .driver_data = (kernel_ulong_t)&sof_rt5682s_max_data 167 }, 168 { 169 .name = "rt5682s-rt1019", 170 .driver_data = (kernel_ulong_t)&sof_rt5682s_rt1019_data 171 }, 172 { 173 .name = "nau8825-max", 174 .driver_data = (kernel_ulong_t)&sof_nau8825_data 175 }, 176 { 177 .name = "rt5682s-hs-rt1019", 178 .driver_data = (kernel_ulong_t)&sof_rt5682s_hs_rt1019_data 179 }, 180 { 181 .name = "nau8821-max", 182 .driver_data = (kernel_ulong_t)&sof_nau8821_max98388_data 183 }, 184 { } 185 }; 186 static struct platform_driver acp_asoc_audio = { 187 .driver = { 188 .name = "sof_mach", 189 .pm = &snd_soc_pm_ops, 190 }, 191 .probe = acp_sof_probe, 192 .id_table = board_ids, 193 }; 194 195 module_platform_driver(acp_asoc_audio); 196 197 MODULE_IMPORT_NS(SND_SOC_AMD_MACH); 198 MODULE_DESCRIPTION("ACP chrome SOF audio support"); 199 MODULE_ALIAS("platform:rt5682-rt1019"); 200 MODULE_ALIAS("platform:rt5682-max"); 201 MODULE_ALIAS("platform:rt5682s-max"); 202 MODULE_ALIAS("platform:rt5682s-rt1019"); 203 MODULE_ALIAS("platform:nau8825-max"); 204 MODULE_ALIAS("platform:rt5682s-hs-rt1019"); 205 MODULE_ALIAS("platform:nau8821-max"); 206 MODULE_LICENSE("GPL v2"); 207