xref: /linux/sound/soc/amd/acp/acp-rembrandt.c (revision be239684b18e1cdcafcf8c7face4a2f562c745ad)
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 #include "../mach-config.h"
27 #include "acp-mach.h"
28 
29 #define DRV_NAME "acp_asoc_rembrandt"
30 
31 #define MP1_C2PMSG_69 0x3B10A14
32 #define MP1_C2PMSG_85 0x3B10A54
33 #define MP1_C2PMSG_93 0x3B10A74
34 #define HOST_BRIDGE_ID 0x14B5
35 
36 static struct acp_resource rsrc = {
37 	.offset = 0,
38 	.no_of_ctrls = 2,
39 	.irqp_used = 1,
40 	.soc_mclk = true,
41 	.irq_reg_offset = 0x1a00,
42 	.i2s_pin_cfg_offset = 0x1440,
43 	.i2s_mode = 0x0a,
44 	.scratch_reg_offset = 0x12800,
45 	.sram_pte_offset = 0x03802800,
46 };
47 
48 static struct snd_soc_acpi_codecs amp_rt1019 = {
49 	.num_codecs = 1,
50 	.codecs = {"10EC1019"}
51 };
52 
53 static struct snd_soc_acpi_codecs amp_max = {
54 	.num_codecs = 1,
55 	.codecs = {"MX98360A"}
56 };
57 
58 static struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines[] = {
59 	{
60 		.id = "10508825",
61 		.drv_name = "rmb-nau8825-max",
62 		.machine_quirk = snd_soc_acpi_codec_list,
63 		.quirk_data = &amp_max,
64 	},
65 	{
66 		.id = "AMDI0007",
67 		.drv_name = "rembrandt-acp",
68 	},
69 	{
70 		.id = "RTL5682",
71 		.drv_name = "rmb-rt5682s-rt1019",
72 		.machine_quirk = snd_soc_acpi_codec_list,
73 		.quirk_data = &amp_rt1019,
74 	},
75 	{},
76 };
77 
78 static struct snd_soc_dai_driver acp_rmb_dai[] = {
79 {
80 	.name = "acp-i2s-sp",
81 	.id = I2S_SP_INSTANCE,
82 	.playback = {
83 		.stream_name = "I2S SP 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 		.stream_name = "I2S SP Capture",
94 		.rates = SNDRV_PCM_RATE_8000_48000,
95 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
96 			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
97 		.channels_min = 2,
98 		.channels_max = 2,
99 		.rate_min = 8000,
100 		.rate_max = 48000,
101 	},
102 	.ops = &asoc_acp_cpu_dai_ops,
103 },
104 {
105 	.name = "acp-i2s-bt",
106 	.id = I2S_BT_INSTANCE,
107 	.playback = {
108 		.stream_name = "I2S BT Playback",
109 		.rates = SNDRV_PCM_RATE_8000_96000,
110 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
111 			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
112 		.channels_min = 2,
113 		.channels_max = 8,
114 		.rate_min = 8000,
115 		.rate_max = 96000,
116 	},
117 	.capture = {
118 		.stream_name = "I2S BT Capture",
119 		.rates = SNDRV_PCM_RATE_8000_48000,
120 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
121 			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
122 		.channels_min = 2,
123 		.channels_max = 2,
124 		.rate_min = 8000,
125 		.rate_max = 48000,
126 	},
127 	.ops = &asoc_acp_cpu_dai_ops,
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 },
154 {
155 	.name = "acp-pdm-dmic",
156 	.id = DMIC_INSTANCE,
157 	.capture = {
158 		.rates = SNDRV_PCM_RATE_8000_48000,
159 		.formats = SNDRV_PCM_FMTBIT_S32_LE,
160 		.channels_min = 2,
161 		.channels_max = 2,
162 		.rate_min = 8000,
163 		.rate_max = 48000,
164 	},
165 	.ops = &acp_dmic_dai_ops,
166 },
167 };
168 
169 static int acp6x_master_clock_generate(struct device *dev)
170 {
171 	int data = 0;
172 	struct pci_dev *smn_dev;
173 
174 	smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, HOST_BRIDGE_ID, NULL);
175 	if (!smn_dev) {
176 		dev_err(dev, "Failed to get host bridge device\n");
177 		return -ENODEV;
178 	}
179 
180 	smn_write(smn_dev, MP1_C2PMSG_93, 0);
181 	smn_write(smn_dev, MP1_C2PMSG_85, 0xC4);
182 	smn_write(smn_dev, MP1_C2PMSG_69, 0x4);
183 	read_poll_timeout(smn_read, data, data, DELAY_US,
184 			  ACP_TIMEOUT, false, smn_dev, MP1_C2PMSG_93);
185 	return 0;
186 }
187 
188 static int rembrandt_audio_probe(struct platform_device *pdev)
189 {
190 	struct device *dev = &pdev->dev;
191 	struct acp_chip_info *chip;
192 	struct acp_dev_data *adata;
193 	struct resource *res;
194 	u32 ret;
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 	adata->platform = REMBRANDT;
233 	adata->flag = chip->flag;
234 	adata->machines = snd_soc_acpi_amd_rmb_acp_machines;
235 	acp_machine_select(adata);
236 
237 	dev_set_drvdata(dev, adata);
238 
239 	if (chip->flag != FLAG_AMD_LEGACY_ONLY_DMIC) {
240 		ret = acp6x_master_clock_generate(dev);
241 		if (ret)
242 			return ret;
243 	}
244 	acp_enable_interrupts(adata);
245 	acp_platform_register(dev);
246 	pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
247 	pm_runtime_use_autosuspend(&pdev->dev);
248 	pm_runtime_mark_last_busy(&pdev->dev);
249 	pm_runtime_set_active(&pdev->dev);
250 	pm_runtime_enable(&pdev->dev);
251 	return 0;
252 }
253 
254 static void rembrandt_audio_remove(struct platform_device *pdev)
255 {
256 	struct device *dev = &pdev->dev;
257 	struct acp_dev_data *adata = dev_get_drvdata(dev);
258 
259 	acp_disable_interrupts(adata);
260 	acp_platform_unregister(dev);
261 	pm_runtime_disable(&pdev->dev);
262 }
263 
264 static int __maybe_unused rmb_pcm_resume(struct device *dev)
265 {
266 	struct acp_dev_data *adata = dev_get_drvdata(dev);
267 	struct acp_stream *stream;
268 	struct snd_pcm_substream *substream;
269 	snd_pcm_uframes_t buf_in_frames;
270 	u64 buf_size;
271 
272 	if (adata->flag != FLAG_AMD_LEGACY_ONLY_DMIC)
273 		acp6x_master_clock_generate(dev);
274 
275 	spin_lock(&adata->acp_lock);
276 	list_for_each_entry(stream, &adata->stream_list, list) {
277 		substream = stream->substream;
278 		if (substream && substream->runtime) {
279 			buf_in_frames = (substream->runtime->buffer_size);
280 			buf_size = frames_to_bytes(substream->runtime, buf_in_frames);
281 			config_pte_for_stream(adata, stream);
282 			config_acp_dma(adata, stream, buf_size);
283 			if (stream->dai_id)
284 				restore_acp_i2s_params(substream, adata, stream);
285 			else
286 				restore_acp_pdm_params(substream, adata);
287 		}
288 	}
289 	spin_unlock(&adata->acp_lock);
290 	return 0;
291 }
292 
293 static const struct dev_pm_ops rmb_dma_pm_ops = {
294 	SET_SYSTEM_SLEEP_PM_OPS(NULL, rmb_pcm_resume)
295 };
296 
297 static struct platform_driver rembrandt_driver = {
298 	.probe = rembrandt_audio_probe,
299 	.remove_new = rembrandt_audio_remove,
300 	.driver = {
301 		.name = "acp_asoc_rembrandt",
302 		.pm = &rmb_dma_pm_ops,
303 	},
304 };
305 
306 module_platform_driver(rembrandt_driver);
307 
308 MODULE_DESCRIPTION("AMD ACP Rembrandt Driver");
309 MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
310 MODULE_LICENSE("Dual BSD/GPL");
311 MODULE_ALIAS("platform:" DRV_NAME);
312