xref: /openbmc/linux/sound/soc/amd/acp/acp-rembrandt.c (revision fc11d326)
1e8a33a94SV sujith kumar Reddy // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2e8a33a94SV sujith kumar Reddy //
3e8a33a94SV sujith kumar Reddy // This file is provided under a dual BSD/GPLv2 license. When using or
4e8a33a94SV sujith kumar Reddy // redistributing this file, you may do so under either license.
5e8a33a94SV sujith kumar Reddy //
6e8a33a94SV sujith kumar Reddy // Copyright(c) 2022 Advanced Micro Devices, Inc.
7e8a33a94SV sujith kumar Reddy //
8e8a33a94SV sujith kumar Reddy // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
9e8a33a94SV sujith kumar Reddy //          V sujith kumar Reddy <Vsujithkumar.Reddy@amd.com>
10e8a33a94SV sujith kumar Reddy /*
11e8a33a94SV sujith kumar Reddy  * Hardware interface for Renoir ACP block
12e8a33a94SV sujith kumar Reddy  */
13e8a33a94SV sujith kumar Reddy 
14e8a33a94SV sujith kumar Reddy #include <linux/platform_device.h>
15e8a33a94SV sujith kumar Reddy #include <linux/module.h>
16e8a33a94SV sujith kumar Reddy #include <linux/err.h>
17e8a33a94SV sujith kumar Reddy #include <linux/io.h>
18e8a33a94SV sujith kumar Reddy #include <sound/pcm_params.h>
19e8a33a94SV sujith kumar Reddy #include <sound/soc.h>
20e8a33a94SV sujith kumar Reddy #include <sound/soc-dai.h>
21e8a33a94SV sujith kumar Reddy #include <linux/dma-mapping.h>
227ad6fb9dSSyed Saba Kareem #include <linux/pci.h>
23e8a33a94SV sujith kumar Reddy 
24e8a33a94SV sujith kumar Reddy #include "amd.h"
25e8a33a94SV sujith kumar Reddy 
26e8a33a94SV sujith kumar Reddy #define DRV_NAME "acp_asoc_rembrandt"
27e8a33a94SV sujith kumar Reddy 
287ad6fb9dSSyed Saba Kareem #define MP1_C2PMSG_69 0x3B10A14
297ad6fb9dSSyed Saba Kareem #define MP1_C2PMSG_85 0x3B10A54
307ad6fb9dSSyed Saba Kareem #define MP1_C2PMSG_93 0x3B10A74
317ad6fb9dSSyed Saba Kareem #define HOST_BRIDGE_ID 0x14B5
327ad6fb9dSSyed Saba Kareem 
33e8a33a94SV sujith kumar Reddy static struct acp_resource rsrc = {
34e8a33a94SV sujith kumar Reddy 	.offset = 0,
35e8a33a94SV sujith kumar Reddy 	.no_of_ctrls = 2,
36e8a33a94SV sujith kumar Reddy 	.irqp_used = 1,
37e8a33a94SV sujith kumar Reddy 	.soc_mclk = true,
38e8a33a94SV sujith kumar Reddy 	.irq_reg_offset = 0x1a00,
39e8a33a94SV sujith kumar Reddy 	.i2s_pin_cfg_offset = 0x1440,
40e8a33a94SV sujith kumar Reddy 	.i2s_mode = 0x0a,
41e8a33a94SV sujith kumar Reddy 	.scratch_reg_offset = 0x12800,
42e8a33a94SV sujith kumar Reddy 	.sram_pte_offset = 0x03802800,
43e8a33a94SV sujith kumar Reddy };
44e8a33a94SV sujith kumar Reddy 
45e8a33a94SV sujith kumar Reddy static struct snd_soc_acpi_codecs amp_rt1019 = {
46e8a33a94SV sujith kumar Reddy 	.num_codecs = 1,
47e8a33a94SV sujith kumar Reddy 	.codecs = {"10EC1019"}
48e8a33a94SV sujith kumar Reddy };
49e8a33a94SV sujith kumar Reddy 
50e8a33a94SV sujith kumar Reddy static struct snd_soc_acpi_codecs amp_max = {
51e8a33a94SV sujith kumar Reddy 	.num_codecs = 1,
52e8a33a94SV sujith kumar Reddy 	.codecs = {"MX98360A"}
53e8a33a94SV sujith kumar Reddy };
54e8a33a94SV sujith kumar Reddy 
55e8a33a94SV sujith kumar Reddy static struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines[] = {
56e8a33a94SV sujith kumar Reddy 	{
57e8a33a94SV sujith kumar Reddy 		.id = "10508825",
58e8a33a94SV sujith kumar Reddy 		.drv_name = "rmb-nau8825-max",
59e8a33a94SV sujith kumar Reddy 		.machine_quirk = snd_soc_acpi_codec_list,
60e8a33a94SV sujith kumar Reddy 		.quirk_data = &amp_max,
61e8a33a94SV sujith kumar Reddy 	},
62e8a33a94SV sujith kumar Reddy 	{
63e8a33a94SV sujith kumar Reddy 		.id = "AMDI0007",
64e8a33a94SV sujith kumar Reddy 		.drv_name = "rembrandt-acp",
65e8a33a94SV sujith kumar Reddy 	},
66e8a33a94SV sujith kumar Reddy 	{
67e8a33a94SV sujith kumar Reddy 		.id = "RTL5682",
68e8a33a94SV sujith kumar Reddy 		.drv_name = "rmb-rt5682s-rt1019",
69e8a33a94SV sujith kumar Reddy 		.machine_quirk = snd_soc_acpi_codec_list,
70e8a33a94SV sujith kumar Reddy 		.quirk_data = &amp_rt1019,
71e8a33a94SV sujith kumar Reddy 	},
72e8a33a94SV sujith kumar Reddy 	{},
73e8a33a94SV sujith kumar Reddy };
74e8a33a94SV sujith kumar Reddy 
75e8a33a94SV sujith kumar Reddy static struct snd_soc_dai_driver acp_rmb_dai[] = {
76e8a33a94SV sujith kumar Reddy {
77e8a33a94SV sujith kumar Reddy 	.name = "acp-i2s-sp",
78e8a33a94SV sujith kumar Reddy 	.id = I2S_SP_INSTANCE,
79e8a33a94SV sujith kumar Reddy 	.playback = {
80e8a33a94SV sujith kumar Reddy 		.stream_name = "I2S SP Playback",
81e8a33a94SV sujith kumar Reddy 		.rates = SNDRV_PCM_RATE_8000_96000,
82e8a33a94SV sujith kumar Reddy 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
83e8a33a94SV sujith kumar Reddy 			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
84e8a33a94SV sujith kumar Reddy 		.channels_min = 2,
85e8a33a94SV sujith kumar Reddy 		.channels_max = 8,
86e8a33a94SV sujith kumar Reddy 		.rate_min = 8000,
87e8a33a94SV sujith kumar Reddy 		.rate_max = 96000,
88e8a33a94SV sujith kumar Reddy 	},
89e8a33a94SV sujith kumar Reddy 	.capture = {
90e8a33a94SV sujith kumar Reddy 		.stream_name = "I2S SP Capture",
91e8a33a94SV sujith kumar Reddy 		.rates = SNDRV_PCM_RATE_8000_48000,
92e8a33a94SV sujith kumar Reddy 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
93e8a33a94SV sujith kumar Reddy 			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
94e8a33a94SV sujith kumar Reddy 		.channels_min = 2,
95e8a33a94SV sujith kumar Reddy 		.channels_max = 2,
96e8a33a94SV sujith kumar Reddy 		.rate_min = 8000,
97e8a33a94SV sujith kumar Reddy 		.rate_max = 48000,
98e8a33a94SV sujith kumar Reddy 	},
99e8a33a94SV sujith kumar Reddy 	.ops = &asoc_acp_cpu_dai_ops,
100e8a33a94SV sujith kumar Reddy 	.probe = &asoc_acp_i2s_probe,
101e8a33a94SV sujith kumar Reddy },
102e8a33a94SV sujith kumar Reddy {
103e8a33a94SV sujith kumar Reddy 	.name = "acp-i2s-bt",
104e8a33a94SV sujith kumar Reddy 	.id = I2S_BT_INSTANCE,
105e8a33a94SV sujith kumar Reddy 	.playback = {
106e8a33a94SV sujith kumar Reddy 		.stream_name = "I2S BT Playback",
107e8a33a94SV sujith kumar Reddy 		.rates = SNDRV_PCM_RATE_8000_96000,
108e8a33a94SV sujith kumar Reddy 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
109e8a33a94SV sujith kumar Reddy 			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
110e8a33a94SV sujith kumar Reddy 		.channels_min = 2,
111e8a33a94SV sujith kumar Reddy 		.channels_max = 8,
112e8a33a94SV sujith kumar Reddy 		.rate_min = 8000,
113e8a33a94SV sujith kumar Reddy 		.rate_max = 96000,
114e8a33a94SV sujith kumar Reddy 	},
115e8a33a94SV sujith kumar Reddy 	.capture = {
116e8a33a94SV sujith kumar Reddy 		.stream_name = "I2S BT Capture",
117e8a33a94SV sujith kumar Reddy 		.rates = SNDRV_PCM_RATE_8000_48000,
118e8a33a94SV sujith kumar Reddy 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
119e8a33a94SV sujith kumar Reddy 			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
120e8a33a94SV sujith kumar Reddy 		.channels_min = 2,
121e8a33a94SV sujith kumar Reddy 		.channels_max = 2,
122e8a33a94SV sujith kumar Reddy 		.rate_min = 8000,
123e8a33a94SV sujith kumar Reddy 		.rate_max = 48000,
124e8a33a94SV sujith kumar Reddy 	},
125e8a33a94SV sujith kumar Reddy 	.ops = &asoc_acp_cpu_dai_ops,
126e8a33a94SV sujith kumar Reddy 	.probe = &asoc_acp_i2s_probe,
127e8a33a94SV sujith kumar Reddy },
128e8a33a94SV sujith kumar Reddy {
129e8a33a94SV sujith kumar Reddy 	.name = "acp-i2s-hs",
130e8a33a94SV sujith kumar Reddy 	.id = I2S_HS_INSTANCE,
131e8a33a94SV sujith kumar Reddy 	.playback = {
132e8a33a94SV sujith kumar Reddy 		.stream_name = "I2S HS Playback",
133e8a33a94SV sujith kumar Reddy 		.rates = SNDRV_PCM_RATE_8000_96000,
134e8a33a94SV sujith kumar Reddy 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
135e8a33a94SV sujith kumar Reddy 			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
136e8a33a94SV sujith kumar Reddy 		.channels_min = 2,
137e8a33a94SV sujith kumar Reddy 		.channels_max = 8,
138e8a33a94SV sujith kumar Reddy 		.rate_min = 8000,
139e8a33a94SV sujith kumar Reddy 		.rate_max = 96000,
140e8a33a94SV sujith kumar Reddy 	},
141e8a33a94SV sujith kumar Reddy 	.capture = {
142e8a33a94SV sujith kumar Reddy 		.stream_name = "I2S HS Capture",
143e8a33a94SV sujith kumar Reddy 		.rates = SNDRV_PCM_RATE_8000_48000,
144e8a33a94SV sujith kumar Reddy 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
145e8a33a94SV sujith kumar Reddy 			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
146e8a33a94SV sujith kumar Reddy 		.channels_min = 2,
147e8a33a94SV sujith kumar Reddy 		.channels_max = 8,
148e8a33a94SV sujith kumar Reddy 		.rate_min = 8000,
149e8a33a94SV sujith kumar Reddy 		.rate_max = 48000,
150e8a33a94SV sujith kumar Reddy 	},
151e8a33a94SV sujith kumar Reddy 	.ops = &asoc_acp_cpu_dai_ops,
152e8a33a94SV sujith kumar Reddy 	.probe = &asoc_acp_i2s_probe,
153e8a33a94SV sujith kumar Reddy },
154e8a33a94SV sujith kumar Reddy {
155e8a33a94SV sujith kumar Reddy 	.name = "acp-pdm-dmic",
156e8a33a94SV sujith kumar Reddy 	.id = DMIC_INSTANCE,
157e8a33a94SV sujith kumar Reddy 	.capture = {
158e8a33a94SV sujith kumar Reddy 		.rates = SNDRV_PCM_RATE_8000_48000,
159e8a33a94SV sujith kumar Reddy 		.formats = SNDRV_PCM_FMTBIT_S32_LE,
160e8a33a94SV sujith kumar Reddy 		.channels_min = 2,
161e8a33a94SV sujith kumar Reddy 		.channels_max = 2,
162e8a33a94SV sujith kumar Reddy 		.rate_min = 8000,
163e8a33a94SV sujith kumar Reddy 		.rate_max = 48000,
164e8a33a94SV sujith kumar Reddy 	},
165e8a33a94SV sujith kumar Reddy 	.ops = &acp_dmic_dai_ops,
166e8a33a94SV sujith kumar Reddy },
167e8a33a94SV sujith kumar Reddy };
168e8a33a94SV sujith kumar Reddy 
1697ad6fb9dSSyed Saba Kareem static int acp6x_master_clock_generate(struct device *dev)
1707ad6fb9dSSyed Saba Kareem {
1717ad6fb9dSSyed Saba Kareem 	int data = 0;
1727ad6fb9dSSyed Saba Kareem 	struct pci_dev *smn_dev;
1737ad6fb9dSSyed Saba Kareem 
1747ad6fb9dSSyed Saba Kareem 	smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, HOST_BRIDGE_ID, NULL);
1757ad6fb9dSSyed Saba Kareem 	if (!smn_dev) {
1767ad6fb9dSSyed Saba Kareem 		dev_err(dev, "Failed to get host bridge device\n");
1777ad6fb9dSSyed Saba Kareem 		return -ENODEV;
1787ad6fb9dSSyed Saba Kareem 	}
1797ad6fb9dSSyed Saba Kareem 
1807ad6fb9dSSyed Saba Kareem 	smn_write(smn_dev, MP1_C2PMSG_93, 0);
1817ad6fb9dSSyed Saba Kareem 	smn_write(smn_dev, MP1_C2PMSG_85, 0xC4);
1827ad6fb9dSSyed Saba Kareem 	smn_write(smn_dev, MP1_C2PMSG_69, 0x4);
1837ad6fb9dSSyed Saba Kareem 	read_poll_timeout(smn_read, data, data, DELAY_US,
1847ad6fb9dSSyed Saba Kareem 			  ACP_TIMEOUT, false, smn_dev, MP1_C2PMSG_93);
1857ad6fb9dSSyed Saba Kareem 	return 0;
1867ad6fb9dSSyed Saba Kareem }
1877ad6fb9dSSyed Saba Kareem 
188e8a33a94SV sujith kumar Reddy static int rembrandt_audio_probe(struct platform_device *pdev)
189e8a33a94SV sujith kumar Reddy {
190e8a33a94SV sujith kumar Reddy 	struct device *dev = &pdev->dev;
191e8a33a94SV sujith kumar Reddy 	struct acp_chip_info *chip;
192e8a33a94SV sujith kumar Reddy 	struct acp_dev_data *adata;
193e8a33a94SV sujith kumar Reddy 	struct resource *res;
194e8a33a94SV sujith kumar Reddy 
195e8a33a94SV sujith kumar Reddy 	chip = dev_get_platdata(&pdev->dev);
196e8a33a94SV sujith kumar Reddy 	if (!chip || !chip->base) {
197e8a33a94SV sujith kumar Reddy 		dev_err(&pdev->dev, "ACP chip data is NULL\n");
198e8a33a94SV sujith kumar Reddy 		return -ENODEV;
199e8a33a94SV sujith kumar Reddy 	}
200e8a33a94SV sujith kumar Reddy 
201e8a33a94SV sujith kumar Reddy 	if (chip->acp_rev != ACP6X_DEV) {
202e8a33a94SV sujith kumar Reddy 		dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
203e8a33a94SV sujith kumar Reddy 		return -ENODEV;
204e8a33a94SV sujith kumar Reddy 	}
205e8a33a94SV sujith kumar Reddy 
206e8a33a94SV sujith kumar Reddy 	adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
207e8a33a94SV sujith kumar Reddy 	if (!adata)
208e8a33a94SV sujith kumar Reddy 		return -ENOMEM;
209e8a33a94SV sujith kumar Reddy 
210e8a33a94SV sujith kumar Reddy 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem");
211e8a33a94SV sujith kumar Reddy 	if (!res) {
212e8a33a94SV sujith kumar Reddy 		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
213e8a33a94SV sujith kumar Reddy 		return -ENODEV;
214e8a33a94SV sujith kumar Reddy 	}
215e8a33a94SV sujith kumar Reddy 
216e8a33a94SV sujith kumar Reddy 	adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
217e8a33a94SV sujith kumar Reddy 	if (!adata->acp_base)
218e8a33a94SV sujith kumar Reddy 		return -ENOMEM;
219e8a33a94SV sujith kumar Reddy 
220e8a33a94SV sujith kumar Reddy 	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "acp_dai_irq");
221e8a33a94SV sujith kumar Reddy 	if (!res) {
222e8a33a94SV sujith kumar Reddy 		dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
223e8a33a94SV sujith kumar Reddy 		return -ENODEV;
224e8a33a94SV sujith kumar Reddy 	}
225e8a33a94SV sujith kumar Reddy 
226e8a33a94SV sujith kumar Reddy 	adata->i2s_irq = res->start;
227e8a33a94SV sujith kumar Reddy 	adata->dev = dev;
228e8a33a94SV sujith kumar Reddy 	adata->dai_driver = acp_rmb_dai;
229e8a33a94SV sujith kumar Reddy 	adata->num_dai = ARRAY_SIZE(acp_rmb_dai);
230e8a33a94SV sujith kumar Reddy 	adata->rsrc = &rsrc;
231e8a33a94SV sujith kumar Reddy 
232e8a33a94SV sujith kumar Reddy 	adata->machines = snd_soc_acpi_amd_rmb_acp_machines;
233e8a33a94SV sujith kumar Reddy 	acp_machine_select(adata);
234e8a33a94SV sujith kumar Reddy 
235e8a33a94SV sujith kumar Reddy 	dev_set_drvdata(dev, adata);
2367ad6fb9dSSyed Saba Kareem 	acp6x_master_clock_generate(dev);
237*fc11d326SSyed Saba Kareem 	acp_enable_interrupts(adata);
238e8a33a94SV sujith kumar Reddy 	acp_platform_register(dev);
239e8a33a94SV sujith kumar Reddy 
240e8a33a94SV sujith kumar Reddy 	return 0;
241e8a33a94SV sujith kumar Reddy }
242e8a33a94SV sujith kumar Reddy 
24337846af6SUwe Kleine-König static void rembrandt_audio_remove(struct platform_device *pdev)
244e8a33a94SV sujith kumar Reddy {
245e8a33a94SV sujith kumar Reddy 	struct device *dev = &pdev->dev;
246e8a33a94SV sujith kumar Reddy 	struct acp_dev_data *adata = dev_get_drvdata(dev);
247e8a33a94SV sujith kumar Reddy 
248*fc11d326SSyed Saba Kareem 	acp_disable_interrupts(adata);
249e8a33a94SV sujith kumar Reddy 	acp_platform_unregister(dev);
250e8a33a94SV sujith kumar Reddy }
251e8a33a94SV sujith kumar Reddy 
252e8a33a94SV sujith kumar Reddy static struct platform_driver rembrandt_driver = {
253e8a33a94SV sujith kumar Reddy 	.probe = rembrandt_audio_probe,
25437846af6SUwe Kleine-König 	.remove_new = rembrandt_audio_remove,
255e8a33a94SV sujith kumar Reddy 	.driver = {
256e8a33a94SV sujith kumar Reddy 		.name = "acp_asoc_rembrandt",
257e8a33a94SV sujith kumar Reddy 	},
258e8a33a94SV sujith kumar Reddy };
259e8a33a94SV sujith kumar Reddy 
260e8a33a94SV sujith kumar Reddy module_platform_driver(rembrandt_driver);
261e8a33a94SV sujith kumar Reddy 
262e8a33a94SV sujith kumar Reddy MODULE_DESCRIPTION("AMD ACP Rembrandt Driver");
263e8a33a94SV sujith kumar Reddy MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
264e8a33a94SV sujith kumar Reddy MODULE_LICENSE("Dual BSD/GPL");
265e8a33a94SV sujith kumar Reddy MODULE_ALIAS("platform:" DRV_NAME);
266