Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: SOF: mediatek: Add ipc support for mt8195

This patch adds mt8195 IPC support by using mailbox.

On mt8195 resource, there are two mboxes used to handle ipc request
and reply. We create a mtk-adsp-ipc client device to request mbox
controllers.

Signed-off-by: Allen-KH Cheng <Allen-KH.Cheng@mediatek.com>
Reported-by: kernel test robot <lkp@intel.com>
Link: https://lore.kernel.org/r/20220512082215.3018-3-tinghan.shen@mediatek.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Allen-KH Cheng and committed by
Mark Brown
aea93501 9db69df4

+140 -11
+1
sound/soc/sof/mediatek/Kconfig
··· 33 33 config SND_SOC_SOF_MT8195 34 34 tristate "SOF support for MT8195 audio DSP" 35 35 select SND_SOC_SOF_MTK_COMMON 36 + depends on MTK_ADSP_IPC 36 37 help 37 38 This adds support for Sound Open Firmware for Mediatek platforms 38 39 using the mt8195 processors.
+4 -8
sound/soc/sof/mediatek/adsp_helper.h
··· 7 7 #ifndef __MTK_ADSP_HELPER_H__ 8 8 #define __MTK_ADSP_HELPER_H__ 9 9 10 + #include <linux/firmware/mediatek/mtk-adsp-ipc.h> 11 + 10 12 /* 11 13 * Global important adsp data structure. 12 14 */ 13 - #define DSP_MBOX_NUM 3 14 - 15 15 struct mtk_adsp_chip_info { 16 16 phys_addr_t pa_sram; 17 17 phys_addr_t pa_dram; /* adsp dram physical base */ 18 18 phys_addr_t pa_shared_dram; /* adsp dram physical base */ 19 19 phys_addr_t pa_cfgreg; 20 - phys_addr_t pa_mboxreg[DSP_MBOX_NUM]; 21 20 u32 sramsize; 22 21 u32 dramsize; 23 22 u32 cfgregsize; 24 23 void __iomem *va_sram; /* corresponding to pa_sram */ 25 24 void __iomem *va_dram; /* corresponding to pa_dram */ 26 25 void __iomem *va_cfgreg; 27 - void __iomem *va_mboxreg[DSP_MBOX_NUM]; 28 26 void __iomem *shared_sram; /* part of va_sram */ 29 27 void __iomem *shared_dram; /* part of va_dram */ 30 28 phys_addr_t adsp_bootup_addr; ··· 40 42 struct adsp_priv { 41 43 struct device *dev; 42 44 struct snd_sof_dev *sdev; 43 - 44 - /* DSP IPC handler */ 45 - struct mbox_controller *adsp_mbox; 46 - 45 + struct mtk_adsp_ipc *dsp_ipc; 46 + struct platform_device *ipc_dev; 47 47 struct mtk_adsp_chip_info *adsp; 48 48 struct clk **clk; 49 49 u32 (*ap2adsp_addr)(u32 addr, void *data);
+135 -3
sound/soc/sof/mediatek/mt8195/mt8195.c
··· 12 12 #include <linux/delay.h> 13 13 #include <linux/firmware.h> 14 14 #include <linux/io.h> 15 + #include <linux/of_platform.h> 15 16 #include <linux/of_address.h> 16 17 #include <linux/of_irq.h> 17 18 #include <linux/of_platform.h> ··· 27 26 #include "../adsp_helper.h" 28 27 #include "mt8195.h" 29 28 #include "mt8195-clk.h" 29 + 30 + static int mt8195_get_mailbox_offset(struct snd_sof_dev *sdev) 31 + { 32 + return MBOX_OFFSET; 33 + } 34 + 35 + static int mt8195_get_window_offset(struct snd_sof_dev *sdev, u32 id) 36 + { 37 + return MBOX_OFFSET; 38 + } 39 + 40 + static int mt8195_send_msg(struct snd_sof_dev *sdev, 41 + struct snd_sof_ipc_msg *msg) 42 + { 43 + struct adsp_priv *priv = sdev->pdata->hw_pdata; 44 + 45 + sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, 46 + msg->msg_size); 47 + 48 + return mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_REQ, MTK_ADSP_IPC_OP_REQ); 49 + } 50 + 51 + static void mt8195_get_reply(struct snd_sof_dev *sdev) 52 + { 53 + struct snd_sof_ipc_msg *msg = sdev->msg; 54 + struct sof_ipc_reply reply; 55 + int ret = 0; 56 + 57 + if (!msg) { 58 + dev_warn(sdev->dev, "unexpected ipc interrupt\n"); 59 + return; 60 + } 61 + 62 + /* get reply */ 63 + sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply)); 64 + if (reply.error < 0) { 65 + memcpy(msg->reply_data, &reply, sizeof(reply)); 66 + ret = reply.error; 67 + } else { 68 + /* reply has correct size? */ 69 + if (reply.hdr.size != msg->reply_size) { 70 + dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n", 71 + msg->reply_size, reply.hdr.size); 72 + ret = -EINVAL; 73 + } 74 + 75 + /* read the message */ 76 + if (msg->reply_size > 0) 77 + sof_mailbox_read(sdev, sdev->host_box.offset, 78 + msg->reply_data, msg->reply_size); 79 + } 80 + 81 + msg->reply_error = ret; 82 + } 83 + 84 + static void mt8195_dsp_handle_reply(struct mtk_adsp_ipc *ipc) 85 + { 86 + struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc); 87 + unsigned long flags; 88 + 89 + spin_lock_irqsave(&priv->sdev->ipc_lock, flags); 90 + mt8195_get_reply(priv->sdev); 91 + snd_sof_ipc_reply(priv->sdev, 0); 92 + spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags); 93 + } 94 + 95 + static void mt8195_dsp_handle_request(struct mtk_adsp_ipc *ipc) 96 + { 97 + struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc); 98 + u32 p; /* panic code */ 99 + int ret; 100 + 101 + /* Read the message from the debug box. */ 102 + sof_mailbox_read(priv->sdev, priv->sdev->debug_box.offset + 4, 103 + &p, sizeof(p)); 104 + 105 + /* Check to see if the message is a panic code 0x0dead*** */ 106 + if ((p & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) { 107 + snd_sof_dsp_panic(priv->sdev, p, true); 108 + } else { 109 + snd_sof_ipc_msgs_rx(priv->sdev); 110 + 111 + /* tell DSP cmd is done */ 112 + ret = mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_RSP, MTK_ADSP_IPC_OP_RSP); 113 + if (ret) 114 + dev_err(priv->dev, "request send ipc failed"); 115 + } 116 + } 117 + 118 + static struct mtk_adsp_ipc_ops dsp_ops = { 119 + .handle_reply = mt8195_dsp_handle_reply, 120 + .handle_request = mt8195_dsp_handle_request, 121 + }; 30 122 31 123 static int platform_parse_resource(struct platform_device *pdev, void *data) 32 124 { ··· 379 285 } 380 286 381 287 sdev->bar[DSP_REG_BAR] = priv->adsp->va_cfgreg; 382 - sdev->bar[DSP_MBOX0_BAR] = priv->adsp->va_mboxreg[0]; 383 - sdev->bar[DSP_MBOX1_BAR] = priv->adsp->va_mboxreg[1]; 384 - sdev->bar[DSP_MBOX2_BAR] = priv->adsp->va_mboxreg[2]; 385 288 386 289 sdev->mmio_bar = SOF_FW_BLK_TYPE_SRAM; 387 290 sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM; 388 291 292 + /* set default mailbox offset for FW ready message */ 293 + sdev->dsp_box.offset = mt8195_get_mailbox_offset(sdev); 294 + 295 + priv->ipc_dev = platform_device_register_data(&pdev->dev, "mtk-adsp-ipc", 296 + PLATFORM_DEVID_NONE, 297 + pdev, sizeof(*pdev)); 298 + if (IS_ERR(priv->ipc_dev)) { 299 + ret = PTR_ERR(priv->ipc_dev); 300 + dev_err(sdev->dev, "failed to register mtk-adsp-ipc device\n"); 301 + goto err_adsp_sram_power_off; 302 + } 303 + 304 + priv->dsp_ipc = dev_get_drvdata(&priv->ipc_dev->dev); 305 + if (!priv->dsp_ipc) { 306 + ret = -EPROBE_DEFER; 307 + dev_err(sdev->dev, "failed to get drvdata\n"); 308 + goto exit_pdev_unregister; 309 + } 310 + 311 + mtk_adsp_ipc_set_data(priv->dsp_ipc, priv); 312 + priv->dsp_ipc->ops = &dsp_ops; 313 + 389 314 return 0; 390 315 316 + exit_pdev_unregister: 317 + platform_device_unregister(priv->ipc_dev); 391 318 err_adsp_sram_power_off: 392 319 adsp_sram_power_on(&pdev->dev, false); 393 320 exit_clk_disable: ··· 425 310 static int mt8195_dsp_remove(struct snd_sof_dev *sdev) 426 311 { 427 312 struct platform_device *pdev = container_of(sdev->dev, struct platform_device, dev); 313 + struct adsp_priv *priv = sdev->pdata->hw_pdata; 428 314 315 + platform_device_unregister(priv->ipc_dev); 429 316 adsp_sram_power_on(&pdev->dev, false); 430 317 adsp_clock_off(sdev); 431 318 ··· 476 359 static int mt8195_get_bar_index(struct snd_sof_dev *sdev, u32 type) 477 360 { 478 361 return type; 362 + } 363 + 364 + static int mt8195_ipc_msg_data(struct snd_sof_dev *sdev, 365 + struct snd_pcm_substream *substream, 366 + void *p, size_t sz) 367 + { 368 + sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz); 369 + return 0; 479 370 } 480 371 481 372 static struct snd_soc_dai_driver mt8195_dai[] = { ··· 536 411 .read = sof_io_read, 537 412 .write64 = sof_io_write64, 538 413 .read64 = sof_io_read64, 414 + 415 + /* ipc */ 416 + .send_msg = mt8195_send_msg, 417 + .get_mailbox_offset = mt8195_get_mailbox_offset, 418 + .get_window_offset = mt8195_get_window_offset, 419 + .ipc_msg_data = mt8195_ipc_msg_data, 420 + .set_stream_data_offset = sof_set_stream_data_offset, 539 421 540 422 /* misc */ 541 423 .get_bar_index = mt8195_get_bar_index,