Skip to content

Commit e84db12

Browse files
saba-kareembroonie
authored andcommitted
ASoC: amd: acp: Add pci legacy driver support for acp7.0 platform
Add pci legacy driver support and create platform driver for acp7.0 platform. Signed-off-by: Syed Saba Kareem <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent caa126f commit e84db12

File tree

5 files changed

+273
-1
lines changed

5 files changed

+273
-1
lines changed

sound/soc/amd/acp/acp-legacy-common.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#define ACP_RENOIR_PDM_ADDR 0x02
2020
#define ACP_REMBRANDT_PDM_ADDR 0x03
2121
#define ACP63_PDM_ADDR 0x02
22+
#define ACP70_PDM_ADDR 0x02
2223

2324
void acp_enable_interrupts(struct acp_dev_data *adata)
2425
{
@@ -268,6 +269,10 @@ static int acp_power_on(struct acp_chip_info *chip)
268269
acp_pgfsm_stat_reg = ACP63_PGFSM_STATUS;
269270
acp_pgfsm_ctrl_reg = ACP63_PGFSM_CONTROL;
270271
break;
272+
case ACP70_DEV:
273+
acp_pgfsm_stat_reg = ACP70_PGFSM_STATUS;
274+
acp_pgfsm_ctrl_reg = ACP70_PGFSM_CONTROL;
275+
break;
271276
default:
272277
return -EINVAL;
273278
}
@@ -329,7 +334,8 @@ int acp_deinit(struct acp_chip_info *chip)
329334
if (ret)
330335
return ret;
331336

332-
writel(0, chip->base + ACP_CONTROL);
337+
if (chip->acp_rev != ACP70_DEV)
338+
writel(0, chip->base + ACP_CONTROL);
333339
return 0;
334340
}
335341
EXPORT_SYMBOL_NS_GPL(acp_deinit, SND_SOC_ACP_COMMON);
@@ -385,6 +391,9 @@ int check_acp_pdm(struct pci_dev *pci, struct acp_chip_info *chip)
385391
case ACP63_DEV:
386392
pdm_addr = ACP63_PDM_ADDR;
387393
break;
394+
case ACP70_DEV:
395+
pdm_addr = ACP70_PDM_ADDR;
396+
break;
388397
default:
389398
return -EINVAL;
390399
}

sound/soc/amd/acp/acp-mach.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ enum platform_end_point {
5454
RENOIR = 0,
5555
REMBRANDT,
5656
ACP63,
57+
ACP70,
5758
};
5859

5960
struct acp_mach_ops {

sound/soc/amd/acp/acp-pci.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
9191
chip->name = "acp_asoc_acp63";
9292
chip->acp_rev = ACP63_DEV;
9393
break;
94+
case 0x70:
95+
chip->name = "acp_asoc_acp70";
96+
chip->acp_rev = ACP70_DEV;
97+
break;
9498
default:
9599
dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision);
96100
ret = -EINVAL;

sound/soc/amd/acp/acp70.c

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
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) 2023 Advanced Micro Devices, Inc.
7+
//
8+
// Authors: Syed Saba kareem <[email protected]>
9+
/*
10+
* Hardware interface for ACP7.0 block
11+
*/
12+
13+
#include <linux/platform_device.h>
14+
#include <linux/module.h>
15+
#include <linux/err.h>
16+
#include <linux/io.h>
17+
#include <sound/pcm_params.h>
18+
#include <sound/soc.h>
19+
#include <sound/soc-dai.h>
20+
#include <linux/dma-mapping.h>
21+
#include <linux/pm_runtime.h>
22+
#include <linux/pci.h>
23+
#include "amd.h"
24+
#include "acp-mach.h"
25+
26+
#define DRV_NAME "acp_asoc_acp70"
27+
28+
static struct acp_resource rsrc = {
29+
.offset = 0,
30+
.no_of_ctrls = 2,
31+
.irqp_used = 1,
32+
.soc_mclk = true,
33+
.irq_reg_offset = 0x1a00,
34+
.i2s_pin_cfg_offset = 0x1440,
35+
.i2s_mode = 0x0a,
36+
.scratch_reg_offset = 0x12800,
37+
.sram_pte_offset = 0x03802800,
38+
};
39+
40+
static struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_acp_machines[] = {
41+
{
42+
.id = "AMDI0029",
43+
.drv_name = "acp70-acp",
44+
},
45+
{},
46+
};
47+
48+
static struct snd_soc_dai_driver acp70_dai[] = {
49+
{
50+
.name = "acp-i2s-sp",
51+
.id = I2S_SP_INSTANCE,
52+
.playback = {
53+
.stream_name = "I2S SP Playback",
54+
.rates = SNDRV_PCM_RATE_8000_96000,
55+
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
56+
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
57+
.channels_min = 2,
58+
.channels_max = 8,
59+
.rate_min = 8000,
60+
.rate_max = 96000,
61+
},
62+
.capture = {
63+
.stream_name = "I2S SP Capture",
64+
.rates = SNDRV_PCM_RATE_8000_48000,
65+
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
66+
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
67+
.channels_min = 2,
68+
.channels_max = 2,
69+
.rate_min = 8000,
70+
.rate_max = 48000,
71+
},
72+
.ops = &asoc_acp_cpu_dai_ops,
73+
},
74+
{
75+
.name = "acp-i2s-bt",
76+
.id = I2S_BT_INSTANCE,
77+
.playback = {
78+
.stream_name = "I2S BT Playback",
79+
.rates = SNDRV_PCM_RATE_8000_96000,
80+
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
81+
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
82+
.channels_min = 2,
83+
.channels_max = 8,
84+
.rate_min = 8000,
85+
.rate_max = 96000,
86+
},
87+
.capture = {
88+
.stream_name = "I2S BT Capture",
89+
.rates = SNDRV_PCM_RATE_8000_48000,
90+
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
91+
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
92+
.channels_min = 2,
93+
.channels_max = 2,
94+
.rate_min = 8000,
95+
.rate_max = 48000,
96+
},
97+
.ops = &asoc_acp_cpu_dai_ops,
98+
},
99+
{
100+
.name = "acp-i2s-hs",
101+
.id = I2S_HS_INSTANCE,
102+
.playback = {
103+
.stream_name = "I2S HS Playback",
104+
.rates = SNDRV_PCM_RATE_8000_96000,
105+
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
106+
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
107+
.channels_min = 2,
108+
.channels_max = 8,
109+
.rate_min = 8000,
110+
.rate_max = 96000,
111+
},
112+
.capture = {
113+
.stream_name = "I2S HS Capture",
114+
.rates = SNDRV_PCM_RATE_8000_48000,
115+
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
116+
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
117+
.channels_min = 2,
118+
.channels_max = 8,
119+
.rate_min = 8000,
120+
.rate_max = 48000,
121+
},
122+
.ops = &asoc_acp_cpu_dai_ops,
123+
},
124+
{
125+
.name = "acp-pdm-dmic",
126+
.id = DMIC_INSTANCE,
127+
.capture = {
128+
.rates = SNDRV_PCM_RATE_8000_48000,
129+
.formats = SNDRV_PCM_FMTBIT_S32_LE,
130+
.channels_min = 2,
131+
.channels_max = 2,
132+
.rate_min = 8000,
133+
.rate_max = 48000,
134+
},
135+
.ops = &acp_dmic_dai_ops,
136+
},
137+
};
138+
139+
static int acp_acp70_audio_probe(struct platform_device *pdev)
140+
{
141+
struct device *dev = &pdev->dev;
142+
struct acp_chip_info *chip;
143+
struct acp_dev_data *adata;
144+
struct resource *res;
145+
146+
chip = dev_get_platdata(&pdev->dev);
147+
if (!chip || !chip->base) {
148+
dev_err(&pdev->dev, "ACP chip data is NULL\n");
149+
return -ENODEV;
150+
}
151+
152+
if (chip->acp_rev != ACP70_DEV) {
153+
dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
154+
return -ENODEV;
155+
}
156+
157+
adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
158+
if (!adata)
159+
return -ENOMEM;
160+
161+
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem");
162+
if (!res) {
163+
dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
164+
return -ENODEV;
165+
}
166+
167+
adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
168+
if (!adata->acp_base)
169+
return -ENOMEM;
170+
171+
res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "acp_dai_irq");
172+
if (!res) {
173+
dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
174+
return -ENODEV;
175+
}
176+
177+
adata->i2s_irq = res->start;
178+
adata->dev = dev;
179+
adata->dai_driver = acp70_dai;
180+
adata->num_dai = ARRAY_SIZE(acp70_dai);
181+
adata->rsrc = &rsrc;
182+
adata->machines = snd_soc_acpi_amd_acp70_acp_machines;
183+
adata->platform = ACP70;
184+
adata->flag = chip->flag;
185+
acp_machine_select(adata);
186+
187+
dev_set_drvdata(dev, adata);
188+
acp_enable_interrupts(adata);
189+
acp_platform_register(dev);
190+
pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
191+
pm_runtime_use_autosuspend(&pdev->dev);
192+
pm_runtime_mark_last_busy(&pdev->dev);
193+
pm_runtime_set_active(&pdev->dev);
194+
pm_runtime_enable(&pdev->dev);
195+
return 0;
196+
}
197+
198+
static void acp_acp70_audio_remove(struct platform_device *pdev)
199+
{
200+
struct device *dev = &pdev->dev;
201+
struct acp_dev_data *adata = dev_get_drvdata(dev);
202+
203+
acp_disable_interrupts(adata);
204+
acp_platform_unregister(dev);
205+
pm_runtime_disable(&pdev->dev);
206+
}
207+
208+
static int __maybe_unused acp70_pcm_resume(struct device *dev)
209+
{
210+
struct acp_dev_data *adata = dev_get_drvdata(dev);
211+
struct acp_stream *stream;
212+
struct snd_pcm_substream *substream;
213+
snd_pcm_uframes_t buf_in_frames;
214+
u64 buf_size;
215+
216+
spin_lock(&adata->acp_lock);
217+
list_for_each_entry(stream, &adata->stream_list, list) {
218+
if (stream) {
219+
substream = stream->substream;
220+
if (substream && substream->runtime) {
221+
buf_in_frames = (substream->runtime->buffer_size);
222+
buf_size = frames_to_bytes(substream->runtime, buf_in_frames);
223+
config_pte_for_stream(adata, stream);
224+
config_acp_dma(adata, stream, buf_size);
225+
if (stream->dai_id)
226+
restore_acp_i2s_params(substream, adata, stream);
227+
else
228+
restore_acp_pdm_params(substream, adata);
229+
}
230+
}
231+
}
232+
spin_unlock(&adata->acp_lock);
233+
return 0;
234+
}
235+
236+
static const struct dev_pm_ops acp70_dma_pm_ops = {
237+
SET_SYSTEM_SLEEP_PM_OPS(NULL, acp70_pcm_resume)
238+
};
239+
240+
static struct platform_driver acp70_driver = {
241+
.probe = acp_acp70_audio_probe,
242+
.remove_new = acp_acp70_audio_remove,
243+
.driver = {
244+
.name = "acp_asoc_acp70",
245+
.pm = &acp70_dma_pm_ops,
246+
},
247+
};
248+
249+
module_platform_driver(acp70_driver);
250+
251+
MODULE_DESCRIPTION("AMD ACP ACP70 Driver");
252+
MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
253+
MODULE_LICENSE("Dual BSD/GPL");
254+
MODULE_ALIAS("platform:" DRV_NAME);

sound/soc/amd/acp/amd.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#define ACP3X_DEV 3
2222
#define ACP6X_DEV 6
2323
#define ACP63_DEV 0x63
24+
#define ACP70_DEV 0x70
2425

2526
#define DMIC_INSTANCE 0x00
2627
#define I2S_SP_INSTANCE 0x01
@@ -99,6 +100,9 @@
99100
#define ACP63_PGFSM_CONTROL ACP6X_PGFSM_CONTROL
100101
#define ACP63_PGFSM_STATUS ACP6X_PGFSM_STATUS
101102

103+
#define ACP70_PGFSM_CONTROL ACP6X_PGFSM_CONTROL
104+
#define ACP70_PGFSM_STATUS ACP6X_PGFSM_STATUS
105+
102106
#define ACP_SOFT_RST_DONE_MASK 0x00010001
103107

104108
#define ACP_PGFSM_CNTL_POWER_ON_MASK 0xffffffff

0 commit comments

Comments
 (0)