Files
99_7018_lmx/cpu/br28/smart_voice/vad_mic.c
2025-10-29 13:10:02 +08:00

204 lines
5.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*****************************************************************
>file name : vad_mic.c
>create time : Fri 15 Apr 2022 10:27:55 AM CST
*****************************************************************/
#include "smart_voice.h"
#include "vad_mic.h"
#include "asm/efuse.h"
#include "voice_mic_data.h"
#include "update/update.h"
struct low_power_vad_mic {
void *priv;
int (*dma_output)(void *, s16 *, int);
};
extern const int config_lp_vad_enable;
struct low_power_vad_mic *lp_vad = NULL;
static DEFINE_SPINLOCK(lp_vad_lock);
//===========================================================================//
// AUDIO_VAD //
//===========================================================================//
#define AUDIO_VAD_CBUF_ADDR VAD_CBUF_BEGIN
static void p11_vad_mic_dma_irq_handler(void)
{
int buffered_frames = P11_LPVAD->DMA_SHN / VOICE_MIC_DATA_PERIOD_FRAMES * VOICE_MIC_DATA_PERIOD_FRAMES;
int buffered_bytes = buffered_frames * VOICE_ADC_SAMPLE_CH * 2;
u8 *read_ptr = (u8 *)((s16 *)AUDIO_VAD_CBUF_ADDR + P11_LPVAD->DMA_SPTR * VOICE_ADC_SAMPLE_CH);
int write_len = 0;
if (P11_LPVAD->DMA_SPTR + buffered_frames > P11_LPVAD->DMA_LEN) {
int read_len = (P11_LPVAD->DMA_LEN - P11_LPVAD->DMA_SPTR) * VOICE_ADC_SAMPLE_CH * 2;
spin_lock(&lp_vad_lock);
if (lp_vad && lp_vad->dma_output) {
lp_vad->dma_output(lp_vad->priv, (s16 *)read_ptr, read_len);
}
spin_unlock(&lp_vad_lock);
read_ptr = (u8 *)AUDIO_VAD_CBUF_ADDR;
buffered_bytes -= read_len;
}
spin_lock(&lp_vad_lock);
if (lp_vad && lp_vad->dma_output) {
lp_vad->dma_output(lp_vad->priv, (s16 *)read_ptr, buffered_bytes);
}
spin_unlock(&lp_vad_lock);
/*更新P11 LPVAD读指针通过p11传递不可直接设置硬件*/
AUDIO_VAD_DMA_READ_UPDATE(buffered_frames / VOICE_MIC_DATA_PERIOD_FRAMES);
}
/*static u8 p2m_active = 0;*/
/*
* Event from IRQ
*
*/
void audio_vad_coprocessor_event_handler(int event)
{
if (!config_lp_vad_enable) {
return;
}
int msg = SMART_VOICE_MSG_STANDBY;
switch (event) {
case P2M_VAD_TRIGGER_START:
/*p2m_active = 1;*/
msg = SMART_VOICE_MSG_WAKE;
p11_vad_mic_dma_irq_handler();
break;
case P2M_VAD_TRIGGER_DMA:
msg = SMART_VOICE_MSG_DMA;
p11_vad_mic_dma_irq_handler();
break;
case P2M_VAD_TRIGGER_STOP:
msg = SMART_VOICE_MSG_STANDBY;
/*p2m_active = 0;*/
break;
default:
break;
}
smart_voice_core_post_msg(1, msg);
}
/*
* 由主系统P11响应中断调用
*/
void audio_vad_p2mevent_irq_handler(void)
{
audio_vad_coprocessor_event_handler(P2M_MESSAGE_VAD_CMD);
}
static void lp_vad_mic_in_enable(struct vad_mic_platform_data *data)
{
if (!config_lp_vad_enable) {
return;
}
gpio_set_direction(IO_PORTA_01, 1);
gpio_set_die(IO_PORTA_01, 0);
gpio_set_pull_up(IO_PORTA_01, 0);
gpio_set_pull_down(IO_PORTA_01, 0);
if (data->mic_data.mic_mode == AUDIO_MIC_CAP_DIFF_MODE || data->mic_data.mic_bias_inside) {
gpio_set_direction(IO_PORTA_02, 1);
gpio_set_die(IO_PORTA_02, 0);
gpio_set_pull_up(IO_PORTA_02, 0);
gpio_set_pull_down(IO_PORTA_02, 0);
}
}
int lp_vad_mic_data_init(struct vad_mic_platform_data *mic_data)
{
struct vad_mic_platform_data *data = (struct vad_mic_platform_data *)(VAD_AVAD_CONFIG_BEGIN + sizeof(struct avad_config));
memcpy(data, mic_data, sizeof(struct vad_mic_platform_data));
u8 vbg_trim = get_vad_vbg_trim();
if (vbg_trim != 0xf) {
data->power_data.acm_select = get_vad_vbg_trim();
}
lp_vad_mic_in_enable(mic_data);
return 0;
}
void *lp_vad_mic_open(void *priv, int (*dma_output)(void *priv, s16 *data, int len))
{
if (!config_lp_vad_enable) {
return NULL;
}
if (!lp_vad) {
lp_vad = zalloc(sizeof(struct low_power_vad_mic));
if (!lp_vad) {
return NULL;
}
}
P11_VAD_IRQ_ENABLE();
/*
* P11 VAD初始化
*/
struct avad_config *avad_cfg = (struct avad_config *)VAD_AVAD_CONFIG_BEGIN;
struct dvad_config *dvad_cfg = (struct dvad_config *)VAD_DVAD_CONFIG_BEGIN;
//=================================//
// AVAD 效果参数配置 //
//=================================//
avad_cfg->avad_quantile_p = 3; //0.8
avad_cfg->avad_gain_db = 10;
avad_cfg->avad_compare_v = 3;
//=================================//
// DVAD 效果参数配置 //
//=================================//
dvad_cfg->dvad_gain_id = 10;
dvad_cfg->d2a_th_db = 20;
dvad_cfg->d_frame_con = 100;
dvad_cfg->d2a_frame_con = 100;
dvad_cfg->d_stride1 = 3;//<<7
dvad_cfg->d_stride2 = 5;//<<7
dvad_cfg->d_low_con_th = 6;
dvad_cfg->d_high_con_th = 3;
printf("avad_cfg @ 0x%x, dvad_cfg @ 0x%x", (u32)avad_cfg, (u32)dvad_cfg);
lp_vad->priv = priv;
lp_vad->dma_output = dma_output;
audio_vad_m2p_event_post(M2P_VAD_CMD_INIT);
return lp_vad;
}
void lp_vad_mic_disable(void)
{
audio_vad_m2p_event_post(M2P_VAD_CMD_CLOSE);
}
void lp_vad_mic_close(void *vad)
{
if (!config_lp_vad_enable) {
return;
}
if (!vad) {
return;
}
lp_vad_mic_disable();
spin_lock(&lp_vad_lock);
if (vad) {
free(vad);
}
lp_vad = NULL;
spin_unlock(&lp_vad_lock);
}
void lp_vad_mic_test(void)
{
audio_vad_m2p_event_post(M2P_VAD_CMD_TEST);
}
u8 vad_disable(void)
{
lp_vad_mic_disable();
return 0;
}
REGISTER_UPDATE_TARGET(vad_update_target) = {
.name = "vad",
.driver_close = vad_disable,
};