xref: /linux/sound/soc/amd/ps/ps-common.c (revision 9c2f970518c900821acdac47bbd681b99a325e3d)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * AMD ACP PCI driver callback routines for ACP6.3, ACP7.0 & ACP7.1
4  * platforms.
5  *
6  * Copyright 2025 Advanced Micro Devices, Inc.
7  * Authors: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
8  */
9 
10 #include <linux/bitops.h>
11 #include <linux/delay.h>
12 #include <linux/export.h>
13 #include <linux/io.h>
14 #include <linux/iopoll.h>
15 #include <linux/pci.h>
16 #include <linux/platform_device.h>
17 #include <linux/pm_runtime.h>
18 #include <sound/pcm_params.h>
19 
20 #include "acp63.h"
21 
acp63_power_on(void __iomem * acp_base)22 static int acp63_power_on(void __iomem *acp_base)
23 {
24 	u32 val;
25 
26 	val = readl(acp_base + ACP_PGFSM_STATUS);
27 
28 	if (!val)
29 		return val;
30 
31 	if ((val & ACP63_PGFSM_STATUS_MASK) != ACP63_POWER_ON_IN_PROGRESS)
32 		writel(ACP63_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL);
33 
34 	return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP63_TIMEOUT);
35 }
36 
acp63_reset(void __iomem * acp_base)37 static int acp63_reset(void __iomem *acp_base)
38 {
39 	u32 val;
40 	int ret;
41 
42 	writel(1, acp_base + ACP_SOFT_RESET);
43 
44 	ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val,
45 				 val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK,
46 				 DELAY_US, ACP63_TIMEOUT);
47 	if (ret)
48 		return ret;
49 
50 	writel(0, acp_base + ACP_SOFT_RESET);
51 
52 	return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP63_TIMEOUT);
53 }
54 
acp63_enable_interrupts(void __iomem * acp_base)55 static void acp63_enable_interrupts(void __iomem *acp_base)
56 {
57 	writel(1, acp_base + ACP_EXTERNAL_INTR_ENB);
58 	writel(ACP_ERROR_IRQ, acp_base + ACP_EXTERNAL_INTR_CNTL);
59 }
60 
acp63_disable_interrupts(void __iomem * acp_base)61 static void acp63_disable_interrupts(void __iomem *acp_base)
62 {
63 	writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + ACP_EXTERNAL_INTR_STAT);
64 	writel(0, acp_base + ACP_EXTERNAL_INTR_CNTL);
65 	writel(0, acp_base + ACP_EXTERNAL_INTR_ENB);
66 }
67 
acp63_init(void __iomem * acp_base,struct device * dev)68 static int acp63_init(void __iomem *acp_base, struct device *dev)
69 {
70 	int ret;
71 
72 	ret = acp63_power_on(acp_base);
73 	if (ret) {
74 		dev_err(dev, "ACP power on failed\n");
75 		return ret;
76 	}
77 	writel(0x01, acp_base + ACP_CONTROL);
78 	ret = acp63_reset(acp_base);
79 	if (ret) {
80 		dev_err(dev, "ACP reset failed\n");
81 		return ret;
82 	}
83 	acp63_enable_interrupts(acp_base);
84 	writel(0, acp_base + ACP_ZSC_DSP_CTRL);
85 	return 0;
86 }
87 
acp63_deinit(void __iomem * acp_base,struct device * dev)88 static int acp63_deinit(void __iomem *acp_base, struct device *dev)
89 {
90 	int ret;
91 
92 	acp63_disable_interrupts(acp_base);
93 	ret = acp63_reset(acp_base);
94 	if (ret) {
95 		dev_err(dev, "ACP reset failed\n");
96 		return ret;
97 	}
98 	writel(0, acp_base + ACP_CONTROL);
99 	writel(1, acp_base + ACP_ZSC_DSP_CTRL);
100 	return 0;
101 }
102 
acp63_get_config(struct pci_dev * pci,struct acp63_dev_data * acp_data)103 static void acp63_get_config(struct pci_dev *pci, struct acp63_dev_data *acp_data)
104 {
105 	u32 config;
106 
107 	config = readl(acp_data->acp63_base + ACP_PIN_CONFIG);
108 	dev_dbg(&pci->dev, "ACP config value: %d\n", config);
109 	switch (config) {
110 	case ACP_CONFIG_4:
111 	case ACP_CONFIG_5:
112 	case ACP_CONFIG_10:
113 	case ACP_CONFIG_11:
114 		acp_data->is_pdm_config = true;
115 		break;
116 	case ACP_CONFIG_2:
117 	case ACP_CONFIG_3:
118 		acp_data->is_sdw_config = true;
119 		break;
120 	case ACP_CONFIG_6:
121 	case ACP_CONFIG_7:
122 	case ACP_CONFIG_12:
123 	case ACP_CONFIG_8:
124 	case ACP_CONFIG_13:
125 	case ACP_CONFIG_14:
126 		acp_data->is_pdm_config = true;
127 		acp_data->is_sdw_config = true;
128 		break;
129 	default:
130 		break;
131 	}
132 }
133 
check_acp_sdw_enable_status(struct acp63_dev_data * adata)134 static bool check_acp_sdw_enable_status(struct acp63_dev_data *adata)
135 {
136 	u32 sdw0_en, sdw1_en;
137 
138 	sdw0_en = readl(adata->acp63_base + ACP_SW0_EN);
139 	sdw1_en = readl(adata->acp63_base + ACP_SW1_EN);
140 	return (sdw0_en || sdw1_en);
141 }
142 
handle_acp63_sdw_pme_event(struct acp63_dev_data * adata)143 static void handle_acp63_sdw_pme_event(struct acp63_dev_data *adata)
144 {
145 	u32 val;
146 
147 	val = readl(adata->acp63_base + ACP_SW0_WAKE_EN);
148 	if (val && adata->sdw->pdev[0])
149 		pm_request_resume(&adata->sdw->pdev[0]->dev);
150 
151 	val = readl(adata->acp63_base + ACP_SW1_WAKE_EN);
152 	if (val && adata->sdw->pdev[1])
153 		pm_request_resume(&adata->sdw->pdev[1]->dev);
154 }
155 
snd_acp63_suspend(struct device * dev)156 static int __maybe_unused snd_acp63_suspend(struct device *dev)
157 {
158 	struct acp63_dev_data *adata;
159 	int ret;
160 
161 	adata = dev_get_drvdata(dev);
162 	if (adata->is_sdw_dev) {
163 		adata->acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
164 		adata->acp_pad_pulldown_ctrl = readl(adata->acp63_base + ACP_PAD_PULLDOWN_CTRL);
165 		adata->sdw_en_stat = check_acp_sdw_enable_status(adata);
166 		if (adata->sdw_en_stat) {
167 			writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL);
168 			return 0;
169 		}
170 	}
171 	ret = acp_hw_deinit(adata, dev);
172 	if (ret)
173 		dev_err(dev, "ACP de-init failed\n");
174 
175 	return ret;
176 }
177 
snd_acp63_runtime_resume(struct device * dev)178 static int __maybe_unused snd_acp63_runtime_resume(struct device *dev)
179 {
180 	struct acp63_dev_data *adata;
181 	int ret;
182 
183 	adata = dev_get_drvdata(dev);
184 	if (adata->sdw_en_stat) {
185 		writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
186 		return 0;
187 	}
188 	ret = acp_hw_init(adata, dev);
189 	if (ret) {
190 		dev_err(dev, "ACP init failed\n");
191 		return ret;
192 	}
193 
194 	if (!adata->sdw_en_stat)
195 		handle_acp63_sdw_pme_event(adata);
196 	return 0;
197 }
198 
snd_acp63_resume(struct device * dev)199 static int __maybe_unused snd_acp63_resume(struct device *dev)
200 {
201 	struct acp63_dev_data *adata;
202 	u32 acp_sw_pad_keeper_en;
203 	int ret;
204 
205 	adata = dev_get_drvdata(dev);
206 	if (adata->sdw_en_stat) {
207 		writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
208 		return 0;
209 	}
210 
211 	ret = acp_hw_init(adata, dev);
212 	if (ret)
213 		dev_err(dev, "ACP init failed\n");
214 
215 	acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
216 	dev_dbg(dev, "ACP_SW0_PAD_KEEPER_EN:0x%x\n", acp_sw_pad_keeper_en);
217 	if (!acp_sw_pad_keeper_en) {
218 		writel(adata->acp_sw_pad_keeper_en, adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
219 		writel(adata->acp_pad_pulldown_ctrl, adata->acp63_base + ACP_PAD_PULLDOWN_CTRL);
220 	}
221 	return ret;
222 }
223 
acp63_sdw_dma_irq_thread(struct acp63_dev_data * adata)224 static void acp63_sdw_dma_irq_thread(struct acp63_dev_data *adata)
225 {
226 	struct sdw_dma_dev_data *sdw_data;
227 	u32 stream_id;
228 
229 	sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev);
230 
231 	for (stream_id = 0; stream_id < ACP63_SDW0_DMA_MAX_STREAMS; stream_id++) {
232 		if (adata->acp63_sdw0_dma_intr_stat[stream_id]) {
233 			if (sdw_data->acp63_sdw0_dma_stream[stream_id])
234 				snd_pcm_period_elapsed(sdw_data->acp63_sdw0_dma_stream[stream_id]);
235 			adata->acp63_sdw0_dma_intr_stat[stream_id] = 0;
236 		}
237 	}
238 	for (stream_id = 0; stream_id < ACP63_SDW1_DMA_MAX_STREAMS; stream_id++) {
239 		if (adata->acp63_sdw1_dma_intr_stat[stream_id]) {
240 			if (sdw_data->acp63_sdw1_dma_stream[stream_id])
241 				snd_pcm_period_elapsed(sdw_data->acp63_sdw1_dma_stream[stream_id]);
242 			adata->acp63_sdw1_dma_intr_stat[stream_id] = 0;
243 		}
244 	}
245 }
246 
acp63_hw_init_ops(struct acp_hw_ops * hw_ops)247 void acp63_hw_init_ops(struct acp_hw_ops *hw_ops)
248 {
249 	hw_ops->acp_init = acp63_init;
250 	hw_ops->acp_deinit = acp63_deinit;
251 	hw_ops->acp_get_config = acp63_get_config;
252 	hw_ops->acp_sdw_dma_irq_thread = acp63_sdw_dma_irq_thread;
253 	hw_ops->acp_suspend = snd_acp63_suspend;
254 	hw_ops->acp_resume = snd_acp63_resume;
255 	hw_ops->acp_suspend_runtime = snd_acp63_suspend;
256 	hw_ops->acp_resume_runtime = snd_acp63_runtime_resume;
257 }
258 
acp70_power_on(void __iomem * acp_base)259 static int acp70_power_on(void __iomem *acp_base)
260 {
261 	u32 val = 0;
262 
263 	val = readl(acp_base + ACP_PGFSM_STATUS);
264 
265 	if (!val)
266 		return 0;
267 	if (val & ACP70_PGFSM_STATUS_MASK)
268 		writel(ACP70_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL);
269 
270 	return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP70_TIMEOUT);
271 }
272 
acp70_reset(void __iomem * acp_base)273 static int acp70_reset(void __iomem *acp_base)
274 {
275 	u32 val;
276 	int ret;
277 
278 	writel(1, acp_base + ACP_SOFT_RESET);
279 
280 	ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val,
281 				 val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK,
282 				 DELAY_US, ACP70_TIMEOUT);
283 	if (ret)
284 		return ret;
285 
286 	writel(0, acp_base + ACP_SOFT_RESET);
287 
288 	return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP70_TIMEOUT);
289 }
290 
acp70_enable_sdw_host_wake_interrupts(void __iomem * acp_base)291 static void acp70_enable_sdw_host_wake_interrupts(void __iomem *acp_base)
292 {
293 	u32 ext_intr_cntl1;
294 
295 	ext_intr_cntl1 = readl(acp_base + ACP_EXTERNAL_INTR_CNTL1);
296 	ext_intr_cntl1 |= ACP70_SDW_HOST_WAKE_MASK;
297 	writel(ext_intr_cntl1, acp_base + ACP_EXTERNAL_INTR_CNTL1);
298 }
299 
acp70_enable_interrupts(void __iomem * acp_base)300 static void acp70_enable_interrupts(void __iomem *acp_base)
301 {
302 	u32 sdw0_wake_en, sdw1_wake_en;
303 
304 	writel(1, acp_base + ACP_EXTERNAL_INTR_ENB);
305 	writel(ACP_ERROR_IRQ, acp_base + ACP_EXTERNAL_INTR_CNTL);
306 	sdw0_wake_en = readl(acp_base + ACP_SW0_WAKE_EN);
307 	sdw1_wake_en = readl(acp_base + ACP_SW1_WAKE_EN);
308 	if (sdw0_wake_en || sdw1_wake_en)
309 		acp70_enable_sdw_host_wake_interrupts(acp_base);
310 }
311 
acp70_disable_interrupts(void __iomem * acp_base)312 static void acp70_disable_interrupts(void __iomem *acp_base)
313 {
314 	writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + ACP_EXTERNAL_INTR_STAT);
315 	writel(0, acp_base + ACP_EXTERNAL_INTR_CNTL);
316 	writel(0, acp_base + ACP_EXTERNAL_INTR_ENB);
317 }
318 
acp70_init(void __iomem * acp_base,struct device * dev)319 static int acp70_init(void __iomem *acp_base, struct device *dev)
320 {
321 	int ret;
322 
323 	ret = acp70_power_on(acp_base);
324 	if (ret) {
325 		dev_err(dev, "ACP power on failed\n");
326 		return ret;
327 	}
328 	writel(0x01, acp_base + ACP_CONTROL);
329 	ret = acp70_reset(acp_base);
330 	if (ret) {
331 		dev_err(dev, "ACP reset failed\n");
332 		return ret;
333 	}
334 	writel(0, acp_base + ACP_ZSC_DSP_CTRL);
335 	acp70_enable_interrupts(acp_base);
336 	writel(0x1, acp_base + ACP_PME_EN);
337 	return 0;
338 }
339 
acp70_deinit(void __iomem * acp_base,struct device * dev)340 static int acp70_deinit(void __iomem *acp_base, struct device *dev)
341 {
342 	int ret;
343 
344 	acp70_disable_interrupts(acp_base);
345 	ret = acp70_reset(acp_base);
346 	if (ret) {
347 		dev_err(dev, "ACP reset failed\n");
348 		return ret;
349 	}
350 	writel(0x01, acp_base + ACP_ZSC_DSP_CTRL);
351 	return 0;
352 }
353 
acp70_get_config(struct pci_dev * pci,struct acp63_dev_data * acp_data)354 static void acp70_get_config(struct pci_dev *pci, struct acp63_dev_data *acp_data)
355 {
356 	u32 config;
357 
358 	config = readl(acp_data->acp63_base + ACP_PIN_CONFIG);
359 	dev_dbg(&pci->dev, "ACP config value: %d\n", config);
360 	switch (config) {
361 	case ACP_CONFIG_4:
362 	case ACP_CONFIG_5:
363 	case ACP_CONFIG_10:
364 	case ACP_CONFIG_11:
365 	case ACP_CONFIG_20:
366 		acp_data->is_pdm_config = true;
367 		break;
368 	case ACP_CONFIG_2:
369 	case ACP_CONFIG_3:
370 	case ACP_CONFIG_16:
371 		acp_data->is_sdw_config = true;
372 		break;
373 	case ACP_CONFIG_6:
374 	case ACP_CONFIG_7:
375 	case ACP_CONFIG_12:
376 	case ACP_CONFIG_8:
377 	case ACP_CONFIG_13:
378 	case ACP_CONFIG_14:
379 	case ACP_CONFIG_17:
380 	case ACP_CONFIG_18:
381 	case ACP_CONFIG_19:
382 		acp_data->is_pdm_config = true;
383 		acp_data->is_sdw_config = true;
384 		break;
385 	default:
386 		break;
387 	}
388 }
389 
acp70_sdw_dma_irq_thread(struct acp63_dev_data * adata)390 static void acp70_sdw_dma_irq_thread(struct acp63_dev_data *adata)
391 {
392 	struct sdw_dma_dev_data *sdw_data;
393 	u32 stream_id;
394 
395 	sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev);
396 
397 	for (stream_id = 0; stream_id < ACP70_SDW0_DMA_MAX_STREAMS; stream_id++) {
398 		if (adata->acp70_sdw0_dma_intr_stat[stream_id]) {
399 			if (sdw_data->acp70_sdw0_dma_stream[stream_id])
400 				snd_pcm_period_elapsed(sdw_data->acp70_sdw0_dma_stream[stream_id]);
401 			adata->acp70_sdw0_dma_intr_stat[stream_id] = 0;
402 		}
403 	}
404 	for (stream_id = 0; stream_id < ACP70_SDW1_DMA_MAX_STREAMS; stream_id++) {
405 		if (adata->acp70_sdw1_dma_intr_stat[stream_id]) {
406 			if (sdw_data->acp70_sdw1_dma_stream[stream_id])
407 				snd_pcm_period_elapsed(sdw_data->acp70_sdw1_dma_stream[stream_id]);
408 			adata->acp70_sdw1_dma_intr_stat[stream_id] = 0;
409 		}
410 	}
411 }
412 
snd_acp70_suspend(struct device * dev)413 static int __maybe_unused snd_acp70_suspend(struct device *dev)
414 {
415 	struct acp63_dev_data *adata;
416 	int ret;
417 
418 	adata = dev_get_drvdata(dev);
419 	if (adata->is_sdw_dev) {
420 		adata->acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
421 		adata->acp_pad_pulldown_ctrl = readl(adata->acp63_base + ACP_PAD_PULLDOWN_CTRL);
422 		adata->sdw_en_stat = check_acp_sdw_enable_status(adata);
423 		if (adata->sdw_en_stat) {
424 			writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL);
425 			return 0;
426 		}
427 	}
428 	ret = acp_hw_deinit(adata, dev);
429 	if (ret)
430 		dev_err(dev, "ACP de-init failed\n");
431 
432 	return ret;
433 }
434 
snd_acp70_runtime_resume(struct device * dev)435 static int __maybe_unused snd_acp70_runtime_resume(struct device *dev)
436 {
437 	struct acp63_dev_data *adata;
438 	int ret;
439 
440 	adata = dev_get_drvdata(dev);
441 
442 	if (adata->sdw_en_stat) {
443 		writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
444 		writel(1, adata->acp63_base + ACP_PME_EN);
445 		return 0;
446 	}
447 
448 	ret = acp_hw_init(adata, dev);
449 	if (ret) {
450 		dev_err(dev, "ACP init failed\n");
451 		return ret;
452 	}
453 	return 0;
454 }
455 
snd_acp70_resume(struct device * dev)456 static int __maybe_unused snd_acp70_resume(struct device *dev)
457 {
458 	struct acp63_dev_data *adata;
459 	u32 acp_sw_pad_keeper_en;
460 	int ret;
461 
462 	adata = dev_get_drvdata(dev);
463 
464 	if (adata->sdw_en_stat) {
465 		writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
466 		writel(1, adata->acp63_base + ACP_PME_EN);
467 		return 0;
468 	}
469 
470 	ret = acp_hw_init(adata, dev);
471 	if (ret)
472 		dev_err(dev, "ACP init failed\n");
473 
474 	acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
475 	dev_dbg(dev, "ACP_SW0_PAD_KEEPER_EN:0x%x\n", acp_sw_pad_keeper_en);
476 	if (!acp_sw_pad_keeper_en) {
477 		writel(adata->acp_sw_pad_keeper_en, adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
478 		writel(adata->acp_pad_pulldown_ctrl, adata->acp63_base + ACP_PAD_PULLDOWN_CTRL);
479 	}
480 	return ret;
481 }
482 
acp70_hw_init_ops(struct acp_hw_ops * hw_ops)483 void acp70_hw_init_ops(struct acp_hw_ops *hw_ops)
484 {
485 	hw_ops->acp_init = acp70_init;
486 	hw_ops->acp_deinit = acp70_deinit;
487 	hw_ops->acp_get_config = acp70_get_config;
488 	hw_ops->acp_sdw_dma_irq_thread = acp70_sdw_dma_irq_thread;
489 	hw_ops->acp_suspend = snd_acp70_suspend;
490 	hw_ops->acp_resume = snd_acp70_resume;
491 	hw_ops->acp_suspend_runtime = snd_acp70_suspend;
492 	hw_ops->acp_resume_runtime = snd_acp70_runtime_resume;
493 }
494