xref: /openbmc/linux/sound/soc/amd/ps/ps-sdw-dma.c (revision 24069d81)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * AMD ALSA SoC Pink Sardine SoundWire DMA Driver
4  *
5  * Copyright 2023 Advanced Micro Devices, Inc.
6  */
7 
8 #include <linux/err.h>
9 #include <linux/io.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <sound/pcm_params.h>
13 #include <sound/soc.h>
14 #include <sound/soc-dai.h>
15 #include <linux/pm_runtime.h>
16 #include <linux/soundwire/sdw_amd.h>
17 #include "acp63.h"
18 
19 #define DRV_NAME "amd_ps_sdw_dma"
20 
21 static struct sdw_dma_ring_buf_reg sdw0_dma_ring_buf_reg[ACP63_SDW0_DMA_MAX_STREAMS] = {
22 	{ACP_AUDIO0_TX_DMA_SIZE, ACP_AUDIO0_TX_FIFOADDR, ACP_AUDIO0_TX_FIFOSIZE,
23 	 ACP_AUDIO0_TX_RINGBUFSIZE, ACP_AUDIO0_TX_RINGBUFADDR, ACP_AUDIO0_TX_INTR_WATERMARK_SIZE,
24 	 ACP_AUDIO0_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH},
25 	{ACP_AUDIO1_TX_DMA_SIZE, ACP_AUDIO1_TX_FIFOADDR, ACP_AUDIO1_TX_FIFOSIZE,
26 	 ACP_AUDIO1_TX_RINGBUFSIZE, ACP_AUDIO1_TX_RINGBUFADDR, ACP_AUDIO1_TX_INTR_WATERMARK_SIZE,
27 	 ACP_AUDIO1_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO1_TX_LINEARPOSITIONCNTR_HIGH},
28 	{ACP_AUDIO2_TX_DMA_SIZE, ACP_AUDIO2_TX_FIFOADDR, ACP_AUDIO2_TX_FIFOSIZE,
29 	 ACP_AUDIO2_TX_RINGBUFSIZE, ACP_AUDIO2_TX_RINGBUFADDR, ACP_AUDIO2_TX_INTR_WATERMARK_SIZE,
30 	 ACP_AUDIO2_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_TX_LINEARPOSITIONCNTR_HIGH},
31 	{ACP_AUDIO0_RX_DMA_SIZE, ACP_AUDIO0_RX_FIFOADDR, ACP_AUDIO0_RX_FIFOSIZE,
32 	 ACP_AUDIO0_RX_RINGBUFSIZE, ACP_AUDIO0_RX_RINGBUFADDR, ACP_AUDIO0_RX_INTR_WATERMARK_SIZE,
33 	 ACP_AUDIO0_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH},
34 	{ACP_AUDIO1_RX_DMA_SIZE, ACP_AUDIO1_RX_FIFOADDR, ACP_AUDIO1_RX_FIFOSIZE,
35 	 ACP_AUDIO1_RX_RINGBUFSIZE, ACP_AUDIO1_RX_RINGBUFADDR, ACP_AUDIO1_RX_INTR_WATERMARK_SIZE,
36 	 ACP_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH},
37 	{ACP_AUDIO2_RX_DMA_SIZE, ACP_AUDIO2_RX_FIFOADDR, ACP_AUDIO2_RX_FIFOSIZE,
38 	 ACP_AUDIO2_RX_RINGBUFSIZE, ACP_AUDIO2_RX_RINGBUFADDR, ACP_AUDIO2_RX_INTR_WATERMARK_SIZE,
39 	 ACP_AUDIO2_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_RX_LINEARPOSITIONCNTR_HIGH}
40 };
41 
42 static struct sdw_dma_ring_buf_reg sdw1_dma_ring_buf_reg[ACP63_SDW1_DMA_MAX_STREAMS] =  {
43 	{ACP_P1_AUDIO1_TX_DMA_SIZE, ACP_P1_AUDIO1_TX_FIFOADDR, ACP_P1_AUDIO1_TX_FIFOSIZE,
44 	 ACP_P1_AUDIO1_TX_RINGBUFSIZE, ACP_P1_AUDIO1_TX_RINGBUFADDR,
45 	 ACP_P1_AUDIO1_TX_INTR_WATERMARK_SIZE,
46 	 ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_HIGH},
47 	{ACP_P1_AUDIO1_RX_DMA_SIZE, ACP_P1_AUDIO1_RX_FIFOADDR, ACP_P1_AUDIO1_RX_FIFOSIZE,
48 	 ACP_P1_AUDIO1_RX_RINGBUFSIZE, ACP_P1_AUDIO1_RX_RINGBUFADDR,
49 	 ACP_P1_AUDIO1_RX_INTR_WATERMARK_SIZE,
50 	 ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH},
51 };
52 
53 static u32 sdw0_dma_enable_reg[ACP63_SDW0_DMA_MAX_STREAMS] = {
54 	ACP_SW0_AUDIO0_TX_EN,
55 	ACP_SW0_AUDIO1_TX_EN,
56 	ACP_SW0_AUDIO2_TX_EN,
57 	ACP_SW0_AUDIO0_RX_EN,
58 	ACP_SW0_AUDIO1_RX_EN,
59 	ACP_SW0_AUDIO2_RX_EN,
60 };
61 
62 static u32 sdw1_dma_enable_reg[ACP63_SDW1_DMA_MAX_STREAMS] = {
63 	ACP_SW1_AUDIO1_TX_EN,
64 	ACP_SW1_AUDIO1_RX_EN,
65 };
66 
67 static const struct snd_pcm_hardware acp63_sdw_hardware_playback = {
68 	.info = SNDRV_PCM_INFO_INTERLEAVED |
69 		SNDRV_PCM_INFO_BLOCK_TRANSFER |
70 		SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
71 		SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
72 	.formats = SNDRV_PCM_FMTBIT_S16_LE |  SNDRV_PCM_FMTBIT_S8 |
73 		   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
74 	.channels_min = 2,
75 	.channels_max = 2,
76 	.rates = SNDRV_PCM_RATE_48000,
77 	.rate_min = 48000,
78 	.rate_max = 48000,
79 	.buffer_bytes_max = SDW_PLAYBACK_MAX_NUM_PERIODS * SDW_PLAYBACK_MAX_PERIOD_SIZE,
80 	.period_bytes_min = SDW_PLAYBACK_MIN_PERIOD_SIZE,
81 	.period_bytes_max = SDW_PLAYBACK_MAX_PERIOD_SIZE,
82 	.periods_min = SDW_PLAYBACK_MIN_NUM_PERIODS,
83 	.periods_max = SDW_PLAYBACK_MAX_NUM_PERIODS,
84 };
85 
86 static const struct snd_pcm_hardware acp63_sdw_hardware_capture = {
87 	.info = SNDRV_PCM_INFO_INTERLEAVED |
88 		SNDRV_PCM_INFO_BLOCK_TRANSFER |
89 		SNDRV_PCM_INFO_MMAP |
90 		SNDRV_PCM_INFO_MMAP_VALID |
91 		SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
92 	.formats = SNDRV_PCM_FMTBIT_S16_LE |  SNDRV_PCM_FMTBIT_S8 |
93 		   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
94 	.channels_min = 2,
95 	.channels_max = 2,
96 	.rates = SNDRV_PCM_RATE_48000,
97 	.rate_min = 48000,
98 	.rate_max = 48000,
99 	.buffer_bytes_max = SDW_CAPTURE_MAX_NUM_PERIODS * SDW_CAPTURE_MAX_PERIOD_SIZE,
100 	.period_bytes_min = SDW_CAPTURE_MIN_PERIOD_SIZE,
101 	.period_bytes_max = SDW_CAPTURE_MAX_PERIOD_SIZE,
102 	.periods_min = SDW_CAPTURE_MIN_NUM_PERIODS,
103 	.periods_max = SDW_CAPTURE_MAX_NUM_PERIODS,
104 };
105 
106 static void acp63_enable_disable_sdw_dma_interrupts(void __iomem *acp_base, bool enable)
107 {
108 	u32 ext_intr_cntl, ext_intr_cntl1;
109 	u32 irq_mask = ACP_SDW_DMA_IRQ_MASK;
110 	u32 irq_mask1 = ACP_P1_SDW_DMA_IRQ_MASK;
111 
112 	if (enable) {
113 		ext_intr_cntl = readl(acp_base + ACP_EXTERNAL_INTR_CNTL);
114 		ext_intr_cntl |= irq_mask;
115 		writel(ext_intr_cntl, acp_base + ACP_EXTERNAL_INTR_CNTL);
116 		ext_intr_cntl1 = readl(acp_base + ACP_EXTERNAL_INTR_CNTL1);
117 		ext_intr_cntl1 |= irq_mask1;
118 		writel(ext_intr_cntl1, acp_base + ACP_EXTERNAL_INTR_CNTL1);
119 	} else {
120 		ext_intr_cntl = readl(acp_base + ACP_EXTERNAL_INTR_CNTL);
121 		ext_intr_cntl &= ~irq_mask;
122 		writel(ext_intr_cntl, acp_base + ACP_EXTERNAL_INTR_CNTL);
123 		ext_intr_cntl1 = readl(acp_base + ACP_EXTERNAL_INTR_CNTL1);
124 		ext_intr_cntl1 &= ~irq_mask1;
125 		writel(ext_intr_cntl1, acp_base + ACP_EXTERNAL_INTR_CNTL1);
126 	}
127 }
128 
129 static void acp63_config_dma(struct acp_sdw_dma_stream *stream, void __iomem *acp_base,
130 			     u32 stream_id)
131 {
132 	u16 page_idx;
133 	u32 low, high, val;
134 	u32 sdw_dma_pte_offset;
135 	dma_addr_t addr;
136 
137 	addr = stream->dma_addr;
138 	sdw_dma_pte_offset = SDW_PTE_OFFSET(stream->instance);
139 	val = sdw_dma_pte_offset + (stream_id * ACP_SDW_PTE_OFFSET);
140 
141 	/* Group Enable */
142 	writel(ACP_SDW_SRAM_PTE_OFFSET | BIT(31), acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_2);
143 	writel(PAGE_SIZE_4K_ENABLE, acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2);
144 	for (page_idx = 0; page_idx < stream->num_pages; page_idx++) {
145 		/* Load the low address of page int ACP SRAM through SRBM */
146 		low = lower_32_bits(addr);
147 		high = upper_32_bits(addr);
148 
149 		writel(low, acp_base + ACP_SCRATCH_REG_0 + val);
150 		high |= BIT(31);
151 		writel(high, acp_base + ACP_SCRATCH_REG_0 + val + 4);
152 		val += 8;
153 		addr += PAGE_SIZE;
154 	}
155 	writel(0x1, acp_base + ACPAXI2AXI_ATU_CTRL);
156 }
157 
158 static int acp63_configure_sdw_ringbuffer(void __iomem *acp_base, u32 stream_id, u32 size,
159 					  u32 manager_instance)
160 {
161 	u32 reg_dma_size;
162 	u32 reg_fifo_addr;
163 	u32 reg_fifo_size;
164 	u32 reg_ring_buf_size;
165 	u32 reg_ring_buf_addr;
166 	u32 sdw_fifo_addr;
167 	u32 sdw_fifo_offset;
168 	u32 sdw_ring_buf_addr;
169 	u32 sdw_ring_buf_size;
170 	u32 sdw_mem_window_offset;
171 
172 	switch (manager_instance) {
173 	case ACP_SDW0:
174 		reg_dma_size = sdw0_dma_ring_buf_reg[stream_id].reg_dma_size;
175 		reg_fifo_addr =	sdw0_dma_ring_buf_reg[stream_id].reg_fifo_addr;
176 		reg_fifo_size = sdw0_dma_ring_buf_reg[stream_id].reg_fifo_size;
177 		reg_ring_buf_size = sdw0_dma_ring_buf_reg[stream_id].reg_ring_buf_size;
178 		reg_ring_buf_addr = sdw0_dma_ring_buf_reg[stream_id].reg_ring_buf_addr;
179 		break;
180 	case ACP_SDW1:
181 		reg_dma_size = sdw1_dma_ring_buf_reg[stream_id].reg_dma_size;
182 		reg_fifo_addr =	sdw1_dma_ring_buf_reg[stream_id].reg_fifo_addr;
183 		reg_fifo_size = sdw1_dma_ring_buf_reg[stream_id].reg_fifo_size;
184 		reg_ring_buf_size = sdw1_dma_ring_buf_reg[stream_id].reg_ring_buf_size;
185 		reg_ring_buf_addr = sdw1_dma_ring_buf_reg[stream_id].reg_ring_buf_addr;
186 		break;
187 	default:
188 		return -EINVAL;
189 	}
190 	sdw_fifo_offset = ACP_SDW_FIFO_OFFSET(manager_instance);
191 	sdw_mem_window_offset = SDW_MEM_WINDOW_START(manager_instance);
192 	sdw_fifo_addr = sdw_fifo_offset + (stream_id * SDW_FIFO_OFFSET);
193 	sdw_ring_buf_addr = sdw_mem_window_offset + (stream_id * ACP_SDW_RING_BUFF_ADDR_OFFSET);
194 	sdw_ring_buf_size = size;
195 	writel(sdw_ring_buf_size, acp_base + reg_ring_buf_size);
196 	writel(sdw_ring_buf_addr, acp_base + reg_ring_buf_addr);
197 	writel(sdw_fifo_addr, acp_base + reg_fifo_addr);
198 	writel(SDW_DMA_SIZE, acp_base + reg_dma_size);
199 	writel(SDW_FIFO_SIZE, acp_base + reg_fifo_size);
200 	return 0;
201 }
202 
203 static int acp63_sdw_dma_open(struct snd_soc_component *component,
204 			      struct snd_pcm_substream *substream)
205 {
206 	struct snd_pcm_runtime *runtime;
207 	struct acp_sdw_dma_stream *stream;
208 	struct snd_soc_dai *cpu_dai;
209 	struct amd_sdw_manager *amd_manager;
210 	struct snd_soc_pcm_runtime *prtd = substream->private_data;
211 	int ret;
212 
213 	runtime = substream->runtime;
214 	cpu_dai = asoc_rtd_to_cpu(prtd, 0);
215 	amd_manager = snd_soc_dai_get_drvdata(cpu_dai);
216 	stream = kzalloc(sizeof(*stream), GFP_KERNEL);
217 	if (!stream)
218 		return -ENOMEM;
219 
220 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
221 		runtime->hw = acp63_sdw_hardware_playback;
222 	else
223 		runtime->hw = acp63_sdw_hardware_capture;
224 	ret = snd_pcm_hw_constraint_integer(runtime,
225 					    SNDRV_PCM_HW_PARAM_PERIODS);
226 	if (ret < 0) {
227 		dev_err(component->dev, "set integer constraint failed\n");
228 		kfree(stream);
229 		return ret;
230 	}
231 
232 	stream->stream_id = cpu_dai->id;
233 	stream->instance = amd_manager->instance;
234 	runtime->private_data = stream;
235 	return ret;
236 }
237 
238 static int acp63_sdw_dma_hw_params(struct snd_soc_component *component,
239 				   struct snd_pcm_substream *substream,
240 				   struct snd_pcm_hw_params *params)
241 {
242 	struct acp_sdw_dma_stream *stream;
243 	struct sdw_dma_dev_data *sdw_data;
244 	u32 period_bytes;
245 	u32 water_mark_size_reg;
246 	u32 irq_mask, ext_intr_ctrl;
247 	u64 size;
248 	u32 stream_id;
249 	u32 acp_ext_intr_cntl_reg;
250 	int ret;
251 
252 	sdw_data = dev_get_drvdata(component->dev);
253 	stream = substream->runtime->private_data;
254 	if (!stream)
255 		return -EINVAL;
256 	stream_id = stream->stream_id;
257 	switch (stream->instance) {
258 	case ACP_SDW0:
259 		sdw_data->sdw0_dma_stream[stream_id] = substream;
260 		water_mark_size_reg = sdw0_dma_ring_buf_reg[stream_id].water_mark_size_reg;
261 		acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL;
262 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
263 			irq_mask = BIT(SDW0_DMA_TX_IRQ_MASK(stream_id));
264 		else
265 			irq_mask = BIT(SDW0_DMA_RX_IRQ_MASK(stream_id));
266 		break;
267 	case ACP_SDW1:
268 		sdw_data->sdw1_dma_stream[stream_id] = substream;
269 		acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL1;
270 		water_mark_size_reg = sdw1_dma_ring_buf_reg[stream_id].water_mark_size_reg;
271 		irq_mask = BIT(SDW1_DMA_IRQ_MASK(stream_id));
272 		break;
273 	default:
274 		return -EINVAL;
275 	}
276 	size = params_buffer_bytes(params);
277 	period_bytes = params_period_bytes(params);
278 	stream->dma_addr = substream->runtime->dma_addr;
279 	stream->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
280 	acp63_config_dma(stream, sdw_data->acp_base, stream_id);
281 	ret = acp63_configure_sdw_ringbuffer(sdw_data->acp_base, stream_id, size,
282 					     stream->instance);
283 	if (ret) {
284 		dev_err(component->dev, "Invalid DMA channel\n");
285 		return -EINVAL;
286 	}
287 	ext_intr_ctrl = readl(sdw_data->acp_base + acp_ext_intr_cntl_reg);
288 	ext_intr_ctrl |= irq_mask;
289 	writel(ext_intr_ctrl, sdw_data->acp_base + acp_ext_intr_cntl_reg);
290 	writel(period_bytes, sdw_data->acp_base + water_mark_size_reg);
291 	return 0;
292 }
293 
294 static u64 acp63_sdw_get_byte_count(struct acp_sdw_dma_stream *stream, void __iomem *acp_base)
295 {
296 	union acp_sdw_dma_count byte_count;
297 	u32 pos_low_reg, pos_high_reg;
298 
299 	byte_count.bytescount = 0;
300 	switch (stream->instance) {
301 	case ACP_SDW0:
302 		pos_low_reg = sdw0_dma_ring_buf_reg[stream->stream_id].pos_low_reg;
303 		pos_high_reg = sdw0_dma_ring_buf_reg[stream->stream_id].pos_high_reg;
304 		break;
305 	case ACP_SDW1:
306 		pos_low_reg = sdw1_dma_ring_buf_reg[stream->stream_id].pos_low_reg;
307 		pos_high_reg = sdw1_dma_ring_buf_reg[stream->stream_id].pos_high_reg;
308 		break;
309 	default:
310 		return -EINVAL;
311 	}
312 	if (pos_low_reg) {
313 		byte_count.bcount.high = readl(acp_base + pos_high_reg);
314 		byte_count.bcount.low = readl(acp_base + pos_low_reg);
315 	}
316 	return byte_count.bytescount;
317 }
318 
319 static snd_pcm_uframes_t acp63_sdw_dma_pointer(struct snd_soc_component *comp,
320 					       struct snd_pcm_substream *substream)
321 {
322 	struct sdw_dma_dev_data *sdw_data;
323 	struct acp_sdw_dma_stream *stream;
324 	u32 pos, buffersize;
325 	u64 bytescount;
326 
327 	sdw_data = dev_get_drvdata(comp->dev);
328 	stream = substream->runtime->private_data;
329 	buffersize = frames_to_bytes(substream->runtime,
330 				     substream->runtime->buffer_size);
331 	bytescount = acp63_sdw_get_byte_count(stream, sdw_data->acp_base);
332 	if (bytescount > stream->bytescount)
333 		bytescount -= stream->bytescount;
334 	pos = do_div(bytescount, buffersize);
335 	return bytes_to_frames(substream->runtime, pos);
336 }
337 
338 static int acp63_sdw_dma_new(struct snd_soc_component *component,
339 			     struct snd_soc_pcm_runtime *rtd)
340 {
341 	struct device *parent = component->dev->parent;
342 
343 	snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
344 				       parent, SDW_MIN_BUFFER, SDW_MAX_BUFFER);
345 	return 0;
346 }
347 
348 static int acp63_sdw_dma_close(struct snd_soc_component *component,
349 			       struct snd_pcm_substream *substream)
350 {
351 	struct sdw_dma_dev_data *sdw_data;
352 	struct acp_sdw_dma_stream *stream;
353 
354 	sdw_data = dev_get_drvdata(component->dev);
355 	stream = substream->runtime->private_data;
356 	if (!stream)
357 		return -EINVAL;
358 	switch (stream->instance) {
359 	case ACP_SDW0:
360 		sdw_data->sdw0_dma_stream[stream->stream_id] = NULL;
361 		break;
362 	case ACP_SDW1:
363 		sdw_data->sdw1_dma_stream[stream->stream_id] = NULL;
364 		break;
365 	default:
366 		return -EINVAL;
367 	}
368 	kfree(stream);
369 	return 0;
370 }
371 
372 static int acp63_sdw_dma_enable(struct snd_pcm_substream *substream,
373 				void __iomem *acp_base, bool sdw_dma_enable)
374 {
375 	struct acp_sdw_dma_stream *stream;
376 	u32 stream_id;
377 	u32 sdw_dma_en_reg;
378 	u32 sdw_dma_en_stat_reg;
379 	u32 sdw_dma_stat;
380 	u32 dma_enable;
381 
382 	stream = substream->runtime->private_data;
383 	stream_id = stream->stream_id;
384 	switch (stream->instance) {
385 	case ACP_SDW0:
386 		sdw_dma_en_reg = sdw0_dma_enable_reg[stream_id];
387 		break;
388 	case ACP_SDW1:
389 		sdw_dma_en_reg = sdw1_dma_enable_reg[stream_id];
390 		break;
391 	default:
392 		return -EINVAL;
393 	}
394 	sdw_dma_en_stat_reg = sdw_dma_en_reg + 4;
395 	dma_enable = sdw_dma_enable;
396 	writel(dma_enable, acp_base + sdw_dma_en_reg);
397 	return readl_poll_timeout(acp_base + sdw_dma_en_stat_reg, sdw_dma_stat,
398 				  (sdw_dma_stat == dma_enable), ACP_DELAY_US, ACP_COUNTER);
399 }
400 
401 static int acp63_sdw_dma_trigger(struct snd_soc_component *comp,
402 				 struct snd_pcm_substream *substream,
403 				 int cmd)
404 {
405 	struct sdw_dma_dev_data *sdw_data;
406 	int ret;
407 
408 	sdw_data = dev_get_drvdata(comp->dev);
409 	switch (cmd) {
410 	case SNDRV_PCM_TRIGGER_START:
411 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
412 	case SNDRV_PCM_TRIGGER_RESUME:
413 		ret = acp63_sdw_dma_enable(substream, sdw_data->acp_base, true);
414 		break;
415 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
416 	case SNDRV_PCM_TRIGGER_SUSPEND:
417 	case SNDRV_PCM_TRIGGER_STOP:
418 		ret = acp63_sdw_dma_enable(substream, sdw_data->acp_base, false);
419 		break;
420 	default:
421 		ret = -EINVAL;
422 	}
423 	if (ret)
424 		dev_err(comp->dev, "trigger %d failed: %d", cmd, ret);
425 	return ret;
426 }
427 
428 static const struct snd_soc_component_driver acp63_sdw_component = {
429 	.name		= DRV_NAME,
430 	.open		= acp63_sdw_dma_open,
431 	.close		= acp63_sdw_dma_close,
432 	.hw_params	= acp63_sdw_dma_hw_params,
433 	.trigger	= acp63_sdw_dma_trigger,
434 	.pointer	= acp63_sdw_dma_pointer,
435 	.pcm_construct	= acp63_sdw_dma_new,
436 };
437 
438 static int acp63_sdw_platform_probe(struct platform_device *pdev)
439 {
440 	struct resource *res;
441 	struct sdw_dma_dev_data *sdw_data;
442 	struct acp63_dev_data *acp_data;
443 	struct device *parent;
444 	int status;
445 
446 	parent = pdev->dev.parent;
447 	acp_data = dev_get_drvdata(parent);
448 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
449 	if (!res) {
450 		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
451 		return -ENODEV;
452 	}
453 
454 	sdw_data = devm_kzalloc(&pdev->dev, sizeof(*sdw_data), GFP_KERNEL);
455 	if (!sdw_data)
456 		return -ENOMEM;
457 
458 	sdw_data->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
459 	if (!sdw_data->acp_base)
460 		return -ENOMEM;
461 
462 	sdw_data->acp_lock = &acp_data->acp_lock;
463 	dev_set_drvdata(&pdev->dev, sdw_data);
464 	status = devm_snd_soc_register_component(&pdev->dev,
465 						 &acp63_sdw_component,
466 						 NULL, 0);
467 	if (status) {
468 		dev_err(&pdev->dev, "Fail to register sdw dma component\n");
469 		return status;
470 	}
471 	pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
472 	pm_runtime_use_autosuspend(&pdev->dev);
473 	pm_runtime_mark_last_busy(&pdev->dev);
474 	pm_runtime_set_active(&pdev->dev);
475 	pm_runtime_enable(&pdev->dev);
476 	return 0;
477 }
478 
479 static int acp63_sdw_platform_remove(struct platform_device *pdev)
480 {
481 	pm_runtime_disable(&pdev->dev);
482 	return 0;
483 }
484 
485 static int acp_restore_sdw_dma_config(struct sdw_dma_dev_data *sdw_data)
486 {
487 	struct acp_sdw_dma_stream *stream;
488 	struct snd_pcm_substream *substream;
489 	struct snd_pcm_runtime *runtime;
490 	u32 period_bytes, buf_size, water_mark_size_reg;
491 	u32 stream_count;
492 	int index, instance, ret;
493 
494 	for (instance = 0; instance < AMD_SDW_MAX_MANAGERS; instance++) {
495 		if (instance == ACP_SDW0)
496 			stream_count = ACP63_SDW0_DMA_MAX_STREAMS;
497 		else
498 			stream_count = ACP63_SDW1_DMA_MAX_STREAMS;
499 
500 		for (index = 0; index < stream_count; index++) {
501 			if (instance == ACP_SDW0) {
502 				substream = sdw_data->sdw0_dma_stream[index];
503 				water_mark_size_reg =
504 						sdw0_dma_ring_buf_reg[index].water_mark_size_reg;
505 			} else {
506 				substream = sdw_data->sdw1_dma_stream[index];
507 				water_mark_size_reg =
508 						sdw1_dma_ring_buf_reg[index].water_mark_size_reg;
509 			}
510 
511 			if (substream && substream->runtime) {
512 				runtime = substream->runtime;
513 				stream = runtime->private_data;
514 				period_bytes = frames_to_bytes(runtime, runtime->period_size);
515 				buf_size = frames_to_bytes(runtime, runtime->buffer_size);
516 				acp63_config_dma(stream, sdw_data->acp_base, index);
517 				ret = acp63_configure_sdw_ringbuffer(sdw_data->acp_base, index,
518 								     buf_size, instance);
519 				if (ret)
520 					return ret;
521 				writel(period_bytes, sdw_data->acp_base + water_mark_size_reg);
522 			}
523 		}
524 	}
525 	acp63_enable_disable_sdw_dma_interrupts(sdw_data->acp_base, true);
526 	return 0;
527 }
528 
529 static int __maybe_unused acp63_sdw_pcm_resume(struct device *dev)
530 {
531 	struct sdw_dma_dev_data *sdw_data;
532 
533 	sdw_data = dev_get_drvdata(dev);
534 	return acp_restore_sdw_dma_config(sdw_data);
535 }
536 
537 static const struct dev_pm_ops acp63_pm_ops = {
538 	SET_SYSTEM_SLEEP_PM_OPS(NULL, acp63_sdw_pcm_resume)
539 };
540 
541 static struct platform_driver acp63_sdw_dma_driver = {
542 	.probe = acp63_sdw_platform_probe,
543 	.remove = acp63_sdw_platform_remove,
544 	.driver = {
545 		.name = "amd_ps_sdw_dma",
546 		.pm = &acp63_pm_ops,
547 	},
548 };
549 
550 module_platform_driver(acp63_sdw_dma_driver);
551 
552 MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
553 MODULE_DESCRIPTION("AMD ACP6.3 PS SDW DMA Driver");
554 MODULE_LICENSE("GPL");
555 MODULE_ALIAS("platform:" DRV_NAME);
556