Commit e0100bfd authored by Tinghan Shen's avatar Tinghan Shen Committed by Mark Brown

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: default avatarAllen-KH Cheng <Allen-KH.Cheng@mediatek.com>
Signed-off-by: default avatarTinghan Shen <tinghan.shen@mediatek.com>
Link: https://lore.kernel.org/r/20220512082215.3018-4-tinghan.shen@mediatek.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent aea93501
...@@ -24,6 +24,7 @@ config SND_SOC_SOF_MTK_COMMON ...@@ -24,6 +24,7 @@ config SND_SOC_SOF_MTK_COMMON
config SND_SOC_SOF_MT8186 config SND_SOC_SOF_MT8186
tristate "SOF support for MT8186 audio DSP" tristate "SOF support for MT8186 audio DSP"
select SND_SOC_SOF_MTK_COMMON select SND_SOC_SOF_MTK_COMMON
depends on MTK_ADSP_IPC
help help
This adds support for Sound Open Firmware for Mediatek platforms This adds support for Sound Open Firmware for Mediatek platforms
using the mt8186 processors. using the mt8186 processors.
......
...@@ -17,6 +17,11 @@ void mt8186_sof_hifixdsp_boot_sequence(struct snd_sof_dev *sdev, u32 boot_addr) ...@@ -17,6 +17,11 @@ void mt8186_sof_hifixdsp_boot_sequence(struct snd_sof_dev *sdev, u32 boot_addr)
snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_HIFI_IO_CONFIG, snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_HIFI_IO_CONFIG,
RUNSTALL, RUNSTALL); RUNSTALL, RUNSTALL);
/* enable mbox 0 & 1 IRQ */
snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, ADSP_MBOX_IRQ_EN,
DSP_MBOX0_IRQ_EN | DSP_MBOX1_IRQ_EN,
DSP_MBOX0_IRQ_EN | DSP_MBOX1_IRQ_EN);
/* set core boot address */ /* set core boot address */
snd_sof_dsp_write(sdev, DSP_SECREG_BAR, ADSP_ALTVEC_C0, boot_addr); snd_sof_dsp_write(sdev, DSP_SECREG_BAR, ADSP_ALTVEC_C0, boot_addr);
snd_sof_dsp_write(sdev, DSP_SECREG_BAR, ADSP_ALTVECSEL, ADSP_ALTVECSEL_C0); snd_sof_dsp_write(sdev, DSP_SECREG_BAR, ADSP_ALTVECSEL, ADSP_ALTVECSEL_C0);
......
...@@ -27,6 +27,99 @@ ...@@ -27,6 +27,99 @@
#include "mt8186.h" #include "mt8186.h"
#include "mt8186-clk.h" #include "mt8186-clk.h"
static int mt8186_get_mailbox_offset(struct snd_sof_dev *sdev)
{
return MBOX_OFFSET;
}
static int mt8186_get_window_offset(struct snd_sof_dev *sdev, u32 id)
{
return MBOX_OFFSET;
}
static int mt8186_send_msg(struct snd_sof_dev *sdev,
struct snd_sof_ipc_msg *msg)
{
struct adsp_priv *priv = sdev->pdata->hw_pdata;
sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
msg->msg_size);
return mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_REQ, MTK_ADSP_IPC_OP_REQ);
}
static void mt8186_get_reply(struct snd_sof_dev *sdev)
{
struct snd_sof_ipc_msg *msg = sdev->msg;
struct sof_ipc_reply reply;
int ret = 0;
if (!msg) {
dev_warn(sdev->dev, "unexpected ipc interrupt\n");
return;
}
/* get reply */
sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply));
if (reply.error < 0) {
memcpy(msg->reply_data, &reply, sizeof(reply));
ret = reply.error;
} else {
/* reply has correct size? */
if (reply.hdr.size != msg->reply_size) {
dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n",
msg->reply_size, reply.hdr.size);
ret = -EINVAL;
}
/* read the message */
if (msg->reply_size > 0)
sof_mailbox_read(sdev, sdev->host_box.offset,
msg->reply_data, msg->reply_size);
}
msg->reply_error = ret;
}
static void mt8186_dsp_handle_reply(struct mtk_adsp_ipc *ipc)
{
struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc);
unsigned long flags;
spin_lock_irqsave(&priv->sdev->ipc_lock, flags);
mt8186_get_reply(priv->sdev);
snd_sof_ipc_reply(priv->sdev, 0);
spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags);
}
static void mt8186_dsp_handle_request(struct mtk_adsp_ipc *ipc)
{
struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc);
u32 p; /* panic code */
int ret;
/* Read the message from the debug box. */
sof_mailbox_read(priv->sdev, priv->sdev->debug_box.offset + 4,
&p, sizeof(p));
/* Check to see if the message is a panic code 0x0dead*** */
if ((p & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
snd_sof_dsp_panic(priv->sdev, p, true);
} else {
snd_sof_ipc_msgs_rx(priv->sdev);
/* tell DSP cmd is done */
ret = mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_RSP, MTK_ADSP_IPC_OP_RSP);
if (ret)
dev_err(priv->dev, "request send ipc failed");
}
}
static struct mtk_adsp_ipc_ops dsp_ops = {
.handle_reply = mt8186_dsp_handle_reply,
.handle_request = mt8186_dsp_handle_request,
};
static int platform_parse_resource(struct platform_device *pdev, void *data) static int platform_parse_resource(struct platform_device *pdev, void *data)
{ {
struct resource *mmio; struct resource *mmio;
...@@ -271,6 +364,9 @@ static int mt8186_dsp_probe(struct snd_sof_dev *sdev) ...@@ -271,6 +364,9 @@ static int mt8186_dsp_probe(struct snd_sof_dev *sdev)
sdev->mmio_bar = SOF_FW_BLK_TYPE_SRAM; sdev->mmio_bar = SOF_FW_BLK_TYPE_SRAM;
sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM; sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM;
/* set default mailbox offset for FW ready message */
sdev->dsp_box.offset = mt8186_get_mailbox_offset(sdev);
ret = adsp_memory_remap_init(sdev, priv->adsp); ret = adsp_memory_remap_init(sdev, priv->adsp);
if (ret) { if (ret) {
dev_err(sdev->dev, "adsp_memory_remap_init fail!\n"); dev_err(sdev->dev, "adsp_memory_remap_init fail!\n");
...@@ -292,11 +388,41 @@ static int mt8186_dsp_probe(struct snd_sof_dev *sdev) ...@@ -292,11 +388,41 @@ static int mt8186_dsp_probe(struct snd_sof_dev *sdev)
adsp_sram_power_on(sdev); adsp_sram_power_on(sdev);
priv->ipc_dev = platform_device_register_data(&pdev->dev, "mtk-adsp-ipc",
PLATFORM_DEVID_NONE,
pdev, sizeof(*pdev));
if (IS_ERR(priv->ipc_dev)) {
ret = IS_ERR(priv->ipc_dev);
dev_err(sdev->dev, "failed to create mtk-adsp-ipc device\n");
goto err_adsp_off;
}
priv->dsp_ipc = dev_get_drvdata(&priv->ipc_dev->dev);
if (!priv->dsp_ipc) {
ret = -EPROBE_DEFER;
dev_err(sdev->dev, "failed to get drvdata\n");
goto exit_pdev_unregister;
}
mtk_adsp_ipc_set_data(priv->dsp_ipc, priv);
priv->dsp_ipc->ops = &dsp_ops;
return 0; return 0;
exit_pdev_unregister:
platform_device_unregister(priv->ipc_dev);
err_adsp_off:
adsp_sram_power_off(sdev);
mt8186_adsp_clock_off(sdev);
return ret;
} }
static int mt8186_dsp_remove(struct snd_sof_dev *sdev) static int mt8186_dsp_remove(struct snd_sof_dev *sdev)
{ {
struct adsp_priv *priv = sdev->pdata->hw_pdata;
platform_device_unregister(priv->ipc_dev);
mt8186_sof_hifixdsp_shutdown(sdev); mt8186_sof_hifixdsp_shutdown(sdev);
adsp_sram_power_off(sdev); adsp_sram_power_off(sdev);
mt8186_adsp_clock_off(sdev); mt8186_adsp_clock_off(sdev);
...@@ -334,6 +460,14 @@ static int mt8186_get_bar_index(struct snd_sof_dev *sdev, u32 type) ...@@ -334,6 +460,14 @@ static int mt8186_get_bar_index(struct snd_sof_dev *sdev, u32 type)
return type; return type;
} }
static int mt8186_ipc_msg_data(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
void *p, size_t sz)
{
sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
return 0;
}
/* mt8186 ops */ /* mt8186 ops */
static struct snd_sof_dsp_ops sof_mt8186_ops = { static struct snd_sof_dsp_ops sof_mt8186_ops = {
/* probe and remove */ /* probe and remove */
...@@ -353,6 +487,13 @@ static struct snd_sof_dsp_ops sof_mt8186_ops = { ...@@ -353,6 +487,13 @@ static struct snd_sof_dsp_ops sof_mt8186_ops = {
.write64 = sof_io_write64, .write64 = sof_io_write64,
.read64 = sof_io_read64, .read64 = sof_io_read64,
/* ipc */
.send_msg = mt8186_send_msg,
.get_mailbox_offset = mt8186_get_mailbox_offset,
.get_window_offset = mt8186_get_window_offset,
.ipc_msg_data = mt8186_ipc_msg_data,
.set_stream_data_offset = sof_set_stream_data_offset,
/* misc */ /* misc */
.get_bar_index = mt8186_get_bar_index, .get_bar_index = mt8186_get_bar_index,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment