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>
This commit is contained in:
Родитель
aea9350108
Коммит
e0100bfd38
|
@ -24,6 +24,7 @@ config SND_SOC_SOF_MTK_COMMON
|
|||
config SND_SOC_SOF_MT8186
|
||||
tristate "SOF support for MT8186 audio DSP"
|
||||
select SND_SOC_SOF_MTK_COMMON
|
||||
depends on MTK_ADSP_IPC
|
||||
help
|
||||
This adds support for Sound Open Firmware for Mediatek platforms
|
||||
using the mt8186 processors.
|
||||
|
|
|
@ -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,
|
||||
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 */
|
||||
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);
|
||||
|
|
|
@ -27,6 +27,99 @@
|
|||
#include "mt8186.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)
|
||||
{
|
||||
struct resource *mmio;
|
||||
|
@ -271,6 +364,9 @@ static int mt8186_dsp_probe(struct snd_sof_dev *sdev)
|
|||
sdev->mmio_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);
|
||||
if (ret) {
|
||||
dev_err(sdev->dev, "adsp_memory_remap_init fail!\n");
|
||||
|
@ -292,11 +388,41 @@ static int mt8186_dsp_probe(struct snd_sof_dev *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;
|
||||
|
||||
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)
|
||||
{
|
||||
struct adsp_priv *priv = sdev->pdata->hw_pdata;
|
||||
|
||||
platform_device_unregister(priv->ipc_dev);
|
||||
mt8186_sof_hifixdsp_shutdown(sdev);
|
||||
adsp_sram_power_off(sdev);
|
||||
mt8186_adsp_clock_off(sdev);
|
||||
|
@ -334,6 +460,14 @@ static int mt8186_get_bar_index(struct snd_sof_dev *sdev, u32 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 */
|
||||
static struct snd_sof_dsp_ops sof_mt8186_ops = {
|
||||
/* probe and remove */
|
||||
|
@ -353,6 +487,13 @@ static struct snd_sof_dsp_ops sof_mt8186_ops = {
|
|||
.write64 = sof_io_write64,
|
||||
.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 */
|
||||
.get_bar_index = mt8186_get_bar_index,
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче