420 lines
13 KiB
C
420 lines
13 KiB
C
/*
|
||
****************************************************************************
|
||
* Audio Mic_Capless Module
|
||
*省电容mic模块
|
||
*即直接将mic的信号输出接到芯片的MICIN引脚(PA1)
|
||
****************************************************************************
|
||
*/
|
||
#include "system/includes.h"
|
||
#include "media/includes.h"
|
||
#include "app_config.h"
|
||
#include "app_action.h"
|
||
#include "app_main.h"
|
||
#include "audio_config.h"
|
||
|
||
#define LOG_TAG "[APP_AUDIO]"
|
||
#define LOG_ERROR_ENABLE
|
||
#define LOG_DEBUG_ENABLE
|
||
#define LOG_INFO_ENABLE
|
||
/* #define LOG_DUMP_ENABLE */
|
||
#define LOG_CLI_ENABLE
|
||
#include "debug.h"
|
||
|
||
#define TCFG_AUDIO_MC_ENABLE 1 //mic_capless_enable
|
||
|
||
//#define MC_LOG_ENABLE
|
||
#ifdef MC_LOG_ENABLE
|
||
#define MC_LOG_I g_printf
|
||
#define MC_LOG_E r_printf
|
||
#else
|
||
#define MC_LOG_E(...)
|
||
#define MC_LOG_I(...)
|
||
#endif/*MC_LOG_ENABLE*/
|
||
|
||
const int const_mic_capless_dtb = TCFG_MC_DTB_FIXED;
|
||
#if TCFG_AUDIO_MC_ENABLE
|
||
extern struct adc_platform_data adc_data;
|
||
extern void delay_2ms(int cnt);
|
||
extern void wdt_clear(void);
|
||
typedef struct {
|
||
u8 save_bias_res; /*trim结果是否保存*/
|
||
u8 trim; /*trim状态*/
|
||
u8 cur_bias_res;
|
||
OS_SEM sem;
|
||
} MicCapless_trim_t;
|
||
MicCapless_trim_t *mc_trim = NULL;
|
||
|
||
#define MC_TRIM_P BIT(0)
|
||
#define MC_TRIM_N BIT(1)
|
||
|
||
#define LADC_CAPLESS_ADJUST_SAVE
|
||
#ifdef LADC_CAPLESS_ADJUST_SAVE
|
||
#define DIFF_RANGE 50
|
||
#define CFG_DIFF_RANGE 100
|
||
#define CHECK_INTERVAL 10
|
||
#endif/*LADC_CAPLESS_ADJUST_SAVE*/
|
||
|
||
#define DACDTB_RANGE_MAX 8100
|
||
#define DACDTB_RANGE_MIN 6600
|
||
|
||
#define MIC_CAPLESS_ADJUST_BUD_DEFAULT 0
|
||
#define MIC_CAPLESS_ADJUST_BUD 100
|
||
|
||
#define MC_TRIM_SUCC 0
|
||
#define MC_TRIM_ERR 1
|
||
|
||
#define MC_TRIM_TIMEOUT 300
|
||
|
||
static const u8 mic_bias_tab[] = {0, 20, 12, 28, 4, 18, 10, 26, 2, 22, 14, 30, 17, 21, 6, 25, 29, 27, 31, 5, 3, 7};
|
||
#define MIC_BIAS_RSEL(x) SFR(JL_ADDA->ADA_CON0, 17, 5, x)
|
||
|
||
/*不支持自动校准,使用快速收敛*/
|
||
#if TCFG_MC_BIAS_AUTO_ADJUST
|
||
u8 mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD_DEFAULT;
|
||
#else
|
||
u8 mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD;
|
||
#endif/*TCFG_MC_BIAS_AUTO_ADJUST*/
|
||
|
||
u32 read_capless_DTB(void)
|
||
{
|
||
u32 dacr32 = 0;
|
||
int ret = syscfg_read(CFG_DAC_DTB, &dacr32, sizeof(dacr32));
|
||
if (ret != sizeof(dacr32)) {
|
||
/*
|
||
*没有记忆值,使用默认值
|
||
*没有收敛值的时候,使用快速收敛
|
||
*/
|
||
log_info("DAC_DTB NULL,use fast feedback");
|
||
mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD;
|
||
return DACR32_DEFAULT;
|
||
}
|
||
log_info("cfg DTB0:%d,ret = %d\n", dacr32, ret);
|
||
return dacr32;
|
||
}
|
||
|
||
static u32 read_vm_capless_DTB(void)
|
||
{
|
||
u32 vm_dacr32 = 0;
|
||
int ret = syscfg_read(CFG_DAC_DTB, &vm_dacr32, sizeof(vm_dacr32));
|
||
if (ret != sizeof(vm_dacr32)) {
|
||
log_info("vm DTB read err\n");
|
||
return DACR32_DEFAULT;
|
||
}
|
||
log_info("vm DTB0:%d,ret = %d\n", vm_dacr32, ret);
|
||
return vm_dacr32;
|
||
}
|
||
|
||
typedef struct {
|
||
u8 adjust_complete;
|
||
u8 dtb_step_limit; //限制dtb收敛步进
|
||
u16 save_dtb;
|
||
} mc_var_t;
|
||
mc_var_t mc_var = {
|
||
.save_dtb = DACR32_DEFAULT,
|
||
.adjust_complete = 0,
|
||
.dtb_step_limit = 0,
|
||
};
|
||
|
||
#if TCFG_MC_DTB_STEP_LIMIT
|
||
/*获取省电容mic收敛信息配置*/
|
||
int get_mc_dtb_step_limit(void)
|
||
{
|
||
return mc_var.dtb_step_limit;
|
||
}
|
||
#endif /*TCFG_MC_DTB_STEP_LIMIT*/
|
||
|
||
void save_capless_DTB()
|
||
{
|
||
s16 diff;
|
||
u32 save_dac_dtb = 0;
|
||
MC_LOG_I("save_capless_DTB\n");
|
||
/*
|
||
*(1)dtb0或者dtb1有一个不是默认值
|
||
*(2)收敛成功
|
||
*/
|
||
if ((mc_var.save_dtb != DACR32_DEFAULT) && mc_var.adjust_complete) {
|
||
/*读取记忆值,比较是否需要更新配置*/
|
||
u32 cfg_dacr32 = read_vm_capless_DTB();
|
||
/*分离dtb0和dtb1*/
|
||
u16 cfg_dtb0 = (cfg_dacr32 & 0xFFFF);
|
||
mc_var.adjust_complete = 0;
|
||
log_info("save_dtb0:%d,\n", mc_var.save_dtb);
|
||
log_info("cfg_dtb:0x%x,cfg_dtb0:%d\n", cfg_dacr32, cfg_dtb0);
|
||
|
||
diff = mc_var.save_dtb - cfg_dtb0;
|
||
if ((mc_var.save_dtb != DACR32_DEFAULT) && ((cfg_dtb0 == DACR32_DEFAULT) || ((diff < -CFG_DIFF_RANGE) || (diff > CFG_DIFF_RANGE)))) {
|
||
save_dac_dtb = mc_var.save_dtb;
|
||
log_info("dtb0 update:%d,0x%x,save_dac_dtb:%x\n", mc_var.save_dtb, mc_var.save_dtb, save_dac_dtb);
|
||
} else {
|
||
save_dac_dtb = cfg_dtb0;
|
||
log_info("dtb0 need't update:%d,diff:%d\n", mc_var.save_dtb, diff);
|
||
}
|
||
|
||
if (save_dac_dtb != cfg_dacr32) {
|
||
MC_LOG_I("store mc dtb:%x\n", save_dac_dtb);
|
||
syscfg_write(CFG_DAC_DTB, &save_dac_dtb, 4);
|
||
/* u32 tmp_dacr32 = 0;
|
||
syscfg_read(CFG_DAC_DTB,&tmp_dacr32,4);
|
||
MC_LOG_I("read mc dtb:%x\n",tmp_dacr32); */
|
||
}
|
||
} else {
|
||
log_info("dacr32 adjust uncomplete:%d,complete:%d\n", mc_var.save_dtb, mc_var.adjust_complete);
|
||
}
|
||
}
|
||
|
||
/*
|
||
*收敛快调慢调边界
|
||
*/
|
||
u16 get_ladc_capless_bud(void)
|
||
{
|
||
//printf("mc_bud:%d",mic_capless_adjust_bud);
|
||
return mic_capless_adjust_bud;
|
||
}
|
||
|
||
extern void audio_adc_mic_trim_open(u8 mic_idx, u8 gain);
|
||
extern void audio_adc_mic_trim_close(u8 mic_idx);
|
||
|
||
static u8 audio_mc_idle_query(void)
|
||
{
|
||
return (mc_trim ? 0 : 1);
|
||
}
|
||
REGISTER_LP_TARGET(audio_mc_device_lp_target) = {
|
||
.name = "audio_mc_device",
|
||
.is_idle = audio_mc_idle_query,
|
||
};
|
||
|
||
void mic_capless_trim_init(u8 mic_idx)
|
||
{
|
||
log_info("mic_capless_trim_init:%d\n", mic_idx);
|
||
mc_trim = zalloc(sizeof(MicCapless_trim_t));
|
||
if (mc_trim) {
|
||
if (mic_idx == LADC_CH_MIC_L) {
|
||
mc_trim->cur_bias_res = adc_data.mic_bias_res;
|
||
}
|
||
os_sem_create(&mc_trim->sem, 0);
|
||
mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD;
|
||
audio_adc_mic_trim_open(TCFG_AUDIO_ADC_MIC_CHA, app_var.aec_mic_gain);
|
||
log_info("mic_capless_trim_init succ\n");
|
||
} else {
|
||
log_info("mic_capless_trim_init err\n");
|
||
}
|
||
}
|
||
|
||
void mic_capless_trim_exit(u8 trim_result)
|
||
{
|
||
audio_adc_mic_trim_close(TCFG_AUDIO_ADC_MIC_CHA);
|
||
|
||
if (trim_result) {
|
||
log_info("save trim value,bias_res:%d,dtb0:%d\n", adc_data.mic_bias_res, mc_var.save_dtb);
|
||
log_info("save trim value,save_bias:%d,complete:%d\n", mc_trim->save_bias_res, mc_var.adjust_complete);
|
||
if (mc_trim->save_bias_res) {
|
||
int ret = syscfg_write(CFG_MC_BIAS, &adc_data.mic_bias_res, 1);
|
||
}
|
||
if (mc_var.adjust_complete) {
|
||
save_capless_DTB();
|
||
}
|
||
mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD_DEFAULT;
|
||
MC_LOG_E("mc_trim succ,use default adjust bud:%d\n", mic_capless_adjust_bud);
|
||
} else {
|
||
mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD;
|
||
MC_LOG_E("mc_trim err,use fast adjust bud:%d\n", mic_capless_adjust_bud);
|
||
}
|
||
|
||
free(mc_trim);
|
||
mc_trim = NULL;
|
||
log_info("mic_capless_bias_adjust_exit\n");
|
||
}
|
||
|
||
void mic_capless_trim_result(u8 result)
|
||
{
|
||
if (mc_trim) {
|
||
/*预收敛*/
|
||
log_info("mc_pre_auto_adjust_result:%d\n", result);
|
||
if (mc_trim->trim && (mc_trim->trim < (MC_TRIM_P | MC_TRIM_N))) {
|
||
mc_trim->save_bias_res = 1;
|
||
adc_data.mic_bias_res = mc_trim->cur_bias_res;
|
||
}
|
||
os_sem_post(&mc_trim->sem);
|
||
} else {
|
||
/*运行过程收敛*/
|
||
log_info("mc_run_auto_adjust_result:%d\n", result);
|
||
}
|
||
}
|
||
|
||
#define POWER_RESET_VDDIO_POR BIT(0) /*上电reset*/
|
||
#define POWER_RESET_PPINR BIT(3) /*长按reset*/
|
||
extern u8 power_reset_flag;
|
||
/*
|
||
*检查mic偏置是否需要校准,以下情况需要重新校准:
|
||
*1、power on reset
|
||
*2、vm被擦除
|
||
*/
|
||
u8 mc_bias_adjust_check(void)
|
||
{
|
||
u8 por_flag = 0;
|
||
#if (TCFG_MC_BIAS_AUTO_ADJUST == MC_BIAS_ADJUST_ALWAYS)
|
||
return 1;
|
||
#endif
|
||
int ret = syscfg_read(CFG_POR_FLAG, &por_flag, 1);
|
||
if (ret == 1) {
|
||
if (por_flag == 0xA5) {
|
||
log_info("power on reset 1");
|
||
por_flag = 0;
|
||
ret = syscfg_write(CFG_POR_FLAG, &por_flag, 1);
|
||
return 1;
|
||
}
|
||
}
|
||
if (power_reset_flag & POWER_RESET_VDDIO_POR) {
|
||
log_info("power on reset 2");
|
||
return 1;
|
||
}
|
||
if (read_vm_capless_DTB() == DACR32_DEFAULT) {
|
||
log_info("vm format");
|
||
return 1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
void mc_trim_init(int update)
|
||
{
|
||
u8 por_flag = 0;
|
||
u8 cur_por_flag = 0;
|
||
if (adc_data.mic_capless == 0) {
|
||
return;
|
||
}
|
||
/*
|
||
*1.update
|
||
*2.power_on_reset
|
||
*3.pin reset
|
||
*/
|
||
if (update || (power_reset_flag & POWER_RESET_VDDIO_POR) || (power_reset_flag & POWER_RESET_PPINR)) {
|
||
log_info("reset_flag:0x%x", power_reset_flag);
|
||
cur_por_flag = 0xA5;
|
||
}
|
||
int ret = syscfg_read(CFG_POR_FLAG, &por_flag, 1);
|
||
log_info("POR flag:%x-%x", cur_por_flag, por_flag);
|
||
if ((cur_por_flag == 0xA5) && (por_flag != cur_por_flag)) {
|
||
//log_info("update POR flag");
|
||
/*需要保存上电状态时因为开机有可能进入soft poweroff,下次开机的时候需要知道上次的开机状态*/
|
||
ret = syscfg_write(CFG_POR_FLAG, &cur_por_flag, 1);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* 省电容mic预收敛
|
||
*/
|
||
void mic_trim_run()
|
||
{
|
||
int ret = 0;
|
||
|
||
#if (!(TCFG_AUDIO_ADC_MIC_CHA & (LADC_CH_MIC_L | LADC_CH_MIC_R)))
|
||
return;
|
||
#endif
|
||
if (adc_data.mic_capless == 0) {
|
||
return;
|
||
}
|
||
|
||
log_info("mic_trim_run\n");
|
||
#if TCFG_MC_BIAS_AUTO_ADJUST
|
||
if (mc_bias_adjust_check()) {
|
||
//printf("MC_BIAS_ADJUST...");
|
||
/*
|
||
*预收敛条件:
|
||
*1、开机检查发现mic的偏置非法,则校准回来,同时重新收敛,比如中途更换mic头的情况
|
||
*2、收敛值丢失(vm被擦除),重新收敛一次(前提是校准成功)
|
||
*/
|
||
mc_var.dtb_step_limit = 0;
|
||
mic_capless_trim_init(TCFG_AUDIO_ADC_MIC_CHA);
|
||
ret = os_sem_pend(&mc_trim->sem, MC_TRIM_TIMEOUT);
|
||
if (ret == OS_TIMEOUT) {
|
||
log_info("mc_trim timeout!\n");
|
||
mic_capless_trim_exit(0);
|
||
} else {
|
||
log_info("mc_trim ok\n");
|
||
mic_capless_trim_exit(1);
|
||
mc_var.dtb_step_limit = TCFG_MC_DTB_STEP_LIMIT;
|
||
}
|
||
} else {
|
||
log_info("mc_need't trim");
|
||
mc_var.dtb_step_limit = TCFG_MC_DTB_STEP_LIMIT;
|
||
}
|
||
#endif/*TCFG_MC_BIAS_AUTO_ADJUST*/
|
||
}
|
||
|
||
void ladc_capless_adjust_post(s32 dacr32, u8 begin)
|
||
{
|
||
static s32 last_dacr32 = 0;
|
||
static u8 check_cnt = 0;
|
||
u8 bias_rsel;
|
||
s32 dacr32_diff;
|
||
|
||
/*adjust_begin,clear*/
|
||
if (begin) {
|
||
last_dacr32 = 0;
|
||
check_cnt = 0;
|
||
mc_var.adjust_complete = 0;
|
||
mc_var.save_dtb = DACR32_DEFAULT;
|
||
return;
|
||
}
|
||
#if TCFG_MC_CONVERGE_TRACE
|
||
printf("<%d>", dacr32);
|
||
#endif/*TCFG_MC_CONVERGE_TRACE*/
|
||
if (mc_var.adjust_complete == 0) {
|
||
if (++check_cnt > CHECK_INTERVAL) {
|
||
check_cnt = 0;
|
||
#if TCFG_MC_BIAS_AUTO_ADJUST
|
||
if (mc_trim) {
|
||
if (dacr32 > DACDTB_RANGE_MAX) {
|
||
if (mc_trim->cur_bias_res < 21) {
|
||
mc_trim->cur_bias_res++;
|
||
} else {
|
||
printf("[Assert]mic_bias_rsel err 1!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
||
ASSERT(0, "mic_bias_rsel err 1\n");
|
||
}
|
||
bias_rsel = mic_bias_tab[mc_trim->cur_bias_res];
|
||
y_printf("[-]mic_bias_rsel:%d = %d", mc_trim->cur_bias_res, bias_rsel);
|
||
MIC_BIAS_RSEL(bias_rsel);
|
||
mc_trim->trim |= MC_TRIM_P;
|
||
return;
|
||
} else if (dacr32 < DACDTB_RANGE_MIN) {
|
||
if (mc_trim->cur_bias_res > 1) {
|
||
mc_trim->cur_bias_res--;
|
||
} else {
|
||
printf("[Assert]mic_bias_rsel err 2!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
||
ASSERT(0, "mic_bias_rsel err 2\n");
|
||
}
|
||
bias_rsel = mic_bias_tab[mc_trim->cur_bias_res];
|
||
y_printf("[+]mic_bias_rsel:%d = %d", mc_trim->cur_bias_res, bias_rsel);
|
||
MIC_BIAS_RSEL(bias_rsel);
|
||
mc_trim->trim |= MC_TRIM_N;
|
||
return;
|
||
}
|
||
|
||
if (mc_trim->trim == (MC_TRIM_P | MC_TRIM_N)) {
|
||
mic_capless_trim_result(MC_TRIM_ERR);
|
||
}
|
||
}
|
||
#endif/*TCFG_MC_BIAS_AUTO_ADJUST*/
|
||
|
||
dacr32_diff = dacr32 - last_dacr32;
|
||
//printf("[capless:%d-%d-%d]",dacr32,last_dacr32,dacr32_diff);
|
||
last_dacr32 = dacr32;
|
||
if (mc_var.adjust_complete == 0) {
|
||
mc_var.save_dtb = dacr32;
|
||
}
|
||
|
||
/*调整稳定*/
|
||
if ((dacr32_diff > -DIFF_RANGE) && (dacr32_diff < DIFF_RANGE)) {
|
||
log_info("adjust_OK:%d\n", dacr32);
|
||
mc_var.adjust_complete = 1;
|
||
#if TCFG_MC_BIAS_AUTO_ADJUST
|
||
mic_capless_trim_result(MC_TRIM_SUCC);
|
||
#endif/*TCFG_MC_BIAS_AUTO_ADJUST*/
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#endif/*TCFG_AUDIO_MC_ENABLE*/
|
||
|