#ifdef SUPPORT_MS_EXTENSIONS #pragma bss_seg(".adc_file.data.bss") #pragma data_seg(".adc_file.data") #pragma const_seg(".adc_file.text.const") #pragma code_seg(".adc_file.text") #endif #include "source_node.h" #include "asm/audio_adc.h" #include "audio_config.h" #include "adc_file.h" #include "gpio_config.h" #include "effects/effects_adj.h" #include "audio_cvp.h" #include "asm/audio_common.h" #if TCFG_AUDIO_ANC_ENABLE #include "audio_anc.h" #endif #if TCFG_AUDIO_DUT_ENABLE #include "audio_dut_control.h" #endif #if defined(TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN) && TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN #include "icsd_adt_app.h" #endif #if TCFG_AUDIO_DUT_ENABLE #include "audio_dut_control.h" #endif #if 1 #define adc_file_log printf #else #define adc_file_log(...) #endif/*log_en*/ extern struct audio_adc_hdl adc_hdl; extern const struct adc_platform_cfg adc_platform_cfg_table[AUDIO_ADC_MAX_NUM]; #define ESCO_ADC_BUF_NUM 2 //mic_adc采样buf个数 struct adc_file_common ; struct adc_file_hdl { char name[16]; void *source_node; struct stream_node *node; enum stream_scene scene; struct adc_mic_ch mic_ch; struct audio_adc_output_hdl adc_output; s16 *adc_buf; struct adc_file_common *adc_f; u16 sample_rate; u16 irq_points; u8 adc_seq; u8 Qval; u8 start; u8 dump_cnt; u8 ch_num; }; struct adc_file_common { u8 read_flag; //读取配置的标志 struct adc_file_hdl *hdl; //当前ADC节点的句柄 struct adc_file_cfg cfg; //ADC的参数信息 struct adc_platform_cfg platform_cfg[AUDIO_ADC_MAX_NUM]; }; struct adc_file_global { u8 fixed_ch_num; s16 *fixed_buf; //固定的ADCbuffer struct adc_file_cfg cfg; //ESCO ADC的参数信息 }; static struct adc_file_common esco_adc_f = {0}; static struct adc_file_global esco_adc_file_g = {0}; /*根据mic通道值获取使用的第几个mic*/ u8 audio_get_mic_index(u8 mic_ch) { u8 i = 0; for (i = 0; i < AUDIO_ADC_MAX_NUM; i++) { if (mic_ch & 0x1) { return i; } mic_ch >>= 1; } return 0; } /*根据mic通道值获取使用了多少个mic*/ u8 audio_get_mic_num(u32 mic_ch) { u8 mic_num = 0; for (int i = 0; i < AUDIO_ADC_MAX_NUM; i++) { if (mic_ch & BIT(i)) { mic_num++; } } return mic_num; } u8 audio_anc_adt_mic_ch_num_get() { #if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN return adc_hdl.anc_adt_mic_ch_num; #else return 0; #endif/*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/ } struct adc_file_cfg *audio_adc_file_get_cfg(void) { return &esco_adc_f.cfg; } struct adc_platform_cfg *audio_adc_platform_get_cfg(void) { return &esco_adc_f.platform_cfg[0]; } u8 audio_adc_file_get_esco_mic_num(void) { u8 mic_en = 0; for (int i = 0; i < AUDIO_ADC_MAX_NUM; i++) { if (esco_adc_f.cfg.mic_en_map & BIT(i)) { mic_en++; } } return mic_en; } u8 audio_adc_file_get_mic_en_map(void) { return esco_adc_f.cfg.mic_en_map; } void audio_adc_file_set_mic_en_map(u8 mic_en_map) { esco_adc_f.cfg.mic_en_map = mic_en_map; } void audio_adc_file_global_cfg_init(void) { memcpy(&esco_adc_file_g.cfg, &esco_adc_f.cfg, sizeof(struct adc_file_cfg)); #if TCFG_AUDIO_ANC_ENABLE && (defined CONFIG_CPU_BR28) if (!esco_adc_file_g.fixed_buf) { //JL701 ANC开启ADC必须固定buffer /中断点数 if (esco_adc_file_g.cfg.mic_en_map & AUDIO_ADC_MIC_0) { esco_adc_file_g.fixed_ch_num++; } if (esco_adc_file_g.cfg.mic_en_map & AUDIO_ADC_MIC_1) { esco_adc_file_g.fixed_ch_num++; } if (esco_adc_file_g.cfg.mic_en_map & AUDIO_ADC_MIC_2) { esco_adc_file_g.fixed_ch_num++; } if (esco_adc_file_g.cfg.mic_en_map & AUDIO_ADC_MIC_3) { esco_adc_file_g.fixed_ch_num++; } if (!adc_hdl.hw_buf) { u8 adc_num = adc_hdl.max_adc_num; #if defined(TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN) && TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN adc_num = adc_hdl.max_adc_num > get_icsd_adt_mic_num() ? adc_hdl.max_adc_num : get_icsd_adt_mic_num(); #endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/ esco_adc_file_g.fixed_buf = malloc(ESCO_ADC_BUF_NUM * 256 * ((adc_hdl.bit_width == ADC_BIT_WIDTH_16) ? 2 : 4) * adc_num); } } #endif/*TCFG_AUDIO_ANC_ENABLE && CONFIG_CPU_BR28*/ } void audio_adc_fixed_digital_set_buffs(void) { audio_adc_mic_set_buffs(NULL, esco_adc_file_g.fixed_buf, 256 * 2, ESCO_ADC_BUF_NUM); audio_adc_set_buf_fix(1, &adc_hdl); } void audio_all_adc_file_init(void) { #if 0 int subid = 0; char node_name[16]; struct adc_file_cfg adc_cfg; for (subid = 0; subid < 0xff; subid++) { //遍历所有adc节点来获取累计开了多少路mic if (jlstream_read_node_data_new(NODE_UUID_ADC, subid, &adc_cfg, node_name)) { adc_file_log("read adc cfg :%d,%x,%s,%x\n", __LINE__, subid, node_name, adc_cfg.mic_en_map); for (int i = 0; i < AUDIO_ADC_MAX_NUM; i++) { if (adc_cfg.mic_en_map & BIT(i)) { audio_adc_add_ch(&adc_hdl, i); } } } } #else for (int i = 0; i < AUDIO_ADC_MAX_NUM; i++) { //默认按最大通道开ADC 数字 audio_adc_add_ch(&adc_hdl, i); } #endif } void audio_adc_file_init(void) //通话的ADC节点配置 { u32 i; if (!esco_adc_f.read_flag) { esco_adc_f.hdl = NULL; /* *解析配置文件内效果配置 * */ int len; char mode_index = 0; char cfg_index = 0;//目标配置项序号 struct cfg_info info = {0}; if (!jlstream_read_form_node_info_base(mode_index, "esco_adc", cfg_index, &info)) { len = jlstream_read_form_cfg_data(&info, &esco_adc_f.cfg); } else { len = 0; } if (len != sizeof(struct adc_file_cfg)) { printf("esco_adc_file read cfg data err !!!\n"); /* while (1); */ } memcpy(&esco_adc_f.platform_cfg, adc_platform_cfg_table, sizeof(struct adc_platform_cfg) * AUDIO_ADC_MAX_NUM); adc_file_log(" %s len %d, sizeof(cfg) %d\n", __func__, len, (int)sizeof(struct adc_file_cfg)); #if 0 adc_file_log(" esco_adc_f.cfg.mic_en_map = %x\n", esco_adc_f.cfg.mic_en_map); for (i = 0; i < AUDIO_ADC_MAX_NUM; i++) { adc_file_log(" esco_adc_f.cfg.param[%d].mic_gain = %d\n", i, esco_adc_f.cfg.param[i].mic_gain); adc_file_log(" esco_adc_f.cfg.param[%d].mic_pre_gain = %d\n", i, esco_adc_f.cfg.param[i].mic_pre_gain); } #endif esco_adc_f.read_flag = 1; for (i = 0; i < AUDIO_ADC_MAX_NUM; i++) { if (esco_adc_f.cfg.mic_en_map & BIT(i)) { audio_adc_add_ch(&adc_hdl, i); } } } /* audio_all_adc_file_init(); */ audio_adc_file_global_cfg_init(); } void audio_adc_cfg_init(struct adc_file_common *adc_f) //通话外其他ADC节点读配置 { if (!adc_f->read_flag) { /* adc_f->hdl = NULL; */ /* *解析配置文件内效果配置 * */ int len = sizeof(adc_f->cfg); char mode_index = 0; char cfg_index = 0;//目标配置项序号 struct cfg_info info = {0}; if (!jlstream_read_form_node_info_base(mode_index, adc_f->hdl->name, cfg_index, &info)) { jlstream_read_form_cfg_data(&info, &adc_f->cfg); } else { len = 0; } if (len != sizeof(struct adc_file_cfg)) { printf("adc_file read cfg data err !!!\n"); } memcpy(&adc_f->platform_cfg, adc_platform_cfg_table, sizeof(struct adc_platform_cfg) * AUDIO_ADC_MAX_NUM); adc_file_log(" %s len %d, sizeof(cfg) %d\n", __func__, len, (int)sizeof(struct adc_file_cfg)); u32 i; #if 0 adc_file_log(" adc_f->cfg.mic_en_map = %x\n", adc_f->cfg.mic_en_map); for (i = 0; i < AUDIO_ADC_MAX_NUM; i++) { adc_file_log(" adc_f->cfg.param[%d].mic_gain = %d\n", i, adc_f->cfg.param[i].mic_gain); adc_file_log(" adc_f->cfg.param[%d].mic_pre_gain = %d\n", i, adc_f->cfg.param[i].mic_pre_gain); } #endif adc_f->hdl->ch_num = 0; adc_f->read_flag = 1; for (i = 0; i < AUDIO_ADC_MAX_NUM; i++) { if (adc_f->cfg.mic_en_map & BIT(i)) { audio_adc_add_ch(&adc_hdl, i); adc_f->hdl->ch_num++; } } } } void audio_adc_file_set_gain(u8 mic_index, u8 mic_gain) { if (mic_index > AUDIO_ADC_MAX_NUM) { adc_file_log("mic_index[%d] err !!!", mic_index); } esco_adc_f.cfg.param[mic_index].mic_gain = mic_gain; if (esco_adc_f.hdl) { audio_adc_mic_set_gain(&esco_adc_f.hdl->mic_ch, BIT(mic_index), mic_gain); } } u8 audio_adc_file_get_gain(u8 mic_index) { audio_adc_file_init(); //如果获取的时候没有初始化,则跑初始化流程 return esco_adc_f.cfg.param[mic_index].mic_gain; } u8 audio_adc_file_get_mic_mode(u8 mic_index) { audio_adc_file_init(); //如果获取的时候没有初始化,则跑初始化流程 return esco_adc_f.platform_cfg[mic_index].mic_mode; } /** * @brief MIC 的中断回调函数 * * @param _hdl MIC 节点的操作句柄 * @param data MIC 中断采集到的数据地址 * @param len MIC 单个通道中断采集到的数据字节长度 */ static void adc_mic_output_handler(void *_hdl, s16 *data, int len) { struct adc_file_hdl *hdl = (struct adc_file_hdl *)_hdl; struct stream_frame *frame; /* printf(">> %d %d\n", data[0], data[1]); */ if (hdl->dump_cnt < 10) { hdl->dump_cnt++; return; } #if defined(TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN) && TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN u8 esco_mic_num = audio_adc_file_get_esco_mic_num(); u8 adt_mic_num = audio_anc_adt_mic_ch_num_get(); /* 1mic通话,2mic/3mic免摘 * 2mic通话,3mic免摘*/ if (esco_mic_num < adt_mic_num) { for (int i = 0; i < len / 2; i++) { memcpy(&data[esco_mic_num * i], &data[adt_mic_num * i], esco_mic_num * sizeof(short)); } } #endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/ frame = source_plug_get_output_frame(hdl->source_node, (len * hdl->ch_num)); if (hdl->scene == STREAM_SCENE_ESCO || hdl->scene == STREAM_SCENE_PC_MIC || (hdl->scene == STREAM_SCENE_AI_VOICE)) { //cvp读dac 参考数据 #if TCFG_AUDIO_DUT_ENABLE //打开产测功能,只有算法模式,才会读dac参考数据,避免 data full if (cvp_dut_mode_get() == CVP_DUT_MODE_ALGORITHM) { audio_cvp_phase_align(); } #else audio_cvp_phase_align(); #endif } if (frame) { #ifdef TCFG_AUDIO_ADC_ENABLE_ALL_DIGITAL_CH //ADC DIGITAL 按最大通道数开启时使用 if (hdl->ch_num != adc_hdl.max_adc_num) { #else if (0) { #endif /* printf("l:%d,%d,%d\n",hdl->adc_seq,hdl->ch_num,adc_hdl.max_adc_num); */ if (adc_hdl.bit_width != ADC_BIT_WIDTH_16) { s32 *s32_src = (s32 *)data; s32 *s32_dst = (s32 *)frame->data; for (int i = 0; i < len / 4; i++) { for (int j = 0; j < hdl->ch_num; j++) { s32_dst[hdl->ch_num * i + j] = s32_src[adc_hdl.max_adc_num * i + hdl->adc_seq + j]; } } } else { s16 *s16_src = data; s16 *s16_dst = (s16 *)frame->data; for (int i = 0; i < len / 2; i++) { for (int j = 0; j < hdl->ch_num; j++) { s16_dst[hdl->ch_num * i + j] = s16_src[adc_hdl.max_adc_num * i + hdl->adc_seq + j]; } } } } else { memcpy(frame->data, data, (len * hdl->ch_num)); } len *= hdl->ch_num; if (audio_common_mic_mute_en_get()) { //mute ADC memset((u8 *)frame->data, 0x0, len); } frame->len = len; frame->flags = FRAME_FLAG_TIMESTAMP_ENABLE | FRAME_FLAG_PERIOD_SAMPLE | FRAME_FLAG_UPDATE_TIMESTAMP; frame->timestamp = audio_jiffies_usec() * TIMESTAMP_US_DENOMINATOR; source_plug_put_output_frame(hdl->source_node, frame); } } static void *adc_init(void *source_node, struct stream_node *node) { struct adc_file_hdl *hdl = zalloc(sizeof(*hdl)); hdl->source_node = source_node; hdl->node = node; node->type |= NODE_TYPE_IRQ; #if ((defined TCFG_CALL_KWS_SWITCH_ENABLE) && TCFG_CALL_KWS_SWITCH_ENABLE) extern void smart_voice_mcu_mic_suspend(); smart_voice_mcu_mic_suspend(); #endif return hdl; } static void adc_ioc_get_fmt(struct adc_file_hdl *hdl, struct stream_fmt *fmt) { fmt->coding_type = AUDIO_CODING_PCM; switch (hdl->scene) { case STREAM_SCENE_ESCO: #if SUPPORT_CHAGE_AUDIO_CLK fmt->sample_rate = audio_common_clock_get() ? 17778 : 16000; #else fmt->sample_rate = 16000; #endif fmt->channel_mode = AUDIO_CH_MIX; break; #if TCFG_USB_SLAVE_AUDIO_MIC_ENABLE case STREAM_SCENE_PC_MIC: fmt->sample_rate = pc_mic_get_fmt_sample_rate(); fmt->channel_mode = AUDIO_CH_MIX; break; #endif case STREAM_SCENE_HEARING_AID: #ifdef TCFG_AUDIO_HEARING_AID_SAMPLE_RATE fmt->sample_rate = TCFG_AUDIO_HEARING_AID_SAMPLE_RATE; #else fmt->sample_rate = 44100; #endif fmt->channel_mode = (hdl->ch_num == 2) ? AUDIO_CH_LR : AUDIO_CH_MIX ; break; default: #if SUPPORT_CHAGE_AUDIO_CLK fmt->sample_rate = audio_common_clock_get() ? 49000 : 44100; #else fmt->sample_rate = 44100; #endif fmt->channel_mode = (hdl->ch_num == 2) ? AUDIO_CH_LR : AUDIO_CH_MIX ; break; } hdl->sample_rate = fmt->sample_rate; if (adc_hdl.bit_width == ADC_BIT_WIDTH_24) { fmt->bit_wide = DATA_BIT_WIDE_24BIT; } else { fmt->bit_wide = DATA_BIT_WIDE_16BIT; } } static int adc_ioc_set_fmt(struct adc_file_hdl *hdl, struct stream_fmt *fmt) { hdl->sample_rate = fmt->sample_rate; return 0; } int adc_file_mic_open(struct adc_mic_ch *mic, int ch) //用于打开通话使用的mic { struct mic_open_param mic_param = {0}; int mic_gain; int mic_pre_gain; int ch_index; u32 i = 0; for (i = 0; i < AUDIO_ADC_MAX_NUM; i++) { if (ch & BIT(i)) { ch_index = i; audio_adc_param_fill(&mic_param, &esco_adc_f.platform_cfg[ch_index]); mic_gain = esco_adc_f.cfg.param[ch_index].mic_gain; mic_pre_gain = esco_adc_f.cfg.param[ch_index].mic_pre_gain; if ((mic_param.mic_bias_sel == 0) && (esco_adc_f.platform_cfg[ch_index].power_io != 0)) { u32 gpio = uuid2gpio(esco_adc_f.platform_cfg[ch_index].power_io); gpio_set_mode(IO_PORT_SPILT(gpio), PORT_OUTPUT_HIGH); } audio_adc_mic_open(mic, AUDIO_ADC_MIC(ch_index), &adc_hdl, &mic_param); audio_adc_mic_set_gain(mic, AUDIO_ADC_MIC(ch_index), mic_gain); audio_adc_mic_gain_boost(AUDIO_ADC_MIC(ch_index), mic_pre_gain); } } return 0; } int adc_file_cfg_mic_open(struct adc_mic_ch *mic, int ch, struct adc_file_common *adc_f) //用于打开通话外其他mic { struct mic_open_param mic_param = {0}; int mic_gain; int mic_pre_gain; int ch_index; u32 i = 0; for (i = 0; i < AUDIO_ADC_MAX_NUM; i++) { if (ch & BIT(i)) { ch_index = i; audio_adc_param_fill(&mic_param, &adc_f->platform_cfg[ch_index]); mic_gain = adc_f->cfg.param[ch_index].mic_gain; mic_pre_gain = adc_f->cfg.param[ch_index].mic_pre_gain; if ((mic_param.mic_bias_sel == 0) && (adc_f->platform_cfg[ch_index].power_io != 0)) { u32 gpio = uuid2gpio(adc_f->platform_cfg[ch_index].power_io); gpio_set_mode(IO_PORT_SPILT(gpio), PORT_OUTPUT_HIGH); } audio_adc_mic_open(mic, AUDIO_ADC_MIC(ch_index), &adc_hdl, &mic_param); audio_adc_mic_set_gain(mic, AUDIO_ADC_MIC(ch_index), mic_gain); audio_adc_mic_gain_boost(AUDIO_ADC_MIC(ch_index), mic_pre_gain); } } return 0; } static u8 adc_mic_start = 0; static void adc_open_task(void *_hdl) { struct adc_file_hdl *hdl = (struct adc_file_hdl *)_hdl; /*y_printf("adc_mic_start\n");*/ audio_adc_mic_start(&hdl->mic_ch); adc_mic_start = 1; while (1) { os_time_dly(0xffff); } } static int adc_file_ioc_start(struct adc_file_hdl *hdl) { int ret = 0; /* *获取配置文件内的参数,及名字 * */ if (hdl->scene == STREAM_SCENE_ESCO) { hdl->adc_f = &esco_adc_f; } else if (!hdl->adc_f) { hdl->adc_f = zalloc(sizeof(struct adc_file_common)); } hdl->adc_f->hdl = hdl; if (!jlstream_read_node_data_new(NODE_UUID_ADC, hdl->node->subid, (void *) & (hdl->adc_f->cfg), hdl->name)) { printf("%s, read node data err\n", __FUNCTION__); return -1; } #if TCFG_AUDIO_DUT_ENABLE //产测bypass 模式,MIC的使能位从产测命令读取 if (cvp_dut_mode_get() == CVP_DUT_MODE_BYPASS) { hdl->adc_f->cfg.mic_en_map = cvp_dut_mic_ch_get(); } #endif if (hdl->scene != STREAM_SCENE_ESCO) { audio_adc_cfg_init(hdl->adc_f); } else { //初始化通话通道数 hdl->ch_num = 0; for (int i = 0; i < AUDIO_ADC_MIC_MAX_NUM; i++) { if (hdl->adc_f->cfg.mic_en_map & BIT(i)) { hdl->ch_num++; } } } if (jlstream_read_effects_online_param(NODE_UUID_ADC, hdl->name, &hdl->adc_f->cfg, sizeof(hdl->adc_f->cfg))) { adc_file_log("get adc online param\n"); } if (hdl->start == 0) { hdl->start = 1; hdl->dump_cnt = 0; //不启动ANC动态MIC增益时,由用户自己保证ANC与通话复用的ADC增益一致 #if TCFG_AUDIO_ANC_ENABLE && TCFG_AUDIO_DYNAMIC_ADC_GAIN #if (!TCFG_AUDIO_DUAL_MIC_ENABLE && (TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_1)) || \ (TCFG_AUDIO_DUAL_MIC_ENABLE && (TCFG_AUDIO_DMS_MIC_MANAGE == DMS_MASTER_MIC0)) anc_dynamic_micgain_start(hdl->adc_f->cfg.param[1].mic_gain); #else anc_dynamic_micgain_start(hdl->adc_f->cfg.param[0].mic_gain); #endif/*TCFG_AUDIO_DUAL_MIC_ENABLE*/ #endif/*TCFG_AUDIO_ANC_ENABLE && TCFG_AUDIO_DYNAMIC_ADC_GAIN*/ //br50的LPADC需要根据采样率配置模拟部分的时钟分频,需要先设置采样率才能打开MIC audio_adc_mic_set_sample_rate(&hdl->mic_ch, hdl->sample_rate); adc_file_cfg_mic_open(&hdl->mic_ch, hdl->adc_f->cfg.mic_en_map, (void *)hdl->adc_f); if (esco_adc_file_g.fixed_buf) { hdl->adc_buf = esco_adc_file_g.fixed_buf; audio_adc_set_buf_fix(1, &adc_hdl); } if (!hdl->adc_buf && !adc_hdl.hw_buf) { //避免没有设置ADC的中断点数,以及数据流stop之后重新start申请buffer if (!hdl->irq_points) { hdl->irq_points = 256; } hdl->adc_buf = zalloc(ESCO_ADC_BUF_NUM * hdl->irq_points * ((adc_hdl.bit_width == ADC_BIT_WIDTH_16) ? 2 : 4) * (adc_hdl.max_adc_num)); if (!hdl->adc_buf) { ret = -1; return ret; } } ret = audio_adc_mic_set_buffs(&hdl->mic_ch, hdl->adc_buf, hdl->irq_points * 2, ESCO_ADC_BUF_NUM); if (ret && hdl->adc_buf) { free(hdl->adc_buf); hdl->adc_buf = NULL; } hdl->adc_output.priv = hdl; hdl->adc_output.handler = adc_mic_output_handler; audio_adc_add_output_handler(&adc_hdl, &hdl->adc_output); #ifdef CONFIG_CPU_BR36 /*r_printf("-----create_adc_open_task\n");*/ adc_mic_start = 0; int err = os_task_create(adc_open_task, hdl, 2, 512, 0, "adc_open"); if (err) { adc_mic_start = 1; audio_adc_mic_start(&hdl->mic_ch); } #else audio_adc_mic_start(&hdl->mic_ch); #endif } return ret; } static int adc_file_ioc_stop(struct adc_file_hdl *hdl) { if (hdl->start) { hdl->start = 0; #if TCFG_AUDIO_ANC_ENABLE && TCFG_AUDIO_DYNAMIC_ADC_GAIN anc_dynamic_micgain_stop(); #endif #ifdef CONFIG_CPU_BR36 while (adc_mic_start == 0) { os_time_dly(1); /*puts("--wait\n");*/ } /*r_printf("-----del_adc_open_task\n");*/ os_task_del("adc_open"); #endif audio_adc_mic_close(&hdl->mic_ch); if (!esco_adc_file_g.fixed_buf) { hdl->adc_buf = NULL; //在adc 驱动中释放了这个buffer } audio_adc_del_output_handler(&adc_hdl, &hdl->adc_output); for (u32 i = 0; i < AUDIO_ADC_MAX_NUM; i++) { if (hdl->adc_f->cfg.mic_en_map & BIT(i)) { if ((hdl->adc_f->platform_cfg[i].mic_bias_sel == 0) && (hdl->adc_f->platform_cfg[i].power_io != 0)) { if (!audio_adc_is_active()) { u32 gpio = uuid2gpio(hdl->adc_f->platform_cfg[i].power_io); gpio_set_mode(IO_PORT_SPILT(gpio), PORT_OUTPUT_LOW); } } } } } return 0; } static int adc_file_ioc_update_parm(struct adc_file_hdl *hdl, int parm) { int i; int ret = false; struct adc_file_cfg *cfg = (struct adc_file_cfg *)parm; if (hdl) { for (i = 0; i < AUDIO_ADC_MAX_NUM; i++) { if (hdl->adc_f->cfg.mic_en_map & BIT(i)) { //目前仅支持更新增益 audio_adc_mic_set_gain(&hdl->mic_ch, BIT(i), cfg->param[i].mic_gain); audio_adc_mic_gain_boost(BIT(i), cfg->param[i].mic_pre_gain); } } ret = true; } return ret; } static int adc_ioctl(void *_hdl, int cmd, int arg) { int ret = 0; struct adc_file_hdl *hdl = (struct adc_file_hdl *)_hdl; switch (cmd) { case NODE_IOC_GET_FMT: adc_ioc_get_fmt(hdl, (struct stream_fmt *)arg); break; case NODE_IOC_SET_FMT: ret = adc_ioc_set_fmt(hdl, (struct stream_fmt *)arg); break; case NODE_IOC_SET_SCENE: hdl->scene = arg; break; case NODE_IOC_SET_PRIV_FMT: hdl->irq_points = arg; break; case NODE_IOC_START: ret = adc_file_ioc_start(hdl); hdl->adc_seq = get_adc_seq(&adc_hdl, hdl->adc_f->cfg.mic_en_map); //查询模拟mic对应的ADC通道 break; case NODE_IOC_SUSPEND: case NODE_IOC_STOP: adc_file_ioc_stop(hdl); break; case NODE_IOC_SET_PARAM: ret = adc_file_ioc_update_parm(hdl, arg); break; case NODE_IOC_NODE_CONFIG: hdl->ch_num = (u8)arg; break; } return ret; } static void adc_release(void *_hdl) { struct adc_file_hdl *hdl = (struct adc_file_hdl *)_hdl; if (hdl->adc_f && hdl->scene != STREAM_SCENE_ESCO) { free(hdl->adc_f); hdl->adc_f = NULL; } free(hdl); esco_adc_f.hdl = NULL; } REGISTER_SOURCE_NODE_PLUG(adc_file_plug) = { .uuid = NODE_UUID_ADC, .init = adc_init, .ioctl = adc_ioctl, .release = adc_release, }; REGISTER_ONLINE_ADJUST_TARGET(adc) = { .uuid = NODE_UUID_ADC, };