Skip to content

Commit f6e9289

Browse files
committed
ASoC: SOF: mediatek: Add mt8365 support
Add MT8365 support for SOF, by adding hardware support, along with clocks, dsp loader, and using the IPI mechanism. Signed-off-by: Aary Patil <aary.patil@mediatek.com>
1 parent fb66eed commit f6e9289

File tree

8 files changed

+1107
-0
lines changed

8 files changed

+1107
-0
lines changed

sound/soc/sof/mediatek/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,13 @@ config SND_SOC_SOF_MT8195
4242
Say Y if you have such a device.
4343
If unsure select "N".
4444

45+
config SND_SOC_SOF_MT8365
46+
tristate "SOF support for MT8365 audio DSP"
47+
select SND_SOC_SOF_MTK_COMMON
48+
help
49+
This adds support for Sound Open Firmware for MediaTek platforms
50+
using the mt8365 processors.
51+
Say Y if you have such a device.
52+
If unsure select "N".
53+
4554
endif ## SND_SOC_SOF_MTK_TOPLEVEL

sound/soc/sof/mediatek/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
obj-$(CONFIG_SND_SOC_SOF_MTK_COMMON) += mtk-adsp-common.o
33
obj-$(CONFIG_SND_SOC_SOF_MT8195) += mt8195/
44
obj-$(CONFIG_SND_SOC_SOF_MT8186) += mt8186/
5+
obj-$(CONFIG_SND_SOC_SOF_MT8365) += mt8365/
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2+
snd-sof-mt8365-objs := mt8365.o mt8365-clk.o mt8365-loader.o
3+
obj-$(CONFIG_SND_SOC_SOF_MT8365) += snd-sof-mt8365.o
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2+
/*
3+
* Copyright (c) 2025 MediaTek Inc.
4+
*
5+
* Author: Aary Patil <aary.patil@mediatek.com>
6+
*
7+
* Hardware interface for mt8365 DSP clock
8+
*/
9+
10+
#include <linux/clk.h>
11+
#include <linux/pm_runtime.h>
12+
#include <linux/io.h>
13+
#include "mt8365.h"
14+
#include "mt8365-clk.h"
15+
#include "../adsp_helper.h"
16+
#include "../../sof-audio.h"
17+
18+
static const char *adsp_clks[CLK_TOP_DSP_MAX] = {
19+
[CLK_TOP_DSP_SEL] = "CLK_DSP_SEL",
20+
[CLK_TOP_CLK26M_D52] = "CLK26M_CK",
21+
[CLK_TOP_SYS_26M_D2] = "AD_SYS_26M_D2",
22+
[CLK_TOP_DSPPLL] = "DSPPLL_CK",
23+
[CLK_TOP_DSPPLL_D2] = "DSPPLL_D2",
24+
[CLK_TOP_DSPPLL_D4] = "DSPPLL_D4",
25+
[CLK_TOP_DSPPLL_D8] = "DSPPLL_D8",
26+
[CLK_TOP_DSP_26M] = "PDN_DSP_26M",
27+
[CLK_TOP_DSP_32K] = "PDN_DSP_32K",
28+
};
29+
30+
int mt8365_adsp_init_clock(struct snd_sof_dev *sdev)
31+
{
32+
struct device *dev = sdev->dev;
33+
struct adsp_priv *priv = sdev->pdata->hw_pdata;
34+
int i;
35+
36+
priv->clk = devm_kcalloc(dev, CLK_TOP_DSP_MAX, sizeof(*priv->clk), GFP_KERNEL);
37+
38+
if (!priv->clk)
39+
return -ENOMEM;
40+
41+
for (i = 0; i < CLK_TOP_DSP_MAX; i++) {
42+
priv->clk[i] = devm_clk_get(dev, adsp_clks[i]);
43+
if (IS_ERR(priv->clk[i]))
44+
return PTR_ERR(priv->clk[i]);
45+
}
46+
47+
return 0;
48+
}
49+
50+
static int adsp_enable_all_clock(struct snd_sof_dev *sdev)
51+
{
52+
struct device *dev = sdev->dev;
53+
struct adsp_priv *priv = sdev->pdata->hw_pdata;
54+
int ret;
55+
56+
ret = clk_prepare_enable(priv->clk[CLK_TOP_DSPPLL]);
57+
if (ret) {
58+
dev_err(dev, "%s clk_prepare_enable(CLK_TOP_DSPPLL) fail %d\n",
59+
__func__, ret);
60+
return ret;
61+
}
62+
63+
ret = clk_prepare_enable(priv->clk[CLK_TOP_DSP_SEL]);
64+
if (ret) {
65+
dev_err(dev, "%s clk_prepare_enable(CLK_DSP_SEL) fail %d\n",
66+
__func__, ret);
67+
goto disable_top_dsppll_clk;
68+
}
69+
70+
ret = clk_prepare_enable(priv->clk[CLK_TOP_SYS_26M_D2]);
71+
if (ret) {
72+
dev_err(dev, "%s clk_prepare_enable(CLK_TOP_SYS_26M_D2) fail %d\n",
73+
__func__, ret);
74+
goto disable_top_dsp_sel_clk;
75+
}
76+
77+
ret = clk_prepare_enable(priv->clk[CLK_TOP_DSPPLL_D2]);
78+
if (ret) {
79+
dev_err(dev, "%s clk_prepare_enable(CLK_TOP_DSPPLL_D2) fail %d\n",
80+
__func__, ret);
81+
goto disable_top_sys_26m_d2_clk;
82+
}
83+
84+
ret = clk_prepare_enable(priv->clk[CLK_TOP_DSPPLL_D4]);
85+
if (ret) {
86+
dev_err(dev, "%s clk_prepare_enable(CLK_TOP_DSPPLL_D4) fail %d\n",
87+
__func__, ret);
88+
goto disable_top_dsppll_d2_clk;
89+
}
90+
91+
ret = clk_prepare_enable(priv->clk[CLK_TOP_DSPPLL_D8]);
92+
if (ret) {
93+
dev_err(dev, "%s clk_prepare_enable(CLK_TOP_DSPPLL_D8) fail %d\n",
94+
__func__, ret);
95+
goto disable_top_dsppll_d4_clk;
96+
}
97+
98+
ret = clk_prepare_enable(priv->clk[CLK_TOP_DSP_26M]);
99+
if (ret) {
100+
dev_err(dev, "%s clk_prepare_enable(CLK_TOP_DSP_26M) fail %d\n",
101+
__func__, ret);
102+
goto disable_top_dsppll_d8_clk;
103+
}
104+
105+
ret = clk_prepare_enable(priv->clk[CLK_TOP_DSP_32K]);
106+
if (ret) {
107+
dev_err(dev, "%s clk_prepare_enable(CLK_TOP_DSP_32K) fail %d\n",
108+
__func__, ret);
109+
goto disable_top_dsp_26m_clk;
110+
}
111+
112+
return 0;
113+
114+
disable_top_dsp_26m_clk:
115+
clk_disable_unprepare(priv->clk[CLK_TOP_DSP_26M]);
116+
disable_top_dsppll_d8_clk:
117+
clk_disable_unprepare(priv->clk[CLK_TOP_DSPPLL_D8]);
118+
disable_top_dsppll_d4_clk:
119+
clk_disable_unprepare(priv->clk[CLK_TOP_DSPPLL_D4]);
120+
disable_top_dsppll_d2_clk:
121+
clk_disable_unprepare(priv->clk[CLK_TOP_DSPPLL_D2]);
122+
disable_top_sys_26m_d2_clk:
123+
clk_disable_unprepare(priv->clk[CLK_TOP_SYS_26M_D2]);
124+
disable_top_dsp_sel_clk:
125+
clk_disable_unprepare(priv->clk[CLK_TOP_DSP_SEL]);
126+
disable_top_dsppll_clk:
127+
clk_disable_unprepare(priv->clk[CLK_TOP_DSPPLL]);
128+
129+
return ret;
130+
}
131+
132+
static void adsp_disable_all_clock(struct snd_sof_dev *sdev)
133+
{
134+
struct adsp_priv *priv = sdev->pdata->hw_pdata;
135+
136+
clk_disable_unprepare(priv->clk[CLK_TOP_DSP_32K]);
137+
clk_disable_unprepare(priv->clk[CLK_TOP_DSP_26M]);
138+
clk_disable_unprepare(priv->clk[CLK_TOP_DSPPLL_D8]);
139+
clk_disable_unprepare(priv->clk[CLK_TOP_DSPPLL_D4]);
140+
clk_disable_unprepare(priv->clk[CLK_TOP_DSPPLL_D2]);
141+
clk_disable_unprepare(priv->clk[CLK_TOP_SYS_26M_D2]);
142+
clk_disable_unprepare(priv->clk[CLK_TOP_DSP_SEL]);
143+
clk_disable_unprepare(priv->clk[CLK_TOP_DSPPLL]);
144+
}
145+
146+
static int adsp_default_clk_init(struct snd_sof_dev *sdev, bool enable)
147+
{
148+
struct device *dev = sdev->dev;
149+
int ret;
150+
151+
dev_dbg(dev, "%s: %s\n", __func__, enable ? "on" : "off");
152+
153+
if (enable) {
154+
ret = adsp_enable_all_clock(sdev);
155+
if (ret) {
156+
dev_err(dev, "failed to adsp_enable_clock: %d\n", ret);
157+
return ret;
158+
}
159+
} else {
160+
adsp_disable_all_clock(sdev);
161+
}
162+
163+
return 0;
164+
}
165+
166+
int adsp_clock_on(struct snd_sof_dev *sdev)
167+
{
168+
/* Open ADSP clock */
169+
return adsp_default_clk_init(sdev, 1);
170+
}
171+
172+
int adsp_clock_off(struct snd_sof_dev *sdev)
173+
{
174+
/* Close ADSP clock */
175+
return adsp_default_clk_init(sdev, 0);
176+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (c) 2025 MediaTek Inc.
4+
*
5+
* Author: Aary Patil <aary.patil@mediatek.com>
6+
*
7+
* Header file for the mt8365 DSP clock definition
8+
*/
9+
10+
#ifndef __MT8365_CLK_H
11+
#define __MT8365_CLK_H
12+
13+
struct snd_sof_dev;
14+
15+
/*DSP clock*/
16+
enum adsp_clk_id {
17+
CLK_TOP_DSP_SEL,
18+
CLK_TOP_CLK26M_D52,
19+
CLK_TOP_SYS_26M_D2,
20+
CLK_TOP_DSPPLL,
21+
CLK_TOP_DSPPLL_D2,
22+
CLK_TOP_DSPPLL_D4,
23+
CLK_TOP_DSPPLL_D8,
24+
CLK_TOP_DSP_26M,
25+
CLK_TOP_DSP_32K,
26+
CLK_TOP_DSP_MAX
27+
};
28+
29+
int mt8365_adsp_init_clock(struct snd_sof_dev *sdev);
30+
int adsp_clock_on(struct snd_sof_dev *sdev);
31+
int adsp_clock_off(struct snd_sof_dev *sdev);
32+
#endif
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2+
/*
3+
* Copyright (c) 2025 MediaTek Inc.
4+
*
5+
* Author: Aary Patil <aary.patil@mediatek.com>
6+
*
7+
* Hardware interface for mt8365 DSP code loader
8+
*/
9+
10+
#include <sound/sof.h>
11+
#include "mt8365.h"
12+
#include "../../ops.h"
13+
14+
void sof_hifixdsp_boot_sequence(struct snd_sof_dev *sdev, u32 boot_addr)
15+
{
16+
/* ADSP bootup base */
17+
snd_sof_dsp_write(sdev, DSP_REG_BAR, DSP_ALTRESETVEC, boot_addr);
18+
19+
/* pull high RunStall (set bit3 to 1) */
20+
snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, DSP_RESET_SW,
21+
ADSP_RUNSTALL, ADSP_RUNSTALL);
22+
23+
/* pull high StatVectorSel to use AltResetVec (set bit4 to 1) */
24+
snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, DSP_RESET_SW,
25+
STATVECTOR_SEL, STATVECTOR_SEL);
26+
27+
/* toggle DReset & BReset */
28+
/* pull high DReset & BReset */
29+
snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, DSP_RESET_SW,
30+
ADSP_BRESET_SW | ADSP_DRESET_SW,
31+
ADSP_BRESET_SW | ADSP_DRESET_SW);
32+
33+
/* delay 10 DSP cycles at 26M about 1us by IP vendor's suggestion */
34+
udelay(1);
35+
36+
/* pull low DReset & BReset */
37+
snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, DSP_RESET_SW,
38+
ADSP_BRESET_SW | ADSP_DRESET_SW,
39+
0);
40+
41+
/* Enable PDebug */
42+
snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, DSP_PDEBUGBUS0,
43+
PDEBUG_ENABLE,
44+
PDEBUG_ENABLE);
45+
46+
/* release RunStall (set bit3 to 0) */
47+
snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, DSP_RESET_SW,
48+
ADSP_RUNSTALL, 0);
49+
}
50+
51+
void sof_hifixdsp_shutdown(struct snd_sof_dev *sdev)
52+
{
53+
/* RUN_STALL pull high again to reset */
54+
snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, DSP_RESET_SW,
55+
ADSP_RUNSTALL, ADSP_RUNSTALL);
56+
57+
/* pull high DReset & BReset */
58+
snd_sof_dsp_update_bits(sdev, DSP_REG_BAR, DSP_RESET_SW,
59+
ADSP_BRESET_SW | ADSP_DRESET_SW,
60+
ADSP_BRESET_SW | ADSP_DRESET_SW);
61+
}

0 commit comments

Comments
 (0)