Skip to content

Commit e5f29d1

Browse files
author
Cyril Chao
committed
mtk: add Zephyr native AFE DAI driver
Expose each AFE MEMIF as a Zephyr DAI device via DEVICE_DT_INST_DEFINE. Hardware start/stop is handled by the MEMIF DMA driver; DAI trigger is a no-op. Signed-off-by: Cyril Chao <cyril.chao@mediatek.corp-partner.google.com>
1 parent 92646e1 commit e5f29d1

1 file changed

Lines changed: 162 additions & 0 deletions

File tree

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/*
2+
* Copyright 2026 MediaTek
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/device.h>
8+
#include <zephyr/drivers/dai.h>
9+
#include <zephyr/logging/log.h>
10+
#include <sof/drivers/afe-drv.h>
11+
#include <ipc/stream.h>
12+
#include <ipc/dai.h>
13+
#include <ipc/dai-mediatek.h>
14+
15+
#define DT_DRV_COMPAT mediatek_afe
16+
17+
LOG_MODULE_REGISTER(dai_mtk_afe);
18+
19+
struct dai_mtk_afe_cfg {
20+
uint32_t dai_index;
21+
uint32_t memif_index;
22+
bool downlink;
23+
};
24+
25+
struct dai_mtk_afe_data {
26+
struct dai_config cfg;
27+
struct dai_properties tx_props;
28+
struct dai_properties rx_props;
29+
};
30+
31+
static int dai_mtk_afe_probe(const struct device *dev)
32+
{
33+
LOG_DBG("%s: probe", dev->name);
34+
return 0;
35+
}
36+
37+
static int dai_mtk_afe_remove(const struct device *dev)
38+
{
39+
LOG_DBG("%s: remove", dev->name);
40+
return 0;
41+
}
42+
43+
static int dai_mtk_afe_config_set(const struct device *dev,
44+
const struct dai_config *cfg,
45+
const void *bespoke_cfg, size_t size)
46+
{
47+
const struct dai_mtk_afe_cfg *dev_cfg = dev->config;
48+
struct dai_mtk_afe_data *data = dev->data;
49+
const struct sof_ipc_dai_config *sof_cfg = bespoke_cfg;
50+
struct mtk_base_afe *afe;
51+
int ret;
52+
53+
if (cfg) {
54+
data->cfg.channels = cfg->channels;
55+
data->cfg.rate = cfg->rate;
56+
data->cfg.format = cfg->format;
57+
data->cfg.word_size = cfg->word_size;
58+
}
59+
60+
if (sof_cfg) {
61+
int probe_ret;
62+
63+
afe = afe_get();
64+
probe_ret = afe_probe(afe);
65+
if (probe_ret < 0) {
66+
LOG_ERR("%s: afe_probe failed: %d", dev->name, probe_ret);
67+
return probe_ret;
68+
}
69+
ret = afe_dai_set_config(afe, dev_cfg->dai_index,
70+
sof_cfg->afe.dai_channels,
71+
sof_cfg->afe.dai_rate,
72+
sof_cfg->afe.dai_format);
73+
if (ret < 0) {
74+
LOG_ERR("%s: afe_dai_set_config failed: %d",
75+
dev->name, ret);
76+
return ret;
77+
}
78+
79+
LOG_DBG("%s: config_set dai=%u ch=%u rate=%u fmt=%u",
80+
dev->name, dev_cfg->dai_index,
81+
sof_cfg->afe.dai_channels,
82+
sof_cfg->afe.dai_rate,
83+
sof_cfg->afe.dai_format);
84+
}
85+
86+
return 0;
87+
}
88+
89+
static int dai_mtk_afe_config_get(const struct device *dev,
90+
struct dai_config *cfg, enum dai_dir dir)
91+
{
92+
const struct dai_mtk_afe_cfg *dev_cfg = dev->config;
93+
struct dai_mtk_afe_data *data = dev->data;
94+
95+
if (!cfg) {
96+
return -EINVAL;
97+
}
98+
99+
*cfg = data->cfg;
100+
cfg->type = DAI_MEDIATEK_AFE;
101+
cfg->dai_index = dev_cfg->dai_index;
102+
103+
return 0;
104+
}
105+
106+
static const struct dai_properties *dai_mtk_afe_get_properties(
107+
const struct device *dev, enum dai_dir dir, int stream_id)
108+
{
109+
const struct dai_mtk_afe_data *data = dev->data;
110+
111+
if (dir == DAI_DIR_TX) {
112+
return &data->tx_props;
113+
}
114+
return &data->rx_props;
115+
}
116+
117+
static int dai_mtk_afe_trigger(const struct device *dev,
118+
enum dai_dir dir, enum dai_trigger_cmd cmd)
119+
{
120+
LOG_DBG("%s: trigger dir=%d cmd=%d", dev->name, dir, cmd);
121+
return 0;
122+
}
123+
124+
static DEVICE_API(dai, dai_mtk_afe_api) = {
125+
.probe = dai_mtk_afe_probe,
126+
.remove = dai_mtk_afe_remove,
127+
.config_set = dai_mtk_afe_config_set,
128+
.config_get = dai_mtk_afe_config_get,
129+
.get_properties = dai_mtk_afe_get_properties,
130+
.trigger = dai_mtk_afe_trigger,
131+
};
132+
133+
#define DAI_MTK_AFE_HANDSHAKE(inst) \
134+
((inst) << 16) | DT_INST_PROP(inst, dai_id)
135+
136+
#define DAI_MTK_AFE_INIT(inst) \
137+
static struct dai_mtk_afe_data dai_mtk_afe_data_##inst = { \
138+
.cfg = { \
139+
.type = DAI_MEDIATEK_AFE, \
140+
.dai_index = DT_INST_PROP(inst, dai_id), \
141+
}, \
142+
.tx_props = { \
143+
.dma_hs_id = DAI_MTK_AFE_HANDSHAKE(inst), \
144+
}, \
145+
.rx_props = { \
146+
.dma_hs_id = DAI_MTK_AFE_HANDSHAKE(inst), \
147+
}, \
148+
}; \
149+
\
150+
static const struct dai_mtk_afe_cfg dai_mtk_afe_cfg_##inst = { \
151+
.dai_index = DT_INST_PROP(inst, dai_id), \
152+
.memif_index = inst, \
153+
.downlink = DT_INST_PROP(inst, downlink), \
154+
}; \
155+
\
156+
DEVICE_DT_INST_DEFINE(inst, NULL, NULL, \
157+
&dai_mtk_afe_data_##inst, \
158+
&dai_mtk_afe_cfg_##inst, \
159+
POST_KERNEL, CONFIG_DAI_INIT_PRIORITY, \
160+
&dai_mtk_afe_api);
161+
162+
DT_INST_FOREACH_STATUS_OKAY(DAI_MTK_AFE_INIT)

0 commit comments

Comments
 (0)