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) 2025 Advanced Micro Devices, Inc. 7 // 8 // Authors: Vijendar Mukunda <Vijendar.Mukunda@amd.com> 9 10 /* 11 * Hardware interface for Audio DSP on ACP7.B/7.F platforms 12 */ 13 14 #include <linux/acpi.h> 15 #include <linux/module.h> 16 #include <linux/platform_device.h> 17 #include <linux/pci.h> 18 #include <sound/soc-acpi.h> 19 20 #include "../ops.h" 21 #include "../sof-audio.h" 22 #include "acp.h" 23 #include "acp-dsp-offset.h" 24 25 #define I2S_TDM0_INSTANCE 0 26 #define I2S_TDM1_INSTANCE 1 27 #define I2S_TDM2_INSTANCE 2 28 #define PDM0_DMIC_INSTANCE 3 29 #define PDM1_DMIC_INSTANCE 4 30 31 static struct snd_soc_dai_driver acp7x_sof_dai[] = { 32 [I2S_TDM0_INSTANCE] = { 33 .id = I2S_TDM0_INSTANCE, 34 .name = "acp-sof-i2s0", 35 .playback = { 36 .rates = SNDRV_PCM_RATE_8000_96000, 37 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 38 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 39 .channels_min = 2, 40 .channels_max = 8, 41 .rate_min = 8000, 42 .rate_max = 96000, 43 }, 44 .capture = { 45 .rates = SNDRV_PCM_RATE_8000_48000, 46 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 47 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 48 /* Supporting only stereo for I2S HS controller capture */ 49 .channels_min = 2, 50 .channels_max = 2, 51 .rate_min = 8000, 52 .rate_max = 48000, 53 }, 54 }, 55 56 [I2S_TDM1_INSTANCE] = { 57 .id = I2S_TDM1_INSTANCE, 58 .name = "acp-sof-i2s1", 59 .playback = { 60 .rates = SNDRV_PCM_RATE_8000_96000, 61 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 62 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 63 .channels_min = 2, 64 .channels_max = 8, 65 .rate_min = 8000, 66 .rate_max = 96000, 67 }, 68 .capture = { 69 .rates = SNDRV_PCM_RATE_8000_48000, 70 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 71 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 72 /* Supporting only stereo for I2S BT controller capture */ 73 .channels_min = 2, 74 .channels_max = 2, 75 .rate_min = 8000, 76 .rate_max = 48000, 77 }, 78 }, 79 80 [I2S_TDM2_INSTANCE] = { 81 .id = I2S_TDM2_INSTANCE, 82 .name = "acp-sof-i2s2", 83 .playback = { 84 .rates = SNDRV_PCM_RATE_8000_96000, 85 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 86 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 87 .channels_min = 2, 88 .channels_max = 8, 89 .rate_min = 8000, 90 .rate_max = 96000, 91 }, 92 .capture = { 93 .rates = SNDRV_PCM_RATE_8000_48000, 94 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 95 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 96 /* Supporting only stereo for I2S SP controller capture */ 97 .channels_min = 2, 98 .channels_max = 2, 99 .rate_min = 8000, 100 .rate_max = 48000, 101 }, 102 }, 103 104 [PDM0_DMIC_INSTANCE] = { 105 .id = PDM0_DMIC_INSTANCE, 106 .name = "acp-sof-dmic0", 107 .capture = { 108 .rates = SNDRV_PCM_RATE_8000_48000, 109 .formats = SNDRV_PCM_FMTBIT_S32_LE, 110 .channels_min = 2, 111 .channels_max = 4, 112 .rate_min = 8000, 113 .rate_max = 48000, 114 }, 115 }, 116 117 [PDM1_DMIC_INSTANCE] = { 118 .id = PDM1_DMIC_INSTANCE, 119 .name = "acp-sof-dmic1", 120 .capture = { 121 .rates = SNDRV_PCM_RATE_8000_96000, 122 .formats = SNDRV_PCM_FMTBIT_S32_LE, 123 .channels_min = 2, 124 .channels_max = 4, 125 .rate_min = 8000, 126 .rate_max = 96000, 127 }, 128 }, 129 }; 130 131 static int sof_acp7x_post_fw_run_delay(struct snd_sof_dev *sdev) 132 { 133 /* 134 * Resuming from suspend in some cases may cause the DSP firmware 135 * to enter an unrecoverable faulty state. Delaying a bit any host 136 * to DSP transmission right after firmware boot completion seems 137 * to resolve the issue. 138 */ 139 if (!sdev->first_boot) 140 usleep_range(100, 150); 141 142 return 0; 143 } 144 145 struct snd_sof_dsp_ops sof_acp7x_ops; 146 EXPORT_SYMBOL_NS(sof_acp7x_ops, "SND_SOC_SOF_AMD_COMMON"); 147 148 int sof_acp7x_ops_init(struct snd_sof_dev *sdev) 149 { 150 struct acpi_device *adev = ACPI_COMPANION(&to_pci_dev(sdev->dev)->dev); 151 const union acpi_object *obj; 152 int acp_sof_signed_firmware_image = 0; 153 int acp_sof_post_fw_run_delay = 0; 154 155 /* common defaults */ 156 memcpy(&sof_acp7x_ops, &sof_acp_common_ops, sizeof(struct snd_sof_dsp_ops)); 157 158 sof_acp7x_ops.drv = acp7x_sof_dai; 159 sof_acp7x_ops.num_drv = ARRAY_SIZE(acp7x_sof_dai); 160 sof_acp7x_ops.probe = amd_sof_acp7x_probe; 161 sof_acp7x_ops.remove = amd_sof_acp7x_remove; 162 163 if (adev) { 164 if (!acpi_dev_get_property(adev, "acp-sof-signed-firmware-image", 165 ACPI_TYPE_INTEGER, &obj)) 166 acp_sof_signed_firmware_image = obj->integer.value; 167 168 if (!acpi_dev_get_property(adev, "acp-sof-post_fw_run_delay", 169 ACPI_TYPE_INTEGER, &obj)) 170 acp_sof_post_fw_run_delay = obj->integer.value; 171 } 172 173 if (acp_sof_signed_firmware_image) 174 sof_acp7x_ops.load_firmware = acp_sof_load_signed_firmware; 175 176 if (acp_sof_post_fw_run_delay) 177 sof_acp7x_ops.post_fw_run = sof_acp7x_post_fw_run_delay; 178 179 return 0; 180 } 181