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

ASoC: SOF: mediatek: Add mt8186 ipc support

mt8186 DSP uses two hardware mailbox IP to communicate with AP.
One mailbox is used for requests coming from AP, and the other
one is for requests from DSP.

Signed-off-by: Allen-KH Cheng <Allen-KH.Cheng@mediatek.com>
Signed-off-by: Tinghan Shen <tinghan.shen@mediatek.com>
Link: https://lore.kernel.org/r/20220512082215.3018-4-tinghan.shen@mediatek.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Tinghan Shen and committed by
Mark Brown
e0100bfd aea93501

+147
+1
sound/soc/sof/mediatek/Kconfig
··· 24 24 config SND_SOC_SOF_MT8186 25 25 tristate "SOF support for MT8186 audio DSP" 26 26 select SND_SOC_SOF_MTK_COMMON 27 + depends on MTK_ADSP_IPC 27 28 help 28 29 This adds support for Sound Open Firmware for Mediatek platforms 29 30 using the mt8186 processors.
+5
sound/soc/sof/mediatek/mt8186/mt8186-loader.c
··· 17 17 snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_HIFI_IO_CONFIG, 18 18 RUNSTALL, RUNSTALL); 19 19 20 + /* enable mbox 0 & 1 IRQ */ 21 + snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_MBOX_IRQ_EN, 22 + DSP_MBOX0_IRQ_EN | DSP_MBOX1_IRQ_EN, 23 + DSP_MBOX0_IRQ_EN | DSP_MBOX1_IRQ_EN); 24 + 20 25 /* set core boot address */ 21 26 snd_sof_dsp_write(sdev, DSP_SECREG_BAR, ADSP_ALTVEC_C0, boot_addr); 22 27 snd_sof_dsp_write(sdev, DSP_SECREG_BAR, ADSP_ALTVECSEL, ADSP_ALTVECSEL_C0);
+141
sound/soc/sof/mediatek/mt8186/mt8186.c
··· 27 27 #include "mt8186.h" 28 28 #include "mt8186-clk.h" 29 29 30 + static int mt8186_get_mailbox_offset(struct snd_sof_dev *sdev) 31 + { 32 + return MBOX_OFFSET; 33 + } 34 + 35 + static int mt8186_get_window_offset(struct snd_sof_dev *sdev, u32 id) 36 + { 37 + return MBOX_OFFSET; 38 + } 39 + 40 + static int mt8186_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 mt8186_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 mt8186_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 + mt8186_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 mt8186_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 = mt8186_dsp_handle_reply, 120 + .handle_request = mt8186_dsp_handle_request, 121 + }; 122 + 30 123 static int platform_parse_resource(struct platform_device *pdev, void *data) 31 124 { 32 125 struct resource *mmio; ··· 364 271 sdev->mmio_bar = SOF_FW_BLK_TYPE_SRAM; 365 272 sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM; 366 273 274 + /* set default mailbox offset for FW ready message */ 275 + sdev->dsp_box.offset = mt8186_get_mailbox_offset(sdev); 276 + 367 277 ret = adsp_memory_remap_init(sdev, priv->adsp); 368 278 if (ret) { 369 279 dev_err(sdev->dev, "adsp_memory_remap_init fail!\n"); ··· 388 292 389 293 adsp_sram_power_on(sdev); 390 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 = IS_ERR(priv->ipc_dev); 300 + dev_err(sdev->dev, "failed to create mtk-adsp-ipc device\n"); 301 + goto err_adsp_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 + 391 314 return 0; 315 + 316 + exit_pdev_unregister: 317 + platform_device_unregister(priv->ipc_dev); 318 + err_adsp_off: 319 + adsp_sram_power_off(sdev); 320 + mt8186_adsp_clock_off(sdev); 321 + 322 + return ret; 392 323 } 393 324 394 325 static int mt8186_dsp_remove(struct snd_sof_dev *sdev) 395 326 { 327 + struct adsp_priv *priv = sdev->pdata->hw_pdata; 328 + 329 + platform_device_unregister(priv->ipc_dev); 396 330 mt8186_sof_hifixdsp_shutdown(sdev); 397 331 adsp_sram_power_off(sdev); 398 332 mt8186_adsp_clock_off(sdev); ··· 460 334 return type; 461 335 } 462 336 337 + static int mt8186_ipc_msg_data(struct snd_sof_dev *sdev, 338 + struct snd_pcm_substream *substream, 339 + void *p, size_t sz) 340 + { 341 + sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz); 342 + return 0; 343 + } 344 + 463 345 /* mt8186 ops */ 464 346 static struct snd_sof_dsp_ops sof_mt8186_ops = { 465 347 /* probe and remove */ ··· 486 352 .read = sof_io_read, 487 353 .write64 = sof_io_write64, 488 354 .read64 = sof_io_read64, 355 + 356 + /* ipc */ 357 + .send_msg = mt8186_send_msg, 358 + .get_mailbox_offset = mt8186_get_mailbox_offset, 359 + .get_window_offset = mt8186_get_window_offset, 360 + .ipc_msg_data = mt8186_ipc_msg_data, 361 + .set_stream_data_offset = sof_set_stream_data_offset, 489 362 490 363 /* misc */ 491 364 .get_bar_index = mt8186_get_bar_index,