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) 2021 Advanced Micro Devices, Inc.
7 //
8 // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
9 //
10
11 /*
12 * Hardware interface for Renoir ACP block
13 */
14
15 #include <linux/platform_device.h>
16 #include <linux/module.h>
17 #include <linux/err.h>
18 #include <linux/io.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>
24
25 #include "amd.h"
26 #include "acp-mach.h"
27
28 #define DRV_NAME "acp_asoc_renoir"
29
30 static struct snd_soc_dai_driver acp_renoir_dai[] = {
31 {
32 .name = "acp-i2s-sp",
33 .id = I2S_SP_INSTANCE,
34 .playback = {
35 .stream_name = "I2S SP Playback",
36 .rates = SNDRV_PCM_RATE_8000_96000,
37 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
38 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
39 .channels_min = 2,
40 .channels_max = 8,
41 .rate_min = 8000,
42 .rate_max = 96000,
43 },
44 .capture = {
45 .stream_name = "I2S SP Capture",
46 .rates = SNDRV_PCM_RATE_8000_48000,
47 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
48 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
49 .channels_min = 2,
50 .channels_max = 2,
51 .rate_min = 8000,
52 .rate_max = 48000,
53 },
54 .ops = &asoc_acp_cpu_dai_ops,
55 },
56 {
57 .name = "acp-i2s-bt",
58 .id = I2S_BT_INSTANCE,
59 .playback = {
60 .stream_name = "I2S BT Playback",
61 .rates = SNDRV_PCM_RATE_8000_96000,
62 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
63 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
64 .channels_min = 2,
65 .channels_max = 8,
66 .rate_min = 8000,
67 .rate_max = 96000,
68 },
69 .capture = {
70 .stream_name = "I2S BT Capture",
71 .rates = SNDRV_PCM_RATE_8000_48000,
72 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
73 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
74 .channels_min = 2,
75 .channels_max = 2,
76 .rate_min = 8000,
77 .rate_max = 48000,
78 },
79 .ops = &asoc_acp_cpu_dai_ops,
80 },
81 {
82 .name = "acp-pdm-dmic",
83 .id = DMIC_INSTANCE,
84 .capture = {
85 .rates = SNDRV_PCM_RATE_8000_48000,
86 .formats = SNDRV_PCM_FMTBIT_S32_LE,
87 .channels_min = 2,
88 .channels_max = 2,
89 .rate_min = 8000,
90 .rate_max = 48000,
91 },
92 .ops = &acp_dmic_dai_ops,
93 },
94 };
95
96
renoir_audio_probe(struct platform_device * pdev)97 static int renoir_audio_probe(struct platform_device *pdev)
98 {
99 struct device *dev = &pdev->dev;
100 struct acp_chip_info *chip;
101 int ret;
102
103 chip = dev_get_platdata(&pdev->dev);
104 if (!chip || !chip->base) {
105 dev_err(&pdev->dev, "ACP chip data is NULL\n");
106 return -ENODEV;
107 }
108
109 if (chip->acp_rev != ACP_RN_PCI_ID) {
110 dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
111 return -ENODEV;
112 }
113
114 chip->dev = dev;
115 chip->dai_driver = acp_renoir_dai;
116 chip->num_dai = ARRAY_SIZE(acp_renoir_dai);
117
118 ret = acp_hw_en_interrupts(chip);
119 if (ret) {
120 dev_err(dev, "ACP en-interrupts failed\n");
121 return ret;
122 }
123
124 acp_platform_register(dev);
125
126 pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
127 pm_runtime_use_autosuspend(&pdev->dev);
128 pm_runtime_mark_last_busy(&pdev->dev);
129 pm_runtime_set_active(&pdev->dev);
130 pm_runtime_enable(&pdev->dev);
131 return 0;
132 }
133
renoir_audio_remove(struct platform_device * pdev)134 static void renoir_audio_remove(struct platform_device *pdev)
135 {
136 struct device *dev = &pdev->dev;
137 struct acp_chip_info *chip = dev_get_platdata(dev);
138 int ret;
139
140 ret = acp_hw_dis_interrupts(chip);
141 if (ret)
142 dev_err(dev, "ACP dis-interrupts failed\n");
143
144 acp_platform_unregister(dev);
145 }
146
rn_pcm_resume(struct device * dev)147 static int rn_pcm_resume(struct device *dev)
148 {
149 struct acp_chip_info *chip = dev_get_drvdata(dev->parent);
150 struct acp_stream *stream;
151 struct snd_pcm_substream *substream;
152 snd_pcm_uframes_t buf_in_frames;
153 u64 buf_size;
154
155 spin_lock(&chip->acp_lock);
156 list_for_each_entry(stream, &chip->stream_list, list) {
157 substream = stream->substream;
158 if (substream && substream->runtime) {
159 buf_in_frames = (substream->runtime->buffer_size);
160 buf_size = frames_to_bytes(substream->runtime, buf_in_frames);
161 config_pte_for_stream(chip, stream);
162 config_acp_dma(chip, stream, buf_size);
163 if (stream->dai_id)
164 restore_acp_i2s_params(substream, chip, stream);
165 else
166 restore_acp_pdm_params(substream, chip);
167 }
168 }
169 spin_unlock(&chip->acp_lock);
170 return 0;
171 }
172
173 static const struct dev_pm_ops rn_dma_pm_ops = {
174 SYSTEM_SLEEP_PM_OPS(NULL, rn_pcm_resume)
175 };
176
177 static struct platform_driver renoir_driver = {
178 .probe = renoir_audio_probe,
179 .remove = renoir_audio_remove,
180 .driver = {
181 .name = "acp_asoc_renoir",
182 .pm = pm_ptr(&rn_dma_pm_ops),
183 },
184 };
185
186 module_platform_driver(renoir_driver);
187
188 MODULE_DESCRIPTION("AMD ACP Renoir Driver");
189 MODULE_IMPORT_NS("SND_SOC_ACP_COMMON");
190 MODULE_LICENSE("Dual BSD/GPL");
191 MODULE_ALIAS("platform:" DRV_NAME);
192