xref: /openbmc/linux/sound/soc/amd/acp/acp-rembrandt.c (revision c17bd30d0ba5ca59266771cdfc387f26271a7042)
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) 2022 Advanced Micro Devices, Inc.
7 //
8 // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
9 //          V sujith kumar Reddy <Vsujithkumar.Reddy@amd.com>
10 /*
11  * Hardware interface for Renoir ACP block
12  */
13 
14 #include <linux/platform_device.h>
15 #include <linux/module.h>
16 #include <linux/err.h>
17 #include <linux/io.h>
18 #include <sound/pcm_params.h>
19 #include <sound/soc.h>
20 #include <sound/soc-dai.h>
21 #include <linux/dma-mapping.h>
22 #include <linux/pci.h>
23 #include <linux/pm_runtime.h>
24 
25 #include "amd.h"
26 
27 #define DRV_NAME "acp_asoc_rembrandt"
28 
29 #define MP1_C2PMSG_69 0x3B10A14
30 #define MP1_C2PMSG_85 0x3B10A54
31 #define MP1_C2PMSG_93 0x3B10A74
32 #define HOST_BRIDGE_ID 0x14B5
33 
34 static struct acp_resource rsrc = {
35 	.offset = 0,
36 	.no_of_ctrls = 2,
37 	.irqp_used = 1,
38 	.soc_mclk = true,
39 	.irq_reg_offset = 0x1a00,
40 	.i2s_pin_cfg_offset = 0x1440,
41 	.i2s_mode = 0x0a,
42 	.scratch_reg_offset = 0x12800,
43 	.sram_pte_offset = 0x03802800,
44 };
45 
46 static struct snd_soc_acpi_codecs amp_rt1019 = {
47 	.num_codecs = 1,
48 	.codecs = {"10EC1019"}
49 };
50 
51 static struct snd_soc_acpi_codecs amp_max = {
52 	.num_codecs = 1,
53 	.codecs = {"MX98360A"}
54 };
55 
56 static struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines[] = {
57 	{
58 		.id = "10508825",
59 		.drv_name = "rmb-nau8825-max",
60 		.machine_quirk = snd_soc_acpi_codec_list,
61 		.quirk_data = &amp_max,
62 	},
63 	{
64 		.id = "AMDI0007",
65 		.drv_name = "rembrandt-acp",
66 	},
67 	{
68 		.id = "RTL5682",
69 		.drv_name = "rmb-rt5682s-rt1019",
70 		.machine_quirk = snd_soc_acpi_codec_list,
71 		.quirk_data = &amp_rt1019,
72 	},
73 	{},
74 };
75 
76 static struct snd_soc_dai_driver acp_rmb_dai[] = {
77 {
78 	.name = "acp-i2s-sp",
79 	.id = I2S_SP_INSTANCE,
80 	.playback = {
81 		.stream_name = "I2S SP Playback",
82 		.rates = SNDRV_PCM_RATE_8000_96000,
83 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
84 			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
85 		.channels_min = 2,
86 		.channels_max = 8,
87 		.rate_min = 8000,
88 		.rate_max = 96000,
89 	},
90 	.capture = {
91 		.stream_name = "I2S SP Capture",
92 		.rates = SNDRV_PCM_RATE_8000_48000,
93 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
94 			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
95 		.channels_min = 2,
96 		.channels_max = 2,
97 		.rate_min = 8000,
98 		.rate_max = 48000,
99 	},
100 	.ops = &asoc_acp_cpu_dai_ops,
101 	.probe = &asoc_acp_i2s_probe,
102 },
103 {
104 	.name = "acp-i2s-bt",
105 	.id = I2S_BT_INSTANCE,
106 	.playback = {
107 		.stream_name = "I2S BT Playback",
108 		.rates = SNDRV_PCM_RATE_8000_96000,
109 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
110 			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
111 		.channels_min = 2,
112 		.channels_max = 8,
113 		.rate_min = 8000,
114 		.rate_max = 96000,
115 	},
116 	.capture = {
117 		.stream_name = "I2S BT Capture",
118 		.rates = SNDRV_PCM_RATE_8000_48000,
119 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
120 			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
121 		.channels_min = 2,
122 		.channels_max = 2,
123 		.rate_min = 8000,
124 		.rate_max = 48000,
125 	},
126 	.ops = &asoc_acp_cpu_dai_ops,
127 	.probe = &asoc_acp_i2s_probe,
128 },
129 {
130 	.name = "acp-i2s-hs",
131 	.id = I2S_HS_INSTANCE,
132 	.playback = {
133 		.stream_name = "I2S HS Playback",
134 		.rates = SNDRV_PCM_RATE_8000_96000,
135 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
136 			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
137 		.channels_min = 2,
138 		.channels_max = 8,
139 		.rate_min = 8000,
140 		.rate_max = 96000,
141 	},
142 	.capture = {
143 		.stream_name = "I2S HS Capture",
144 		.rates = SNDRV_PCM_RATE_8000_48000,
145 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
146 			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
147 		.channels_min = 2,
148 		.channels_max = 8,
149 		.rate_min = 8000,
150 		.rate_max = 48000,
151 	},
152 	.ops = &asoc_acp_cpu_dai_ops,
153 	.probe = &asoc_acp_i2s_probe,
154 },
155 {
156 	.name = "acp-pdm-dmic",
157 	.id = DMIC_INSTANCE,
158 	.capture = {
159 		.rates = SNDRV_PCM_RATE_8000_48000,
160 		.formats = SNDRV_PCM_FMTBIT_S32_LE,
161 		.channels_min = 2,
162 		.channels_max = 2,
163 		.rate_min = 8000,
164 		.rate_max = 48000,
165 	},
166 	.ops = &acp_dmic_dai_ops,
167 },
168 };
169 
170 static int acp6x_master_clock_generate(struct device *dev)
171 {
172 	int data = 0;
173 	struct pci_dev *smn_dev;
174 
175 	smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, HOST_BRIDGE_ID, NULL);
176 	if (!smn_dev) {
177 		dev_err(dev, "Failed to get host bridge device\n");
178 		return -ENODEV;
179 	}
180 
181 	smn_write(smn_dev, MP1_C2PMSG_93, 0);
182 	smn_write(smn_dev, MP1_C2PMSG_85, 0xC4);
183 	smn_write(smn_dev, MP1_C2PMSG_69, 0x4);
184 	read_poll_timeout(smn_read, data, data, DELAY_US,
185 			  ACP_TIMEOUT, false, smn_dev, MP1_C2PMSG_93);
186 	return 0;
187 }
188 
189 static int rembrandt_audio_probe(struct platform_device *pdev)
190 {
191 	struct device *dev = &pdev->dev;
192 	struct acp_chip_info *chip;
193 	struct acp_dev_data *adata;
194 	struct resource *res;
195 
196 	chip = dev_get_platdata(&pdev->dev);
197 	if (!chip || !chip->base) {
198 		dev_err(&pdev->dev, "ACP chip data is NULL\n");
199 		return -ENODEV;
200 	}
201 
202 	if (chip->acp_rev != ACP6X_DEV) {
203 		dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
204 		return -ENODEV;
205 	}
206 
207 	adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
208 	if (!adata)
209 		return -ENOMEM;
210 
211 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem");
212 	if (!res) {
213 		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
214 		return -ENODEV;
215 	}
216 
217 	adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
218 	if (!adata->acp_base)
219 		return -ENOMEM;
220 
221 	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "acp_dai_irq");
222 	if (!res) {
223 		dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
224 		return -ENODEV;
225 	}
226 
227 	adata->i2s_irq = res->start;
228 	adata->dev = dev;
229 	adata->dai_driver = acp_rmb_dai;
230 	adata->num_dai = ARRAY_SIZE(acp_rmb_dai);
231 	adata->rsrc = &rsrc;
232 
233 	adata->machines = snd_soc_acpi_amd_rmb_acp_machines;
234 	acp_machine_select(adata);
235 
236 	dev_set_drvdata(dev, adata);
237 	acp6x_master_clock_generate(dev);
238 	acp_enable_interrupts(adata);
239 	acp_platform_register(dev);
240 	pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
241 	pm_runtime_use_autosuspend(&pdev->dev);
242 	pm_runtime_mark_last_busy(&pdev->dev);
243 	pm_runtime_set_active(&pdev->dev);
244 	pm_runtime_enable(&pdev->dev);
245 	return 0;
246 }
247 
248 static void rembrandt_audio_remove(struct platform_device *pdev)
249 {
250 	struct device *dev = &pdev->dev;
251 	struct acp_dev_data *adata = dev_get_drvdata(dev);
252 
253 	acp_disable_interrupts(adata);
254 	acp_platform_unregister(dev);
255 	pm_runtime_disable(&pdev->dev);
256 }
257 
258 static int __maybe_unused rmb_pcm_resume(struct device *dev)
259 {
260 	struct acp_dev_data *adata = dev_get_drvdata(dev);
261 	struct acp_stream *stream;
262 	struct snd_pcm_substream *substream;
263 	snd_pcm_uframes_t buf_in_frames;
264 	u64 buf_size;
265 
266 	acp6x_master_clock_generate(dev);
267 	spin_lock(&adata->acp_lock);
268 	list_for_each_entry(stream, &adata->stream_list, list) {
269 		substream = stream->substream;
270 		if (substream && substream->runtime) {
271 			buf_in_frames = (substream->runtime->buffer_size);
272 			buf_size = frames_to_bytes(substream->runtime, buf_in_frames);
273 			config_pte_for_stream(adata, stream);
274 			config_acp_dma(adata, stream, buf_size);
275 			if (stream->dai_id)
276 				restore_acp_i2s_params(substream, adata, stream);
277 			else
278 				restore_acp_pdm_params(substream, adata);
279 		}
280 	}
281 	spin_unlock(&adata->acp_lock);
282 	return 0;
283 }
284 
285 static const struct dev_pm_ops rmb_dma_pm_ops = {
286 	SET_SYSTEM_SLEEP_PM_OPS(NULL, rmb_pcm_resume)
287 };
288 
289 static struct platform_driver rembrandt_driver = {
290 	.probe = rembrandt_audio_probe,
291 	.remove_new = rembrandt_audio_remove,
292 	.driver = {
293 		.name = "acp_asoc_rembrandt",
294 		.pm = &rmb_dma_pm_ops,
295 	},
296 };
297 
298 module_platform_driver(rembrandt_driver);
299 
300 MODULE_DESCRIPTION("AMD ACP Rembrandt Driver");
301 MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
302 MODULE_LICENSE("Dual BSD/GPL");
303 MODULE_ALIAS("platform:" DRV_NAME);
304