From 620979a5b55b8325f96a62ec6d2fb49f747db737 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Fri, 22 Nov 2024 18:23:05 -0800 Subject: [PATCH] afe all wired up --- app/Kconfig | 6 + src/platform/mtk/dai.c | 246 ++++++++++++++++++++++++++++++++++-- src/platform/mtk/platform.c | 86 +++++++++++-- zephyr/CMakeLists.txt | 4 + 4 files changed, 322 insertions(+), 20 deletions(-) diff --git a/app/Kconfig b/app/Kconfig index 5fa46f871817..5e140788f858 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -26,5 +26,11 @@ config SMP_BOOT_DELAY config TRACE default n +# FIXME: figure this out, "host page table", MTK/NXP both need it, old +# old flag (see commit fb784218b500). But I **think** MTK doesn't +# care about host addresses? Might be just cut/paste +config HOST_PTABLE + default y if CONFIG_SOC_FAMILY_MTK + source "Kconfig.zephyr" diff --git a/src/platform/mtk/dai.c b/src/platform/mtk/dai.c index dce8987deb36..ee3cc704eea6 100644 --- a/src/platform/mtk/dai.c +++ b/src/platform/mtk/dai.c @@ -1,5 +1,6 @@ #include #include +#include #define DAI_HANDSHAKE(dai, irq, chan) ((chan << 16) | (irq << 8) | dai) @@ -13,23 +14,26 @@ extern const struct dai_driver afe_dai_driver; //////////////////////////////////////////////////////////////////////// // Cribbed from mt8196, need to source from DTS // -// Notes: basically there is only one "type" of DAI in mtk, each dai -// represents one "device" equivalent, which is parametrized by an -// "index" (corresponds to the memif used) an irq number and a channel -// enumerant. -// -// FIXME: I *think* these enumerants exist only within SOF and aren't -// hardware config or understood by the kernel? Maybe it matches on -// handshake? +// MONSTER 7MB HEADER, MUST FIX +#include "../../mt8196/include/platform/mt8196-afe-reg.h" + +// Note that there are two sets of enumerants, and the order is +// mismatched! (DL1 and DL_24CH are swapped). The DAI numbering is +// the master and what the host uses, from there you can unpack the +// "channel" from the handshake value which is the memif index. I +// think the variant ordering of memif_data[] is just a mistake... I +// don't think the handshake value exists on the host, I only see it +// being parsed here in SOF. + enum { MT8196_DAI_I2S_OUT4, /* speaker */ MT8196_DAI_I2S_OUT6, /* headset out */ MT8196_DAI_AP_DMIC, /* DMIC */ MT8196_DAI_I2S_IN6, /* headset mic */ MT8196_DAI_AP_DMIC_CH34, - MT8196_DAI_NUM, }; +// Indexes that identify an afe driver enum { MT8196_MEMIF_DL1, MT8196_MEMIF_DL_24CH, @@ -38,6 +42,8 @@ enum { MT8196_MEMIF_UL2, }; +// Note: the IRQ's used are always equal to their enumerants, not sure +// if that's guaranteed. Maybe academic as no interrupts currently static struct dai mtk_dais[] = { DAI_DEFINE(MT8196_DAI_I2S_OUT4, 12, MT8196_MEMIF_DL_24CH), DAI_DEFINE(MT8196_DAI_I2S_OUT6, 1, MT8196_MEMIF_DL1), @@ -46,8 +52,183 @@ static struct dai mtk_dais[] = { DAI_DEFINE(MT8196_DAI_AP_DMIC_CH34, 15, MT8196_MEMIF_UL2), }; +static const struct mtk_base_memif_data mtk_memif_data[] = { + [MT8196_MEMIF_DL1] = { + .name = "DL1", + .id = MT8196_MEMIF_DL1, + .reg_ofs_base = AFE_DL1_BASE, + .reg_ofs_cur = AFE_DL1_CUR, + .reg_ofs_end = AFE_DL1_END, + .reg_ofs_base_msb = AFE_DL1_BASE_MSB, + .reg_ofs_cur_msb = AFE_DL1_CUR_MSB, + .reg_ofs_end_msb = AFE_DL1_END_MSB, + .fs_reg = AFE_DL1_CON0, + .fs_shift = DL1_SEL_FS_SFT, + .fs_maskbit = DL1_SEL_FS_MASK, + .mono_reg = AFE_DL1_CON0, + .mono_shift = DL1_MONO_SFT, + .int_odd_flag_reg = -1, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DL1_CON0, + .enable_shift = DL1_ON_SFT, + .hd_reg = AFE_DL1_CON0, + .hd_shift = DL1_HD_MODE_SFT, + .hd_align_reg = AFE_DL1_CON0, + .hd_align_mshift = DL1_HALIGN_SFT, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + .ch_num_reg = -1, + .msb_reg = -1, + .msb_shift = -1, + .pbuf_reg = AFE_DL1_CON0, + .pbuf_mask = DL1_PBUF_SIZE_MASK, + .pbuf_shift = DL1_PBUF_SIZE_SFT, + .minlen_reg = AFE_DL1_CON0, + .minlen_mask = DL1_MINLEN_MASK, + .minlen_shift = DL1_MINLEN_SFT, + }, + [MT8196_MEMIF_DL_24CH] = { + .name = "DL_24CH", + .id = MT8196_MEMIF_DL_24CH, + .reg_ofs_base = AFE_DL_24CH_BASE, + .reg_ofs_cur = AFE_DL_24CH_CUR, + .reg_ofs_end = AFE_DL_24CH_END, + .reg_ofs_base_msb = AFE_DL_24CH_BASE_MSB, + .reg_ofs_cur_msb = AFE_DL_24CH_CUR_MSB, + .reg_ofs_end_msb = AFE_DL_24CH_END_MSB, + .fs_reg = AFE_DL_24CH_CON0, + .fs_shift = DL_24CH_SEL_FS_SFT, + .fs_maskbit = DL_24CH_SEL_FS_MASK, + .mono_reg = -1, + .mono_shift = -1, + .int_odd_flag_reg = -1, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DL_24CH_CON0, + .enable_shift = DL_24CH_ON_SFT, + .hd_reg = AFE_DL_24CH_CON0, + .hd_shift = DL_24CH_HD_MODE_SFT, + .hd_align_reg = AFE_DL_24CH_CON0, + .hd_align_mshift = DL_24CH_HALIGN_SFT, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + .msb_reg = -1, + .msb_shift = -1, + .pbuf_reg = AFE_DL_24CH_CON0, + .pbuf_mask = DL_24CH_PBUF_SIZE_MASK, + .pbuf_shift = DL_24CH_PBUF_SIZE_SFT, + .minlen_reg = AFE_DL_24CH_CON0, + .minlen_mask = DL_24CH_MINLEN_MASK, + .minlen_shift = DL_24CH_MINLEN_SFT, + .ch_num_reg = AFE_DL_24CH_CON0, + .ch_num_maskbit = DL_24CH_NUM_MASK, + .ch_num_shift = DL_24CH_NUM_SFT, + }, + [MT8196_MEMIF_UL0] = { + .name = "UL0", + .id = MT8196_MEMIF_UL0, + .reg_ofs_base = AFE_VUL0_BASE, + .reg_ofs_cur = AFE_VUL0_CUR, + .reg_ofs_end = AFE_VUL0_END, + .reg_ofs_base_msb = AFE_VUL0_BASE_MSB, + .reg_ofs_cur_msb = AFE_VUL0_CUR_MSB, + .reg_ofs_end_msb = AFE_VUL0_END_MSB, + .fs_reg = AFE_VUL0_CON0, + .fs_shift = VUL0_SEL_FS_SFT, + .fs_maskbit = VUL0_SEL_FS_MASK, + .mono_reg = AFE_VUL0_CON0, + .mono_shift = VUL0_MONO_SFT, + .int_odd_flag_reg = -1, + .int_odd_flag_shift = 0, + .enable_reg = AFE_VUL0_CON0, + .enable_shift = VUL0_ON_SFT, + .hd_reg = AFE_VUL0_CON0, + .hd_shift = VUL0_HD_MODE_SFT, + .hd_align_reg = AFE_VUL0_CON0, + .hd_align_mshift = VUL0_HALIGN_SFT, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + .msb_reg = -1, + .msb_shift = -1, + }, + [MT8196_MEMIF_UL1] = { + .name = "UL1", + .id = MT8196_MEMIF_UL1, + .reg_ofs_base = AFE_VUL1_BASE, + .reg_ofs_cur = AFE_VUL1_CUR, + .reg_ofs_end = AFE_VUL1_END, + .reg_ofs_base_msb = AFE_VUL1_BASE_MSB, + .reg_ofs_cur_msb = AFE_VUL1_CUR_MSB, + .reg_ofs_end_msb = AFE_VUL1_END_MSB, + .fs_reg = AFE_VUL1_CON0, + .fs_shift = VUL1_SEL_FS_SFT, + .fs_maskbit = VUL1_SEL_FS_MASK, + .mono_reg = AFE_VUL1_CON0, + .mono_shift = VUL1_MONO_SFT, + .enable_reg = AFE_VUL1_CON0, + .enable_shift = VUL1_ON_SFT, + .hd_reg = AFE_VUL1_CON0, + .hd_shift = VUL1_HD_MODE_SFT, + .hd_align_reg = AFE_VUL1_CON0, + .hd_align_mshift = VUL1_HALIGN_SFT, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + .msb_reg = -1, + .msb_shift = -1, + }, + [MT8196_MEMIF_UL2] = { + .name = "UL2", + .id = MT8196_MEMIF_UL2, + .reg_ofs_base = AFE_VUL2_BASE, + .reg_ofs_cur = AFE_VUL2_CUR, + .reg_ofs_end = AFE_VUL2_END, + .reg_ofs_base_msb = AFE_VUL2_BASE_MSB, + .reg_ofs_cur_msb = AFE_VUL2_CUR_MSB, + .reg_ofs_end_msb = AFE_VUL2_END_MSB, + .fs_reg = AFE_VUL2_CON0, + .fs_shift = VUL2_SEL_FS_SFT, + .fs_maskbit = VUL2_SEL_FS_MASK, + .mono_reg = AFE_VUL2_CON0, + .mono_shift = VUL2_MONO_SFT, + .int_odd_flag_reg = -1, + .int_odd_flag_shift = 0, + .enable_reg = AFE_VUL2_CON0, + .enable_shift = VUL2_ON_SFT, + .hd_reg = AFE_VUL2_CON0, + .hd_shift = VUL2_HD_MODE_SFT, + .hd_align_reg = AFE_VUL2_CON0, + .hd_align_mshift = VUL2_HALIGN_SFT, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + .msb_reg = -1, + .msb_shift = -1, + }, +}; + +#define MTK_AFE_BASE 0x1a110000 +#define MTK_DL_NUM 2 + //////////////////////////////////////////////////////////////////////// +extern const struct dma_ops memif_ops; + +static struct dma mtk_dma[] = { + { + .plat_data = { + .id = 0, // 0 == DMA_ID_AFE_MEMIF + .dir = DMA_DIR_MEM_TO_DEV | DMA_DIR_DEV_TO_MEM, + .devs = DMA_DEV_AFE_MEMIF, + .base = MTK_AFE_BASE, + .channels = ARRAY_SIZE(mtk_dais), + }, + .ops = &memif_ops, + }, +}; + +static const struct dma_info mtk_dma_info = { + .dma_array = mtk_dma, + .num_dmas = ARRAY_SIZE(mtk_dma), +}; + static const struct dai_type_info mtk_dai_types[] = { { .type = SOF_DAI_MEDIATEK_AFE, .dai_array = mtk_dais, @@ -59,9 +240,56 @@ static const struct dai_info mtk_dai_info = { .num_dai_types = ARRAY_SIZE(mtk_dai_types), }; +static unsigned int mtk_afe_fs_timing(unsigned int rate) +{ + /* Static table of fs register values. TODO: sort it and binary search */ + static const struct { int hz, reg; } rate2reg[] = { + { 8000, 0 }, + { 11025, 1 }, + { 12000, 2 }, + { 16000, 4 }, + { 22050, 5 }, + { 24000, 6 }, + { 32000, 8 }, + { 44100, 9 }, + { 48000, 10 }, + { 88200, 13 }, + { 96000, 14 }, + { 176400, 17 }, + { 192000, 18 }, + { 352800, 21 }, + { 384000, 22 }, + }; + + for (int i = 0; i < ARRAY_SIZE(rate2reg); i++) + if (rate2reg[i].hz == rate) + return rate2reg[i].reg; + return -EINVAL; +} + +static unsigned int mtk_afe_fs(unsigned int rate, int aud_blk) +{ + return mtk_afe_fs_timing(rate); +} + +/* Global symbol referenced by AFE driver */ +struct mtk_base_afe_platform mtk_afe_platform = { + .base_addr = MTK_AFE_BASE, + .memif_datas = mtk_memif_data, + .memif_size = ARRAY_SIZE(mtk_memif_data), + .memif_dl_num = MTK_DL_NUM, + .memif_32bit_supported = 0, + .irq_datas = NULL, + .irqs_size = 0, + .dais_size = ARRAY_SIZE(mtk_dais), + .afe_fs = mtk_afe_fs, + .irq_fs = mtk_afe_fs_timing, +}; + int mtk_dai_init(struct sof *sof) { printk("ANDY %s:%d\n", __func__, __LINE__); sof->dai_info = &mtk_dai_info; + sof->dma_info = &mtk_dma_info; return 0; } diff --git a/src/platform/mtk/platform.c b/src/platform/mtk/platform.c index 0c97d8290c4c..bb9d31226af4 100644 --- a/src/platform/mtk/platform.c +++ b/src/platform/mtk/platform.c @@ -1,31 +1,95 @@ +#include +#include +#include #include #include -#include -#include +#include +#include +#include +#include +#include -int platform_init(struct sof *sof) +void mtk_dai_init(struct sof *sof); + +int platform_ipc_init(struct ipc *ipc) { printk("ANDY %s:%d\n", __func__, __LINE__); - return 0; + // FIXME + return 0; } -int platform_boot_complete(uint32_t boot_message) +void ipc_platform_complete_cmd(struct ipc *ipc) { printk("ANDY %s:%d\n", __func__, __LINE__); + // FIXME +} + +int ipc_platform_send_msg(const struct ipc_msg *msg) +{ + printk("ANDY %s:%d\n", __func__, __LINE__); + // FIXME return 0; } -void ipc_platform_complete_cmd(struct ipc *ipc) +static int set_cpuclk(int clock, int hz) +{ + return clock == 0 && hz == CONFIG_XTENSA_CCOUNT_HZ ? 0 : -EINVAL; +} + +void clocks_init(struct sof *sof) { + // Dummy CPU clock driver that supports one known frequency. + // This hardware has clock scaling support, but it hasn't + // historically been exercised so we have nothing to test + // against. + static struct freq_table freqs[] = { + { .freq = CONFIG_XTENSA_CCOUNT_HZ, + .ticks_per_msec = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000, } + }; + static struct clock_info clks[] = { + { .freqs_num = ARRAY_SIZE(freqs), + .freqs = freqs, + .notification_id = NOTIFIER_ID_CPU_FREQ, + .notification_mask = NOTIFIER_TARGET_CORE_MASK(0), + .set_freq = set_cpuclk, }, + }; + sof->clocks = clks; +} + +int platform_init(struct sof *sof) +{ + int ret; printk("ANDY %s:%d\n", __func__, __LINE__); + + clocks_init(sof); + + sof->platform_timer_domain = zephyr_domain_init(PLATFORM_DEFAULT_CLOCK); + + ipc_init(sof); + + mtk_dai_init(sof); + + scheduler_init_edf(); + scheduler_init_ll(sof->platform_timer_domain); + + sa_init(sof, CONFIG_SYSTICK_PERIOD); // watchdoggy thingy + + return 0; +} + +int platform_boot_complete(uint32_t boot_message) +{ + printk("ANDY %s:%d (send an IPC here, right?)\n", __func__, __LINE__); + // FIXME + return 0; } // Extended manifest window record. Note the alignment attribute is -// critical as rimage demands allocation in units of 16 bytes, yet -// other records emitted into the same section are not padded! -// (Really this is an rimage bug, it should separately validate each -// symbol in the section and re-pack the array instead of relying on -// the poor linker to do it). +// critical as rimage demands allocation in units of 16 bytes, yet the +// C struct records emitted into the section are not in general padded +// and will pack tighter than that! (Really this is an rimage bug, it +// should separately validate each symbol in the section and re-pack +// the array instead of relying on the poor linker to do it). #define WINDOW(region) \ { .type = SOF_IPC_REGION_##region, \ diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 12bb977cdf17..f38c04f74d7e 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -375,7 +375,11 @@ if (CONFIG_SOC_FAMILY_MTK) zephyr_library_sources( ${SOF_PLATFORM_PATH}/mtk/platform.c + ${SOF_PLATFORM_PATH}/mtk/dai.c ${SOF_SRC_PATH}/schedule/zephyr_ll.c + ${SOF_SRC_PATH}/drivers/mediatek/afe/afe-memif.c + ${SOF_SRC_PATH}/drivers/mediatek/afe/afe-dai.c + ${SOF_SRC_PATH}/drivers/mediatek/afe/afe-drv.c ) endif()