GNU Linux-libre 5.19-rc6-gnu
[releases.git] / sound / soc / amd / acp / acp-renoir.c
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
24 #include "amd.h"
25
26 #define DRV_NAME "acp_asoc_renoir"
27
28 #define ACP_SOFT_RST_DONE_MASK  0x00010001
29
30 #define ACP_PWR_ON_MASK         0x01
31 #define ACP_PWR_OFF_MASK        0x00
32 #define ACP_PGFSM_STAT_MASK     0x03
33 #define ACP_POWERED_ON          0x00
34 #define ACP_PWR_ON_IN_PROGRESS  0x01
35 #define ACP_POWERED_OFF         0x02
36 #define DELAY_US                5
37 #define ACP_TIMEOUT             500
38
39 #define ACP_ERROR_MASK 0x20000000
40 #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
41
42 static struct snd_soc_acpi_codecs amp_rt1019 = {
43         .num_codecs = 1,
44         .codecs = {"10EC1019"}
45 };
46
47 static struct snd_soc_acpi_codecs amp_max = {
48         .num_codecs = 1,
49         .codecs = {"MX98360A"}
50 };
51
52 static struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines[] = {
53         {
54                 .id = "10EC5682",
55                 .drv_name = "acp3xalc56821019",
56                 .machine_quirk = snd_soc_acpi_codec_list,
57                 .quirk_data = &amp_rt1019,
58         },
59         {
60                 .id = "RTL5682",
61                 .drv_name = "acp3xalc5682sm98360",
62                 .machine_quirk = snd_soc_acpi_codec_list,
63                 .quirk_data = &amp_max,
64         },
65         {
66                 .id = "RTL5682",
67                 .drv_name = "acp3xalc5682s1019",
68                 .machine_quirk = snd_soc_acpi_codec_list,
69                 .quirk_data = &amp_rt1019,
70         },
71         {
72                 .id = "AMDI1019",
73                 .drv_name = "renoir-acp",
74         },
75         {},
76 };
77
78 static struct snd_soc_dai_driver acp_renoir_dai[] = {
79 {
80         .name = "acp-i2s-sp",
81         .id = I2S_SP_INSTANCE,
82         .playback = {
83                 .stream_name = "I2S SP Playback",
84                 .rates = SNDRV_PCM_RATE_8000_96000,
85                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
86                            SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
87                 .channels_min = 2,
88                 .channels_max = 8,
89                 .rate_min = 8000,
90                 .rate_max = 96000,
91         },
92         .capture = {
93                 .stream_name = "I2S SP Capture",
94                 .rates = SNDRV_PCM_RATE_8000_48000,
95                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
96                            SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
97                 .channels_min = 2,
98                 .channels_max = 2,
99                 .rate_min = 8000,
100                 .rate_max = 48000,
101         },
102         .ops = &asoc_acp_cpu_dai_ops,
103         .probe = &asoc_acp_i2s_probe,
104 },
105 {
106         .name = "acp-i2s-bt",
107         .id = I2S_BT_INSTANCE,
108         .playback = {
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,
113                 .channels_min = 2,
114                 .channels_max = 8,
115                 .rate_min = 8000,
116                 .rate_max = 96000,
117         },
118         .capture = {
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,
123                 .channels_min = 2,
124                 .channels_max = 2,
125                 .rate_min = 8000,
126                 .rate_max = 48000,
127         },
128         .ops = &asoc_acp_cpu_dai_ops,
129         .probe = &asoc_acp_i2s_probe,
130 },
131 {
132         .name = "acp-pdm-dmic",
133         .id = DMIC_INSTANCE,
134         .capture = {
135                 .rates = SNDRV_PCM_RATE_8000_48000,
136                 .formats = SNDRV_PCM_FMTBIT_S32_LE,
137                 .channels_min = 2,
138                 .channels_max = 2,
139                 .rate_min = 8000,
140                 .rate_max = 48000,
141         },
142         .ops = &acp_dmic_dai_ops,
143 },
144 };
145
146 static int acp3x_power_on(void __iomem *base)
147 {
148         u32 val;
149
150         val = readl(base + ACP_PGFSM_STATUS);
151
152         if (val == ACP_POWERED_ON)
153                 return 0;
154
155         if ((val & ACP_PGFSM_STAT_MASK) != ACP_PWR_ON_IN_PROGRESS)
156                 writel(ACP_PWR_ON_MASK, base + ACP_PGFSM_CONTROL);
157
158         return readl_poll_timeout(base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP_TIMEOUT);
159 }
160
161 static int acp3x_power_off(void __iomem *base)
162 {
163         u32 val;
164
165         writel(ACP_PWR_OFF_MASK, base + ACP_PGFSM_CONTROL);
166
167         return readl_poll_timeout(base + ACP_PGFSM_STATUS, val,
168                                   (val & ACP_PGFSM_STAT_MASK) == ACP_POWERED_OFF,
169                                   DELAY_US, ACP_TIMEOUT);
170 }
171
172 static int acp3x_reset(void __iomem *base)
173 {
174         u32 val;
175         int ret;
176
177         writel(1, base + ACP_SOFT_RESET);
178
179         ret = readl_poll_timeout(base + ACP_SOFT_RESET, val, val & ACP_SOFT_RST_DONE_MASK,
180                                  DELAY_US, ACP_TIMEOUT);
181         if (ret)
182                 return ret;
183
184         writel(0, base + ACP_SOFT_RESET);
185
186         return readl_poll_timeout(base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP_TIMEOUT);
187 }
188
189 static void acp3x_enable_interrupts(void __iomem *base)
190 {
191         u32 ext_intr_ctrl;
192
193         writel(0x01, base + ACP_EXTERNAL_INTR_ENB);
194         ext_intr_ctrl = readl(base + ACP_EXTERNAL_INTR_CNTL);
195         ext_intr_ctrl |= ACP_ERROR_MASK;
196         writel(ext_intr_ctrl, base + ACP_EXTERNAL_INTR_CNTL);
197 }
198
199 static void acp3x_disable_interrupts(void __iomem *base)
200 {
201         writel(ACP_EXT_INTR_STAT_CLEAR_MASK, base + ACP_EXTERNAL_INTR_STAT);
202         writel(0x00, base + ACP_EXTERNAL_INTR_ENB);
203 }
204
205 static int rn_acp_init(void __iomem *base)
206 {
207         int ret;
208
209         /* power on */
210         ret = acp3x_power_on(base);
211         if (ret)
212                 return ret;
213
214         writel(0x01, base + ACP_CONTROL);
215
216         /* Reset */
217         ret = acp3x_reset(base);
218         if (ret)
219                 return ret;
220
221         acp3x_enable_interrupts(base);
222
223         return 0;
224 }
225
226 static int rn_acp_deinit(void __iomem *base)
227 {
228         int ret = 0;
229
230         acp3x_disable_interrupts(base);
231
232         /* Reset */
233         ret = acp3x_reset(base);
234         if (ret)
235                 return ret;
236
237         writel(0x00, base + ACP_CONTROL);
238
239         /* power off */
240         ret = acp3x_power_off(base);
241         if (ret)
242                 return ret;
243
244         return 0;
245 }
246 static int renoir_audio_probe(struct platform_device *pdev)
247 {
248         struct device *dev = &pdev->dev;
249         struct acp_chip_info *chip;
250         struct acp_dev_data *adata;
251         struct resource *res;
252         int ret;
253
254         chip = dev_get_platdata(&pdev->dev);
255         if (!chip || !chip->base) {
256                 dev_err(&pdev->dev, "ACP chip data is NULL\n");
257                 return -ENODEV;
258         }
259
260         if (chip->acp_rev != ACP3X_DEV) {
261                 dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
262                 return -ENODEV;
263         }
264
265         ret = rn_acp_init(chip->base);
266         if (ret) {
267                 dev_err(&pdev->dev, "ACP Init failed\n");
268                 return -EINVAL;
269         }
270
271         adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
272         if (!adata)
273                 return -ENOMEM;
274
275         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem");
276         if (!res) {
277                 dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
278                 return -ENODEV;
279         }
280
281         adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
282         if (!adata->acp_base)
283                 return -ENOMEM;
284
285         ret = platform_get_irq_byname(pdev, "acp_dai_irq");
286         if (ret < 0)
287                 return ret;
288         adata->i2s_irq = ret;
289
290         adata->dev = dev;
291         adata->dai_driver = acp_renoir_dai;
292         adata->num_dai = ARRAY_SIZE(acp_renoir_dai);
293
294         adata->machines = snd_soc_acpi_amd_acp_machines;
295         acp_machine_select(adata);
296
297         dev_set_drvdata(dev, adata);
298         acp_platform_register(dev);
299
300         return 0;
301 }
302
303 static int renoir_audio_remove(struct platform_device *pdev)
304 {
305         struct device *dev = &pdev->dev;
306         struct acp_chip_info *chip;
307         int ret;
308
309         chip = dev_get_platdata(&pdev->dev);
310         if (!chip || !chip->base) {
311                 dev_err(&pdev->dev, "ACP chip data is NULL\n");
312                 return -ENODEV;
313         }
314
315         ret = rn_acp_deinit(chip->base);
316         if (ret) {
317                 dev_err(&pdev->dev, "ACP de-init Failed\n");
318                 return -EINVAL;
319         }
320
321         acp_platform_unregister(dev);
322         return 0;
323 }
324
325 static struct platform_driver renoir_driver = {
326         .probe = renoir_audio_probe,
327         .remove = renoir_audio_remove,
328         .driver = {
329                 .name = "acp_asoc_renoir",
330         },
331 };
332
333 module_platform_driver(renoir_driver);
334
335 MODULE_DESCRIPTION("AMD ACP Renoir Driver");
336 MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
337 MODULE_LICENSE("Dual BSD/GPL");
338 MODULE_ALIAS("platform:" DRV_NAME);