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
34static 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
46static struct snd_soc_acpi_codecs amp_rt1019 = {
47	.num_codecs = 1,
48	.codecs = {"10EC1019"}
49};
50
51static struct snd_soc_acpi_codecs amp_max = {
52	.num_codecs = 1,
53	.codecs = {"MX98360A"}
54};
55
56static 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
76static 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},
102{
103	.name = "acp-i2s-bt",
104	.id = I2S_BT_INSTANCE,
105	.playback = {
106		.stream_name = "I2S BT Playback",
107		.rates = SNDRV_PCM_RATE_8000_96000,
108		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
109			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
110		.channels_min = 2,
111		.channels_max = 8,
112		.rate_min = 8000,
113		.rate_max = 96000,
114	},
115	.capture = {
116		.stream_name = "I2S BT Capture",
117		.rates = SNDRV_PCM_RATE_8000_48000,
118		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
119			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
120		.channels_min = 2,
121		.channels_max = 2,
122		.rate_min = 8000,
123		.rate_max = 48000,
124	},
125	.ops = &asoc_acp_cpu_dai_ops,
126},
127{
128	.name = "acp-i2s-hs",
129	.id = I2S_HS_INSTANCE,
130	.playback = {
131		.stream_name = "I2S HS Playback",
132		.rates = SNDRV_PCM_RATE_8000_96000,
133		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
134			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
135		.channels_min = 2,
136		.channels_max = 8,
137		.rate_min = 8000,
138		.rate_max = 96000,
139	},
140	.capture = {
141		.stream_name = "I2S HS Capture",
142		.rates = SNDRV_PCM_RATE_8000_48000,
143		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
144			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
145		.channels_min = 2,
146		.channels_max = 8,
147		.rate_min = 8000,
148		.rate_max = 48000,
149	},
150	.ops = &asoc_acp_cpu_dai_ops,
151},
152{
153	.name = "acp-pdm-dmic",
154	.id = DMIC_INSTANCE,
155	.capture = {
156		.rates = SNDRV_PCM_RATE_8000_48000,
157		.formats = SNDRV_PCM_FMTBIT_S32_LE,
158		.channels_min = 2,
159		.channels_max = 2,
160		.rate_min = 8000,
161		.rate_max = 48000,
162	},
163	.ops = &acp_dmic_dai_ops,
164},
165};
166
167static int acp6x_master_clock_generate(struct device *dev)
168{
169	int data = 0;
170	struct pci_dev *smn_dev;
171
172	smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, HOST_BRIDGE_ID, NULL);
173	if (!smn_dev) {
174		dev_err(dev, "Failed to get host bridge device\n");
175		return -ENODEV;
176	}
177
178	smn_write(smn_dev, MP1_C2PMSG_93, 0);
179	smn_write(smn_dev, MP1_C2PMSG_85, 0xC4);
180	smn_write(smn_dev, MP1_C2PMSG_69, 0x4);
181	read_poll_timeout(smn_read, data, data, DELAY_US,
182			  ACP_TIMEOUT, false, smn_dev, MP1_C2PMSG_93);
183	return 0;
184}
185
186static int rembrandt_audio_probe(struct platform_device *pdev)
187{
188	struct device *dev = &pdev->dev;
189	struct acp_chip_info *chip;
190	struct acp_dev_data *adata;
191	struct resource *res;
192
193	chip = dev_get_platdata(&pdev->dev);
194	if (!chip || !chip->base) {
195		dev_err(&pdev->dev, "ACP chip data is NULL\n");
196		return -ENODEV;
197	}
198
199	if (chip->acp_rev != ACP6X_DEV) {
200		dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
201		return -ENODEV;
202	}
203
204	adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
205	if (!adata)
206		return -ENOMEM;
207
208	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem");
209	if (!res) {
210		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
211		return -ENODEV;
212	}
213
214	adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
215	if (!adata->acp_base)
216		return -ENOMEM;
217
218	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "acp_dai_irq");
219	if (!res) {
220		dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
221		return -ENODEV;
222	}
223
224	adata->i2s_irq = res->start;
225	adata->dev = dev;
226	adata->dai_driver = acp_rmb_dai;
227	adata->num_dai = ARRAY_SIZE(acp_rmb_dai);
228	adata->rsrc = &rsrc;
229
230	adata->machines = snd_soc_acpi_amd_rmb_acp_machines;
231	acp_machine_select(adata);
232
233	dev_set_drvdata(dev, adata);
234	acp6x_master_clock_generate(dev);
235	acp_enable_interrupts(adata);
236	acp_platform_register(dev);
237	pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
238	pm_runtime_use_autosuspend(&pdev->dev);
239	pm_runtime_mark_last_busy(&pdev->dev);
240	pm_runtime_set_active(&pdev->dev);
241	pm_runtime_enable(&pdev->dev);
242	return 0;
243}
244
245static void rembrandt_audio_remove(struct platform_device *pdev)
246{
247	struct device *dev = &pdev->dev;
248	struct acp_dev_data *adata = dev_get_drvdata(dev);
249
250	acp_disable_interrupts(adata);
251	acp_platform_unregister(dev);
252	pm_runtime_disable(&pdev->dev);
253}
254
255static int __maybe_unused rmb_pcm_resume(struct device *dev)
256{
257	struct acp_dev_data *adata = dev_get_drvdata(dev);
258	struct acp_stream *stream;
259	struct snd_pcm_substream *substream;
260	snd_pcm_uframes_t buf_in_frames;
261	u64 buf_size;
262
263	acp6x_master_clock_generate(dev);
264	spin_lock(&adata->acp_lock);
265	list_for_each_entry(stream, &adata->stream_list, list) {
266		substream = stream->substream;
267		if (substream && substream->runtime) {
268			buf_in_frames = (substream->runtime->buffer_size);
269			buf_size = frames_to_bytes(substream->runtime, buf_in_frames);
270			config_pte_for_stream(adata, stream);
271			config_acp_dma(adata, stream, buf_size);
272			if (stream->dai_id)
273				restore_acp_i2s_params(substream, adata, stream);
274			else
275				restore_acp_pdm_params(substream, adata);
276		}
277	}
278	spin_unlock(&adata->acp_lock);
279	return 0;
280}
281
282static const struct dev_pm_ops rmb_dma_pm_ops = {
283	SET_SYSTEM_SLEEP_PM_OPS(NULL, rmb_pcm_resume)
284};
285
286static struct platform_driver rembrandt_driver = {
287	.probe = rembrandt_audio_probe,
288	.remove_new = rembrandt_audio_remove,
289	.driver = {
290		.name = "acp_asoc_rembrandt",
291		.pm = &rmb_dma_pm_ops,
292	},
293};
294
295module_platform_driver(rembrandt_driver);
296
297MODULE_DESCRIPTION("AMD ACP Rembrandt Driver");
298MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
299MODULE_LICENSE("Dual BSD/GPL");
300MODULE_ALIAS("platform:" DRV_NAME);
301