/***************************************************************** >file name : audio_codec_clock.c >create time : Thu 03 Jun 2021 09:36:12 AM CST >History : 2021-11-19 : 增加后台叠加时钟的配置,用于满足一些后台运行的 音频处理 *****************************************************************/ #define LOG_TAG "[CODEC_CLK]" #define LOG_INFO_ENABLE #define LOG_DEBUG_ENABLE #define LOG_DUMP_ENABLE #define LOG_ERROR_ENABLE #define LOG_WARN_ENABLE #include "debug.h" #include "app_config.h" #include "system/includes.h" #include "audio_codec_clock.h" #include "audio_dec_eff.h" #include "asm/dac.h" #include "avctp_user.h" #define AUDIO_CODING_ALL (0xffffffff) #define MAX_CODING_TYPE_NUM 4 //可根据模式的解码格式需求扩展 #define AUDIO_CODEC_BASE_CLK SYS_24M static LIST_HEAD(codec_clock_head); struct audio_codec_clock { u32 coding_type; u32 clk; u8 background; //后台运行的时钟 }; struct audio_codec_clk_context { u8 mode; struct audio_codec_clock params; struct list_head entry; }; #define SYS_60M SYS_64M const struct audio_codec_clock audio_clock[AUDIO_MAX_MODE][MAX_CODING_TYPE_NUM] = { { //A2DP_MODE { AUDIO_CODING_SBC, #if defined(AUDIO_SPK_EQ_CONFIG) && AUDIO_SPK_EQ_CONFIG || defined(TCFG_AUDIO_MDRC_ENABLE) && TCFG_AUDIO_MDRC_ENABLE SYS_76M, #elif (AUDIO_SURROUND_CONFIG && (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)) || (defined(TCFG_AUDIO_DAC_24BIT_MODE) && TCFG_AUDIO_DAC_24BIT_MODE) SYS_76M, #elif (TCFG_BT_MUSIC_EQ_ENABLE && ((EQ_SECTION_MAX >= 10) && AUDIO_OUT_EFFECT_ENABLE)) || (AUDIO_VBASS_CONFIG || AUDIO_SURROUND_CONFIG) SYS_60M, #elif (TCFG_BT_MUSIC_EQ_ENABLE && ((EQ_SECTION_MAX >= 10) || AUDIO_OUT_EFFECT_ENABLE) || TCFG_DRC_ENABLE || TCFG_AUDIO_ANC_ENABLE || TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR) SYS_48M, #else SYS_32M, #endif }, { AUDIO_CODING_AAC, #if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR) SYS_96M, #else #if defined(AUDIO_SPK_EQ_CONFIG) && AUDIO_SPK_EQ_CONFIG || AUDIO_VBASS_CONFIG || defined(TCFG_AUDIO_MDRC_ENABLE) && TCFG_AUDIO_MDRC_ENABLE SYS_76M, #elif (AUDIO_SURROUND_CONFIG && (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR))|| (defined(TCFG_AUDIO_DAC_24BIT_MODE) && TCFG_AUDIO_DAC_24BIT_MODE) SYS_64M, #elif (TCFG_BT_MUSIC_EQ_ENABLE && ((EQ_SECTION_MAX >= 10) || AUDIO_OUT_EFFECT_ENABLE)) || AUDIO_SURROUND_CONFIG || TCFG_DRC_ENABLE #if (TCFG_AUDIO_ANC_ENABLE) SYS_64M, #else SYS_60M, #endif /*TCFG_AUDIO_ANC_ENABLE*/ #else SYS_48M, #endif #endif }, { AUDIO_CODING_LDAC, #if (AUDIO_SURROUND_CONFIG && (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR))|| (defined(TCFG_AUDIO_DAC_24BIT_MODE) && TCFG_AUDIO_DAC_24BIT_MODE) SYS_128M, #elif (TCFG_BT_MUSIC_EQ_ENABLE && ((EQ_SECTION_MAX >= 10) || AUDIO_OUT_EFFECT_ENABLE)) | (AUDIO_VBASS_CONFIG || AUDIO_SURROUND_CONFIG) || TCFG_DRC_ENABLE #if (TCFG_AUDIO_ANC_ENABLE) SYS_128M, #else SYS_128M, #endif /*TCFG_AUDIO_ANC_ENABLE*/ #else #if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR) SYS_128M, #else SYS_128M, #endif /*TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR*/ #endif } }, { //ESCO MODE { AUDIO_CODING_MSBC, #if TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR #if (TCFG_AUDIO_CVP_NS_MODE == CVP_ANS_MODE) SYS_76M, #else /*TCFG_AUDIO_CVP_NS_MODE == CVP_DNS_MODE*/ SYS_96M, #endif /*TCFG_AUDIO_CVP_NS_MODE == CVP_ANS_MODE*/ #else /* SYS_48M, */ 0, #endif }, {AUDIO_CODING_CVSD, 0}, }, { //TONE MODE {AUDIO_CODING_AAC | AUDIO_CODING_WAV | AUDIO_CODING_WTGV2 | AUDIO_CODING_MP3, SYS_64M}, {AUDIO_CODING_ALL, 0}, }, { //FILE MODE {AUDIO_CODING_ALL, 120 * 1000000L}, }, { //PC MODE {AUDIO_CODING_ALL, 96 * 1000000L}, }, { //USB MIC MODE #if (TCFG_CVP_DEVELOP_ENABLE == CVP_CFG_AIS_3MIC) {AUDIO_CODING_ALL, 128 * 1000000L}, #else {AUDIO_CODING_ALL, 96 * 1000000L}, #endif }, { //VAD MODE {AUDIO_CODING_ALL, SYS_32M, 1}, }, { //SPATIAL EFFECT MODE #if ((defined TCFG_AUDIO_EFFECT_TASK_EBABLE) && TCFG_AUDIO_EFFECT_TASK_EBABLE) {AUDIO_CODING_ALL, SYS_32M, 1}, #else {AUDIO_CODING_ALL, SYS_120M, 1}, #endif /*TCFG_AUDIO_EFFECT_TASK_EBABLE*/ }, { // SPEAK_TO_CHAT_MODE {AUDIO_CODING_ALL, 48 * 1000000L} }, { // ANC_EAR_ADAPTIVE_MODE {AUDIO_CODING_ALL, SYS_160M, 0} }, { // ANC_DUT_SZ_FFT_MODE {AUDIO_CODING_ALL, SYS_120M, 0} }, //TODO }; static u32 audio_codec_background_clock(void) { struct audio_codec_clk_context *ctx; u32 clk = 0; if (list_empty(&codec_clock_head)) { return 0; } list_for_each_entry(ctx, &codec_clock_head, entry) { if (ctx->params.background) { clk += ctx->params.clk; } } return clk; } static void audio_codec_background_clock_add(u32 clk) { struct audio_codec_clk_context *ctx; if (list_empty(&codec_clock_head)) { return; } list_for_each_entry(ctx, &codec_clock_head, entry) { ctx->params.clk += clk; } } static void audio_codec_background_clock_del(u32 clk) { struct audio_codec_clk_context *ctx; if (list_empty(&codec_clock_head)) { return; } list_for_each_entry(ctx, &codec_clock_head, entry) { ctx->params.clk -= clk; } } static bool audio_codec_mode_exist(u8 mode) { struct audio_codec_clk_context *ctx; if (list_empty(&codec_clock_head)) { return false; } list_for_each_entry(ctx, &codec_clock_head, entry) { if (ctx->mode == mode) { return true; } } return false; } int audio_codec_clock_set(u8 mode, u32 coding_type, u8 preemption) { u32 new_clk = 0; u32 background_clk = 0; if (mode >= AUDIO_MAX_MODE) { log_error("Not support this mode : %d", mode); return -EINVAL; } if (audio_codec_mode_exist(mode)) { return 0; } const struct audio_codec_clock *params = audio_clock[mode]; int i = 0; for (i = 0; i < MAX_CODING_TYPE_NUM; i++) { if (params[i].coding_type & coding_type) { goto match_clock; } } log_error("Not found right coding type : %d", coding_type); return -EINVAL; match_clock: if (params[i].background) { /*如果是后台运行的,则需要处理最终时钟为前台+后台时钟总和*/ audio_codec_background_clock_add(params[i].clk); new_clk = params[i].clk; struct audio_codec_clk_context *first = list_empty(&codec_clock_head) ? NULL : list_first_entry(&codec_clock_head, struct audio_codec_clk_context, entry); if (first) { new_clk = first->params.clk; } else { /*后台运行时钟比较接近负载极限,容易导致其他跑不过来,因此多加12M*/ new_clk += 12 * 1000000L; } goto clock_set; } background_clk = audio_codec_background_clock(); new_clk = (params[i].clk ? params[i].clk : clk_get("sys")) + background_clk; if (!preemption) { struct audio_codec_clk_context *ctx1; if (!list_empty(&codec_clock_head)) { ctx1 = list_first_entry(&codec_clock_head, struct audio_codec_clk_context, entry); if (ctx1 && !ctx1->params.background) { if (new_clk <= ctx1->params.clk) { /*叠加解码的时钟不可小于在播放的音频时钟*/ new_clk = ctx1->params.clk + 12 * 1000000; } else { new_clk += 32 * 1000000; } } } } clock_set: struct audio_codec_clk_context *ctx = (struct audio_codec_clk_context *)zalloc(sizeof(struct audio_codec_clk_context)); ctx->mode = mode; ctx->params.coding_type = coding_type; ctx->params.background = params[i].background; ctx->params.clk = ctx->params.background ? params[i].clk : new_clk; clk_set("sys", new_clk); if (ctx->params.background) { list_add_tail(&ctx->entry, &codec_clock_head); } else { list_add(&ctx->entry, &codec_clock_head); } return 0; } void audio_codec_clock_del(u8 mode) { struct audio_codec_clk_context *ctx; int next_clk = 0; u32 remove_clk = 0; list_for_each_entry(ctx, &codec_clock_head, entry) { if (ctx->mode == mode) { goto clock_del; } } return; clock_del: list_del(&ctx->entry); if (ctx->params.background) { audio_codec_background_clock_del(ctx->params.clk); remove_clk = ctx->params.clk; } free(ctx); if (!list_empty(&codec_clock_head)) { ctx = list_first_entry(&codec_clock_head, struct audio_codec_clk_context, entry); if (ctx) { next_clk = ctx->params.clk; } } else { u32 current_clk = clk_get("sys"); #if (TCFG_BD_NUM == 2)&&(TCFG_BT_SUPPORT_AAC==1) if ((mode == AUDIO_A2DP_MODE) && (get_total_connect_dev() > 1)) { next_clk = current_clk - remove_clk; } else { if (remove_clk) { next_clk = current_clk - remove_clk; } else { next_clk = AUDIO_CODEC_BASE_CLK; //不是后台时钟,设置音频基础时钟 } } #else if (remove_clk) { next_clk = current_clk - remove_clk; } else { next_clk = AUDIO_CODEC_BASE_CLK; //不是后台时钟,设置音频基础时钟 } #endif } if (!next_clk || next_clk < AUDIO_CODEC_BASE_CLK) { next_clk = list_empty(&codec_clock_head) ? clk_get("sys") : AUDIO_CODEC_BASE_CLK; } clk_set("sys", next_clk); } void audio_codec_clock_check(void) { struct audio_codec_clk_context *ctx; if (!list_empty(&codec_clock_head)) { ctx = list_first_entry(&codec_clock_head, struct audio_codec_clk_context, entry); if (!ctx) { return; } u32 current_clk = clk_get("sys"); u32 expect_clk = ctx->params.background ? (ctx->params.clk + 12 * 1000000L) : ctx->params.clk; if ((current_clk < 192 * 1000000L) && current_clk < expect_clk) { log_error("Audio codec clock error : %dM, %dM.", current_clk / 1000000, expect_clk / 1000000); clk_set("sys", expect_clk); } } }