Files
AC707N/SDK/audio/framework/plugs/source/adc_file.c
T
2025-12-03 11:12:34 +08:00

740 lines
23 KiB
C

#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,
};