xref: /linux/sound/soc/sof/amd/acp7x.c (revision 7af6ac41cd470b04ebd1d2ee972159f2dd5be7cd)
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