1 // SPDX-License-Identifier: GPL-2.0-only
3 * AMD ALSA SoC Pink Sardine SoundWire DMA Driver
5 * Copyright 2023 Advanced Micro Devices, Inc.
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>
19 #define DRV_NAME "amd_ps_sdw_dma"
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_RX_LINEARPOSITIONCNTR_LOW
, ACP_AUDIO0_RX_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
}
43 * SDW1 instance supports one TX stream and one RX stream.
44 * For TX/RX streams DMA registers programming for SDW1 instance, it uses ACP_P1_AUDIO1 register
45 * set as per hardware register documentation
47 static struct sdw_dma_ring_buf_reg sdw1_dma_ring_buf_reg
[ACP63_SDW1_DMA_MAX_STREAMS
] = {
48 {ACP_P1_AUDIO1_TX_DMA_SIZE
, ACP_P1_AUDIO1_TX_FIFOADDR
, ACP_P1_AUDIO1_TX_FIFOSIZE
,
49 ACP_P1_AUDIO1_TX_RINGBUFSIZE
, ACP_P1_AUDIO1_TX_RINGBUFADDR
,
50 ACP_P1_AUDIO1_TX_INTR_WATERMARK_SIZE
,
51 ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_LOW
, ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_HIGH
},
52 {ACP_P1_AUDIO1_RX_DMA_SIZE
, ACP_P1_AUDIO1_RX_FIFOADDR
, ACP_P1_AUDIO1_RX_FIFOSIZE
,
53 ACP_P1_AUDIO1_RX_RINGBUFSIZE
, ACP_P1_AUDIO1_RX_RINGBUFADDR
,
54 ACP_P1_AUDIO1_RX_INTR_WATERMARK_SIZE
,
55 ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_LOW
, ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH
},
58 static u32 sdw0_dma_enable_reg
[ACP63_SDW0_DMA_MAX_STREAMS
] = {
68 * SDW1 instance supports one TX stream and one RX stream.
69 * For TX/RX streams DMA enable register programming for SDW1 instance,
70 * it uses ACP_SW1_AUDIO1_TX_EN and ACP_SW1_AUDIO1_RX_EN registers
71 * as per hardware register documentation.
73 static u32 sdw1_dma_enable_reg
[ACP63_SDW1_DMA_MAX_STREAMS
] = {
78 static const struct snd_pcm_hardware acp63_sdw_hardware_playback
= {
79 .info
= SNDRV_PCM_INFO_INTERLEAVED
|
80 SNDRV_PCM_INFO_BLOCK_TRANSFER
|
81 SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_MMAP_VALID
|
82 SNDRV_PCM_INFO_PAUSE
| SNDRV_PCM_INFO_RESUME
,
83 .formats
= SNDRV_PCM_FMTBIT_S16_LE
| SNDRV_PCM_FMTBIT_S8
|
84 SNDRV_PCM_FMTBIT_U8
| SNDRV_PCM_FMTBIT_S24_LE
| SNDRV_PCM_FMTBIT_S32_LE
,
87 .rates
= SNDRV_PCM_RATE_48000
,
90 .buffer_bytes_max
= SDW_PLAYBACK_MAX_NUM_PERIODS
* SDW_PLAYBACK_MAX_PERIOD_SIZE
,
91 .period_bytes_min
= SDW_PLAYBACK_MIN_PERIOD_SIZE
,
92 .period_bytes_max
= SDW_PLAYBACK_MAX_PERIOD_SIZE
,
93 .periods_min
= SDW_PLAYBACK_MIN_NUM_PERIODS
,
94 .periods_max
= SDW_PLAYBACK_MAX_NUM_PERIODS
,
97 static const struct snd_pcm_hardware acp63_sdw_hardware_capture
= {
98 .info
= SNDRV_PCM_INFO_INTERLEAVED
|
99 SNDRV_PCM_INFO_BLOCK_TRANSFER
|
100 SNDRV_PCM_INFO_MMAP
|
101 SNDRV_PCM_INFO_MMAP_VALID
|
102 SNDRV_PCM_INFO_PAUSE
| SNDRV_PCM_INFO_RESUME
,
103 .formats
= SNDRV_PCM_FMTBIT_S16_LE
| SNDRV_PCM_FMTBIT_S8
|
104 SNDRV_PCM_FMTBIT_U8
| SNDRV_PCM_FMTBIT_S24_LE
| SNDRV_PCM_FMTBIT_S32_LE
,
107 .rates
= SNDRV_PCM_RATE_48000
,
110 .buffer_bytes_max
= SDW_CAPTURE_MAX_NUM_PERIODS
* SDW_CAPTURE_MAX_PERIOD_SIZE
,
111 .period_bytes_min
= SDW_CAPTURE_MIN_PERIOD_SIZE
,
112 .period_bytes_max
= SDW_CAPTURE_MAX_PERIOD_SIZE
,
113 .periods_min
= SDW_CAPTURE_MIN_NUM_PERIODS
,
114 .periods_max
= SDW_CAPTURE_MAX_NUM_PERIODS
,
117 static void acp63_enable_disable_sdw_dma_interrupts(void __iomem
*acp_base
, bool enable
)
119 u32 ext_intr_cntl
, ext_intr_cntl1
;
120 u32 irq_mask
= ACP_SDW_DMA_IRQ_MASK
;
121 u32 irq_mask1
= ACP_P1_SDW_DMA_IRQ_MASK
;
124 ext_intr_cntl
= readl(acp_base
+ ACP_EXTERNAL_INTR_CNTL
);
125 ext_intr_cntl
|= irq_mask
;
126 writel(ext_intr_cntl
, acp_base
+ ACP_EXTERNAL_INTR_CNTL
);
127 ext_intr_cntl1
= readl(acp_base
+ ACP_EXTERNAL_INTR_CNTL1
);
128 ext_intr_cntl1
|= irq_mask1
;
129 writel(ext_intr_cntl1
, acp_base
+ ACP_EXTERNAL_INTR_CNTL1
);
131 ext_intr_cntl
= readl(acp_base
+ ACP_EXTERNAL_INTR_CNTL
);
132 ext_intr_cntl
&= ~irq_mask
;
133 writel(ext_intr_cntl
, acp_base
+ ACP_EXTERNAL_INTR_CNTL
);
134 ext_intr_cntl1
= readl(acp_base
+ ACP_EXTERNAL_INTR_CNTL1
);
135 ext_intr_cntl1
&= ~irq_mask1
;
136 writel(ext_intr_cntl1
, acp_base
+ ACP_EXTERNAL_INTR_CNTL1
);
140 static void acp63_config_dma(struct acp_sdw_dma_stream
*stream
, void __iomem
*acp_base
,
145 u32 sdw_dma_pte_offset
;
148 addr
= stream
->dma_addr
;
149 sdw_dma_pte_offset
= SDW_PTE_OFFSET(stream
->instance
);
150 val
= sdw_dma_pte_offset
+ (stream_id
* ACP_SDW_PTE_OFFSET
);
153 writel(ACP_SDW_SRAM_PTE_OFFSET
| BIT(31), acp_base
+ ACPAXI2AXI_ATU_BASE_ADDR_GRP_2
);
154 writel(PAGE_SIZE_4K_ENABLE
, acp_base
+ ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2
);
155 for (page_idx
= 0; page_idx
< stream
->num_pages
; page_idx
++) {
156 /* Load the low address of page int ACP SRAM through SRBM */
157 low
= lower_32_bits(addr
);
158 high
= upper_32_bits(addr
);
160 writel(low
, acp_base
+ ACP_SCRATCH_REG_0
+ val
);
162 writel(high
, acp_base
+ ACP_SCRATCH_REG_0
+ val
+ 4);
166 writel(0x1, acp_base
+ ACPAXI2AXI_ATU_CTRL
);
169 static int acp63_configure_sdw_ringbuffer(void __iomem
*acp_base
, u32 stream_id
, u32 size
,
170 u32 manager_instance
)
175 u32 reg_ring_buf_size
;
176 u32 reg_ring_buf_addr
;
179 u32 sdw_ring_buf_addr
;
180 u32 sdw_ring_buf_size
;
181 u32 sdw_mem_window_offset
;
183 switch (manager_instance
) {
185 reg_dma_size
= sdw0_dma_ring_buf_reg
[stream_id
].reg_dma_size
;
186 reg_fifo_addr
= sdw0_dma_ring_buf_reg
[stream_id
].reg_fifo_addr
;
187 reg_fifo_size
= sdw0_dma_ring_buf_reg
[stream_id
].reg_fifo_size
;
188 reg_ring_buf_size
= sdw0_dma_ring_buf_reg
[stream_id
].reg_ring_buf_size
;
189 reg_ring_buf_addr
= sdw0_dma_ring_buf_reg
[stream_id
].reg_ring_buf_addr
;
192 reg_dma_size
= sdw1_dma_ring_buf_reg
[stream_id
].reg_dma_size
;
193 reg_fifo_addr
= sdw1_dma_ring_buf_reg
[stream_id
].reg_fifo_addr
;
194 reg_fifo_size
= sdw1_dma_ring_buf_reg
[stream_id
].reg_fifo_size
;
195 reg_ring_buf_size
= sdw1_dma_ring_buf_reg
[stream_id
].reg_ring_buf_size
;
196 reg_ring_buf_addr
= sdw1_dma_ring_buf_reg
[stream_id
].reg_ring_buf_addr
;
201 sdw_fifo_offset
= ACP_SDW_FIFO_OFFSET(manager_instance
);
202 sdw_mem_window_offset
= SDW_MEM_WINDOW_START(manager_instance
);
203 sdw_fifo_addr
= sdw_fifo_offset
+ (stream_id
* SDW_FIFO_OFFSET
);
204 sdw_ring_buf_addr
= sdw_mem_window_offset
+ (stream_id
* ACP_SDW_RING_BUFF_ADDR_OFFSET
);
205 sdw_ring_buf_size
= size
;
206 writel(sdw_ring_buf_size
, acp_base
+ reg_ring_buf_size
);
207 writel(sdw_ring_buf_addr
, acp_base
+ reg_ring_buf_addr
);
208 writel(sdw_fifo_addr
, acp_base
+ reg_fifo_addr
);
209 writel(SDW_DMA_SIZE
, acp_base
+ reg_dma_size
);
210 writel(SDW_FIFO_SIZE
, acp_base
+ reg_fifo_size
);
214 static int acp63_sdw_dma_open(struct snd_soc_component
*component
,
215 struct snd_pcm_substream
*substream
)
217 struct snd_pcm_runtime
*runtime
;
218 struct acp_sdw_dma_stream
*stream
;
219 struct snd_soc_dai
*cpu_dai
;
220 struct amd_sdw_manager
*amd_manager
;
221 struct snd_soc_pcm_runtime
*prtd
= snd_soc_substream_to_rtd(substream
);
224 runtime
= substream
->runtime
;
225 cpu_dai
= snd_soc_rtd_to_cpu(prtd
, 0);
226 amd_manager
= snd_soc_dai_get_drvdata(cpu_dai
);
227 stream
= kzalloc(sizeof(*stream
), GFP_KERNEL
);
231 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
232 runtime
->hw
= acp63_sdw_hardware_playback
;
234 runtime
->hw
= acp63_sdw_hardware_capture
;
235 ret
= snd_pcm_hw_constraint_integer(runtime
,
236 SNDRV_PCM_HW_PARAM_PERIODS
);
238 dev_err(component
->dev
, "set integer constraint failed\n");
243 stream
->stream_id
= cpu_dai
->id
;
244 stream
->instance
= amd_manager
->instance
;
245 runtime
->private_data
= stream
;
249 static int acp63_sdw_dma_hw_params(struct snd_soc_component
*component
,
250 struct snd_pcm_substream
*substream
,
251 struct snd_pcm_hw_params
*params
)
253 struct acp_sdw_dma_stream
*stream
;
254 struct sdw_dma_dev_data
*sdw_data
;
256 u32 water_mark_size_reg
;
257 u32 irq_mask
, ext_intr_ctrl
;
260 u32 acp_ext_intr_cntl_reg
;
263 sdw_data
= dev_get_drvdata(component
->dev
);
264 stream
= substream
->runtime
->private_data
;
267 stream_id
= stream
->stream_id
;
268 switch (stream
->instance
) {
270 sdw_data
->sdw0_dma_stream
[stream_id
] = substream
;
271 water_mark_size_reg
= sdw0_dma_ring_buf_reg
[stream_id
].water_mark_size_reg
;
272 acp_ext_intr_cntl_reg
= ACP_EXTERNAL_INTR_CNTL
;
273 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
274 irq_mask
= BIT(SDW0_DMA_TX_IRQ_MASK(stream_id
));
276 irq_mask
= BIT(SDW0_DMA_RX_IRQ_MASK(stream_id
));
279 sdw_data
->sdw1_dma_stream
[stream_id
] = substream
;
280 acp_ext_intr_cntl_reg
= ACP_EXTERNAL_INTR_CNTL1
;
281 water_mark_size_reg
= sdw1_dma_ring_buf_reg
[stream_id
].water_mark_size_reg
;
282 irq_mask
= BIT(SDW1_DMA_IRQ_MASK(stream_id
));
287 size
= params_buffer_bytes(params
);
288 period_bytes
= params_period_bytes(params
);
289 stream
->dma_addr
= substream
->runtime
->dma_addr
;
290 stream
->num_pages
= (PAGE_ALIGN(size
) >> PAGE_SHIFT
);
291 acp63_config_dma(stream
, sdw_data
->acp_base
, stream_id
);
292 ret
= acp63_configure_sdw_ringbuffer(sdw_data
->acp_base
, stream_id
, size
,
295 dev_err(component
->dev
, "Invalid DMA channel\n");
298 ext_intr_ctrl
= readl(sdw_data
->acp_base
+ acp_ext_intr_cntl_reg
);
299 ext_intr_ctrl
|= irq_mask
;
300 writel(ext_intr_ctrl
, sdw_data
->acp_base
+ acp_ext_intr_cntl_reg
);
301 writel(period_bytes
, sdw_data
->acp_base
+ water_mark_size_reg
);
305 static u64
acp63_sdw_get_byte_count(struct acp_sdw_dma_stream
*stream
, void __iomem
*acp_base
)
307 union acp_sdw_dma_count byte_count
;
308 u32 pos_low_reg
, pos_high_reg
;
310 byte_count
.bytescount
= 0;
311 switch (stream
->instance
) {
313 pos_low_reg
= sdw0_dma_ring_buf_reg
[stream
->stream_id
].pos_low_reg
;
314 pos_high_reg
= sdw0_dma_ring_buf_reg
[stream
->stream_id
].pos_high_reg
;
317 pos_low_reg
= sdw1_dma_ring_buf_reg
[stream
->stream_id
].pos_low_reg
;
318 pos_high_reg
= sdw1_dma_ring_buf_reg
[stream
->stream_id
].pos_high_reg
;
321 goto POINTER_RETURN_BYTES
;
324 byte_count
.bcount
.high
= readl(acp_base
+ pos_high_reg
);
325 byte_count
.bcount
.low
= readl(acp_base
+ pos_low_reg
);
327 POINTER_RETURN_BYTES
:
328 return byte_count
.bytescount
;
331 static snd_pcm_uframes_t
acp63_sdw_dma_pointer(struct snd_soc_component
*comp
,
332 struct snd_pcm_substream
*substream
)
334 struct sdw_dma_dev_data
*sdw_data
;
335 struct acp_sdw_dma_stream
*stream
;
339 sdw_data
= dev_get_drvdata(comp
->dev
);
340 stream
= substream
->runtime
->private_data
;
341 buffersize
= frames_to_bytes(substream
->runtime
,
342 substream
->runtime
->buffer_size
);
343 bytescount
= acp63_sdw_get_byte_count(stream
, sdw_data
->acp_base
);
344 if (bytescount
> stream
->bytescount
)
345 bytescount
-= stream
->bytescount
;
346 pos
= do_div(bytescount
, buffersize
);
347 return bytes_to_frames(substream
->runtime
, pos
);
350 static int acp63_sdw_dma_new(struct snd_soc_component
*component
,
351 struct snd_soc_pcm_runtime
*rtd
)
353 struct device
*parent
= component
->dev
->parent
;
355 snd_pcm_set_managed_buffer_all(rtd
->pcm
, SNDRV_DMA_TYPE_DEV
,
356 parent
, SDW_MIN_BUFFER
, SDW_MAX_BUFFER
);
360 static int acp63_sdw_dma_close(struct snd_soc_component
*component
,
361 struct snd_pcm_substream
*substream
)
363 struct sdw_dma_dev_data
*sdw_data
;
364 struct acp_sdw_dma_stream
*stream
;
366 sdw_data
= dev_get_drvdata(component
->dev
);
367 stream
= substream
->runtime
->private_data
;
370 switch (stream
->instance
) {
372 sdw_data
->sdw0_dma_stream
[stream
->stream_id
] = NULL
;
375 sdw_data
->sdw1_dma_stream
[stream
->stream_id
] = NULL
;
384 static int acp63_sdw_dma_enable(struct snd_pcm_substream
*substream
,
385 void __iomem
*acp_base
, bool sdw_dma_enable
)
387 struct acp_sdw_dma_stream
*stream
;
390 u32 sdw_dma_en_stat_reg
;
394 stream
= substream
->runtime
->private_data
;
395 stream_id
= stream
->stream_id
;
396 switch (stream
->instance
) {
398 sdw_dma_en_reg
= sdw0_dma_enable_reg
[stream_id
];
401 sdw_dma_en_reg
= sdw1_dma_enable_reg
[stream_id
];
406 sdw_dma_en_stat_reg
= sdw_dma_en_reg
+ 4;
407 dma_enable
= sdw_dma_enable
;
408 writel(dma_enable
, acp_base
+ sdw_dma_en_reg
);
409 return readl_poll_timeout(acp_base
+ sdw_dma_en_stat_reg
, sdw_dma_stat
,
410 (sdw_dma_stat
== dma_enable
), ACP_DELAY_US
, ACP_COUNTER
);
413 static int acp63_sdw_dma_trigger(struct snd_soc_component
*comp
,
414 struct snd_pcm_substream
*substream
,
417 struct sdw_dma_dev_data
*sdw_data
;
420 sdw_data
= dev_get_drvdata(comp
->dev
);
422 case SNDRV_PCM_TRIGGER_START
:
423 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
424 case SNDRV_PCM_TRIGGER_RESUME
:
425 ret
= acp63_sdw_dma_enable(substream
, sdw_data
->acp_base
, true);
427 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
428 case SNDRV_PCM_TRIGGER_SUSPEND
:
429 case SNDRV_PCM_TRIGGER_STOP
:
430 ret
= acp63_sdw_dma_enable(substream
, sdw_data
->acp_base
, false);
436 dev_err(comp
->dev
, "trigger %d failed: %d", cmd
, ret
);
440 static const struct snd_soc_component_driver acp63_sdw_component
= {
442 .open
= acp63_sdw_dma_open
,
443 .close
= acp63_sdw_dma_close
,
444 .hw_params
= acp63_sdw_dma_hw_params
,
445 .trigger
= acp63_sdw_dma_trigger
,
446 .pointer
= acp63_sdw_dma_pointer
,
447 .pcm_construct
= acp63_sdw_dma_new
,
448 .use_dai_pcm_id
= true,
452 static int acp63_sdw_platform_probe(struct platform_device
*pdev
)
454 struct resource
*res
;
455 struct sdw_dma_dev_data
*sdw_data
;
456 struct acp63_dev_data
*acp_data
;
457 struct device
*parent
;
460 parent
= pdev
->dev
.parent
;
461 acp_data
= dev_get_drvdata(parent
);
462 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
464 dev_err(&pdev
->dev
, "IORESOURCE_MEM FAILED\n");
468 sdw_data
= devm_kzalloc(&pdev
->dev
, sizeof(*sdw_data
), GFP_KERNEL
);
472 sdw_data
->acp_base
= devm_ioremap(&pdev
->dev
, res
->start
, resource_size(res
));
473 if (!sdw_data
->acp_base
)
476 sdw_data
->acp_lock
= &acp_data
->acp_lock
;
477 dev_set_drvdata(&pdev
->dev
, sdw_data
);
478 status
= devm_snd_soc_register_component(&pdev
->dev
,
479 &acp63_sdw_component
,
482 dev_err(&pdev
->dev
, "Fail to register sdw dma component\n");
485 pm_runtime_set_autosuspend_delay(&pdev
->dev
, ACP_SUSPEND_DELAY_MS
);
486 pm_runtime_use_autosuspend(&pdev
->dev
);
487 pm_runtime_mark_last_busy(&pdev
->dev
);
488 pm_runtime_set_active(&pdev
->dev
);
489 pm_runtime_enable(&pdev
->dev
);
493 static void acp63_sdw_platform_remove(struct platform_device
*pdev
)
495 pm_runtime_disable(&pdev
->dev
);
498 static int acp_restore_sdw_dma_config(struct sdw_dma_dev_data
*sdw_data
)
500 struct acp_sdw_dma_stream
*stream
;
501 struct snd_pcm_substream
*substream
;
502 struct snd_pcm_runtime
*runtime
;
503 u32 period_bytes
, buf_size
, water_mark_size_reg
;
505 int index
, instance
, ret
;
507 for (instance
= 0; instance
< AMD_SDW_MAX_MANAGERS
; instance
++) {
508 if (instance
== ACP_SDW0
)
509 stream_count
= ACP63_SDW0_DMA_MAX_STREAMS
;
511 stream_count
= ACP63_SDW1_DMA_MAX_STREAMS
;
513 for (index
= 0; index
< stream_count
; index
++) {
514 if (instance
== ACP_SDW0
) {
515 substream
= sdw_data
->sdw0_dma_stream
[index
];
516 water_mark_size_reg
=
517 sdw0_dma_ring_buf_reg
[index
].water_mark_size_reg
;
519 substream
= sdw_data
->sdw1_dma_stream
[index
];
520 water_mark_size_reg
=
521 sdw1_dma_ring_buf_reg
[index
].water_mark_size_reg
;
524 if (substream
&& substream
->runtime
) {
525 runtime
= substream
->runtime
;
526 stream
= runtime
->private_data
;
527 period_bytes
= frames_to_bytes(runtime
, runtime
->period_size
);
528 buf_size
= frames_to_bytes(runtime
, runtime
->buffer_size
);
529 acp63_config_dma(stream
, sdw_data
->acp_base
, index
);
530 ret
= acp63_configure_sdw_ringbuffer(sdw_data
->acp_base
, index
,
534 writel(period_bytes
, sdw_data
->acp_base
+ water_mark_size_reg
);
538 acp63_enable_disable_sdw_dma_interrupts(sdw_data
->acp_base
, true);
542 static int __maybe_unused
acp63_sdw_pcm_resume(struct device
*dev
)
544 struct sdw_dma_dev_data
*sdw_data
;
546 sdw_data
= dev_get_drvdata(dev
);
547 return acp_restore_sdw_dma_config(sdw_data
);
550 static const struct dev_pm_ops acp63_pm_ops
= {
551 SET_SYSTEM_SLEEP_PM_OPS(NULL
, acp63_sdw_pcm_resume
)
554 static struct platform_driver acp63_sdw_dma_driver
= {
555 .probe
= acp63_sdw_platform_probe
,
556 .remove
= acp63_sdw_platform_remove
,
558 .name
= "amd_ps_sdw_dma",
563 module_platform_driver(acp63_sdw_dma_driver
);
565 MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
566 MODULE_DESCRIPTION("AMD ACP6.3 PS SDW DMA Driver");
567 MODULE_LICENSE("GPL");
568 MODULE_ALIAS("platform:" DRV_NAME
);