1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
3 // Copyright(c) 2022 Mediatek Inc. All rights reserved.
5 // Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com>
6 // Tinghan Shen <tinghan.shen@mediatek.com>
9 * Hardware interface for audio DSP on mt8186
12 #include <linux/delay.h>
13 #include <linux/firmware.h>
15 #include <linux/of_address.h>
16 #include <linux/of_irq.h>
17 #include <linux/of_platform.h>
18 #include <linux/of_reserved_mem.h>
19 #include <linux/module.h>
21 #include <sound/sof.h>
22 #include <sound/sof/xtensa.h>
23 #include "../../ops.h"
24 #include "../../sof-of-dev.h"
25 #include "../../sof-audio.h"
26 #include "../adsp_helper.h"
27 #include "../mtk-adsp-common.h"
29 #include "mt8186-clk.h"
31 static int mt8186_get_mailbox_offset(struct snd_sof_dev
*sdev
)
36 static int mt8186_get_window_offset(struct snd_sof_dev
*sdev
, u32 id
)
41 static int mt8186_send_msg(struct snd_sof_dev
*sdev
,
42 struct snd_sof_ipc_msg
*msg
)
44 struct adsp_priv
*priv
= sdev
->pdata
->hw_pdata
;
46 sof_mailbox_write(sdev
, sdev
->host_box
.offset
, msg
->msg_data
,
49 return mtk_adsp_ipc_send(priv
->dsp_ipc
, MTK_ADSP_IPC_REQ
, MTK_ADSP_IPC_OP_REQ
);
52 static void mt8186_dsp_handle_reply(struct mtk_adsp_ipc
*ipc
)
54 struct adsp_priv
*priv
= mtk_adsp_ipc_get_data(ipc
);
57 spin_lock_irqsave(&priv
->sdev
->ipc_lock
, flags
);
58 snd_sof_ipc_process_reply(priv
->sdev
, 0);
59 spin_unlock_irqrestore(&priv
->sdev
->ipc_lock
, flags
);
62 static void mt8186_dsp_handle_request(struct mtk_adsp_ipc
*ipc
)
64 struct adsp_priv
*priv
= mtk_adsp_ipc_get_data(ipc
);
65 u32 p
; /* panic code */
68 /* Read the message from the debug box. */
69 sof_mailbox_read(priv
->sdev
, priv
->sdev
->debug_box
.offset
+ 4,
72 /* Check to see if the message is a panic code 0x0dead*** */
73 if ((p
& SOF_IPC_PANIC_MAGIC_MASK
) == SOF_IPC_PANIC_MAGIC
) {
74 snd_sof_dsp_panic(priv
->sdev
, p
, true);
76 snd_sof_ipc_msgs_rx(priv
->sdev
);
78 /* tell DSP cmd is done */
79 ret
= mtk_adsp_ipc_send(priv
->dsp_ipc
, MTK_ADSP_IPC_RSP
, MTK_ADSP_IPC_OP_RSP
);
81 dev_err(priv
->dev
, "request send ipc failed");
85 static const struct mtk_adsp_ipc_ops dsp_ops
= {
86 .handle_reply
= mt8186_dsp_handle_reply
,
87 .handle_request
= mt8186_dsp_handle_request
,
90 static int platform_parse_resource(struct platform_device
*pdev
, void *data
)
92 struct resource
*mmio
;
94 struct device_node
*mem_region
;
95 struct device
*dev
= &pdev
->dev
;
96 struct mtk_adsp_chip_info
*adsp
= data
;
99 ret
= of_reserved_mem_device_init(dev
);
101 dev_err(dev
, "of_reserved_mem_device_init failed\n");
105 mem_region
= of_parse_phandle(dev
->of_node
, "memory-region", 1);
107 dev_err(dev
, "no memory-region sysmem phandle\n");
111 ret
= of_address_to_resource(mem_region
, 0, &res
);
112 of_node_put(mem_region
);
114 dev_err(dev
, "of_address_to_resource sysmem failed\n");
118 adsp
->pa_dram
= (phys_addr_t
)res
.start
;
119 if (adsp
->pa_dram
& DRAM_REMAP_MASK
) {
120 dev_err(dev
, "adsp memory(%#x) is not 4K-aligned\n",
125 adsp
->dramsize
= resource_size(&res
);
126 if (adsp
->dramsize
< TOTAL_SIZE_SHARED_DRAM_FROM_TAIL
) {
127 dev_err(dev
, "adsp memory(%#x) is not enough for share\n",
132 dev_dbg(dev
, "dram pbase=%pa size=%#x\n", &adsp
->pa_dram
, adsp
->dramsize
);
134 mmio
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "cfg");
136 dev_err(dev
, "no ADSP-CFG register resource\n");
140 adsp
->va_cfgreg
= devm_ioremap_resource(dev
, mmio
);
141 if (IS_ERR(adsp
->va_cfgreg
))
142 return PTR_ERR(adsp
->va_cfgreg
);
144 adsp
->pa_cfgreg
= (phys_addr_t
)mmio
->start
;
145 adsp
->cfgregsize
= resource_size(mmio
);
147 dev_dbg(dev
, "cfgreg pbase=%pa size=%#x\n", &adsp
->pa_cfgreg
, adsp
->cfgregsize
);
149 mmio
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "sram");
151 dev_err(dev
, "no SRAM resource\n");
155 adsp
->pa_sram
= (phys_addr_t
)mmio
->start
;
156 adsp
->sramsize
= resource_size(mmio
);
158 dev_dbg(dev
, "sram pbase=%pa size=%#x\n", &adsp
->pa_sram
, adsp
->sramsize
);
160 mmio
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "sec");
162 dev_err(dev
, "no SEC register resource\n");
166 adsp
->va_secreg
= devm_ioremap_resource(dev
, mmio
);
167 if (IS_ERR(adsp
->va_secreg
))
168 return PTR_ERR(adsp
->va_secreg
);
170 adsp
->pa_secreg
= (phys_addr_t
)mmio
->start
;
171 adsp
->secregsize
= resource_size(mmio
);
173 dev_dbg(dev
, "secreg pbase=%pa size=%#x\n", &adsp
->pa_secreg
, adsp
->secregsize
);
175 mmio
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "bus");
177 dev_err(dev
, "no BUS register resource\n");
181 adsp
->va_busreg
= devm_ioremap_resource(dev
, mmio
);
182 if (IS_ERR(adsp
->va_busreg
))
183 return PTR_ERR(adsp
->va_busreg
);
185 adsp
->pa_busreg
= (phys_addr_t
)mmio
->start
;
186 adsp
->busregsize
= resource_size(mmio
);
188 dev_dbg(dev
, "busreg pbase=%pa size=%#x\n", &adsp
->pa_busreg
, adsp
->busregsize
);
193 static void adsp_sram_power_on(struct snd_sof_dev
*sdev
)
195 snd_sof_dsp_update_bits(sdev
, DSP_BUSREG_BAR
, ADSP_SRAM_POOL_CON
,
196 DSP_SRAM_POOL_PD_MASK
, 0);
199 static void adsp_sram_power_off(struct snd_sof_dev
*sdev
)
201 snd_sof_dsp_update_bits(sdev
, DSP_BUSREG_BAR
, ADSP_SRAM_POOL_CON
,
202 DSP_SRAM_POOL_PD_MASK
, DSP_SRAM_POOL_PD_MASK
);
205 /* Init the basic DSP DRAM address */
206 static int adsp_memory_remap_init(struct snd_sof_dev
*sdev
, struct mtk_adsp_chip_info
*adsp
)
210 offset
= adsp
->pa_dram
- DRAM_PHYS_BASE_FROM_DSP_VIEW
;
211 adsp
->dram_offset
= offset
;
212 offset
>>= DRAM_REMAP_SHIFT
;
214 dev_dbg(sdev
->dev
, "adsp->pa_dram %pa, offset %#x\n", &adsp
->pa_dram
, offset
);
216 snd_sof_dsp_write(sdev
, DSP_BUSREG_BAR
, DSP_C0_EMI_MAP_ADDR
, offset
);
217 snd_sof_dsp_write(sdev
, DSP_BUSREG_BAR
, DSP_C0_DMAEMI_MAP_ADDR
, offset
);
219 if (offset
!= snd_sof_dsp_read(sdev
, DSP_BUSREG_BAR
, DSP_C0_EMI_MAP_ADDR
) ||
220 offset
!= snd_sof_dsp_read(sdev
, DSP_BUSREG_BAR
, DSP_C0_DMAEMI_MAP_ADDR
)) {
221 dev_err(sdev
->dev
, "emi remap fail\n");
228 static int mt8186_run(struct snd_sof_dev
*sdev
)
230 u32 adsp_bootup_addr
;
232 adsp_bootup_addr
= SRAM_PHYS_BASE_FROM_DSP_VIEW
;
233 dev_dbg(sdev
->dev
, "HIFIxDSP boot from base : 0x%08X\n", adsp_bootup_addr
);
234 mt8186_sof_hifixdsp_boot_sequence(sdev
, adsp_bootup_addr
);
239 static int mt8186_dsp_probe(struct snd_sof_dev
*sdev
)
241 struct platform_device
*pdev
= container_of(sdev
->dev
, struct platform_device
, dev
);
242 struct adsp_priv
*priv
;
245 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
249 sdev
->pdata
->hw_pdata
= priv
;
250 priv
->dev
= sdev
->dev
;
253 priv
->adsp
= devm_kzalloc(&pdev
->dev
, sizeof(struct mtk_adsp_chip_info
), GFP_KERNEL
);
257 ret
= platform_parse_resource(pdev
, priv
->adsp
);
261 sdev
->bar
[SOF_FW_BLK_TYPE_IRAM
] = devm_ioremap(sdev
->dev
,
263 priv
->adsp
->sramsize
);
264 if (!sdev
->bar
[SOF_FW_BLK_TYPE_IRAM
]) {
265 dev_err(sdev
->dev
, "failed to ioremap base %pa size %#x\n",
266 &priv
->adsp
->pa_sram
, priv
->adsp
->sramsize
);
270 priv
->adsp
->va_sram
= sdev
->bar
[SOF_FW_BLK_TYPE_IRAM
];
272 sdev
->bar
[SOF_FW_BLK_TYPE_SRAM
] = devm_ioremap(sdev
->dev
,
274 priv
->adsp
->dramsize
);
276 if (!sdev
->bar
[SOF_FW_BLK_TYPE_SRAM
]) {
277 dev_err(sdev
->dev
, "failed to ioremap base %pa size %#x\n",
278 &priv
->adsp
->pa_dram
, priv
->adsp
->dramsize
);
282 priv
->adsp
->va_dram
= sdev
->bar
[SOF_FW_BLK_TYPE_SRAM
];
284 sdev
->bar
[DSP_REG_BAR
] = priv
->adsp
->va_cfgreg
;
285 sdev
->bar
[DSP_SECREG_BAR
] = priv
->adsp
->va_secreg
;
286 sdev
->bar
[DSP_BUSREG_BAR
] = priv
->adsp
->va_busreg
;
288 sdev
->mmio_bar
= SOF_FW_BLK_TYPE_SRAM
;
289 sdev
->mailbox_bar
= SOF_FW_BLK_TYPE_SRAM
;
291 /* set default mailbox offset for FW ready message */
292 sdev
->dsp_box
.offset
= mt8186_get_mailbox_offset(sdev
);
294 ret
= adsp_memory_remap_init(sdev
, priv
->adsp
);
296 dev_err(sdev
->dev
, "adsp_memory_remap_init fail!\n");
300 /* enable adsp clock before touching registers */
301 ret
= mt8186_adsp_init_clock(sdev
);
303 dev_err(sdev
->dev
, "mt8186_adsp_init_clock failed\n");
307 ret
= mt8186_adsp_clock_on(sdev
);
309 dev_err(sdev
->dev
, "mt8186_adsp_clock_on fail!\n");
313 adsp_sram_power_on(sdev
);
315 priv
->ipc_dev
= platform_device_register_data(&pdev
->dev
, "mtk-adsp-ipc",
317 pdev
, sizeof(*pdev
));
318 if (IS_ERR(priv
->ipc_dev
)) {
319 ret
= PTR_ERR(priv
->ipc_dev
);
320 dev_err(sdev
->dev
, "failed to create mtk-adsp-ipc device\n");
324 priv
->dsp_ipc
= dev_get_drvdata(&priv
->ipc_dev
->dev
);
325 if (!priv
->dsp_ipc
) {
327 dev_err(sdev
->dev
, "failed to get drvdata\n");
328 goto exit_pdev_unregister
;
331 mtk_adsp_ipc_set_data(priv
->dsp_ipc
, priv
);
332 priv
->dsp_ipc
->ops
= &dsp_ops
;
336 exit_pdev_unregister
:
337 platform_device_unregister(priv
->ipc_dev
);
339 adsp_sram_power_off(sdev
);
340 mt8186_adsp_clock_off(sdev
);
345 static void mt8186_dsp_remove(struct snd_sof_dev
*sdev
)
347 struct adsp_priv
*priv
= sdev
->pdata
->hw_pdata
;
349 platform_device_unregister(priv
->ipc_dev
);
350 mt8186_sof_hifixdsp_shutdown(sdev
);
351 adsp_sram_power_off(sdev
);
352 mt8186_adsp_clock_off(sdev
);
355 static int mt8186_dsp_shutdown(struct snd_sof_dev
*sdev
)
357 return snd_sof_suspend(sdev
->dev
);
360 static int mt8186_dsp_suspend(struct snd_sof_dev
*sdev
, u32 target_state
)
362 mt8186_sof_hifixdsp_shutdown(sdev
);
363 adsp_sram_power_off(sdev
);
364 mt8186_adsp_clock_off(sdev
);
369 static int mt8186_dsp_resume(struct snd_sof_dev
*sdev
)
373 ret
= mt8186_adsp_clock_on(sdev
);
375 dev_err(sdev
->dev
, "mt8186_adsp_clock_on fail!\n");
379 adsp_sram_power_on(sdev
);
384 /* on mt8186 there is 1 to 1 match between type and BAR idx */
385 static int mt8186_get_bar_index(struct snd_sof_dev
*sdev
, u32 type
)
390 static int mt8186_pcm_hw_params(struct snd_sof_dev
*sdev
,
391 struct snd_pcm_substream
*substream
,
392 struct snd_pcm_hw_params
*params
,
393 struct snd_sof_platform_stream_params
*platform_params
)
395 platform_params
->cont_update_posn
= 1;
400 static snd_pcm_uframes_t
mt8186_pcm_pointer(struct snd_sof_dev
*sdev
,
401 struct snd_pcm_substream
*substream
)
404 snd_pcm_uframes_t pos
;
405 struct snd_sof_pcm
*spcm
;
406 struct sof_ipc_stream_posn posn
;
407 struct snd_sof_pcm_stream
*stream
;
408 struct snd_soc_component
*scomp
= sdev
->component
;
409 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
411 spcm
= snd_sof_find_spcm_dai(scomp
, rtd
);
413 dev_warn_ratelimited(sdev
->dev
, "warn: can't find PCM with DAI ID %d\n",
418 stream
= &spcm
->stream
[substream
->stream
];
419 ret
= snd_sof_ipc_msg_data(sdev
, stream
, &posn
, sizeof(posn
));
421 dev_warn(sdev
->dev
, "failed to read stream position: %d\n", ret
);
425 memcpy(&stream
->posn
, &posn
, sizeof(posn
));
426 pos
= spcm
->stream
[substream
->stream
].posn
.host_posn
;
427 pos
= bytes_to_frames(substream
->runtime
, pos
);
432 static void mt8186_adsp_dump(struct snd_sof_dev
*sdev
, u32 flags
)
434 u32 dbg_pc
, dbg_data
, dbg_inst
, dbg_ls0stat
, dbg_status
, faultinfo
;
436 /* dump debug registers */
437 dbg_pc
= snd_sof_dsp_read(sdev
, DSP_REG_BAR
, DSP_PDEBUGPC
);
438 dbg_data
= snd_sof_dsp_read(sdev
, DSP_REG_BAR
, DSP_PDEBUGDATA
);
439 dbg_inst
= snd_sof_dsp_read(sdev
, DSP_REG_BAR
, DSP_PDEBUGINST
);
440 dbg_ls0stat
= snd_sof_dsp_read(sdev
, DSP_REG_BAR
, DSP_PDEBUGLS0STAT
);
441 dbg_status
= snd_sof_dsp_read(sdev
, DSP_REG_BAR
, DSP_PDEBUGSTATUS
);
442 faultinfo
= snd_sof_dsp_read(sdev
, DSP_REG_BAR
, DSP_PFAULTINFO
);
444 dev_info(sdev
->dev
, "adsp dump : pc %#x, data %#x, dbg_inst %#x,",
445 dbg_pc
, dbg_data
, dbg_inst
);
446 dev_info(sdev
->dev
, "ls0stat %#x, status %#x, faultinfo %#x",
447 dbg_ls0stat
, dbg_status
, faultinfo
);
449 mtk_adsp_dump(sdev
, flags
);
452 static struct snd_soc_dai_driver mt8186_dai
[] = {
484 static const struct snd_sof_dsp_ops sof_mt8186_ops
= {
485 /* probe and remove */
486 .probe
= mt8186_dsp_probe
,
487 .remove
= mt8186_dsp_remove
,
488 .shutdown
= mt8186_dsp_shutdown
,
494 .block_read
= sof_block_read
,
495 .block_write
= sof_block_write
,
498 .mailbox_read
= sof_mailbox_read
,
499 .mailbox_write
= sof_mailbox_write
,
502 .write
= sof_io_write
,
504 .write64
= sof_io_write64
,
505 .read64
= sof_io_read64
,
508 .send_msg
= mt8186_send_msg
,
509 .get_mailbox_offset
= mt8186_get_mailbox_offset
,
510 .get_window_offset
= mt8186_get_window_offset
,
511 .ipc_msg_data
= sof_ipc_msg_data
,
512 .set_stream_data_offset
= sof_set_stream_data_offset
,
515 .get_bar_index
= mt8186_get_bar_index
,
517 /* stream callbacks */
518 .pcm_open
= sof_stream_pcm_open
,
519 .pcm_hw_params
= mt8186_pcm_hw_params
,
520 .pcm_pointer
= mt8186_pcm_pointer
,
521 .pcm_close
= sof_stream_pcm_close
,
523 /* firmware loading */
524 .load_firmware
= snd_sof_load_firmware_memcpy
,
527 .dsp_arch_ops
= &sof_xtensa_arch_ops
,
531 .num_drv
= ARRAY_SIZE(mt8186_dai
),
533 /* Debug information */
534 .dbg_dump
= mt8186_adsp_dump
,
535 .debugfs_add_region_item
= snd_sof_debugfs_add_region_item_iomem
,
538 .suspend
= mt8186_dsp_suspend
,
539 .resume
= mt8186_dsp_resume
,
541 /* ALSA HW info flags */
542 .hw_info
= SNDRV_PCM_INFO_MMAP
|
543 SNDRV_PCM_INFO_MMAP_VALID
|
544 SNDRV_PCM_INFO_INTERLEAVED
|
545 SNDRV_PCM_INFO_PAUSE
|
546 SNDRV_PCM_INFO_NO_PERIOD_WAKEUP
,
549 static struct snd_sof_of_mach sof_mt8186_machs
[] = {
551 .compatible
= "mediatek,mt8186",
552 .sof_tplg_filename
= "sof-mt8186.tplg",
557 static const struct sof_dev_desc sof_of_mt8186_desc
= {
558 .of_machines
= sof_mt8186_machs
,
559 .ipc_supported_mask
= BIT(SOF_IPC_TYPE_3
),
560 .ipc_default
= SOF_IPC_TYPE_3
,
562 [SOF_IPC_TYPE_3
] = "mediatek/sof",
564 .default_tplg_path
= {
565 [SOF_IPC_TYPE_3
] = "mediatek/sof-tplg",
567 .default_fw_filename
= {
568 [SOF_IPC_TYPE_3
] = "sof-mt8186.ri",
570 .nocodec_tplg_filename
= "sof-mt8186-nocodec.tplg",
571 .ops
= &sof_mt8186_ops
,
575 * DL2, DL3, UL4, UL5 are registered as SOF FE, so creating the corresponding
576 * SOF BE to complete the pipeline.
578 static struct snd_soc_dai_driver mt8188_dai
[] = {
610 static struct snd_sof_dsp_ops sof_mt8188_ops
;
612 static int sof_mt8188_ops_init(struct snd_sof_dev
*sdev
)
614 /* common defaults */
615 memcpy(&sof_mt8188_ops
, &sof_mt8186_ops
, sizeof(sof_mt8188_ops
));
617 sof_mt8188_ops
.drv
= mt8188_dai
;
618 sof_mt8188_ops
.num_drv
= ARRAY_SIZE(mt8188_dai
);
623 static struct snd_sof_of_mach sof_mt8188_machs
[] = {
625 .compatible
= "mediatek,mt8188",
626 .sof_tplg_filename
= "sof-mt8188.tplg",
631 static const struct sof_dev_desc sof_of_mt8188_desc
= {
632 .of_machines
= sof_mt8188_machs
,
633 .ipc_supported_mask
= BIT(SOF_IPC_TYPE_3
),
634 .ipc_default
= SOF_IPC_TYPE_3
,
636 [SOF_IPC_TYPE_3
] = "mediatek/sof",
638 .default_tplg_path
= {
639 [SOF_IPC_TYPE_3
] = "mediatek/sof-tplg",
641 .default_fw_filename
= {
642 [SOF_IPC_TYPE_3
] = "sof-mt8188.ri",
644 .nocodec_tplg_filename
= "sof-mt8188-nocodec.tplg",
645 .ops
= &sof_mt8188_ops
,
646 .ops_init
= sof_mt8188_ops_init
,
649 static const struct of_device_id sof_of_mt8186_ids
[] = {
650 { .compatible
= "mediatek,mt8186-dsp", .data
= &sof_of_mt8186_desc
},
651 { .compatible
= "mediatek,mt8188-dsp", .data
= &sof_of_mt8188_desc
},
654 MODULE_DEVICE_TABLE(of
, sof_of_mt8186_ids
);
656 /* DT driver definition */
657 static struct platform_driver snd_sof_of_mt8186_driver
= {
658 .probe
= sof_of_probe
,
659 .remove
= sof_of_remove
,
660 .shutdown
= sof_of_shutdown
,
662 .name
= "sof-audio-of-mt8186",
664 .of_match_table
= sof_of_mt8186_ids
,
667 module_platform_driver(snd_sof_of_mt8186_driver
);
669 MODULE_LICENSE("Dual BSD/GPL");
670 MODULE_DESCRIPTION("SOF support for MT8186/MT8188 platforms");
671 MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
672 MODULE_IMPORT_NS("SND_SOC_SOF_MTK_COMMON");