Commit aea93501 authored by Allen-KH Cheng's avatar Allen-KH Cheng Committed by Mark Brown

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: default avatarAllen-KH Cheng <Allen-KH.Cheng@mediatek.com>
Reported-by: default avatarkernel test robot <lkp@intel.com>
Link: https://lore.kernel.org/r/20220512082215.3018-3-tinghan.shen@mediatek.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 9db69df4
...@@ -33,6 +33,7 @@ config SND_SOC_SOF_MT8186 ...@@ -33,6 +33,7 @@ config SND_SOC_SOF_MT8186
config SND_SOC_SOF_MT8195 config SND_SOC_SOF_MT8195
tristate "SOF support for MT8195 audio DSP" tristate "SOF support for MT8195 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 mt8195 processors. using the mt8195 processors.
......
...@@ -7,24 +7,22 @@ ...@@ -7,24 +7,22 @@
#ifndef __MTK_ADSP_HELPER_H__ #ifndef __MTK_ADSP_HELPER_H__
#define __MTK_ADSP_HELPER_H__ #define __MTK_ADSP_HELPER_H__
#include <linux/firmware/mediatek/mtk-adsp-ipc.h>
/* /*
* Global important adsp data structure. * Global important adsp data structure.
*/ */
#define DSP_MBOX_NUM 3
struct mtk_adsp_chip_info { struct mtk_adsp_chip_info {
phys_addr_t pa_sram; phys_addr_t pa_sram;
phys_addr_t pa_dram; /* adsp dram physical base */ phys_addr_t pa_dram; /* adsp dram physical base */
phys_addr_t pa_shared_dram; /* adsp dram physical base */ phys_addr_t pa_shared_dram; /* adsp dram physical base */
phys_addr_t pa_cfgreg; phys_addr_t pa_cfgreg;
phys_addr_t pa_mboxreg[DSP_MBOX_NUM];
u32 sramsize; u32 sramsize;
u32 dramsize; u32 dramsize;
u32 cfgregsize; u32 cfgregsize;
void __iomem *va_sram; /* corresponding to pa_sram */ void __iomem *va_sram; /* corresponding to pa_sram */
void __iomem *va_dram; /* corresponding to pa_dram */ void __iomem *va_dram; /* corresponding to pa_dram */
void __iomem *va_cfgreg; void __iomem *va_cfgreg;
void __iomem *va_mboxreg[DSP_MBOX_NUM];
void __iomem *shared_sram; /* part of va_sram */ void __iomem *shared_sram; /* part of va_sram */
void __iomem *shared_dram; /* part of va_dram */ void __iomem *shared_dram; /* part of va_dram */
phys_addr_t adsp_bootup_addr; phys_addr_t adsp_bootup_addr;
...@@ -42,10 +40,8 @@ struct mtk_adsp_chip_info { ...@@ -42,10 +40,8 @@ struct mtk_adsp_chip_info {
struct adsp_priv { struct adsp_priv {
struct device *dev; struct device *dev;
struct snd_sof_dev *sdev; struct snd_sof_dev *sdev;
struct mtk_adsp_ipc *dsp_ipc;
/* DSP IPC handler */ struct platform_device *ipc_dev;
struct mbox_controller *adsp_mbox;
struct mtk_adsp_chip_info *adsp; struct mtk_adsp_chip_info *adsp;
struct clk **clk; struct clk **clk;
u32 (*ap2adsp_addr)(u32 addr, void *data); u32 (*ap2adsp_addr)(u32 addr, void *data);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_platform.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
...@@ -27,6 +28,99 @@ ...@@ -27,6 +28,99 @@
#include "mt8195.h" #include "mt8195.h"
#include "mt8195-clk.h" #include "mt8195-clk.h"
static int mt8195_get_mailbox_offset(struct snd_sof_dev *sdev)
{
return MBOX_OFFSET;
}
static int mt8195_get_window_offset(struct snd_sof_dev *sdev, u32 id)
{
return MBOX_OFFSET;
}
static int mt8195_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 mt8195_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 mt8195_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);
mt8195_get_reply(priv->sdev);
snd_sof_ipc_reply(priv->sdev, 0);
spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags);
}
static void mt8195_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 = mt8195_dsp_handle_reply,
.handle_request = mt8195_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;
...@@ -285,15 +379,36 @@ static int mt8195_dsp_probe(struct snd_sof_dev *sdev) ...@@ -285,15 +379,36 @@ static int mt8195_dsp_probe(struct snd_sof_dev *sdev)
} }
sdev->bar[DSP_REG_BAR] = priv->adsp->va_cfgreg; sdev->bar[DSP_REG_BAR] = priv->adsp->va_cfgreg;
sdev->bar[DSP_MBOX0_BAR] = priv->adsp->va_mboxreg[0];
sdev->bar[DSP_MBOX1_BAR] = priv->adsp->va_mboxreg[1];
sdev->bar[DSP_MBOX2_BAR] = priv->adsp->va_mboxreg[2];
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 = mt8195_get_mailbox_offset(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 = PTR_ERR(priv->ipc_dev);
dev_err(sdev->dev, "failed to register mtk-adsp-ipc device\n");
goto err_adsp_sram_power_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_sram_power_off: err_adsp_sram_power_off:
adsp_sram_power_on(&pdev->dev, false); adsp_sram_power_on(&pdev->dev, false);
exit_clk_disable: exit_clk_disable:
...@@ -310,7 +425,9 @@ static int mt8195_dsp_shutdown(struct snd_sof_dev *sdev) ...@@ -310,7 +425,9 @@ static int mt8195_dsp_shutdown(struct snd_sof_dev *sdev)
static int mt8195_dsp_remove(struct snd_sof_dev *sdev) static int mt8195_dsp_remove(struct snd_sof_dev *sdev)
{ {
struct platform_device *pdev = container_of(sdev->dev, struct platform_device, dev); struct platform_device *pdev = container_of(sdev->dev, struct platform_device, dev);
struct adsp_priv *priv = sdev->pdata->hw_pdata;
platform_device_unregister(priv->ipc_dev);
adsp_sram_power_on(&pdev->dev, false); adsp_sram_power_on(&pdev->dev, false);
adsp_clock_off(sdev); adsp_clock_off(sdev);
...@@ -361,6 +478,14 @@ static int mt8195_get_bar_index(struct snd_sof_dev *sdev, u32 type) ...@@ -361,6 +478,14 @@ static int mt8195_get_bar_index(struct snd_sof_dev *sdev, u32 type)
return type; return type;
} }
static int mt8195_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;
}
static struct snd_soc_dai_driver mt8195_dai[] = { static struct snd_soc_dai_driver mt8195_dai[] = {
{ {
.name = "SOF_DL2", .name = "SOF_DL2",
...@@ -412,6 +537,13 @@ static struct snd_sof_dsp_ops sof_mt8195_ops = { ...@@ -412,6 +537,13 @@ static struct snd_sof_dsp_ops sof_mt8195_ops = {
.write64 = sof_io_write64, .write64 = sof_io_write64,
.read64 = sof_io_read64, .read64 = sof_io_read64,
/* ipc */
.send_msg = mt8195_send_msg,
.get_mailbox_offset = mt8195_get_mailbox_offset,
.get_window_offset = mt8195_get_window_offset,
.ipc_msg_data = mt8195_ipc_msg_data,
.set_stream_data_offset = sof_set_stream_data_offset,
/* misc */ /* misc */
.get_bar_index = mt8195_get_bar_index, .get_bar_index = mt8195_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