From 6efe377756cd6685dc31ed88fbe9caae22942466 Mon Sep 17 00:00:00 2001 From: CY Kuei Date: Thu, 11 Aug 2022 13:43:53 +0800 Subject: [PATCH 01/14] module_adapter: correct the way to get the scheduling period Scheduling period should be acquired from dev->pipeline->period Signed-off-by: CY Kuei --- src/audio/module_adapter/module/waves.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/audio/module_adapter/module/waves.c b/src/audio/module_adapter/module/waves.c index 991834f7f9da..52e9e198e2d1 100644 --- a/src/audio/module_adapter/module/waves.c +++ b/src/audio/module_adapter/module/waves.c @@ -342,8 +342,11 @@ static int waves_effect_init(struct processing_module *mod) waves_codec->o_format = waves_codec->i_format; waves_codec->sample_size_in_bytes = sample_bytes; - waves_codec->buffer_bytes = mod->period_bytes; - waves_codec->buffer_samples = waves_codec->buffer_bytes / src_fmt->channels / + /* Prepare a buffer for 1 period worth of data + * dev->pipeline->period stands for the scheduling period in us + */ + waves_codec->buffer_samples = src_fmt->rate * dev->pipeline->period / 1000000; + waves_codec->buffer_bytes = waves_codec->buffer_samples * src_fmt->channels * waves_codec->sample_size_in_bytes; // trace allows printing only up-to 4 words at a time From cd8f38cf99cef7e1b41815358b71c7d15c5902c2 Mon Sep 17 00:00:00 2001 From: "barry.jan" Date: Wed, 3 Aug 2022 09:09:32 +0800 Subject: [PATCH 02/14] topology: add Waves for sof-mt8186-mt6366-rt1019-rt5682s tplg Signed-off-by: barry.jan --- .../xtensa/configs/override/mt8186_chrome_waves.config | 2 ++ tools/topology/topology1/CMakeLists.txt | 1 + tools/topology/topology1/sof-mt8186-mt6366.m4 | 8 ++++++-- 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 src/arch/xtensa/configs/override/mt8186_chrome_waves.config diff --git a/src/arch/xtensa/configs/override/mt8186_chrome_waves.config b/src/arch/xtensa/configs/override/mt8186_chrome_waves.config new file mode 100644 index 000000000000..6e0143275ba6 --- /dev/null +++ b/src/arch/xtensa/configs/override/mt8186_chrome_waves.config @@ -0,0 +1,2 @@ +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_WAVES_CODEC=y diff --git a/tools/topology/topology1/CMakeLists.txt b/tools/topology/topology1/CMakeLists.txt index 01616ac90d18..678a048b6942 100644 --- a/tools/topology/topology1/CMakeLists.txt +++ b/tools/topology/topology1/CMakeLists.txt @@ -237,6 +237,7 @@ set(TPLGS "sof-mt8195-mt6359-rt1019-rt5682\;sof-mt8195-mt6359-max98390-rt5682-rtnr\;-DCHANNELS=2\;-DRTNR" "sof-mt8195-mt6359-rt1019-rt5682\;sof-mt8195-mt6359-max98390-rt5682-google-aec-rtnr\;-DGOOGLE_RTC_AUDIO_PROCESSING\;-DCHANNELS=2\;-DRTNR" "sof-mt8186-mt6366\;sof-mt8186-mt6366-rt1019-rt5682s" + "sof-mt8186-mt6366\;sof-mt8186-mt6366-rt1019-rt5682s-waves\;-DWAVES=1" "sof-mt8186-mt6366\;sof-mt8186-mt6366-da7219-max98357" "sof-acp-renoir\;sof-acp" diff --git a/tools/topology/topology1/sof-mt8186-mt6366.m4 b/tools/topology/topology1/sof-mt8186-mt6366.m4 index a0d8da2a9510..dfd851adbb66 100644 --- a/tools/topology/topology1/sof-mt8186-mt6366.m4 +++ b/tools/topology/topology1/sof-mt8186-mt6366.m4 @@ -34,19 +34,23 @@ dnl period, priority, core, dnl pcm_min_rate, pcm_max_rate, pipeline_rate, dnl time_domain, sched_comp) +define(`ENDPOINT_NAME', `Speakers') # Low Latency playback pipeline 1 on PCM 25 using max 2 channels of s16le # Set 1000us deadline with priority 0 on core 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, +PIPELINE_PCM_ADD(ifdef(`WAVES', sof/pipe-waves-codec-playback.m4, sof/pipe-passthrough-playback.m4), 1, 25, 2, s16le, 1000, 0, 0, 48000, 48000, 48000) +undefine(`ENDPOINT_NAME') +define(`ENDPOINT_NAME', `Headphones') # Low Latency playback pipeline 2 on PCM 26 using max 2 channels of s16le # Set 1000us deadline with priority 0 on core 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, +PIPELINE_PCM_ADD(ifdef(`WAVES', sof/pipe-waves-codec-playback.m4, sof/pipe-passthrough-playback.m4), 2, 26, 2, s16le, 1000, 0, 0, 48000, 48000, 48000) +undefine(`ENDPOINT_NAME') # Low Latency capture pipeline 3 on PCM 27 using max 2 channels of s16le # Set 2000us deadline with priority 0 on core 0 From 5494c58af7385352c1334664fd07004c36791473 Mon Sep 17 00:00:00 2001 From: "barry.jan" Date: Wed, 3 Aug 2022 10:07:38 +0800 Subject: [PATCH 03/14] Waves: fix buffer acquisition In module adapter, Waves will receive bin file from user space before .prepare method be called. To support this change, move buffer acquisition in .ini method instead. Signed-off-by: barry.jan --- src/audio/module_adapter/module/waves.c | 75 +++++++++++-------------- 1 file changed, 33 insertions(+), 42 deletions(-) diff --git a/src/audio/module_adapter/module/waves.c b/src/audio/module_adapter/module/waves.c index 52e9e198e2d1..553276dce79c 100644 --- a/src/audio/module_adapter/module/waves.c +++ b/src/audio/module_adapter/module/waves.c @@ -209,10 +209,9 @@ static int waves_effect_allocate(struct processing_module *mod) return -ENOMEM; } - comp_info(dev, "waves_codec_init() allocated %d bytes for effect", + comp_dbg(dev, "waves_effect_allocate() allocated %d bytes for effect", waves_codec->effect_size); - comp_dbg(dev, "waves_codec_init() done"); return 0; } @@ -329,8 +328,6 @@ static int waves_effect_init(struct processing_module *mod) } waves_codec->request_max_bytes = 0; - waves_codec->response_max_bytes = 0; - waves_codec->response = 0; waves_codec->i_buffer = 0; waves_codec->o_buffer = 0; @@ -338,7 +335,6 @@ static int waves_effect_init(struct processing_module *mod) waves_codec->i_format.numChannels = src_fmt->channels; waves_codec->i_format.samplesFormat = sample_format; waves_codec->i_format.samplesLayout = buffer_format; - waves_codec->o_format = waves_codec->i_format; waves_codec->sample_size_in_bytes = sample_bytes; @@ -375,30 +371,11 @@ static int waves_effect_buffers(struct processing_module *mod) struct comp_dev *dev = mod->dev; struct module_data *codec = &mod->priv; struct waves_codec_data *waves_codec = codec->private; - MaxxStatus_t status; int ret; - void *i_buffer = NULL, *o_buffer = NULL, *response = NULL; + void *i_buffer = NULL, *o_buffer = NULL; comp_dbg(dev, "waves_effect_buffers() start"); - status = MaxxEffect_GetMessageMaxSize(waves_codec->effect, &waves_codec->request_max_bytes, - &waves_codec->response_max_bytes); - - if (status) { - comp_err(dev, "waves_effect_buffers() MaxxEffect_GetMessageMaxSize returned %d", - status); - ret = -EINVAL; - goto err; - } - - response = module_allocate_memory(mod, waves_codec->response_max_bytes, 16); - if (!response) { - comp_err(dev, "waves_effect_buffers() failed to allocate %d bytes for response", - waves_codec->response_max_bytes); - ret = -ENOMEM; - goto err; - } - i_buffer = module_allocate_memory(mod, waves_codec->buffer_bytes, 16); if (!i_buffer) { comp_err(dev, "waves_effect_buffers() failed to allocate %d bytes for i_buffer", @@ -417,15 +394,13 @@ static int waves_effect_buffers(struct processing_module *mod) waves_codec->i_buffer = i_buffer; waves_codec->o_buffer = o_buffer; - waves_codec->response = response; codec->mpd.in_buff = waves_codec->i_buffer; codec->mpd.in_buff_size = waves_codec->buffer_bytes; codec->mpd.out_buff = waves_codec->o_buffer; codec->mpd.out_buff_size = waves_codec->buffer_bytes; - comp_info(dev, "waves_effect_buffers() size response %d, i_buffer %d, o_buffer %d", - waves_codec->response_max_bytes, waves_codec->buffer_bytes, - waves_codec->buffer_bytes); + comp_dbg(dev, "waves_effect_buffers() in_buff_size %d, out_buff_size %d", + codec->mpd.in_buff_size, codec->mpd.out_buff_size); comp_dbg(dev, "waves_effect_buffers() done"); return 0; @@ -435,8 +410,6 @@ static int waves_effect_buffers(struct processing_module *mod) module_free_memory(mod, i_buffer); if (o_buffer) module_free_memory(mod, o_buffer); - if (response) - module_free_memory(mod, response); return ret; } @@ -494,7 +467,7 @@ static int waves_effect_message(struct processing_module *mod, void *data, uint3 { struct module_data *codec = &mod->priv; struct waves_codec_data *waves_codec = codec->private; - struct module_data *codec = &mod->priv; + struct comp_dev *dev = mod->dev; MaxxStatus_t status; uint32_t response_size = 0; @@ -621,6 +594,7 @@ static int waves_codec_init(struct processing_module *mod) struct module_data *codec = &mod->priv; struct waves_codec_data *waves_codec; int ret = 0; + void *response = NULL; comp_dbg(dev, "waves_codec_init() start"); @@ -640,9 +614,10 @@ static int waves_codec_init(struct processing_module *mod) } } - if (ret) + if (ret) { comp_err(dev, "waves_codec_init() failed %d", ret); - + return ret; + } waves_codec->setup_cfg.avail = false; /* copy the setup config only for the first init */ @@ -652,7 +627,7 @@ static int waves_codec_init(struct processing_module *mod) /* allocate memory for set up config */ setup_cfg->data = rballoc(0, SOF_MEM_CAPS_RAM, codec->cfg.size); if (!setup_cfg->data) { - comp_err(dev, "cadence_codec_init(): failed to alloc setup config"); + comp_err(dev, "waves_codec_init(): failed to alloc setup config"); module_free_memory(mod, waves_codec); return -ENOMEM; } @@ -661,13 +636,29 @@ static int waves_codec_init(struct processing_module *mod) setup_cfg->size = codec->cfg.size; ret = memcpy_s(setup_cfg->data, setup_cfg->size, codec->cfg.data, setup_cfg->size); if (ret) { - comp_err(dev, "cadence_codec_init(): failed to copy setup config %d", ret); + comp_err(dev, "waves_codec_init(): failed to copy setup config %d", ret); module_free_memory(mod, waves_codec); return ret; } setup_cfg->avail = true; } + ret = MaxxEffect_GetMessageMaxSize(waves_codec->effect, &waves_codec->request_max_bytes, + &waves_codec->response_max_bytes); + + if (ret) { + comp_err(dev, "waves_codec_init() MaxxEffect_GetMessageMaxSize returned %d", ret); + return -EINVAL; + } + + response = module_allocate_memory(mod, waves_codec->response_max_bytes, 16); + if (!response) { + comp_err(dev, "waves_codec_init() failed to allocate %d bytes for response", + waves_codec->response_max_bytes); + return -ENOMEM; + } + waves_codec->response = response; + comp_dbg(dev, "waves_codec_init() done"); return ret; } @@ -728,7 +719,7 @@ waves_codec_process(struct processing_module *mod, } if (!codec->mpd.init_done) - waves_codec_init_process(dev); + waves_codec_init_process(mod); memcpy_s(codec->mpd.in_buff, codec->mpd.in_buff_size, input_buffers[0].data, codec->mpd.in_buff_size); @@ -785,13 +776,13 @@ waves_codec_process(struct processing_module *mod, return ret; } -static int waves_codec_apply_config(struct comp_dev *dev) +static int waves_codec_apply_config(struct processing_module *mod) { int ret; + struct comp_dev *dev = mod->dev; comp_dbg(dev, "waves_codec_apply_config() start"); - ret = waves_effect_config(dev); - + ret = waves_effect_config(mod); if (ret) comp_err(dev, "waves_codec_apply_config() failed %d", ret); @@ -807,7 +798,7 @@ static int waves_codec_reset(struct processing_module *mod) struct module_data *codec = &mod->priv; struct waves_codec_data *waves_codec = codec->private; - comp_dbg(dev, "waves_codec_reset() start"); + comp_info(dev, "waves_codec_reset() start"); status = MaxxEffect_Reset(waves_codec->effect); if (status) { @@ -850,7 +841,7 @@ waves_codec_set_configuration(struct processing_module *mod, uint32_t config_id, return 0; /* whole configuration received, apply it now */ - ret = waves_codec_apply_config(dev); + ret = waves_codec_apply_config(mod); if (ret) { comp_err(dev, "waves_codec_set_configuration(): error %x: runtime config apply failed", ret); From 4fd2b14fbf5ac323ea52faaebdfdb81ccb63f733 Mon Sep 17 00:00:00 2001 From: Chunxu Li Date: Thu, 25 Aug 2022 15:31:16 +0800 Subject: [PATCH 04/14] topology1: remove mt8186 unused topologies Remove mt8186 unused topologies. We use sof-mt8186 on our demo board, sof-mt8186-mt6366-rt1019-rt5682s and sof-mt8186-mt6366-da7219-max98357 will no be used anymore. Signed-off-by: Chunxu Li (cherry picked from commit 8d9c5485c40371b5b9e2439d1f4de4fbc1af06ef) --- tools/topology/topology1/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/topology/topology1/CMakeLists.txt b/tools/topology/topology1/CMakeLists.txt index 678a048b6942..6442ba1ebcb5 100644 --- a/tools/topology/topology1/CMakeLists.txt +++ b/tools/topology/topology1/CMakeLists.txt @@ -236,9 +236,8 @@ set(TPLGS "sof-mt8195-mt6359-rt1019-rt5682\;sof-mt8195-mt6359-max98390-rt5682" "sof-mt8195-mt6359-rt1019-rt5682\;sof-mt8195-mt6359-max98390-rt5682-rtnr\;-DCHANNELS=2\;-DRTNR" "sof-mt8195-mt6359-rt1019-rt5682\;sof-mt8195-mt6359-max98390-rt5682-google-aec-rtnr\;-DGOOGLE_RTC_AUDIO_PROCESSING\;-DCHANNELS=2\;-DRTNR" - "sof-mt8186-mt6366\;sof-mt8186-mt6366-rt1019-rt5682s" + "sof-mt8186-mt6366\;sof-mt8186" "sof-mt8186-mt6366\;sof-mt8186-mt6366-rt1019-rt5682s-waves\;-DWAVES=1" - "sof-mt8186-mt6366\;sof-mt8186-mt6366-da7219-max98357" "sof-acp-renoir\;sof-acp" "sof-rn-rt5682-rt1019\;sof-rn-rt5682-rt1019" From 6bd61c945c6bfc0c86119d6b5669f4bc258bf56a Mon Sep 17 00:00:00 2001 From: Tinghan Shen Date: Wed, 2 Nov 2022 20:19:13 +0800 Subject: [PATCH 05/14] platform: mt8186: Change ADSP max clock frequency Change the maximum frequency to 300M because power issue. The mt8186 supports 800M/400M/300M frequencies, each requires 0.8/0.7/0.65 minimum core voltages. The 300M is the most compatible option because it has the lowest minimum core voltage. Signed-off-by: Tinghan Shen --- .../mt8186/include/platform/lib/clk.h | 11 +++++----- src/platform/mt8186/lib/clk.c | 21 +++++++------------ 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/platform/mt8186/include/platform/lib/clk.h b/src/platform/mt8186/include/platform/lib/clk.h index 6647630bb282..a0725c929833 100644 --- a/src/platform/mt8186/include/platform/lib/clk.h +++ b/src/platform/mt8186/include/platform/lib/clk.h @@ -18,9 +18,10 @@ struct sof; #define CLK_CPU(x) (x) #define CLK_DEFAULT_CPU_HZ 26000000 -#define CLK_MAX_CPU_HZ 800000000 +/* check vcore voltage before select higher frequency than 300M */ +#define CLK_MAX_CPU_HZ 300000000 #define NUM_CLOCKS 1 -#define NUM_CPU_FREQ 5 +#define NUM_CPU_FREQ 3 /* MTK_ADSP_CLK_BUS_UPDATE */ #define MTK_ADSP_CLK_BUS_UPDATE_BIT BIT(31) @@ -46,10 +47,8 @@ struct sof; /* 0 is the lowest request */ enum ADSP_HW_DSP_CLK { ADSP_CLK_26M = 0, - ADSP_CLK_PLL_800M_D_8, - ADSP_CLK_PLL_800M_D_4, - ADSP_CLK_PLL_800M_D_2, - ADSP_CLK_PLL_800M, + ADSP_CLK_PLL_300M, + ADSP_CLK_PLL_400M, }; void platform_clock_init(struct sof *sof); diff --git a/src/platform/mt8186/lib/clk.c b/src/platform/mt8186/lib/clk.c index 7d21da9a0a1e..6eddbdea52f8 100644 --- a/src/platform/mt8186/lib/clk.c +++ b/src/platform/mt8186/lib/clk.c @@ -26,10 +26,8 @@ DECLARE_TR_CTX(clkdrv_tr, SOF_UUID(clkdrv_uuid), LOG_LEVEL_INFO); /* default voltage is 0.8V */ const struct freq_table platform_cpu_freq[] = { { 26000000, 26000}, - { 100000000, 26000}, - { 200000000, 26000}, + { 300000000, 26000}, { 400000000, 26000}, - { 800000000, 26000}, }; STATIC_ASSERT(ARRAY_SIZE(platform_cpu_freq) == NUM_CPU_FREQ, @@ -62,20 +60,17 @@ static int clock_platform_set_dsp_freq(int clock, int freq_idx) case ADSP_CLK_26M: set_mux_adsp_sel(MTK_CLK_ADSP_26M); break; - case ADSP_CLK_PLL_800M_D_8: - set_mux_adsp_sel(MTK_CLK_ADSP_DSPPLL_8); - break; - case ADSP_CLK_PLL_800M_D_4: - set_mux_adsp_sel(MTK_CLK_ADSP_DSPPLL_4); - break; - case ADSP_CLK_PLL_800M_D_2: - set_mux_adsp_sel(MTK_CLK_ADSP_DSPPLL_2); + case ADSP_CLK_PLL_300M: + clock_platform_set_dsp_freq(clock, ADSP_CLK_26M); + set_mux_adsp_sel(MTK_CLK_ADSP_DSPPLL); break; - case ADSP_CLK_PLL_800M: + case ADSP_CLK_PLL_400M: + clock_platform_set_dsp_freq(clock, ADSP_CLK_26M); set_mux_adsp_sel(MTK_CLK_ADSP_DSPPLL); break; default: - set_mux_adsp_sel(MTK_CLK_ADSP_26M); + clock_platform_set_dsp_freq(clock, ADSP_CLK_26M); + tr_err(&clkdrv_tr, "unknown freq index %x\n", freq_idx); break; } From 81d71765ef34af0127b5c003e92e8fcd60fd7de4 Mon Sep 17 00:00:00 2001 From: Tinghan Shen Date: Wed, 2 Nov 2022 20:11:44 +0800 Subject: [PATCH 06/14] platform: mt8186: Init ADSP PLL and ADSP bus clock Initialize the mt8186 ADSP PLL before change ADSP core to high frequency because the clock source of high frequency is coming from ADSP PLL. Because the ADSP bus source switches to the EMI clock, the ADSP local bus clock should switch to 26M. Signed-off-by: Tinghan Shen --- .../mt8186/include/platform/lib/clk.h | 23 +++++++- src/platform/mt8186/lib/clk.c | 58 ++++++++++++++++++- 2 files changed, 75 insertions(+), 6 deletions(-) diff --git a/src/platform/mt8186/include/platform/lib/clk.h b/src/platform/mt8186/include/platform/lib/clk.h index a0725c929833..c1cd3756a62c 100644 --- a/src/platform/mt8186/include/platform/lib/clk.h +++ b/src/platform/mt8186/include/platform/lib/clk.h @@ -30,10 +30,8 @@ struct sof; #define MTK_ADSP_CLK_BUS_SRC_EMI 0 #define MTK_ADSP_CLK_BUS_SRC_LOCAL 1 -/* MTK_CLK_CFG_UPDATE */ -#define MTK_CLK_CFG_ADSP_UPDATE BIT(16) - /* MTK_CLK_CFG_11 */ +#define MTK_CLK_CFG_ADSP_UPDATE BIT(16) #define MTK_CLK_ADSP_OFFSET 24 #define MTK_CLK_ADSP_MASK 0x7 #define MTK_CLK_ADSP_26M 0 @@ -43,6 +41,25 @@ struct sof; #define MTK_CLK_ADSP_DSPPLL_4 4 #define MTK_CLK_ADSP_DSPPLL_8 5 +/* MTK_CLK_CFG_15 */ +#define MTK_CLK_CFG_ADSP_BUS_UPDATE BIT(31) +#define MTK_CLK_ADSP_BUS_OFFSET 17 +#define MTK_CLK_ADSP_BUS_MASK 0x7 +#define MTK_CLK_ADSP_BUS_26M 0 +#define MTK_CLK_ADSP_BUS_ULPOSC_D_2 1 +#define MTK_CLK_ADSP_BUS_MAINPPLL_D_5 2 +#define MTK_CLK_ADSP_BUS_MAINPPLL_D_2_D_2 3 +#define MTK_CLK_ADSP_BUS_MAINPPLL_D_3 4 +#define MTK_CLK_ADSP_BUS_RESERVED 5 +#define MTK_CLK_ADSP_BUS_UNIVPLL_D_3 6 + +#define MTK_PLL_BASE_EN BIT(0) +#define MTK_PLL_PWR_ON BIT(0) +#define MTK_PLL_ISO_EN BIT(1) + +#define MTK_PLL_DIV_RATIO_300M 0x831713B2 +#define MTK_PLL_DIV_RATIO_400M 0x831EC4ED + /* List resource from low to high request */ /* 0 is the lowest request */ enum ADSP_HW_DSP_CLK { diff --git a/src/platform/mt8186/lib/clk.c b/src/platform/mt8186/lib/clk.c index 6eddbdea52f8..84f0092cc4df 100644 --- a/src/platform/mt8186/lib/clk.c +++ b/src/platform/mt8186/lib/clk.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,41 @@ STATIC_ASSERT(ARRAY_SIZE(platform_cpu_freq) == NUM_CPU_FREQ, static SHARED_DATA struct clock_info platform_clocks_info[NUM_CLOCKS]; +static void clk_dsppll_enable(uint32_t value) +{ + tr_dbg(&clkdrv_tr, "clk_dsppll_enable: %d\n", value); + + switch (value) { + case ADSP_CLK_PLL_300M: + io_reg_write(MTK_ADSPPLL_CON1, MTK_PLL_DIV_RATIO_300M); + break; + case ADSP_CLK_PLL_400M: + io_reg_write(MTK_ADSPPLL_CON1, MTK_PLL_DIV_RATIO_400M); + break; + default: + tr_err(&clkdrv_tr, "invalid dsppll: %d\n", value); + return; + } + + io_reg_update_bits(MTK_ADSPPLL_CON3, MTK_PLL_PWR_ON, MTK_PLL_PWR_ON); + wait_delay_us(20); + io_reg_update_bits(MTK_ADSPPLL_CON3, MTK_PLL_ISO_EN, 0); + wait_delay_us(1); + io_reg_update_bits(MTK_ADSPPLL_CON0, MTK_PLL_BASE_EN, MTK_PLL_BASE_EN); + wait_delay_us(20); +} + +static void clk_dsppll_disable(void) +{ + tr_dbg(&clkdrv_tr, "clk_dsppll_disable\n"); + + io_reg_update_bits(MTK_ADSPPLL_CON0, MTK_PLL_BASE_EN, 0); + wait_delay_us(1); + io_reg_update_bits(MTK_ADSPPLL_CON3, MTK_PLL_ISO_EN, MTK_PLL_ISO_EN); + wait_delay_us(1); + io_reg_update_bits(MTK_ADSPPLL_CON3, MTK_PLL_PWR_ON, 0); +} + static void set_mux_adsp_sel(uint32_t value) { io_reg_write(MTK_CLK_CFG_11_CLR, MTK_CLK_ADSP_MASK << MTK_CLK_ADSP_OFFSET); @@ -54,19 +90,38 @@ static void set_mux_adsp_bus_src_sel(uint32_t value) value, io_reg_read(MTK_ADSP_BUS_SRC)); } +static void set_mux_adsp_bus_sel(uint32_t value) +{ + io_reg_write(MTK_CLK_CFG_15_CLR, MTK_CLK_ADSP_BUS_MASK << MTK_CLK_ADSP_BUS_OFFSET); + io_reg_write(MTK_CLK_CFG_15_SET, value << MTK_CLK_ADSP_BUS_OFFSET); + io_reg_write(MTK_CLK_CFG_UPDATE, MTK_CLK_CFG_ADSP_BUS_UPDATE); + + tr_dbg(&clkdrv_tr, "adsp_bus_clk_mux=%x, CLK_CFG_15=0x%08x\n", + value, io_reg_read(MTK_CLK_CFG_15)); +} + static int clock_platform_set_dsp_freq(int clock, int freq_idx) { switch (freq_idx) { case ADSP_CLK_26M: + set_mux_adsp_bus_sel(MTK_CLK_ADSP_BUS_26M); + set_mux_adsp_bus_src_sel(MTK_ADSP_CLK_BUS_SRC_LOCAL); set_mux_adsp_sel(MTK_CLK_ADSP_26M); + clk_dsppll_disable(); break; case ADSP_CLK_PLL_300M: clock_platform_set_dsp_freq(clock, ADSP_CLK_26M); + clk_dsppll_enable(ADSP_CLK_PLL_300M); set_mux_adsp_sel(MTK_CLK_ADSP_DSPPLL); + set_mux_adsp_bus_src_sel(MTK_ADSP_CLK_BUS_SRC_EMI); + set_mux_adsp_bus_sel(MTK_CLK_ADSP_BUS_26M); break; case ADSP_CLK_PLL_400M: clock_platform_set_dsp_freq(clock, ADSP_CLK_26M); + clk_dsppll_enable(ADSP_CLK_PLL_400M); set_mux_adsp_sel(MTK_CLK_ADSP_DSPPLL); + set_mux_adsp_bus_src_sel(MTK_ADSP_CLK_BUS_SRC_EMI); + set_mux_adsp_bus_sel(MTK_CLK_ADSP_BUS_26M); break; default: clock_platform_set_dsp_freq(clock, ADSP_CLK_26M); @@ -96,7 +151,4 @@ void platform_clock_init(struct sof *sof) k_spinlock_init(&sof->clocks[i].lock); } - - /* DSP bus clock */ - set_mux_adsp_bus_src_sel(MTK_ADSP_CLK_BUS_SRC_EMI); } From 77e6f344edf226b8ac6f0b6f0e847f59ded38630 Mon Sep 17 00:00:00 2001 From: Tinghan Shen Date: Wed, 26 Oct 2022 10:31:38 +0800 Subject: [PATCH 07/14] platform: mt8186: Revise mt8186 clock flow Add the missing necessary delay after changing DSP bus frequency. Change the core frequency when initialize clock to avoid altering the core frequency in the middle of execution. Signed-off-by: Tinghan Shen --- src/platform/mt8186/lib/clk.c | 3 +++ src/platform/mt8186/platform.c | 6 ------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/platform/mt8186/lib/clk.c b/src/platform/mt8186/lib/clk.c index 84f0092cc4df..5a98246e27d5 100644 --- a/src/platform/mt8186/lib/clk.c +++ b/src/platform/mt8186/lib/clk.c @@ -85,6 +85,7 @@ static void set_mux_adsp_bus_src_sel(uint32_t value) { io_reg_write(MTK_ADSP_BUS_SRC, value); io_reg_write(MTK_ADSP_CLK_BUS_UPDATE, MTK_ADSP_CLK_BUS_UPDATE_BIT); + wait_delay_us(1); tr_dbg(&clkdrv_tr, "adsp_bus_mux=%x, MTK_ADSP_BUS_SRC=0x%08x\n", value, io_reg_read(MTK_ADSP_BUS_SRC)); @@ -151,4 +152,6 @@ void platform_clock_init(struct sof *sof) k_spinlock_init(&sof->clocks[i].lock); } + + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); } diff --git a/src/platform/mt8186/platform.c b/src/platform/mt8186/platform.c index bd9a5f0ff43f..1b7f6a26c5b2 100644 --- a/src/platform/mt8186/platform.c +++ b/src/platform/mt8186/platform.c @@ -153,12 +153,6 @@ int platform_boot_complete(uint32_t boot_message) /* now interrupt host to tell it we are done booting */ trigger_irq_to_host_req(); - /* boot now complete so we can relax the CPU */ - /* For now skip this to gain more processing performance - * for SRC component. - */ - clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); - return 0; } From d3d49dce58d3d316cd7044ee84996e48b1457df4 Mon Sep 17 00:00:00 2001 From: Tinghan Shen Date: Fri, 11 Nov 2022 19:33:53 +0800 Subject: [PATCH 08/14] platform: mt8186: Disable ADSPPLL in S3 stage The ADSPPLL clock is expected to be disabled in S3 stage. Fail to disable it may have premature wakeup in S3 stage. Signed-off-by: Tinghan Shen --- src/platform/mt8186/platform.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/platform/mt8186/platform.c b/src/platform/mt8186/platform.c index 1b7f6a26c5b2..1f067a0d275a 100644 --- a/src/platform/mt8186/platform.c +++ b/src/platform/mt8186/platform.c @@ -208,5 +208,6 @@ int platform_init(struct sof *sof) int platform_context_save(struct sof *sof) { + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_DEFAULT_CPU_HZ); return 0; } From ba6a29d5a8355c78b15fe6d36a07579961ca4367 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 16 Nov 2022 09:15:16 -0600 Subject: [PATCH 09/14] dai: move AMD_HS to end of list to restore backwards-compatibility The addition of AMD_HS breaks Mediatek platforms by using an index previously allocated to Mediatek. This is a backwards-compatibility issue and needs to be fixed. All firmware released by AMD needs to be re-generated and re-distributed. Fixes: 83ee5b49a987 ("dai: support for amd specific hs dai id") Link: https://github.com/thesofproject/sof/issues/6615 Link: https://lore.kernel.org/alsa-devel/36a45c7a-820a-7675-d740-c0e83ae2c417@collabora.com/ Reported-by: AngeloGioacchino Del Regno Signed-off-by: Pierre-Louis Bossart --- src/include/ipc/dai.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/ipc/dai.h b/src/include/ipc/dai.h index b06b66ff35bb..809f554afb83 100644 --- a/src/include/ipc/dai.h +++ b/src/include/ipc/dai.h @@ -89,8 +89,8 @@ enum sof_ipc_dai_type { SOF_DAI_AMD_BT, /**< Amd BT */ SOF_DAI_AMD_SP, /**< Amd SP */ SOF_DAI_AMD_DMIC, /**< Amd DMIC */ + SOF_DAI_MEDIATEK_AFE, /**< Mtk AFE */ SOF_DAI_AMD_HS, /**< Amd HS */ - SOF_DAI_MEDIATEK_AFE /**< Mtk AFE */ }; /* general purpose DAI configuration */ From ab201624a1fd215f528657d2dbc9f4e781990640 Mon Sep 17 00:00:00 2001 From: Pin-chih Lin Date: Fri, 19 Aug 2022 04:14:18 +0800 Subject: [PATCH 10/14] module_adapter: get the actual period_bytes At present module_adapter, period_bytes is calculated assuming the schedule period is 1ms, which could be arbitrary in practice determined by the topology. This commit replaces the calculation code by audio_stream_period_bytes(). In addition, the timing for getting period_bytes is moved to the beginning of prepare() (prior to the module prepare). At that moment it is guaranteed that all parameters in components/buffers are settled through the pipeline. Signed-off-by: Pin-chih Lin (cherry picked from commit b3106c396e540c260bba3b08c218f6598ea74726) --- src/audio/module_adapter/module_adapter.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index b0be4b18f286..a9c7936bbf2d 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -128,6 +128,7 @@ int module_adapter_prepare(struct comp_dev *dev) int ret; struct processing_module *mod = comp_get_drvdata(dev); struct module_data *md = &mod->priv; + struct comp_buffer *sink; struct list_item *blist, *_blist; uint32_t buff_periods; uint32_t buff_size; /* size of local buffer */ @@ -145,6 +146,13 @@ int module_adapter_prepare(struct comp_dev *dev) return PPL_STATUS_PATH_STOP; } + /* Get period_bytes first on prepare(). At this point it is guaranteed that the stream + * parameter from sink buffer is settled, and still prior to all references to period_bytes. + */ + sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); + mod->period_bytes = audio_stream_period_bytes(&sink->stream, dev->frames); + comp_dbg(dev, "module_adapter_prepare(): got period_bytes = %u", mod->period_bytes); + /* Prepare module */ ret = module_prepare(mod); if (ret) { @@ -360,8 +368,6 @@ int module_adapter_params(struct comp_dev *dev, struct sof_ipc_stream_params *pa return ret; } - mod->period_bytes = params->sample_container_bytes * - params->channels * params->rate / 1000; return 0; } From 420aaa262d3a4ed52ae4a354ec09645e8ffd7519 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 31 Aug 2022 09:27:47 -0700 Subject: [PATCH 11/14] module_adapter: Modify reset API Modify the definition of the reset API in the module adapter interface to make sure that it should reset the module state back to MODULE_INITIALIZED and free all memory that was allocated during the prepare() callback. With this change, stopping and restarting streams will always be guaranteed to invoke the module's prepare() callback. Also, fix the passthrough and cadence codec implementation to follow the new definition. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Ranjani Sridharan (cherry picked from commit b9889d52d0e1b6002ee016b55fa0487544fc0593) --- src/audio/module_adapter/module/cadence.c | 7 ------- src/audio/module_adapter/module/generic.c | 7 ++++--- src/audio/module_adapter/module/passthrough.c | 12 +++++------- .../sof/audio/module_adapter/module/generic.h | 4 ++-- 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/audio/module_adapter/module/cadence.c b/src/audio/module_adapter/module/cadence.c index eab5b0d1b15e..3e8df03e6a04 100644 --- a/src/audio/module_adapter/module/cadence.c +++ b/src/audio/module_adapter/module/cadence.c @@ -653,7 +653,6 @@ cadence_codec_process(struct processing_module *mod, static int cadence_codec_reset(struct processing_module *mod) { - struct comp_dev *dev = mod->dev; struct module_data *codec = &mod->priv; struct cadence_codec_data *cd = codec->private; int ret; @@ -675,12 +674,6 @@ static int cadence_codec_reset(struct processing_module *mod) rfree(cd->self); cd->self = NULL; - ret = cadence_codec_prepare(mod); - if (ret) { - comp_err(dev, "cadence_codec_reset() error %x: could not re-prepare codec after reset", - ret); - } - return ret; } diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index add72bd4f8bc..43d1995929ee 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -280,10 +280,11 @@ int module_reset(struct processing_module *mod) md->cfg.size = 0; rfree(md->cfg.data); - /* module resets itself to the initial condition after prepare() - * so let's change its state to reflect that. + /* + * reset the state to allow the module's prepare callback to be invoked again for the + * subsequent triggers */ - md->state = MODULE_IDLE; + md->state = MODULE_INITIALIZED; return 0; } diff --git a/src/audio/module_adapter/module/passthrough.c b/src/audio/module_adapter/module/passthrough.c index 23f310bf068d..cb833207f535 100644 --- a/src/audio/module_adapter/module/passthrough.c +++ b/src/audio/module_adapter/module/passthrough.c @@ -96,22 +96,20 @@ passthrough_codec_process(struct processing_module *mod, static int passthrough_codec_reset(struct processing_module *mod) { + struct module_data *codec = &mod->priv; + comp_info(mod->dev, "passthrough_codec_reset()"); - /* nothing to do */ + rfree(codec->mpd.in_buff); + rfree(codec->mpd.out_buff); return 0; } static int passthrough_codec_free(struct processing_module *mod) { - struct comp_dev *dev = mod->dev; - struct module_data *codec = &mod->priv; - comp_info(dev, "passthrough_codec_free()"); - rfree(codec->mpd.in_buff); - rfree(codec->mpd.out_buff); - + /* Nothing to do */ return 0; } diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h index 2599e6a914b6..e86ce426431e 100644 --- a/src/include/sof/audio/module_adapter/module/generic.h +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -190,12 +190,12 @@ struct module_interface { /** * Module specific reset procedure, called as part of module_adapter component * reset in .reset(). This should reset all parameters to their initial stage - * but leave allocated memory intact. + * and free all memory allocated during prepare(). */ int (*reset)(struct processing_module *mod); /** * Module specific free procedure, called as part of module_adapter component - * free in .free(). This should free all memory allocated by module. + * free in .free(). This should free all memory allocated during module initialization. */ int (*free)(struct processing_module *mod); }; From 0c4e041837673cd5cb8dd08aff761ba1a2a71cb2 Mon Sep 17 00:00:00 2001 From: Balakishorepati Date: Fri, 16 Sep 2022 12:22:41 +0530 Subject: [PATCH 12/14] module_adapter:Fix dangling pointer issue in module reset During module_reset and module_free Calls, pointers are not getting reset to NULL which causes dangling pointer exceptions. Initialize pointers to NULL after deallocating the memory. Signed-off-by: Balakishorepati (cherry picked from commit 53b3bc6a956ae5957966336f88980438f1f85a88) --- src/audio/module_adapter/module/generic.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index 43d1995929ee..42303974e7af 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -279,6 +279,7 @@ int module_reset(struct processing_module *mod) md->cfg.avail = false; md->cfg.size = 0; rfree(md->cfg.data); + md->cfg.data = NULL; /* * reset the state to allow the module's prepare callback to be invoked again for the @@ -318,9 +319,11 @@ int module_free(struct processing_module *mod) md->cfg.avail = false; md->cfg.size = 0; rfree(md->cfg.data); - if (md->runtime_params) + md->cfg.data = NULL; + if (md->runtime_params) { rfree(md->runtime_params); - + md->runtime_params = NULL; + } md->state = MODULE_DISABLED; return ret; From 714c6d4d8917684b4b1c44ebb61bc9483f915cfe Mon Sep 17 00:00:00 2001 From: Chunxu Li Date: Tue, 13 Dec 2022 20:07:42 +0800 Subject: [PATCH 13/14] topology1: mt8186: support 1ms pipeline capture period Default support 1ms period capture pipeline to update host position more precisely. Signed-off-by: Chunxu Li (cherry picked from commit b0ae15a0bc17b1eea2e3e3b13b15b1d98ab1e5e3) --- tools/topology/topology1/sof-mt8186-mt6366.m4 | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/topology/topology1/sof-mt8186-mt6366.m4 b/tools/topology/topology1/sof-mt8186-mt6366.m4 index dfd851adbb66..4e1ce495afa5 100644 --- a/tools/topology/topology1/sof-mt8186-mt6366.m4 +++ b/tools/topology/topology1/sof-mt8186-mt6366.m4 @@ -53,17 +53,17 @@ PIPELINE_PCM_ADD(ifdef(`WAVES', sof/pipe-waves-codec-playback.m4, sof/pipe-passt undefine(`ENDPOINT_NAME') # Low Latency capture pipeline 3 on PCM 27 using max 2 channels of s16le -# Set 2000us deadline with priority 0 on core 0 +# Set 1000us deadline with priority 0 on core 0 PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, 3, 27, 2, s16le, - 2000, 0, 0, + 1000, 0, 0, 48000, 48000, 48000) # Low Latency capture pipeline 4 on PCM 28 using max 2 channels of s16le -# Set 2000us deadline with priority 0 on core 0 +# Set 1000us deadline with priority 0 on core 0 PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, 4, 28, 2, s16le, - 2000, 0, 0, + 1000, 0, 0, 48000, 48000, 48000) # @@ -91,18 +91,18 @@ DAI_ADD(sof/pipe-dai-playback.m4, 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) # capture DAI is AFE using 2 periods -# Buffers use s16le format, with 96 frame per 2000us on core 0 with priority 0 +# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 DAI_ADD(sof/pipe-dai-capture.m4, 3, AFE, 2, AFE_SOF_UL1, PIPELINE_SINK_3, 2, s16le, - 2000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) # capture DAI is AFE using 2 periods -# Buffers use s16le format, with 96 frame per 2000us on core 0 with priority 0 +# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 DAI_ADD(sof/pipe-dai-capture.m4, 4, AFE, 3, AFE_SOF_UL2, PIPELINE_SINK_4, 2, s16le, - 2000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) #SCHEDULE_TIME_DOMAIN_DMA dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) From e4f8104fee9882e249c9aa617d85fe9fc16ba637 Mon Sep 17 00:00:00 2001 From: "barry.jan" Date: Tue, 13 Dec 2022 16:36:09 +0800 Subject: [PATCH 14/14] module_adapter: free memory resource Since module-specific prepare API will be called every time on prepare of module_adapter (stream start trigger), the reset API should free all memory that was allocated during the prepare API. Signed-off-by: barry.jan (cherry picked from commit 6275d18ce2a58e85a5f77bcbdf133fcdc6722216) --- src/audio/module_adapter/module/waves.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/audio/module_adapter/module/waves.c b/src/audio/module_adapter/module/waves.c index 553276dce79c..8002174e1a5f 100644 --- a/src/audio/module_adapter/module/waves.c +++ b/src/audio/module_adapter/module/waves.c @@ -809,6 +809,12 @@ static int waves_codec_reset(struct processing_module *mod) if (ret) comp_err(dev, "waves_codec_reset() failed %d", ret); + if (codec->mpd.in_buff) + module_free_memory(mod, codec->mpd.in_buff); + + if (codec->mpd.out_buff) + module_free_memory(mod, codec->mpd.out_buff); + comp_dbg(dev, "waves_codec_reset() done"); return ret; }