1 // SPDX-License-Identifier: GPL-2.0+
3 // AMD ALSA SoC PCM Driver
5 //Copyright 2016 Advanced Micro Devices, Inc.
7 #include <linux/platform_device.h>
8 #include <linux/module.h>
11 #include <linux/pm_runtime.h>
12 #include <sound/pcm_params.h>
13 #include <sound/soc.h>
14 #include <sound/soc-dai.h>
18 #define DRV_NAME "acp3x-i2s-audio"
20 static const struct snd_pcm_hardware acp3x_pcm_hardware_playback
= {
21 .info
= SNDRV_PCM_INFO_INTERLEAVED
|
22 SNDRV_PCM_INFO_BLOCK_TRANSFER
|
23 SNDRV_PCM_INFO_BATCH
|
24 SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_MMAP_VALID
|
25 SNDRV_PCM_INFO_PAUSE
| SNDRV_PCM_INFO_RESUME
,
26 .formats
= SNDRV_PCM_FMTBIT_S16_LE
| SNDRV_PCM_FMTBIT_S8
|
27 SNDRV_PCM_FMTBIT_U8
| SNDRV_PCM_FMTBIT_S24_LE
|
28 SNDRV_PCM_FMTBIT_S32_LE
,
31 .rates
= SNDRV_PCM_RATE_8000_96000
,
34 .buffer_bytes_max
= PLAYBACK_MAX_NUM_PERIODS
* PLAYBACK_MAX_PERIOD_SIZE
,
35 .period_bytes_min
= PLAYBACK_MIN_PERIOD_SIZE
,
36 .period_bytes_max
= PLAYBACK_MAX_PERIOD_SIZE
,
37 .periods_min
= PLAYBACK_MIN_NUM_PERIODS
,
38 .periods_max
= PLAYBACK_MAX_NUM_PERIODS
,
41 static const struct snd_pcm_hardware acp3x_pcm_hardware_capture
= {
42 .info
= SNDRV_PCM_INFO_INTERLEAVED
|
43 SNDRV_PCM_INFO_BLOCK_TRANSFER
|
44 SNDRV_PCM_INFO_BATCH
|
45 SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_MMAP_VALID
|
46 SNDRV_PCM_INFO_PAUSE
| SNDRV_PCM_INFO_RESUME
,
47 .formats
= SNDRV_PCM_FMTBIT_S16_LE
| SNDRV_PCM_FMTBIT_S8
|
48 SNDRV_PCM_FMTBIT_U8
| SNDRV_PCM_FMTBIT_S24_LE
|
49 SNDRV_PCM_FMTBIT_S32_LE
,
52 .rates
= SNDRV_PCM_RATE_8000_48000
,
55 .buffer_bytes_max
= CAPTURE_MAX_NUM_PERIODS
* CAPTURE_MAX_PERIOD_SIZE
,
56 .period_bytes_min
= CAPTURE_MIN_PERIOD_SIZE
,
57 .period_bytes_max
= CAPTURE_MAX_PERIOD_SIZE
,
58 .periods_min
= CAPTURE_MIN_NUM_PERIODS
,
59 .periods_max
= CAPTURE_MAX_NUM_PERIODS
,
62 static irqreturn_t
i2s_irq_handler(int irq
, void *dev_id
)
64 struct i2s_dev_data
*rv_i2s_data
;
65 u16 play_flag
, cap_flag
;
74 val
= rv_readl(rv_i2s_data
->acp3x_base
+ mmACP_EXTERNAL_INTR_STAT
);
75 if ((val
& BIT(BT_TX_THRESHOLD
)) && rv_i2s_data
->play_stream
) {
76 rv_writel(BIT(BT_TX_THRESHOLD
), rv_i2s_data
->acp3x_base
+
77 mmACP_EXTERNAL_INTR_STAT
);
78 snd_pcm_period_elapsed(rv_i2s_data
->play_stream
);
81 if ((val
& BIT(I2S_TX_THRESHOLD
)) &&
82 rv_i2s_data
->i2ssp_play_stream
) {
83 rv_writel(BIT(I2S_TX_THRESHOLD
),
84 rv_i2s_data
->acp3x_base
+ mmACP_EXTERNAL_INTR_STAT
);
85 snd_pcm_period_elapsed(rv_i2s_data
->i2ssp_play_stream
);
89 if ((val
& BIT(BT_RX_THRESHOLD
)) && rv_i2s_data
->capture_stream
) {
90 rv_writel(BIT(BT_RX_THRESHOLD
), rv_i2s_data
->acp3x_base
+
91 mmACP_EXTERNAL_INTR_STAT
);
92 snd_pcm_period_elapsed(rv_i2s_data
->capture_stream
);
95 if ((val
& BIT(I2S_RX_THRESHOLD
)) &&
96 rv_i2s_data
->i2ssp_capture_stream
) {
97 rv_writel(BIT(I2S_RX_THRESHOLD
),
98 rv_i2s_data
->acp3x_base
+ mmACP_EXTERNAL_INTR_STAT
);
99 snd_pcm_period_elapsed(rv_i2s_data
->i2ssp_capture_stream
);
103 if (play_flag
| cap_flag
)
109 static void config_acp3x_dma(struct i2s_stream_instance
*rtd
, int direction
)
112 u32 low
, high
, val
, acp_fifo_addr
, reg_fifo_addr
;
113 u32 reg_ringbuf_size
, reg_dma_size
, reg_fifo_size
;
116 addr
= rtd
->dma_addr
;
118 if (direction
== SNDRV_PCM_STREAM_PLAYBACK
) {
119 switch (rtd
->i2s_instance
) {
120 case I2S_BT_INSTANCE
:
121 val
= ACP_SRAM_BT_PB_PTE_OFFSET
;
123 case I2S_SP_INSTANCE
:
125 val
= ACP_SRAM_SP_PB_PTE_OFFSET
;
128 switch (rtd
->i2s_instance
) {
129 case I2S_BT_INSTANCE
:
130 val
= ACP_SRAM_BT_CP_PTE_OFFSET
;
132 case I2S_SP_INSTANCE
:
134 val
= ACP_SRAM_SP_CP_PTE_OFFSET
;
138 rv_writel(ACP_SRAM_PTE_OFFSET
| BIT(31), rtd
->acp3x_base
+
139 mmACPAXI2AXI_ATU_BASE_ADDR_GRP_1
);
140 rv_writel(PAGE_SIZE_4K_ENABLE
, rtd
->acp3x_base
+
141 mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_1
);
143 for (page_idx
= 0; page_idx
< rtd
->num_pages
; page_idx
++) {
144 /* Load the low address of page int ACP SRAM through SRBM */
145 low
= lower_32_bits(addr
);
146 high
= upper_32_bits(addr
);
148 rv_writel(low
, rtd
->acp3x_base
+ mmACP_SCRATCH_REG_0
+ val
);
150 rv_writel(high
, rtd
->acp3x_base
+ mmACP_SCRATCH_REG_0
+ val
152 /* Move to next physically contiguos page */
157 if (direction
== SNDRV_PCM_STREAM_PLAYBACK
) {
158 switch (rtd
->i2s_instance
) {
159 case I2S_BT_INSTANCE
:
160 reg_ringbuf_size
= mmACP_BT_TX_RINGBUFSIZE
;
161 reg_dma_size
= mmACP_BT_TX_DMA_SIZE
;
162 acp_fifo_addr
= ACP_SRAM_PTE_OFFSET
+
163 BT_PB_FIFO_ADDR_OFFSET
;
164 reg_fifo_addr
= mmACP_BT_TX_FIFOADDR
;
165 reg_fifo_size
= mmACP_BT_TX_FIFOSIZE
;
166 rv_writel(I2S_BT_TX_MEM_WINDOW_START
,
167 rtd
->acp3x_base
+ mmACP_BT_TX_RINGBUFADDR
);
170 case I2S_SP_INSTANCE
:
172 reg_ringbuf_size
= mmACP_I2S_TX_RINGBUFSIZE
;
173 reg_dma_size
= mmACP_I2S_TX_DMA_SIZE
;
174 acp_fifo_addr
= ACP_SRAM_PTE_OFFSET
+
175 SP_PB_FIFO_ADDR_OFFSET
;
176 reg_fifo_addr
= mmACP_I2S_TX_FIFOADDR
;
177 reg_fifo_size
= mmACP_I2S_TX_FIFOSIZE
;
178 rv_writel(I2S_SP_TX_MEM_WINDOW_START
,
179 rtd
->acp3x_base
+ mmACP_I2S_TX_RINGBUFADDR
);
182 switch (rtd
->i2s_instance
) {
183 case I2S_BT_INSTANCE
:
184 reg_ringbuf_size
= mmACP_BT_RX_RINGBUFSIZE
;
185 reg_dma_size
= mmACP_BT_RX_DMA_SIZE
;
186 acp_fifo_addr
= ACP_SRAM_PTE_OFFSET
+
187 BT_CAPT_FIFO_ADDR_OFFSET
;
188 reg_fifo_addr
= mmACP_BT_RX_FIFOADDR
;
189 reg_fifo_size
= mmACP_BT_RX_FIFOSIZE
;
190 rv_writel(I2S_BT_RX_MEM_WINDOW_START
,
191 rtd
->acp3x_base
+ mmACP_BT_RX_RINGBUFADDR
);
194 case I2S_SP_INSTANCE
:
196 reg_ringbuf_size
= mmACP_I2S_RX_RINGBUFSIZE
;
197 reg_dma_size
= mmACP_I2S_RX_DMA_SIZE
;
198 acp_fifo_addr
= ACP_SRAM_PTE_OFFSET
+
199 SP_CAPT_FIFO_ADDR_OFFSET
;
200 reg_fifo_addr
= mmACP_I2S_RX_FIFOADDR
;
201 reg_fifo_size
= mmACP_I2S_RX_FIFOSIZE
;
202 rv_writel(I2S_SP_RX_MEM_WINDOW_START
,
203 rtd
->acp3x_base
+ mmACP_I2S_RX_RINGBUFADDR
);
206 rv_writel(MAX_BUFFER
, rtd
->acp3x_base
+ reg_ringbuf_size
);
207 rv_writel(DMA_SIZE
, rtd
->acp3x_base
+ reg_dma_size
);
208 rv_writel(acp_fifo_addr
, rtd
->acp3x_base
+ reg_fifo_addr
);
209 rv_writel(FIFO_SIZE
, rtd
->acp3x_base
+ reg_fifo_size
);
210 rv_writel(BIT(I2S_RX_THRESHOLD
) | BIT(BT_RX_THRESHOLD
)
211 | BIT(I2S_TX_THRESHOLD
) | BIT(BT_TX_THRESHOLD
),
212 rtd
->acp3x_base
+ mmACP_EXTERNAL_INTR_CNTL
);
215 static int acp3x_dma_open(struct snd_soc_component
*component
,
216 struct snd_pcm_substream
*substream
)
218 struct snd_pcm_runtime
*runtime
;
219 struct snd_soc_pcm_runtime
*prtd
;
220 struct i2s_dev_data
*adata
;
221 struct i2s_stream_instance
*i2s_data
;
224 runtime
= substream
->runtime
;
225 prtd
= substream
->private_data
;
226 component
= snd_soc_rtdcom_lookup(prtd
, DRV_NAME
);
227 adata
= dev_get_drvdata(component
->dev
);
228 i2s_data
= kzalloc(sizeof(*i2s_data
), GFP_KERNEL
);
232 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
233 runtime
->hw
= acp3x_pcm_hardware_playback
;
235 runtime
->hw
= acp3x_pcm_hardware_capture
;
237 ret
= snd_pcm_hw_constraint_integer(runtime
,
238 SNDRV_PCM_HW_PARAM_PERIODS
);
240 dev_err(component
->dev
, "set integer constraint failed\n");
245 if (!adata
->play_stream
&& !adata
->capture_stream
&&
246 adata
->i2ssp_play_stream
&& !adata
->i2ssp_capture_stream
)
247 rv_writel(1, adata
->acp3x_base
+ mmACP_EXTERNAL_INTR_ENB
);
249 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
250 adata
->play_stream
= substream
;
251 adata
->i2ssp_play_stream
= substream
;
253 adata
->capture_stream
= substream
;
254 adata
->i2ssp_capture_stream
= substream
;
257 i2s_data
->acp3x_base
= adata
->acp3x_base
;
258 runtime
->private_data
= i2s_data
;
263 static int acp3x_dma_hw_params(struct snd_soc_component
*component
,
264 struct snd_pcm_substream
*substream
,
265 struct snd_pcm_hw_params
*params
)
267 struct i2s_stream_instance
*rtd
;
268 struct snd_soc_pcm_runtime
*prtd
;
269 struct snd_soc_card
*card
;
270 struct acp3x_platform_info
*pinfo
;
273 prtd
= substream
->private_data
;
275 pinfo
= snd_soc_card_get_drvdata(card
);
276 rtd
= substream
->runtime
->private_data
;
281 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
282 rtd
->i2s_instance
= pinfo
->play_i2s_instance
;
284 rtd
->i2s_instance
= pinfo
->cap_i2s_instance
;
286 pr_err("pinfo failed\n");
288 size
= params_buffer_bytes(params
);
289 rtd
->dma_addr
= substream
->dma_buffer
.addr
;
290 rtd
->num_pages
= (PAGE_ALIGN(size
) >> PAGE_SHIFT
);
291 config_acp3x_dma(rtd
, substream
->stream
);
295 static snd_pcm_uframes_t
acp3x_dma_pointer(struct snd_soc_component
*component
,
296 struct snd_pcm_substream
*substream
)
298 struct snd_soc_pcm_runtime
*prtd
;
299 struct snd_soc_card
*card
;
300 struct acp3x_platform_info
*pinfo
;
301 struct i2s_stream_instance
*rtd
;
306 prtd
= substream
->private_data
;
308 rtd
= substream
->runtime
->private_data
;
309 pinfo
= snd_soc_card_get_drvdata(card
);
311 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
312 rtd
->i2s_instance
= pinfo
->play_i2s_instance
;
314 rtd
->i2s_instance
= pinfo
->cap_i2s_instance
;
317 buffersize
= frames_to_bytes(substream
->runtime
,
318 substream
->runtime
->buffer_size
);
319 bytescount
= acp_get_byte_count(rtd
, substream
->stream
);
320 if (bytescount
> rtd
->bytescount
)
321 bytescount
-= rtd
->bytescount
;
322 pos
= do_div(bytescount
, buffersize
);
323 return bytes_to_frames(substream
->runtime
, pos
);
326 static int acp3x_dma_new(struct snd_soc_component
*component
,
327 struct snd_soc_pcm_runtime
*rtd
)
329 struct device
*parent
= component
->dev
->parent
;
330 snd_pcm_set_managed_buffer_all(rtd
->pcm
, SNDRV_DMA_TYPE_DEV
,
331 parent
, MIN_BUFFER
, MAX_BUFFER
);
335 static int acp3x_dma_mmap(struct snd_soc_component
*component
,
336 struct snd_pcm_substream
*substream
,
337 struct vm_area_struct
*vma
)
339 return snd_pcm_lib_default_mmap(substream
, vma
);
342 static int acp3x_dma_close(struct snd_soc_component
*component
,
343 struct snd_pcm_substream
*substream
)
345 struct snd_soc_pcm_runtime
*prtd
;
346 struct i2s_dev_data
*adata
;
348 prtd
= substream
->private_data
;
349 component
= snd_soc_rtdcom_lookup(prtd
, DRV_NAME
);
350 adata
= dev_get_drvdata(component
->dev
);
352 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
353 adata
->play_stream
= NULL
;
354 adata
->i2ssp_play_stream
= NULL
;
356 adata
->capture_stream
= NULL
;
357 adata
->i2ssp_capture_stream
= NULL
;
360 /* Disable ACP irq, when the current stream is being closed and
361 * another stream is also not active.
363 if (!adata
->play_stream
&& !adata
->capture_stream
&&
364 !adata
->i2ssp_play_stream
&& !adata
->i2ssp_capture_stream
)
365 rv_writel(0, adata
->acp3x_base
+ mmACP_EXTERNAL_INTR_ENB
);
369 static const struct snd_soc_component_driver acp3x_i2s_component
= {
371 .open
= acp3x_dma_open
,
372 .close
= acp3x_dma_close
,
373 .hw_params
= acp3x_dma_hw_params
,
374 .pointer
= acp3x_dma_pointer
,
375 .mmap
= acp3x_dma_mmap
,
376 .pcm_construct
= acp3x_dma_new
,
379 static int acp3x_audio_probe(struct platform_device
*pdev
)
381 struct resource
*res
;
382 struct i2s_dev_data
*adata
;
383 unsigned int irqflags
;
386 if (!pdev
->dev
.platform_data
) {
387 dev_err(&pdev
->dev
, "platform_data not retrieved\n");
390 irqflags
= *((unsigned int *)(pdev
->dev
.platform_data
));
392 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
394 dev_err(&pdev
->dev
, "IORESOURCE_MEM FAILED\n");
398 adata
= devm_kzalloc(&pdev
->dev
, sizeof(*adata
), GFP_KERNEL
);
402 adata
->acp3x_base
= devm_ioremap(&pdev
->dev
, res
->start
,
404 if (!adata
->acp3x_base
)
407 res
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
409 dev_err(&pdev
->dev
, "IORESOURCE_IRQ FAILED\n");
413 adata
->i2s_irq
= res
->start
;
415 dev_set_drvdata(&pdev
->dev
, adata
);
416 status
= devm_snd_soc_register_component(&pdev
->dev
,
417 &acp3x_i2s_component
,
420 dev_err(&pdev
->dev
, "Fail to register acp i2s component\n");
423 status
= devm_request_irq(&pdev
->dev
, adata
->i2s_irq
, i2s_irq_handler
,
424 irqflags
, "ACP3x_I2S_IRQ", adata
);
426 dev_err(&pdev
->dev
, "ACP3x I2S IRQ request failed\n");
430 pm_runtime_set_autosuspend_delay(&pdev
->dev
, 2000);
431 pm_runtime_use_autosuspend(&pdev
->dev
);
432 pm_runtime_enable(&pdev
->dev
);
433 pm_runtime_allow(&pdev
->dev
);
437 static int acp3x_audio_remove(struct platform_device
*pdev
)
439 pm_runtime_disable(&pdev
->dev
);
443 static int acp3x_resume(struct device
*dev
)
445 struct i2s_dev_data
*adata
;
446 u32 val
, reg_val
, frmt_val
;
450 adata
= dev_get_drvdata(dev
);
452 if (adata
->play_stream
&& adata
->play_stream
->runtime
) {
453 struct i2s_stream_instance
*rtd
=
454 adata
->play_stream
->runtime
->private_data
;
455 config_acp3x_dma(rtd
, SNDRV_PCM_STREAM_PLAYBACK
);
456 switch (rtd
->i2s_instance
) {
457 case I2S_BT_INSTANCE
:
458 reg_val
= mmACP_BTTDM_ITER
;
459 frmt_val
= mmACP_BTTDM_TXFRMT
;
461 case I2S_SP_INSTANCE
:
463 reg_val
= mmACP_I2STDM_ITER
;
464 frmt_val
= mmACP_I2STDM_TXFRMT
;
466 rv_writel((rtd
->xfer_resolution
<< 3), rtd
->acp3x_base
+ reg_val
);
468 if (adata
->capture_stream
&& adata
->capture_stream
->runtime
) {
469 struct i2s_stream_instance
*rtd
=
470 adata
->capture_stream
->runtime
->private_data
;
471 config_acp3x_dma(rtd
, SNDRV_PCM_STREAM_CAPTURE
);
472 switch (rtd
->i2s_instance
) {
473 case I2S_BT_INSTANCE
:
474 reg_val
= mmACP_BTTDM_IRER
;
475 frmt_val
= mmACP_BTTDM_RXFRMT
;
477 case I2S_SP_INSTANCE
:
479 reg_val
= mmACP_I2STDM_IRER
;
480 frmt_val
= mmACP_I2STDM_RXFRMT
;
482 rv_writel((rtd
->xfer_resolution
<< 3), rtd
->acp3x_base
+ reg_val
);
484 if (adata
->tdm_mode
== TDM_ENABLE
) {
485 rv_writel(adata
->tdm_fmt
, adata
->acp3x_base
+ frmt_val
);
486 val
= rv_readl(adata
->acp3x_base
+ reg_val
);
487 rv_writel(val
| 0x2, adata
->acp3x_base
+ reg_val
);
489 rv_writel(1, adata
->acp3x_base
+ mmACP_EXTERNAL_INTR_ENB
);
494 static int acp3x_pcm_runtime_suspend(struct device
*dev
)
496 struct i2s_dev_data
*adata
;
498 adata
= dev_get_drvdata(dev
);
500 rv_writel(0, adata
->acp3x_base
+ mmACP_EXTERNAL_INTR_ENB
);
505 static int acp3x_pcm_runtime_resume(struct device
*dev
)
507 struct i2s_dev_data
*adata
;
509 adata
= dev_get_drvdata(dev
);
511 rv_writel(1, adata
->acp3x_base
+ mmACP_EXTERNAL_INTR_ENB
);
515 static const struct dev_pm_ops acp3x_pm_ops
= {
516 .runtime_suspend
= acp3x_pcm_runtime_suspend
,
517 .runtime_resume
= acp3x_pcm_runtime_resume
,
518 .resume
= acp3x_resume
,
521 static struct platform_driver acp3x_dma_driver
= {
522 .probe
= acp3x_audio_probe
,
523 .remove
= acp3x_audio_remove
,
525 .name
= "acp3x_rv_i2s_dma",
530 module_platform_driver(acp3x_dma_driver
);
532 MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com");
533 MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com");
534 MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
535 MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver");
536 MODULE_LICENSE("GPL v2");
537 MODULE_ALIAS("platform:" DRV_NAME
);