1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
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.
6 // Copyright(c) 2021 Advanced Micro Devices, Inc.
8 // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
12 * Hardware interface for Renoir ACP block
15 #include <linux/platform_device.h>
16 #include <linux/module.h>
17 #include <linux/err.h>
19 #include <sound/pcm_params.h>
20 #include <sound/soc.h>
21 #include <sound/soc-dai.h>
22 #include <linux/dma-mapping.h>
23 #include <linux/pm_runtime.h>
28 #define DRV_NAME "acp_asoc_renoir"
30 static struct acp_resource rsrc
= {
34 .irq_reg_offset
= 0x1800,
35 .scratch_reg_offset
= 0x12800,
36 .sram_pte_offset
= 0x02052800,
39 static struct snd_soc_acpi_codecs amp_rt1019
= {
41 .codecs
= {"10EC1019"}
44 static struct snd_soc_acpi_codecs amp_max
= {
46 .codecs
= {"MX98360A"}
49 static struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines
[] = {
52 .drv_name
= "acp3xalc56821019",
53 .machine_quirk
= snd_soc_acpi_codec_list
,
54 .quirk_data
= &_rt1019
,
58 .drv_name
= "acp3xalc5682sm98360",
59 .machine_quirk
= snd_soc_acpi_codec_list
,
60 .quirk_data
= &_max
,
64 .drv_name
= "acp3xalc5682s1019",
65 .machine_quirk
= snd_soc_acpi_codec_list
,
66 .quirk_data
= &_rt1019
,
70 .drv_name
= "renoir-acp",
74 .drv_name
= "acp3x-es83xx",
79 static struct snd_soc_dai_driver acp_renoir_dai
[] = {
82 .id
= I2S_SP_INSTANCE
,
84 .stream_name
= "I2S SP Playback",
85 .rates
= SNDRV_PCM_RATE_8000_96000
,
86 .formats
= SNDRV_PCM_FMTBIT_S16_LE
| SNDRV_PCM_FMTBIT_S8
|
87 SNDRV_PCM_FMTBIT_U8
| SNDRV_PCM_FMTBIT_S32_LE
,
94 .stream_name
= "I2S SP Capture",
95 .rates
= SNDRV_PCM_RATE_8000_48000
,
96 .formats
= SNDRV_PCM_FMTBIT_S16_LE
| SNDRV_PCM_FMTBIT_S8
|
97 SNDRV_PCM_FMTBIT_U8
| SNDRV_PCM_FMTBIT_S32_LE
,
103 .ops
= &asoc_acp_cpu_dai_ops
,
106 .name
= "acp-i2s-bt",
107 .id
= I2S_BT_INSTANCE
,
109 .stream_name
= "I2S BT Playback",
110 .rates
= SNDRV_PCM_RATE_8000_96000
,
111 .formats
= SNDRV_PCM_FMTBIT_S16_LE
| SNDRV_PCM_FMTBIT_S8
|
112 SNDRV_PCM_FMTBIT_U8
| SNDRV_PCM_FMTBIT_S32_LE
,
119 .stream_name
= "I2S BT Capture",
120 .rates
= SNDRV_PCM_RATE_8000_48000
,
121 .formats
= SNDRV_PCM_FMTBIT_S16_LE
| SNDRV_PCM_FMTBIT_S8
|
122 SNDRV_PCM_FMTBIT_U8
| SNDRV_PCM_FMTBIT_S32_LE
,
128 .ops
= &asoc_acp_cpu_dai_ops
,
131 .name
= "acp-pdm-dmic",
134 .rates
= SNDRV_PCM_RATE_8000_48000
,
135 .formats
= SNDRV_PCM_FMTBIT_S32_LE
,
141 .ops
= &acp_dmic_dai_ops
,
146 static int renoir_audio_probe(struct platform_device
*pdev
)
148 struct device
*dev
= &pdev
->dev
;
149 struct acp_chip_info
*chip
;
150 struct acp_dev_data
*adata
;
151 struct resource
*res
;
154 chip
= dev_get_platdata(&pdev
->dev
);
155 if (!chip
|| !chip
->base
) {
156 dev_err(&pdev
->dev
, "ACP chip data is NULL\n");
160 if (chip
->acp_rev
!= ACP_RN_PCI_ID
) {
161 dev_err(&pdev
->dev
, "Un-supported ACP Revision %d\n", chip
->acp_rev
);
165 adata
= devm_kzalloc(dev
, sizeof(struct acp_dev_data
), GFP_KERNEL
);
169 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "acp_mem");
171 dev_err(&pdev
->dev
, "IORESOURCE_MEM FAILED\n");
175 adata
->acp_base
= devm_ioremap(&pdev
->dev
, res
->start
, resource_size(res
));
176 if (!adata
->acp_base
)
179 ret
= platform_get_irq_byname(pdev
, "acp_dai_irq");
182 adata
->i2s_irq
= ret
;
185 adata
->dai_driver
= acp_renoir_dai
;
186 adata
->num_dai
= ARRAY_SIZE(acp_renoir_dai
);
188 adata
->acp_rev
= chip
->acp_rev
;
189 adata
->flag
= chip
->flag
;
191 adata
->machines
= snd_soc_acpi_amd_acp_machines
;
192 acp_machine_select(adata
);
194 dev_set_drvdata(dev
, adata
);
195 acp_enable_interrupts(adata
);
196 acp_platform_register(dev
);
198 pm_runtime_set_autosuspend_delay(&pdev
->dev
, ACP_SUSPEND_DELAY_MS
);
199 pm_runtime_use_autosuspend(&pdev
->dev
);
200 pm_runtime_mark_last_busy(&pdev
->dev
);
201 pm_runtime_set_active(&pdev
->dev
);
202 pm_runtime_enable(&pdev
->dev
);
206 static void renoir_audio_remove(struct platform_device
*pdev
)
208 struct device
*dev
= &pdev
->dev
;
209 struct acp_dev_data
*adata
= dev_get_drvdata(dev
);
211 acp_disable_interrupts(adata
);
212 acp_platform_unregister(dev
);
215 static int __maybe_unused
rn_pcm_resume(struct device
*dev
)
217 struct acp_dev_data
*adata
= dev_get_drvdata(dev
);
218 struct acp_stream
*stream
;
219 struct snd_pcm_substream
*substream
;
220 snd_pcm_uframes_t buf_in_frames
;
223 spin_lock(&adata
->acp_lock
);
224 list_for_each_entry(stream
, &adata
->stream_list
, list
) {
225 substream
= stream
->substream
;
226 if (substream
&& substream
->runtime
) {
227 buf_in_frames
= (substream
->runtime
->buffer_size
);
228 buf_size
= frames_to_bytes(substream
->runtime
, buf_in_frames
);
229 config_pte_for_stream(adata
, stream
);
230 config_acp_dma(adata
, stream
, buf_size
);
232 restore_acp_i2s_params(substream
, adata
, stream
);
234 restore_acp_pdm_params(substream
, adata
);
237 spin_unlock(&adata
->acp_lock
);
241 static const struct dev_pm_ops rn_dma_pm_ops
= {
242 SET_SYSTEM_SLEEP_PM_OPS(NULL
, rn_pcm_resume
)
245 static struct platform_driver renoir_driver
= {
246 .probe
= renoir_audio_probe
,
247 .remove
= renoir_audio_remove
,
249 .name
= "acp_asoc_renoir",
250 .pm
= &rn_dma_pm_ops
,
254 module_platform_driver(renoir_driver
);
256 MODULE_DESCRIPTION("AMD ACP Renoir Driver");
257 MODULE_IMPORT_NS("SND_SOC_ACP_COMMON");
258 MODULE_LICENSE("Dual BSD/GPL");
259 MODULE_ALIAS("platform:" DRV_NAME
);