/***************************************************************************
 *
 * Copyright 2015-2019 BES.
 * All rights reserved. All unpublished rights reserved.
 *
 * No part of this work may be used or reproduced in any form or by any
 * means, or stored in a database or retrieval system, without prior written
 * permission of BES.
 *
 * Use of this work is governed by a license granted by BES.
 * This work contains confidential and proprietary information of
 * BES. which is protected by copyright, trade secret,
 * trademark and other intellectual property rights.
 *
 ****************************************************************************/
#include "analog.h"
#include "cmsis.h"
#include "plat_types.h"
#ifdef RTOS
#include "cmsis_os.h"
#endif
#include "hal_chipid.h"
#include "hal_cmu.h"
#include "hal_codec.h"
#include "hal_timer.h"
#include "hal_trace.h"
#include "pmu.h"
#include "tgt_hardware.h"

#define VCM_ON

// Not using 1uF
#define VCM_CAP_100NF

#if defined(CODEC_HIGH_QUALITY)
#undef LOW_CODEC_BIAS
#else
#define LOW_CODEC_BIAS
#endif

#define DAC_DC_CALIB_BIT_WIDTH 14

#define DEFAULT_ANC_FF_ADC_GAIN_DB 6
#define DEFAULT_ANC_FB_ADC_GAIN_DB 6
#define DEFAULT_VOICE_ADC_GAIN_DB 12

#ifndef ANALOG_ADC_A_GAIN_DB
#if defined(ANC_APP) && defined(ANC_FF_ENABLED) &&                             \
    ((ANC_FF_MIC_CH_L == AUD_CHANNEL_MAP_CH0) ||                               \
     (ANC_FF_MIC_CH_R == AUD_CHANNEL_MAP_CH0))
#define ANALOG_ADC_A_GAIN_DB DEFAULT_ANC_FF_ADC_GAIN_DB
#elif defined(ANC_APP) && defined(ANC_FB_ENABLED) &&                           \
    ((ANC_FB_MIC_CH_L == AUD_CHANNEL_MAP_CH0) ||                               \
     (ANC_FB_MIC_CH_R == AUD_CHANNEL_MAP_CH0))
#define ANALOG_ADC_A_GAIN_DB DEFAULT_ANC_FB_ADC_GAIN_DB
#else
#define ANALOG_ADC_A_GAIN_DB DEFAULT_VOICE_ADC_GAIN_DB
#endif
#endif

#ifndef ANALOG_ADC_B_GAIN_DB
#if defined(ANC_APP) && defined(ANC_FF_ENABLED) &&                             \
    ((ANC_FF_MIC_CH_L == AUD_CHANNEL_MAP_CH1) ||                               \
     (ANC_FF_MIC_CH_R == AUD_CHANNEL_MAP_CH1))
#define ANALOG_ADC_B_GAIN_DB DEFAULT_ANC_FF_ADC_GAIN_DB
#elif defined(ANC_APP) && defined(ANC_FB_ENABLED) &&                           \
    ((ANC_FB_MIC_CH_L == AUD_CHANNEL_MAP_CH1) ||                               \
     (ANC_FB_MIC_CH_R == AUD_CHANNEL_MAP_CH1))
#define ANALOG_ADC_B_GAIN_DB DEFAULT_ANC_FB_ADC_GAIN_DB
#else
#define ANALOG_ADC_B_GAIN_DB DEFAULT_VOICE_ADC_GAIN_DB
#endif
#endif

#ifndef ANALOG_ADC_C_GAIN_DB
#if defined(ANC_APP) && defined(ANC_FF_ENABLED) &&                             \
    ((ANC_FF_MIC_CH_L == AUD_CHANNEL_MAP_CH2) ||                               \
     (ANC_FF_MIC_CH_R == AUD_CHANNEL_MAP_CH2))
#define ANALOG_ADC_C_GAIN_DB DEFAULT_ANC_FF_ADC_GAIN_DB
#elif defined(ANC_APP) && defined(ANC_FB_ENABLED) &&                           \
    ((ANC_FB_MIC_CH_L == AUD_CHANNEL_MAP_CH2) ||                               \
     (ANC_FB_MIC_CH_R == AUD_CHANNEL_MAP_CH2))
#define ANALOG_ADC_C_GAIN_DB DEFAULT_ANC_FB_ADC_GAIN_DB
#else
#define ANALOG_ADC_C_GAIN_DB DEFAULT_VOICE_ADC_GAIN_DB
#endif
#endif

#ifndef ANALOG_ADC_D_GAIN_DB
#if defined(ANC_APP) && defined(ANC_FF_ENABLED) &&                             \
    ((ANC_FF_MIC_CH_L == AUD_CHANNEL_MAP_CH3) ||                               \
     (ANC_FF_MIC_CH_R == AUD_CHANNEL_MAP_CH3))
#define ANALOG_ADC_D_GAIN_DB DEFAULT_ANC_FF_ADC_GAIN_DB
#elif defined(ANC_APP) && defined(ANC_FB_ENABLED) &&                           \
    ((ANC_FB_MIC_CH_L == AUD_CHANNEL_MAP_CH3) ||                               \
     (ANC_FB_MIC_CH_R == AUD_CHANNEL_MAP_CH3))
#define ANALOG_ADC_D_GAIN_DB DEFAULT_ANC_FB_ADC_GAIN_DB
#else
#define ANALOG_ADC_D_GAIN_DB DEFAULT_VOICE_ADC_GAIN_DB
#endif
#endif

#ifndef ANALOG_ADC_E_GAIN_DB
#if defined(ANC_APP) && defined(ANC_FF_ENABLED) &&                             \
    ((ANC_FF_MIC_CH_L == AUD_CHANNEL_MAP_CH4) ||                               \
     (ANC_FF_MIC_CH_R == AUD_CHANNEL_MAP_CH4))
#define ANALOG_ADC_E_GAIN_DB DEFAULT_ANC_FF_ADC_GAIN_DB
#elif defined(ANC_APP) && defined(ANC_FB_ENABLED) &&                           \
    ((ANC_FB_MIC_CH_L == AUD_CHANNEL_MAP_CH4) ||                               \
     (ANC_FB_MIC_CH_R == AUD_CHANNEL_MAP_CH4))
#define ANALOG_ADC_E_GAIN_DB DEFAULT_ANC_FB_ADC_GAIN_DB
#else
#define ANALOG_ADC_E_GAIN_DB DEFAULT_VOICE_ADC_GAIN_DB
#endif
#endif

#ifndef LINEIN_ADC_GAIN_DB
#define LINEIN_ADC_GAIN_DB 0
#endif

#ifndef CFG_HW_AUD_MICKEY_DEV
#define CFG_HW_AUD_MICKEY_DEV (AUD_VMIC_MAP_VMIC1)
#endif

#ifndef ANC_VMIC_CFG
#define ANC_VMIC_CFG (AUD_VMIC_MAP_VMIC1)
#endif

// 61
#define REG_CODEC_EN_ADCA (1 << 0)
#define REG_CODEC_EN_ADCB (1 << 1)
#define REG_CODEC_EN_ADCC (1 << 2)
#define REG_CODEC_EN_ADCD (1 << 3)
#define REG_CODEC_ADCA_DITHER_EN (1 << 4)
#define REG_CODEC_ADCB_DITHER_EN (1 << 5)
#define REG_CODEC_ADCC_DITHER_EN (1 << 6)
#define REG_CODEC_ADCD_DITHER_EN (1 << 7)
#define REG_CODEC_ADCA_CH_SEL_SHIFT 8
#define REG_CODEC_ADCA_CH_SEL_MASK (0x3 << REG_CODEC_ADCA_CH_SEL_SHIFT)
#define REG_CODEC_ADCA_CH_SEL(n) BITFIELD_VAL(REG_CODEC_ADCA_CH_SEL, n)
#define REG_CODEC_ADCB_CH_SEL_SHIFT 10
#define REG_CODEC_ADCB_CH_SEL_MASK (0x3 << REG_CODEC_ADCB_CH_SEL_SHIFT)
#define REG_CODEC_ADCB_CH_SEL(n) BITFIELD_VAL(REG_CODEC_ADCB_CH_SEL, n)
#define REG_CODEC_ADCC_CH_SEL_SHIFT 12
#define REG_CODEC_ADCC_CH_SEL_MASK (0x3 << REG_CODEC_ADCC_CH_SEL_SHIFT)
#define REG_CODEC_ADCC_CH_SEL(n) BITFIELD_VAL(REG_CODEC_ADCC_CH_SEL, n)
#define REG_CODEC_ADCD_CH_SEL_SHIFT 14
#define REG_CODEC_ADCD_CH_SEL_MASK (0x3 << REG_CODEC_ADCD_CH_SEL_SHIFT)
#define REG_CODEC_ADCD_CH_SEL(n) BITFIELD_VAL(REG_CODEC_ADCD_CH_SEL, n)

// 62
#define REG_CODEC_RESET_ADCA (1 << 0)
#define REG_CODEC_RESET_ADCB (1 << 1)
#define REG_CODEC_RESET_ADCC (1 << 2)
#define REG_CODEC_RESET_ADCD (1 << 3)
#define CFG_RESET_ADCA_DR (1 << 4)
#define CFG_RESET_ADCB_DR (1 << 5)
#define CFG_RESET_ADCC_DR (1 << 6)
#define CFG_RESET_ADCD_DR (1 << 7)
#define REG_RX_PGAA_RESET (1 << 8)
#define REG_RX_PGAB_RESET (1 << 9)
#define REG_RX_PGAC_RESET (1 << 10)
#define REG_RX_PGAD_RESET (1 << 11)
#define CFG_RESET_PGAA_DR (1 << 12)
#define CFG_RESET_PGAB_DR (1 << 13)
#define CFG_RESET_PGAC_DR (1 << 14)
#define CFG_RESET_PGAD_DR (1 << 15)

// 63
#define REG_CODEC_ADCA_GAIN_BIT_SHIFT 0
#define REG_CODEC_ADCA_GAIN_BIT_MASK (0x7 << REG_CODEC_ADCA_GAIN_BIT_SHIFT)
#define REG_CODEC_ADCA_GAIN_BIT(n) BITFIELD_VAL(REG_CODEC_ADCA_GAIN_BIT, n)
#define REG_CODEC_ADCB_GAIN_BIT_SHIFT 3
#define REG_CODEC_ADCB_GAIN_BIT_MASK (0x7 << REG_CODEC_ADCB_GAIN_BIT_SHIFT)
#define REG_CODEC_ADCB_GAIN_BIT(n) BITFIELD_VAL(REG_CODEC_ADCB_GAIN_BIT, n)
#define REG_CODEC_ADCC_GAIN_BIT_SHIFT 6
#define REG_CODEC_ADCC_GAIN_BIT_MASK (0x7 << REG_CODEC_ADCC_GAIN_BIT_SHIFT)
#define REG_CODEC_ADCC_GAIN_BIT(n) BITFIELD_VAL(REG_CODEC_ADCC_GAIN_BIT, n)
#define REG_CODEC_ADCD_GAIN_BIT_SHIFT 9
#define REG_CODEC_ADCD_GAIN_BIT_MASK (0x7 << REG_CODEC_ADCD_GAIN_BIT_SHIFT)
#define REG_CODEC_ADCD_GAIN_BIT(n) BITFIELD_VAL(REG_CODEC_ADCD_GAIN_BIT, n)
#define REG_CODEC_ADCA_GAIN_UPDATE (1 << 12)
#define REG_CODEC_ADCB_GAIN_UPDATE (1 << 13)
#define REG_CODEC_ADCC_GAIN_UPDATE (1 << 14)
#define REG_CODEC_ADCD_GAIN_UPDATE (1 << 15)

// 67
#define REG_CODEC_ADC_IBSEL_REG_SHIFT 0
#define REG_CODEC_ADC_IBSEL_REG_MASK (0xF << REG_CODEC_ADC_IBSEL_REG_SHIFT)
#define REG_CODEC_ADC_IBSEL_REG(n) BITFIELD_VAL(REG_CODEC_ADC_IBSEL_REG, n)
#define REG_CODEC_ADC_IBSEL_VCOMP_SHIFT 4
#define REG_CODEC_ADC_IBSEL_VCOMP_MASK (0xF << REG_CODEC_ADC_IBSEL_VCOMP_SHIFT)
#define REG_CODEC_ADC_IBSEL_VCOMP(n) BITFIELD_VAL(REG_CODEC_ADC_IBSEL_VCOMP, n)
#define REG_CODEC_ADC_IBSEL_VREF_SHIFT 8
#define REG_CODEC_ADC_IBSEL_VREF_MASK (0xF << REG_CODEC_ADC_IBSEL_VREF_SHIFT)
#define REG_CODEC_ADC_IBSEL_VREF(n) BITFIELD_VAL(REG_CODEC_ADC_IBSEL_VREF, n)
#define REG_CODEC_ADC_LPFVCM_SW_SHIFT 12
#define REG_CODEC_ADC_LPFVCM_SW_MASK (0xF << REG_CODEC_ADC_LPFVCM_SW_SHIFT)
#define REG_CODEC_ADC_LPFVCM_SW(n) BITFIELD_VAL(REG_CODEC_ADC_LPFVCM_SW, n)

// 68
#define REG_CODEC_ADC_OP1_IBIT_SHIFT 0
#define REG_CODEC_ADC_OP1_IBIT_MASK (0x3 << REG_CODEC_ADC_OP1_IBIT_SHIFT)
#define REG_CODEC_ADC_OP1_IBIT(n) BITFIELD_VAL(REG_CODEC_ADC_OP1_IBIT, n)
#define REG_CODEC_ADC_OP1_R_SEL (1 << 2)
#define REG_CODEC_ADC_OP2_IBIT_SHIFT 3
#define REG_CODEC_ADC_OP2_IBIT_MASK (0x3 << REG_CODEC_ADC_OP2_IBIT_SHIFT)
#define REG_CODEC_ADC_OP2_IBIT(n) BITFIELD_VAL(REG_CODEC_ADC_OP2_IBIT, n)
#define REG_CODEC_ADC_OP2_R_SEL (1 << 5)
#define REG_CODEC_ADC_OP3_IBIT_SHIFT 6
#define REG_CODEC_ADC_OP3_IBIT_MASK (0x3 << REG_CODEC_ADC_OP3_IBIT_SHIFT)
#define REG_CODEC_ADC_OP3_IBIT(n) BITFIELD_VAL(REG_CODEC_ADC_OP3_IBIT, n)
#define REG_CODEC_ADC_OP3_R_SEL (1 << 8)
#define REG_CODEC_ADC_OP4_IBIT_SHIFT 9
#define REG_CODEC_ADC_OP4_IBIT_MASK (0x3 << REG_CODEC_ADC_OP4_IBIT_SHIFT)
#define REG_CODEC_ADC_OP4_IBIT(n) BITFIELD_VAL(REG_CODEC_ADC_OP4_IBIT, n)
#define REG_CODEC_ADC_OP4_R_SEL (1 << 11)
#define REG_CODEC_ADC_VREF_SEL_SHIFT 12
#define REG_CODEC_ADC_VREF_SEL_MASK (0xF << REG_CODEC_ADC_VREF_SEL_SHIFT)
#define REG_CODEC_ADC_VREF_SEL(n) BITFIELD_VAL(REG_CODEC_ADC_VREF_SEL, n)

// 69
#define REG_CODEC_BIAS_IBSEL_SHIFT 0
#define REG_CODEC_BIAS_IBSEL_MASK (0xF << REG_CODEC_BIAS_IBSEL_SHIFT)
#define REG_CODEC_BIAS_IBSEL(n) BITFIELD_VAL(REG_CODEC_BIAS_IBSEL, n)
#define REG_CODEC_BIAS_IBSEL_TX_SHIFT 4
#define REG_CODEC_BIAS_IBSEL_TX_MASK (0xF << REG_CODEC_BIAS_IBSEL_TX_SHIFT)
#define REG_CODEC_BIAS_IBSEL_TX(n) BITFIELD_VAL(REG_CODEC_BIAS_IBSEL_TX, n)
#define REG_CODEC_BIAS_IBSEL_VOICE_SHIFT 8
#define REG_CODEC_BIAS_IBSEL_VOICE_MASK                                        \
  (0xF << REG_CODEC_BIAS_IBSEL_VOICE_SHIFT)
#define REG_CODEC_BIAS_IBSEL_VOICE(n)                                          \
  BITFIELD_VAL(REG_CODEC_BIAS_IBSEL_VOICE, n)
#define REG_CODEC_BIAS_LOWV (1 << 12)
#define REG_CODEC_BIAS_LOWV_LP (1 << 13)
#define REG_CODEC_BUF_LOWPOWER (1 << 14)
#define REG_CODEC_BUF_LOWPOWER2 (1 << 15)

// 6A
#define REG_CODEC_ADC_REG_VSEL_SHIFT 0
#define REG_CODEC_ADC_REG_VSEL_MASK (0x7 << REG_CODEC_ADC_REG_VSEL_SHIFT)
#define REG_CODEC_ADC_REG_VSEL(n) BITFIELD_VAL(REG_CODEC_ADC_REG_VSEL, n)
#define REG_CODEC_ADC_RES_SEL_SHIFT 3
#define REG_CODEC_ADC_RES_SEL_MASK (0x7 << REG_CODEC_ADC_RES_SEL_SHIFT)
#define REG_CODEC_ADC_RES_SEL(n) BITFIELD_VAL(REG_CODEC_ADC_RES_SEL, n)
#define REG_CODEC_BUF_LOWVCM_SHIFT 6
#define REG_CODEC_BUF_LOWVCM_MASK (0x7 << REG_CODEC_BUF_LOWVCM_SHIFT)
#define REG_CODEC_BUF_LOWVCM(n) BITFIELD_VAL(REG_CODEC_BUF_LOWVCM, n)
#define REG_CODEC_EN_BIAS (1 << 9)
#define REG_CODEC_EN_BIAS_LP (1 << 10)
#define REG_CODEC_EN_RX_EXT (1 << 11)
#define REG_CODEC_EN_TX_EXT (1 << 12)
#define REG_CODEC_DAC_CLK_EDGE_SEL (1 << 13)
#define CFG_TX_CH0_MUTE (1 << 14)
#define CFG_TX_CH1_MUTE (1 << 15)

// 6B
#define REG_CODEC_EN_VCM (1 << 0)
#define REG_CODEC_VCM_EN_LPF (1 << 1)
#define REG_CODEC_LP_VCM (1 << 2)
#define REG_CODEC_VCM_LOW_VCM_SHIFT 3
#define REG_CODEC_VCM_LOW_VCM_MASK (0xF << REG_CODEC_VCM_LOW_VCM_SHIFT)
#define REG_CODEC_VCM_LOW_VCM(n) BITFIELD_VAL(REG_CODEC_VCM_LOW_VCM, n)
#define REG_CODEC_VCM_LOW_VCM_LP_SHIFT 7
#define REG_CODEC_VCM_LOW_VCM_LP_MASK (0xF << REG_CODEC_VCM_LOW_VCM_LP_SHIFT)
#define REG_CODEC_VCM_LOW_VCM_LP(n) BITFIELD_VAL(REG_CODEC_VCM_LOW_VCM_LP, n)
#define REG_CODEC_VCM_LOW_VCM_LPF_SHIFT 11
#define REG_CODEC_VCM_LOW_VCM_LPF_MASK (0xF << REG_CODEC_VCM_LOW_VCM_LPF_SHIFT)
#define REG_CODEC_VCM_LOW_VCM_LPF(n) BITFIELD_VAL(REG_CODEC_VCM_LOW_VCM_LPF, n)
#define REG_CODEC_EN_VCM_BUFFER (1 << 15)

// 6C
#define REG_CODEC_RX_EN_VTOI (1 << 0)
#define REG_CODEC_RX_VTOI_I_DAC2_SHIFT 1
#define REG_CODEC_RX_VTOI_I_DAC2_MASK (0x7 << REG_CODEC_RX_VTOI_I_DAC2_SHIFT)
#define REG_CODEC_RX_VTOI_I_DAC2(n) BITFIELD_VAL(REG_CODEC_RX_VTOI_I_DAC2, n)
#define REG_CODEC_RX_VTOI_IDAC_SEL_SHIFT 4
#define REG_CODEC_RX_VTOI_IDAC_SEL_MASK                                        \
  (0xF << REG_CODEC_RX_VTOI_IDAC_SEL_SHIFT)
#define REG_CODEC_RX_VTOI_IDAC_SEL(n)                                          \
  BITFIELD_VAL(REG_CODEC_RX_VTOI_IDAC_SEL, n)
#define REG_CODEC_RX_VTOI_VCS_SEL_SHIFT 8
#define REG_CODEC_RX_VTOI_VCS_SEL_MASK (0x1F << REG_CODEC_RX_VTOI_VCS_SEL_SHIFT)
#define REG_CODEC_RX_VTOI_VCS_SEL(n) BITFIELD_VAL(REG_CODEC_RX_VTOI_VCS_SEL, n)
#define REG_CODEC_ADCA_RES_2P5K_DR (1 << 13)
#define REG_CODEC_ADCB_RES_2P5K_DR (1 << 14)
#define REG_CODEC_ADCC_RES_2P5K_DR (1 << 15)

// 6D
#define REG_CODEC_TX_DAC_MUTEL (1 << 0)
#define REG_CODEC_TX_DAC_MUTER (1 << 1)
#define REG_CODEC_TX_DAC_SWR_SHIFT 2
#define REG_CODEC_TX_DAC_SWR_MASK (0x3 << REG_CODEC_TX_DAC_SWR_SHIFT)
#define REG_CODEC_TX_DAC_SWR(n) BITFIELD_VAL(REG_CODEC_TX_DAC_SWR, n)
#define REG_CODEC_TX_DAC_VREF_L_SHIFT 4
#define REG_CODEC_TX_DAC_VREF_L_MASK (0xF << REG_CODEC_TX_DAC_VREF_L_SHIFT)
#define REG_CODEC_TX_DAC_VREF_L(n) BITFIELD_VAL(REG_CODEC_TX_DAC_VREF_L, n)
#define REG_CODEC_TX_DAC_VREF_R_SHIFT 8
#define REG_CODEC_TX_DAC_VREF_R_MASK (0xF << REG_CODEC_TX_DAC_VREF_R_SHIFT)
#define REG_CODEC_TX_DAC_VREF_R(n) BITFIELD_VAL(REG_CODEC_TX_DAC_VREF_R, n)
#define REG_CODEC_TX_EAR_CAS_BIT_SHIFT 12
#define REG_CODEC_TX_EAR_CAS_BIT_MASK (0x3 << REG_CODEC_TX_EAR_CAS_BIT_SHIFT)
#define REG_CODEC_TX_EAR_CAS_BIT(n) BITFIELD_VAL(REG_CODEC_TX_EAR_CAS_BIT, n)
#define REG_CODEC_TX_EAR_DIS_SHIFT 14
#define REG_CODEC_TX_EAR_DIS_MASK (0x3 << REG_CODEC_TX_EAR_DIS_SHIFT)
#define REG_CODEC_TX_EAR_DIS(n) BITFIELD_VAL(REG_CODEC_TX_EAR_DIS, n)

// 6E
#define REG_CODEC_TX_EAR_COMP_L_SHIFT 0
#define REG_CODEC_TX_EAR_COMP_L_MASK (0x7 << REG_CODEC_TX_EAR_COMP_L_SHIFT)
#define REG_CODEC_TX_EAR_COMP_L(n) BITFIELD_VAL(REG_CODEC_TX_EAR_COMP_L, n)
#define REG_CODEC_TX_EAR_COMP_R_SHIFT 3
#define REG_CODEC_TX_EAR_COMP_R_MASK (0x7 << REG_CODEC_TX_EAR_COMP_R_SHIFT)
#define REG_CODEC_TX_EAR_COMP_R(n) BITFIELD_VAL(REG_CODEC_TX_EAR_COMP_R, n)
#define REG_CODEC_TX_EAR_DOUBLEBIAS (1 << 6)
#define REG_CODEC_TX_EAR_DR_EN (1 << 7)
#define REG_CODEC_TX_EAR_DR_ST_SHIFT 8
#define REG_CODEC_TX_EAR_DR_ST_MASK (0x7 << REG_CODEC_TX_EAR_DR_ST_SHIFT)
#define REG_CODEC_TX_EAR_DR_ST(n) BITFIELD_VAL(REG_CODEC_TX_EAR_DR_ST, n)
#define REG_CODEC_TX_EAR_ENBIAS (1 << 11)
#define REG_CODEC_TX_EAR_FBCAP_SHIFT 12
#define REG_CODEC_TX_EAR_FBCAP_MASK (0x3 << REG_CODEC_TX_EAR_FBCAP_SHIFT)
#define REG_CODEC_TX_EAR_FBCAP(n) BITFIELD_VAL(REG_CODEC_TX_EAR_FBCAP, n)
#define REG_CODEC_TX_EAR_IBSEL_SHIFT 14
#define REG_CODEC_TX_EAR_IBSEL_MASK (0x3 << REG_CODEC_TX_EAR_IBSEL_SHIFT)
#define REG_CODEC_TX_EAR_IBSEL(n) BITFIELD_VAL(REG_CODEC_TX_EAR_IBSEL, n)

// 6F
#define REG_CODEC_TX_EAR_DRE_GAIN_L_SHIFT 0
#define REG_CODEC_TX_EAR_DRE_GAIN_L_MASK                                       \
  (0x1F << REG_CODEC_TX_EAR_DRE_GAIN_L_SHIFT)
#define REG_CODEC_TX_EAR_DRE_GAIN_L(n)                                         \
  BITFIELD_VAL(REG_CODEC_TX_EAR_DRE_GAIN_L, n)
#define REG_CODEC_TX_EAR_DRE_GAIN_R_SHIFT 5
#define REG_CODEC_TX_EAR_DRE_GAIN_R_MASK                                       \
  (0x1F << REG_CODEC_TX_EAR_DRE_GAIN_R_SHIFT)
#define REG_CODEC_TX_EAR_DRE_GAIN_R(n)                                         \
  BITFIELD_VAL(REG_CODEC_TX_EAR_DRE_GAIN_R, n)
#define DRE_GAIN_SEL_L (1 << 10)
#define DRE_GAIN_SEL_R (1 << 11)
#define REG_CODEC_TX_EAR_DRE_GAIN_L_UPDATE (1 << 12)
#define REG_CODEC_TX_EAR_DRE_GAIN_R_UPDATE (1 << 13)
#define REG_CODEC_TX_EAR_GAIN_SHIFT 14
#define REG_CODEC_TX_EAR_GAIN_MASK (0x3 << REG_CODEC_TX_EAR_GAIN_SHIFT)
#define REG_CODEC_TX_EAR_GAIN(n) BITFIELD_VAL(REG_CODEC_TX_EAR_GAIN, n)

// 70
#define REG_CODEC_TX_EAR_LCAL (1 << 0)
#define REG_CODEC_TX_EAR_RCAL (1 << 1)
#define REG_CODEC_TX_EAR_LPBIAS (1 << 2)
#define REG_CODEC_TX_EAR_OCEN (1 << 3)
#define REG_CODEC_TX_EAR_OFFEN (1 << 4)
#define REG_CODEC_TX_EAR_OUTPUTSEL_SHIFT 5
#define REG_CODEC_TX_EAR_OUTPUTSEL_MASK                                        \
  (0xF << REG_CODEC_TX_EAR_OUTPUTSEL_SHIFT)
#define REG_CODEC_TX_EAR_OUTPUTSEL(n)                                          \
  BITFIELD_VAL(REG_CODEC_TX_EAR_OUTPUTSEL, n)
#define REG_CODEC_TX_EAR_SOFTSTART_SHIFT 9
#define REG_CODEC_TX_EAR_SOFTSTART_MASK                                        \
  (0x3F << REG_CODEC_TX_EAR_SOFTSTART_SHIFT)
#define REG_CODEC_TX_EAR_SOFTSTART(n)                                          \
  BITFIELD_VAL(REG_CODEC_TX_EAR_SOFTSTART, n)
#define CFG_TX_TREE_EN (1 << 15)

// 71
#define REG_CODEC_TX_EAR_LOWGAINL_SHIFT 0
#define REG_CODEC_TX_EAR_LOWGAINL_MASK (0x3 << REG_CODEC_TX_EAR_LOWGAINL_SHIFT)
#define REG_CODEC_TX_EAR_LOWGAINL(n) BITFIELD_VAL(REG_CODEC_TX_EAR_LOWGAINL, n)
#define REG_CODEC_TX_EAR_OFF_BITL_SHIFT 2
#define REG_CODEC_TX_EAR_OFF_BITL_MASK                                         \
  (0x3FFF << REG_CODEC_TX_EAR_OFF_BITL_SHIFT)
#define REG_CODEC_TX_EAR_OFF_BITL(n) BITFIELD_VAL(REG_CODEC_TX_EAR_OFF_BITL, n)

// 72
#define REG_CODEC_TX_EAR_LOWGAINR_SHIFT 0
#define REG_CODEC_TX_EAR_LOWGAINR_MASK (0x3 << REG_CODEC_TX_EAR_LOWGAINR_SHIFT)
#define REG_CODEC_TX_EAR_LOWGAINR(n) BITFIELD_VAL(REG_CODEC_TX_EAR_LOWGAINR, n)
#define REG_CODEC_TX_EAR_OFF_BITR_SHIFT 2
#define REG_CODEC_TX_EAR_OFF_BITR_MASK                                         \
  (0x3FFF << REG_CODEC_TX_EAR_OFF_BITR_SHIFT)
#define REG_CODEC_TX_EAR_OFF_BITR(n) BITFIELD_VAL(REG_CODEC_TX_EAR_OFF_BITR, n)

// 73
#define REG_CODEC_TX_EN_DACLDO (1 << 0)
#define REG_CODEC_TX_EN_EARPA_L (1 << 1)
#define REG_CODEC_TX_EN_EARPA_R (1 << 2)
#define REG_CODEC_TX_EN_LCLK (1 << 3)
#define REG_CODEC_TX_EN_RCLK (1 << 4)
#define REG_CODEC_TX_EN_LDAC (1 << 5)
#define REG_CODEC_TX_EN_RDAC (1 << 6)
#define REG_CODEC_TX_EN_LPPA (1 << 7)
#define REG_CODEC_TX_EN_S1PA (1 << 8)
#define REG_CODEC_TX_EN_S2PA (1 << 9)
#define REG_CODEC_TX_EN_S3PA (1 << 10)
#define REG_CODEC_TX_EN_S4PA (1 << 11)
#define REG_CODEC_TX_EN_S5PA (1 << 12)
#define REG_IDETLEAR_EN (1 << 13)
#define REG_IDETREAR_EN (1 << 14)
#define REG_CODEC_TX_SW_MODE (1 << 15)

// 74
#define REG_CODEC_TX_RVREF_CAP_BIT (1 << 0)
#define REG_DAC_LDO0P9_VSEL_SHIFT 1
#define REG_DAC_LDO0P9_VSEL_MASK (0x1F << REG_DAC_LDO0P9_VSEL_SHIFT)
#define REG_DAC_LDO0P9_VSEL(n) BITFIELD_VAL(REG_DAC_LDO0P9_VSEL, n)
#define REG_BYPASS_TX_REGULATOR (1 << 6)
#define REG_PU_TX_REGULATOR (1 << 7)
#define REG_TX_REGULATOR_BIT_SHIFT 8
#define REG_TX_REGULATOR_BIT_MASK (0xF << REG_TX_REGULATOR_BIT_SHIFT)
#define REG_TX_REGULATOR_BIT(n) BITFIELD_VAL(REG_TX_REGULATOR_BIT, n)
#define REG_TX_REG_CAP_BIT (1 << 12)
#define REG_CODEC_TX_EAR_VCM_BIT_SHIFT 13
#define REG_CODEC_TX_EAR_VCM_BIT_MASK (0x3 << REG_CODEC_TX_EAR_VCM_BIT_SHIFT)
#define REG_CODEC_TX_EAR_VCM_BIT(n) BITFIELD_VAL(REG_CODEC_TX_EAR_VCM_BIT, n)
#define REG_CODEC_TX_EAR_VCM_SEL (1 << 15)

// 75
#define REG_CRYSTAL_SEL_LV (1 << 0)
#define REG_EXTPLL_SEL (1 << 1)
#define REG_AUDPLL_CAL_EN (1 << 2)
#define REG_AUDPLL_CP_IEN_SHIFT 3
#define REG_AUDPLL_CP_IEN_MASK (0xF << REG_AUDPLL_CP_IEN_SHIFT)
#define REG_AUDPLL_CP_IEN(n) BITFIELD_VAL(REG_AUDPLL_CP_IEN, n)
#define REG_AUDPLL_CP_SWRC_SHIFT 7
#define REG_AUDPLL_CP_SWRC_MASK (0x3 << REG_AUDPLL_CP_SWRC_SHIFT)
#define REG_AUDPLL_CP_SWRC(n) BITFIELD_VAL(REG_AUDPLL_CP_SWRC, n)
#define REG_AUDPLL_DIG_SWRC_SHIFT 9
#define REG_AUDPLL_DIG_SWRC_MASK (0x3 << REG_AUDPLL_DIG_SWRC_SHIFT)
#define REG_AUDPLL_DIG_SWRC(n) BITFIELD_VAL(REG_AUDPLL_DIG_SWRC, n)
#define REG_AUDPLL_VCO_SPD_SHIFT 11
#define REG_AUDPLL_VCO_SPD_MASK (0x7 << REG_AUDPLL_VCO_SPD_SHIFT)
#define REG_AUDPLL_VCO_SPD(n) BITFIELD_VAL(REG_AUDPLL_VCO_SPD, n)
#define REG_AUDPLL_VCO_SWRC_SHIFT 14
#define REG_AUDPLL_VCO_SWRC_MASK (0x3 << REG_AUDPLL_VCO_SWRC_SHIFT)
#define REG_AUDPLL_VCO_SWRC(n) BITFIELD_VAL(REG_AUDPLL_VCO_SWRC, n)

// 7A
#define REG_PU_OSC (1 << 0)
#define REG_BBPLL_TST_EN (1 << 1)
#define REG_AUDPLL_TRIGGER_EN (1 << 2)
#define REG_AUDPLL_FREQ_EN (1 << 3)
#define REG_AUDPLL_CLK_FBC_EDGE (1 << 4)
#define REG_AUDPLL_INT_DEC_SEL_SHIFT 5
#define REG_AUDPLL_INT_DEC_SEL_MASK (0x7 << REG_AUDPLL_INT_DEC_SEL_SHIFT)
#define REG_AUDPLL_INT_DEC_SEL(n) BITFIELD_VAL(REG_AUDPLL_INT_DEC_SEL, n)
#define REG_AUDPLL_DITHER_BYPASS (1 << 8)
#define REG_AUDPLL_PRESCALER_DEL_SEL_SHIFT 9
#define REG_AUDPLL_PRESCALER_DEL_SEL_MASK                                      \
  (0xF << REG_AUDPLL_PRESCALER_DEL_SEL_SHIFT)
#define REG_AUDPLL_PRESCALER_DEL_SEL(n)                                        \
  BITFIELD_VAL(REG_AUDPLL_PRESCALER_DEL_SEL, n)
#define REG_AUDPLL_FREQ_34_32_SHIFT 13
#define REG_AUDPLL_FREQ_34_32_MASK (0x7 << REG_AUDPLL_FREQ_34_32_SHIFT)
#define REG_AUDPLL_FREQ_34_32(n) BITFIELD_VAL(REG_AUDPLL_FREQ_34_32, n)

// 7E
#define REG_CLKMUX_DVDD_SEL (1 << 0)
#define REG_CLKMUX_LDO0P9_VSEL_SHIFT 1
#define REG_CLKMUX_LDO0P9_VSEL_MASK (0x1F << REG_CLKMUX_LDO0P9_VSEL_SHIFT)
#define REG_CLKMUX_LDO0P9_VSEL(n) BITFIELD_VAL(REG_CLKMUX_LDO0P9_VSEL, n)
#define REG_PU_CLKMUX_LDO0P9 (1 << 6)
#define REG_AUDPLL_LDO_VREF_SHIFT 7
#define REG_AUDPLL_LDO_VREF_MASK (0x7 << REG_AUDPLL_LDO_VREF_SHIFT)
#define REG_AUDPLL_LDO_VREF(n) BITFIELD_VAL(REG_AUDPLL_LDO_VREF, n)
#define REG_AUDPLL_LPF_BW_SEL (1 << 10)
#define REG_CODEC_ADC_DITHER0P5_EN (1 << 11)
#define REG_CODEC_ADC_DITHER0P25_EN (1 << 12)
#define REG_CODEC_ADC_DITHER1_EN (1 << 13)
#define REG_CODEC_ADC_DITHER2_EN (1 << 14)
#define REG_CODEC_ADC_DITHER_PHASE_SEL (1 << 15)

// 174
#define CFG_TX_PEAK_OFF_ADC_EN (1 << 0)
#define CFG_TX_PEAK_OFF_DAC_EN (1 << 1)
#define CFG_PEAK_DET_DR (1 << 2)
#define CFG_TX_PEAK_OFF_ADC (1 << 3)
#define CFG_TX_PEAK_OFF_DAC (1 << 4)
#define CFG_PEAK_DET_DB_DELAY_SHIFT 5
#define CFG_PEAK_DET_DB_DELAY_MASK (0x7 << CFG_PEAK_DET_DB_DELAY_SHIFT)
#define CFG_PEAK_DET_DB_DELAY(n) BITFIELD_VAL(CFG_PEAK_DET_DB_DELAY, n)
#define REG_CODEC_TX_PEAK_DET_BIT (1 << 8)
#define REG_CODEC_TX_PEAK_NL_EN (1 << 9)
#define REG_CODEC_TX_PEAK_NR_EN (1 << 10)
#define REG_CODEC_TX_PEAK_PL_EN (1 << 11)
#define REG_CODEC_TX_PEAK_PR_EN (1 << 12)
#define CFG_TX_CLK_INV (1 << 13)
#define CFG_CODEC_DIN_L_RST (1 << 14)
#define CFG_CODEC_DIN_R_RST (1 << 15)

// C4
#define CODEC_RESAMPLE_CLK_BUF_PU (1 << 2)

// 16A
#define REG_CODEC_EN_ADCE (1 << 0)
#define DIG_CODEC_ADCE_DITHER_EN (1 << 1)
#define DIG_CODEC_ADCE_CH_SEL_SHIFT 2
#define DIG_CODEC_ADCE_CH_SEL_MASK (0x3 << DIG_CODEC_ADCE_CH_SEL_SHIFT)
#define DIG_CODEC_ADCE_CH_SEL(n) BITFIELD_VAL(DIG_CODEC_ADCE_CH_SEL, n)
#define REG_CODEC_RESET_ADCE (1 << 4)
#define CFG_RESET_ADCE_DR (1 << 5)
#define REG_CODEC_ADCE_GAIN_BIT_SHIFT 6
#define REG_CODEC_ADCE_GAIN_BIT_MASK (0x7 << REG_CODEC_ADCE_GAIN_BIT_SHIFT)
#define REG_CODEC_ADCE_GAIN_BIT(n) BITFIELD_VAL(REG_CODEC_ADCE_GAIN_BIT, n)
#define REG_CODEC_ADCE_GAIN_UPDATE (1 << 9)
#define REG_CODEC_ADCE_RES_2P5K (1 << 10)
#define REG_CODEC_ADCE_RES_2P5K_UPDATE (1 << 11)
#define DIG_CODEC_ADCE_IDETE_EN (1 << 12)
#define REG_RX_ADCE_ZERO_DET_EN (1 << 13)
#define CFG_ADCE_DITHER_CLK_INV (1 << 14)
#define DIG_CODEC_ADCE_CLK_SEL (1 << 15)

// 16B
#define DIG_CODEC_ADCE_IBSEL_OP1_SHIFT 0
#define DIG_CODEC_ADCE_IBSEL_OP1_MASK (0xF << DIG_CODEC_ADCE_IBSEL_OP1_SHIFT)
#define DIG_CODEC_ADCE_IBSEL_OP1(n) BITFIELD_VAL(DIG_CODEC_ADCE_IBSEL_OP1, n)
#define DIG_CODEC_ADCE_IBSEL_OP2_SHIFT 4
#define DIG_CODEC_ADCE_IBSEL_OP2_MASK (0xF << DIG_CODEC_ADCE_IBSEL_OP2_SHIFT)
#define DIG_CODEC_ADCE_IBSEL_OP2(n) BITFIELD_VAL(DIG_CODEC_ADCE_IBSEL_OP2, n)
#define DIG_CODEC_ADCE_IBSEL_OP3_SHIFT 8
#define DIG_CODEC_ADCE_IBSEL_OP3_MASK (0xF << DIG_CODEC_ADCE_IBSEL_OP3_SHIFT)
#define DIG_CODEC_ADCE_IBSEL_OP3(n) BITFIELD_VAL(DIG_CODEC_ADCE_IBSEL_OP3, n)
#define DIG_CODEC_ADCE_IBSEL_OP4_SHIFT 12
#define DIG_CODEC_ADCE_IBSEL_OP4_MASK (0xF << DIG_CODEC_ADCE_IBSEL_OP4_SHIFT)
#define DIG_CODEC_ADCE_IBSEL_OP4(n) BITFIELD_VAL(DIG_CODEC_ADCE_IBSEL_OP4, n)

// 16C
#define DIG_CODEC_ADCE_IBSEL_REG_SHIFT 0
#define DIG_CODEC_ADCE_IBSEL_REG_MASK (0xF << DIG_CODEC_ADCE_IBSEL_REG_SHIFT)
#define DIG_CODEC_ADCE_IBSEL_REG(n) BITFIELD_VAL(DIG_CODEC_ADCE_IBSEL_REG, n)
#define DIG_CODEC_ADCE_IBSEL_VCOMP_SHIFT 4
#define DIG_CODEC_ADCE_IBSEL_VCOMP_MASK                                        \
  (0xF << DIG_CODEC_ADCE_IBSEL_VCOMP_SHIFT)
#define DIG_CODEC_ADCE_IBSEL_VCOMP(n)                                          \
  BITFIELD_VAL(DIG_CODEC_ADCE_IBSEL_VCOMP, n)
#define DIG_CODEC_ADCE_IBSEL_VREF_SHIFT 8
#define DIG_CODEC_ADCE_IBSEL_VREF_MASK (0xF << DIG_CODEC_ADCE_IBSEL_VREF_SHIFT)
#define DIG_CODEC_ADCE_IBSEL_VREF(n) BITFIELD_VAL(DIG_CODEC_ADCE_IBSEL_VREF, n)
#define DIG_CODEC_ADCE_IBSEL_VREFBUF_SHIFT 12
#define DIG_CODEC_ADCE_IBSEL_VREFBUF_MASK                                      \
  (0xF << DIG_CODEC_ADCE_IBSEL_VREFBUF_SHIFT)
#define DIG_CODEC_ADCE_IBSEL_VREFBUF(n)                                        \
  BITFIELD_VAL(DIG_CODEC_ADCE_IBSEL_VREFBUF, n)

// 16D
#define DIG_CODEC_ADCE_IBSEL_IDAC2_SHIFT 0
#define DIG_CODEC_ADCE_IBSEL_IDAC2_MASK                                        \
  (0xF << DIG_CODEC_ADCE_IBSEL_IDAC2_SHIFT)
#define DIG_CODEC_ADCE_IBSEL_IDAC2(n)                                          \
  BITFIELD_VAL(DIG_CODEC_ADCE_IBSEL_IDAC2, n)
#define DIG_CODEC_ADCE_OP1_IBIT_SHIFT 4
#define DIG_CODEC_ADCE_OP1_IBIT_MASK (0x3 << DIG_CODEC_ADCE_OP1_IBIT_SHIFT)
#define DIG_CODEC_ADCE_OP1_IBIT(n) BITFIELD_VAL(DIG_CODEC_ADCE_OP1_IBIT, n)
#define DIG_CODEC_ADCE_OP1_R_SEL (1 << 6)
#define DIG_CODEC_ADCE_OP2_IBIT_SHIFT 7
#define DIG_CODEC_ADCE_OP2_IBIT_MASK (0x3 << DIG_CODEC_ADCE_OP2_IBIT_SHIFT)
#define DIG_CODEC_ADCE_OP2_IBIT(n) BITFIELD_VAL(DIG_CODEC_ADCE_OP2_IBIT, n)
#define DIG_CODEC_ADCE_OP2_R_SEL (1 << 9)
#define DIG_CODEC_ADCE_OP3_IBIT_SHIFT 10
#define DIG_CODEC_ADCE_OP3_IBIT_MASK (0x3 << DIG_CODEC_ADCE_OP3_IBIT_SHIFT)
#define DIG_CODEC_ADCE_OP3_IBIT(n) BITFIELD_VAL(DIG_CODEC_ADCE_OP3_IBIT, n)
#define DIG_CODEC_ADCE_OP3_R_SEL (1 << 12)
#define DIG_CODEC_ADCE_OP4_IBIT_SHIFT 13
#define DIG_CODEC_ADCE_OP4_IBIT_MASK (0x3 << DIG_CODEC_ADCE_OP4_IBIT_SHIFT)
#define DIG_CODEC_ADCE_OP4_IBIT(n) BITFIELD_VAL(DIG_CODEC_ADCE_OP4_IBIT, n)
#define DIG_CODEC_ADCE_OP4_R_SEL (1 << 15)

// 16E
#define DIG_CODEC_ADCE_VREF_SEL_SHIFT 0
#define DIG_CODEC_ADCE_VREF_SEL_MASK (0xF << DIG_CODEC_ADCE_VREF_SEL_SHIFT)
#define DIG_CODEC_ADCE_VREF_SEL(n) BITFIELD_VAL(DIG_CODEC_ADCE_VREF_SEL, n)
#define DIG_CODEC_ADCE_VREFBUF_BIT_SHIFT 4
#define DIG_CODEC_ADCE_VREFBUF_BIT_MASK                                        \
  (0xF << DIG_CODEC_ADCE_VREFBUF_BIT_SHIFT)
#define DIG_CODEC_ADCE_VREFBUF_BIT(n)                                          \
  BITFIELD_VAL(DIG_CODEC_ADCE_VREFBUF_BIT, n)
#define DIG_CODEC_ADCE_REG_VSEL_SHIFT 8
#define DIG_CODEC_ADCE_REG_VSEL_MASK (0x7 << DIG_CODEC_ADCE_REG_VSEL_SHIFT)
#define DIG_CODEC_ADCE_REG_VSEL(n) BITFIELD_VAL(DIG_CODEC_ADCE_REG_VSEL, n)
#define DIG_CODEC_ADCE_CAP_BIT (1 << 11)
#define REG_VOICE_SEL_VREF_BIN_SHIFT 12
#define REG_VOICE_SEL_VREF_BIN_MASK (0xF << REG_VOICE_SEL_VREF_BIN_SHIFT)
#define REG_VOICE_SEL_VREF_BIN(n) BITFIELD_VAL(REG_VOICE_SEL_VREF_BIN, n)

// 16F
#define REG_VOICE_LP_COMP_SHIFT 0
#define REG_VOICE_LP_COMP_MASK (0x7 << REG_VOICE_LP_COMP_SHIFT)
#define REG_VOICE_LP_COMP(n) BITFIELD_VAL(REG_VOICE_LP_COMP, n)
#define REG_VOICE_LP_AMPA_SHIFT 3
#define REG_VOICE_LP_AMPA_MASK (0x7 << REG_VOICE_LP_AMPA_SHIFT)
#define REG_VOICE_LP_AMPA(n) BITFIELD_VAL(REG_VOICE_LP_AMPA, n)
#define REG_VOICE_LP_AMPB_SHIFT 6
#define REG_VOICE_LP_AMPB_MASK (0x7 << REG_VOICE_LP_AMPB_SHIFT)
#define REG_VOICE_LP_AMPB(n) BITFIELD_VAL(REG_VOICE_LP_AMPB, n)
#define REG_VOICE_LP_LDO_SHIFT 9
#define REG_VOICE_LP_LDO_MASK (0x7 << REG_VOICE_LP_LDO_SHIFT)
#define REG_VOICE_LP_LDO(n) BITFIELD_VAL(REG_VOICE_LP_LDO, n)
#define REG_VOICE_LP_VREF_SHIFT 12
#define REG_VOICE_LP_VREF_MASK (0x7 << REG_VOICE_LP_VREF_SHIFT)
#define REG_VOICE_LP_VREF(n) BITFIELD_VAL(REG_VOICE_LP_VREF, n)
#define CFG_REG_VOICE_TRIG_ADCE_EN (1 << 15)

// 170
#define REG_VOICE_HIGH_TUNE_A_SHIFT 0
#define REG_VOICE_HIGH_TUNE_A_MASK (0xF << REG_VOICE_HIGH_TUNE_A_SHIFT)
#define REG_VOICE_HIGH_TUNE_A(n) BITFIELD_VAL(REG_VOICE_HIGH_TUNE_A, n)
#define REG_VOICE_HIGH_TUNE_B_SHIFT 4
#define REG_VOICE_HIGH_TUNE_B_MASK (0xF << REG_VOICE_HIGH_TUNE_B_SHIFT)
#define REG_VOICE_HIGH_TUNE_B(n) BITFIELD_VAL(REG_VOICE_HIGH_TUNE_B, n)
#define REG_VOICE_GAIN_A_SHIFT 8
#define REG_VOICE_GAIN_A_MASK (0x7 << REG_VOICE_GAIN_A_SHIFT)
#define REG_VOICE_GAIN_A(n) BITFIELD_VAL(REG_VOICE_GAIN_A, n)
#define REG_VOICE_GAIN_B_SHIFT 11
#define REG_VOICE_GAIN_B_MASK (0x7 << REG_VOICE_GAIN_B_SHIFT)
#define REG_VOICE_GAIN_B(n) BITFIELD_VAL(REG_VOICE_GAIN_B, n)
#define CFG_ADC_START (1 << 14)
#define CFG_VOICE2ADCE (1 << 15)

// 171
#define CFG_VOICE_POWER_ON (1 << 0)
#define CFG_VOICE_TRIG_ENABLE (1 << 1)
#define CFG_VOICE_RESET (1 << 2)
#define CFG_VOICE_DR (1 << 3)
#define CFG_VOICE_PU_DELAY_SHIFT 4
#define CFG_VOICE_PU_DELAY_MASK (0x7 << CFG_VOICE_PU_DELAY_SHIFT)
#define CFG_VOICE_PU_DELAY(n) BITFIELD_VAL(CFG_VOICE_PU_DELAY, n)
#define CFG_VOICE_PRECH_DELAY_SHIFT 7
#define CFG_VOICE_PRECH_DELAY_MASK (0xFF << CFG_VOICE_PRECH_DELAY_SHIFT)
#define CFG_VOICE_PRECH_DELAY(n) BITFIELD_VAL(CFG_VOICE_PRECH_DELAY, n)
#define REG_VOICE_EN_AGPIO_TEST (1 << 15)

// 172
#define REG_VOICE_CLK_EDGE_SEL (1 << 0)
#define REG_VOICE_PRECH (1 << 1)
#define REG_VOICE_PU (1 << 2)
#define REG_VOICE_PU_LDO (1 << 3)
#define REG_VOICE_SEL_VCM0P3_BIN_SHIFT 4
#define REG_VOICE_SEL_VCM0P3_BIN_MASK (0x7 << REG_VOICE_SEL_VCM0P3_BIN_SHIFT)
#define REG_VOICE_SEL_VCM0P3_BIN(n) BITFIELD_VAL(REG_VOICE_SEL_VCM0P3_BIN, n)
#define REG_VOICE_SEL_VCM_BIN_SHIFT 7
#define REG_VOICE_SEL_VCM_BIN_MASK (0xF << REG_VOICE_SEL_VCM_BIN_SHIFT)
#define REG_VOICE_SEL_VCM_BIN(n) BITFIELD_VAL(REG_VOICE_SEL_VCM_BIN, n)
#define REG_VOICE_SEL_VCMIN_BIN_SHIFT 11
#define REG_VOICE_SEL_VCMIN_BIN_MASK (0xF << REG_VOICE_SEL_VCMIN_BIN_SHIFT)
#define REG_VOICE_SEL_VCMIN_BIN(n) BITFIELD_VAL(REG_VOICE_SEL_VCMIN_BIN, n)
#define REG_VOICE_PU_OSC (1 << 15)

// 173
#define REG_VOICE_LDO_VBIT_SHIFT 0
#define REG_VOICE_LDO_VBIT_MASK (0x7 << REG_VOICE_LDO_VBIT_SHIFT)
#define REG_VOICE_LDO_VBIT(n) BITFIELD_VAL(REG_VOICE_LDO_VBIT, n)
#define REG_VOICE_OSC_FR_SHIFT 3
#define REG_VOICE_OSC_FR_MASK (0x7 << REG_VOICE_OSC_FR_SHIFT)
#define REG_VOICE_OSC_FR(n) BITFIELD_VAL(REG_VOICE_OSC_FR, n)
#define REG_VOICE_OSC_PWR_SHIFT 6
#define REG_VOICE_OSC_PWR_MASK (0x3 << REG_VOICE_OSC_PWR_SHIFT)
#define REG_VOICE_OSC_PWR(n) BITFIELD_VAL(REG_VOICE_OSC_PWR, n)
#define CFG_VOICE_DET_DELAY_SHIFT 8
#define CFG_VOICE_DET_DELAY_MASK (0xFF << CFG_VOICE_DET_DELAY_SHIFT)
#define CFG_VOICE_DET_DELAY(n) BITFIELD_VAL(CFG_VOICE_DET_DELAY, n)

// 174
#define CFG_TX_PEAK_OFF_ADC_EN (1 << 0)
#define CFG_TX_PEAK_OFF_DAC_EN (1 << 1)
#define CFG_PEAK_DET_DR (1 << 2)
#define CFG_TX_PEAK_OFF_ADC (1 << 3)
#define CFG_TX_PEAK_OFF_DAC (1 << 4)
#define CFG_PEAK_DET_DB_DELAY_SHIFT 5
#define CFG_PEAK_DET_DB_DELAY_MASK (0x7 << CFG_PEAK_DET_DB_DELAY_SHIFT)
#define CFG_PEAK_DET_DB_DELAY(n) BITFIELD_VAL(CFG_PEAK_DET_DB_DELAY, n)
#define REG_CODEC_TX_PEAK_DET_BIT (1 << 8)
#define REG_CODEC_TX_PEAK_NL_EN (1 << 9)
#define REG_CODEC_TX_PEAK_NR_EN (1 << 10)
#define REG_CODEC_TX_PEAK_PL_EN (1 << 11)
#define REG_CODEC_TX_PEAK_PR_EN (1 << 12)
#define CFG_TX_CLK_INV (1 << 13)
#define CFG_CODEC_DIN_L_RST (1 << 14)
#define CFG_CODEC_DIN_R_RST (1 << 15)

// 175
#define CODEC_DIN_L_HI_RSTVAL_SHIFT 0
#define CODEC_DIN_L_HI_RSTVAL_MASK (0xFFFF << CODEC_DIN_L_HI_RSTVAL_SHIFT)
#define CODEC_DIN_L_HI_RSTVAL(n) BITFIELD_VAL(CODEC_DIN_L_HI_RSTVAL, n)

// 176
#define CODEC_DIN_L_LO_RSTVAL_SHIFT 0
#define CODEC_DIN_L_LO_RSTVAL_MASK (0xFFFF << CODEC_DIN_L_LO_RSTVAL_SHIFT)
#define CODEC_DIN_L_LO_RSTVAL(n) BITFIELD_VAL(CODEC_DIN_L_LO_RSTVAL, n)

// 177
#define CODEC_DIN_R_HI_RSTVAL_SHIFT 0
#define CODEC_DIN_R_HI_RSTVAL_MASK (0xFFFF << CODEC_DIN_R_HI_RSTVAL_SHIFT)
#define CODEC_DIN_R_HI_RSTVAL(n) BITFIELD_VAL(CODEC_DIN_R_HI_RSTVAL, n)

// 178
#define CODEC_DIN_R_LO_RSTVAL_SHIFT 0
#define CODEC_DIN_R_LO_RSTVAL_MASK (0xFFFF << CODEC_DIN_R_LO_RSTVAL_SHIFT)
#define CODEC_DIN_R_LO_RSTVAL(n) BITFIELD_VAL(CODEC_DIN_R_LO_RSTVAL, n)

// 179
#define REG_AUDPLL_LDOPRECHG_TIMER_SHIFT 0
#define REG_AUDPLL_LDOPRECHG_TIMER_MASK                                        \
  (0x1F << REG_AUDPLL_LDOPRECHG_TIMER_SHIFT)
#define REG_AUDPLL_LDOPRECHG_TIMER(n)                                          \
  BITFIELD_VAL(REG_AUDPLL_LDOPRECHG_TIMER, n)
#define REG_AUDPLL_PRECHG_BEGIN_TIMER_SHIFT 5
#define REG_AUDPLL_PRECHG_BEGIN_TIMER_MASK                                     \
  (0x1F << REG_AUDPLL_PRECHG_BEGIN_TIMER_SHIFT)
#define REG_AUDPLL_PRECHG_BEGIN_TIMER(n)                                       \
  BITFIELD_VAL(REG_AUDPLL_PRECHG_BEGIN_TIMER, n)
#define REG_AUDPLL_PRECHG_END_TIMER_SHIFT 10
#define REG_AUDPLL_PRECHG_END_TIMER_MASK                                       \
  (0x1F << REG_AUDPLL_PRECHG_END_TIMER_SHIFT)
#define REG_AUDPLL_PRECHG_END_TIMER(n)                                         \
  BITFIELD_VAL(REG_AUDPLL_PRECHG_END_TIMER, n)
#define REG_CODEC_ADCD_RES_2P5K_DR (1 << 15)

// 17A
#define CFG_PRE_CHARGE_ADCE_DR (1 << 0)
#define REG_CODEC_ADCE_PRE_CHARGE (1 << 1)
#define ADCE_OPEN_TIMER_DLY_SHIFT 2
#define ADCE_OPEN_TIMER_DLY_MASK (0xF << ADCE_OPEN_TIMER_DLY_SHIFT)
#define ADCE_OPEN_TIMER_DLY(n) BITFIELD_VAL(ADCE_OPEN_TIMER_DLY, n)
#define ADCE_PRE_CHARGE_TIMER_DLY_SHIFT 6
#define ADCE_PRE_CHARGE_TIMER_DLY_MASK (0xFF << ADCE_PRE_CHARGE_TIMER_DLY_SHIFT)
#define ADCE_PRE_CHARGE_TIMER_DLY(n) BITFIELD_VAL(ADCE_PRE_CHARGE_TIMER_DLY, n)
#define REG_VOICE_LOW_TUNE_SHIFT 14
#define REG_VOICE_LOW_TUNE_MASK (0x3 << REG_VOICE_LOW_TUNE_SHIFT)
#define REG_VOICE_LOW_TUNE(n) BITFIELD_VAL(REG_VOICE_LOW_TUNE, n)

// 17B
#define REG_COARSE_EN (1 << 0)
#define REG_XTAL_FREQ_LLC_SFT_RSTN (1 << 1)
#define REG_COARSE_POLAR_SEL (1 << 2)
#define REG_AUDPLL_RSTB_TIMER_SHIFT 3
#define REG_AUDPLL_RSTB_TIMER_MASK (0x1F << REG_AUDPLL_RSTB_TIMER_SHIFT)
#define REG_AUDPLL_RSTB_TIMER(n) BITFIELD_VAL(REG_AUDPLL_RSTB_TIMER, n)
#define RX_TIMER_RSTN_DLY_SHIFT 8
#define RX_TIMER_RSTN_DLY_MASK (0xFF << RX_TIMER_RSTN_DLY_SHIFT)
#define RX_TIMER_RSTN_DLY(n) BITFIELD_VAL(RX_TIMER_RSTN_DLY, n)

// 17C
#define REG_CNT_COARSE_MARK_SHIFT 0
#define REG_CNT_COARSE_MARK_MASK (0xFFFF << REG_CNT_COARSE_MARK_SHIFT)
#define REG_CNT_COARSE_MARK(n) BITFIELD_VAL(REG_CNT_COARSE_MARK, n)

// 17D
#define REG_CLK_GOAL_DIV_NUM_SHIFT 0
#define REG_CLK_GOAL_DIV_NUM_MASK (0x1FF << REG_CLK_GOAL_DIV_NUM_SHIFT)
#define REG_CLK_GOAL_DIV_NUM(n) BITFIELD_VAL(REG_CLK_GOAL_DIV_NUM, n)
#define REG_COARSE_TUN_CODE_SHIFT 9
#define REG_COARSE_TUN_CODE_MASK (0x3F << REG_COARSE_TUN_CODE_SHIFT)
#define REG_COARSE_TUN_CODE(n) BITFIELD_VAL(REG_COARSE_TUN_CODE, n)
#define REG_COARSE_TUN_CODE_DR (1 << 15)

// 17E
#define SSC_ENABLE (1 << 0)
#define TRI_FREQ_OFST_SEL_SHIFT 1
#define TRI_FREQ_OFST_SEL_MASK (0x7 << TRI_FREQ_OFST_SEL_SHIFT)
#define TRI_FREQ_OFST_SEL(n) BITFIELD_VAL(TRI_FREQ_OFST_SEL, n)
#define TRI_FREQ_SEL_SHIFT 4
#define TRI_FREQ_SEL_MASK (0x3 << TRI_FREQ_SEL_SHIFT)
#define TRI_FREQ_SEL(n) BITFIELD_VAL(TRI_FREQ_SEL, n)
#define REG_VOICE_EN_REF_TEST (1 << 6)
#define REG_VOICE_GAIN_BASE_SHIFT 7
#define REG_VOICE_GAIN_BASE_MASK (0x7 << REG_VOICE_GAIN_BASE_SHIFT)
#define REG_VOICE_GAIN_BASE(n) BITFIELD_VAL(REG_VOICE_GAIN_BASE, n)
#define CFG_VOICE_PRECH_DONE_DELAY_SHIFT 10
#define CFG_VOICE_PRECH_DONE_DELAY_MASK                                        \
  (0x1F << CFG_VOICE_PRECH_DONE_DELAY_SHIFT)
#define CFG_VOICE_PRECH_DONE_DELAY(n)                                          \
  BITFIELD_VAL(CFG_VOICE_PRECH_DONE_DELAY, n)
#define REG_CODEC_LP_VCM_DR (1 << 15)

// 17F
#define TX_PEAK_DET_STATUS (1 << 0)
#define TX_PEAK_DET_NL_STATUS (1 << 1)
#define TX_PEAK_DET_NR_STATUS (1 << 2)
#define TX_PEAK_DET_PL_STATUS (1 << 3)
#define TX_PEAK_DET_PR_STATUS (1 << 4)
#define DBG_STATE_SHIFT 5
#define DBG_STATE_MASK (0x3 << DBG_STATE_SHIFT)
#define DBG_STATE(n) BITFIELD_VAL(DBG_STATE, n)

enum ANA_REG_T {
  ANA_REG_61 = 0x61,
  ANA_REG_62,
  ANA_REG_63,
  ANA_REG_64,
  ANA_REG_65,
  ANA_REG_66,
  ANA_REG_67,
  ANA_REG_68,
  ANA_REG_69,
  ANA_REG_6A,
  ANA_REG_6B,
  ANA_REG_6C,
  ANA_REG_6D,
  ANA_REG_6E,
  ANA_REG_6F,
  ANA_REG_70,
  ANA_REG_71,
  ANA_REG_72,
  ANA_REG_73,
  ANA_REG_74,
  ANA_REG_75,
  ANA_REG_76,
  ANA_REG_77,
  ANA_REG_78,
  ANA_REG_79,
  ANA_REG_7A,
  ANA_REG_7B,
  ANA_REG_7C,
  ANA_REG_7D,
  ANA_REG_7E,
  ANA_REG_7F,

  ANA_REG_161 = 0x161,
  ANA_REG_162,
  ANA_REG_163,
  ANA_REG_164,
  ANA_REG_165,
  ANA_REG_166,
  ANA_REG_167,
  ANA_REG_168,
  ANA_REG_169,
  ANA_REG_16A,
  ANA_REG_16B,
  ANA_REG_16C,
  ANA_REG_16D,
  ANA_REG_16E,
  ANA_REG_16F,
  ANA_REG_170,
  ANA_REG_171,
  ANA_REG_172,
  ANA_REG_173,
  ANA_REG_174,
  ANA_REG_175,
  ANA_REG_176,
  ANA_REG_177,
  ANA_REG_178,
  ANA_REG_179,
  ANA_REG_17A,
  ANA_REG_17B,
  ANA_REG_17C,
  ANA_REG_17D,
  ANA_REG_17E,
  ANA_REG_17F,

  ANA_REG_RF_C4 = 0xC4,
};

enum ANA_CODEC_USER_T {
  ANA_CODEC_USER_DAC = (1 << 0),
  ANA_CODEC_USER_ADC = (1 << 1),

  ANA_CODEC_USER_CODEC = (1 << 2),
  ANA_CODEC_USER_MICKEY = (1 << 3),

  ANA_CODEC_USER_ANC_FF = (1 << 4),
  ANA_CODEC_USER_ANC_FB = (1 << 5),

  ANA_CODEC_USER_VAD = (1 << 6),
};

struct ANALOG_PLL_CFG_T {
  uint32_t freq;
  uint8_t div;
  uint64_t val;
};

#ifdef ANC_PROD_TEST
#define OPT_TYPE
#else
#define OPT_TYPE const
#endif

static OPT_TYPE uint16_t vcodec_mv = (uint16_t)(VCODEC_VOLT * 1000);

static bool ana_spk_req;
static bool ana_spk_muted;
static bool ana_spk_enabled;

static bool anc_calib_mode;

static enum ANA_CODEC_USER_T adc_map[MAX_ANA_MIC_CH_NUM];
static enum ANA_CODEC_USER_T vmic_map[MAX_ANA_MIC_CH_NUM];
static enum ANA_CODEC_USER_T codec_common_map;
static enum ANA_CODEC_USER_T adda_common_map;
static enum ANA_CODEC_USER_T vcodec_map;

static enum ANA_AUD_PLL_USER_T ana_aud_pll_map;

#ifdef ANC_APP
#ifndef DYN_ADC_GAIN
#define DYN_ADC_GAIN
#endif
#endif

#ifdef DYN_ADC_GAIN
static int8_t adc_gain_offset[MAX_ANA_MIC_CH_NUM];
#endif

static const int8_t adc_db[] = {
    -9, -6, -3, 0, 3, 6, 9, 12,
};

static const int8_t tgt_adc_db[MAX_ANA_MIC_CH_NUM] = {
    ANALOG_ADC_A_GAIN_DB, ANALOG_ADC_B_GAIN_DB, ANALOG_ADC_C_GAIN_DB,
    ANALOG_ADC_D_GAIN_DB, ANALOG_ADC_E_GAIN_DB,
};

// Max allowed total tune ratio (5000ppm)
#define MAX_TOTAL_TUNE_RATIO 0.005000

static struct ANALOG_PLL_CFG_T ana_pll_cfg[2];
static int pll_cfg_idx;

void analog_aud_freq_pll_config(uint32_t freq, uint32_t div) {
  // CODEC_FREQ is likely 24.576M (48K series) or 22.5792M (44.1K series)
  // PLL_nominal = CODEC_FREQ * CODEC_DIV
  // PLL_cfg_val = ((CODEC_FREQ * CODEC_DIV) / 26M) * (1 << 28)

  int i, j;
  uint64_t PLL_cfg_val;
  uint16_t high, low, bit34_32;
  uint16_t val;

  if (pll_cfg_idx < ARRAY_SIZE(ana_pll_cfg) &&
      ana_pll_cfg[pll_cfg_idx].freq == freq &&
      ana_pll_cfg[pll_cfg_idx].div == div) {
    return;
  }

  j = ARRAY_SIZE(ana_pll_cfg);
  for (i = 0; i < ARRAY_SIZE(ana_pll_cfg); i++) {
    if (ana_pll_cfg[i].freq == freq && ana_pll_cfg[i].div == div) {
      break;
    }
    if (j == ARRAY_SIZE(ana_pll_cfg) && ana_pll_cfg[i].freq == 0) {
      j = i;
    }
  }

  if (i < ARRAY_SIZE(ana_pll_cfg)) {
    pll_cfg_idx = i;
    PLL_cfg_val = ana_pll_cfg[pll_cfg_idx].val;
  } else {
    if (j < ARRAY_SIZE(ana_pll_cfg)) {
      pll_cfg_idx = j;
    } else {
      pll_cfg_idx = 0;
    }

    PLL_cfg_val = ((uint64_t)(1 << 28) * freq * div + 26000000 / 2) / 26000000;

    ana_pll_cfg[pll_cfg_idx].freq = freq;
    ana_pll_cfg[pll_cfg_idx].div = div;
    ana_pll_cfg[pll_cfg_idx].val = PLL_cfg_val;
  }

  low = PLL_cfg_val & 0xFFFF;
  high = (PLL_cfg_val >> 16) & 0xFFFF;
  bit34_32 = (PLL_cfg_val >> 32) & 0xFFFF;

  pmu_pll_div_set(HAL_CMU_PLL_AUD, PMU_PLL_DIV_CODEC, div);

  analog_write(ANA_REG_7C, low);
  analog_write(ANA_REG_7B, high);
  analog_read(ANA_REG_7A, &val);
  val = SET_BITFIELD(val, REG_AUDPLL_FREQ_34_32, bit34_32) | REG_AUDPLL_FREQ_EN;
  analog_write(ANA_REG_7A, val);
}

void analog_aud_pll_tune(float ratio) {
#ifdef __AUDIO_RESAMPLE__
  if (hal_cmu_get_audio_resample_status()) {
    return;
  }
#endif

  // CODEC_FREQ is likely 24.576M (48K series) or 22.5792M (44.1K series)
  // PLL_nominal = CODEC_FREQ * CODEC_DIV
  // PLL_cfg_val = ((CODEC_FREQ * CODEC_DIV) / 26M) * (1 << 28)
  // Delta = ((SampleDiff / Fs) / TimeDiff) * PLL_cfg_val

  int64_t delta, new_pll;
  uint16_t new_high, new_low;
  uint16_t val, new_bit34_32;

  if (pll_cfg_idx >= ARRAY_SIZE(ana_pll_cfg) ||
      ana_pll_cfg[pll_cfg_idx].freq == 0) {
    ANALOG_INFO_TRACE(1,
                      "%s: WARNING: aud pll config cache invalid. Skip tuning",
                      __FUNCTION__);
    return;
  }

  if (ABS(ratio) > MAX_TOTAL_TUNE_RATIO) {
    ANALOG_INFO_TRACE(1,
                      "\n------\nWARNING: TUNE: ratio=%d is too large and will "
                      "be cut\n------\n",
                      FLOAT_TO_PPB_INT(ratio));
    if (ratio > 0) {
      ratio = MAX_TOTAL_TUNE_RATIO;
    } else {
      ratio = -MAX_TOTAL_TUNE_RATIO;
    }
  }

  ANALOG_INFO_TRACE(2, "%s: ratio=%d", __FUNCTION__, FLOAT_TO_PPB_INT(ratio));

  new_pll = (int64_t)ana_pll_cfg[pll_cfg_idx].val;
  delta = (int64_t)(new_pll * ratio);

  new_pll += delta;

  new_low = new_pll & 0xFFFF;
  new_high = (new_pll >> 16) & 0xFFFF;
  new_bit34_32 = (new_pll >> 32) & 0xFFFF;

  analog_write(ANA_REG_7C, new_low);
  analog_write(ANA_REG_7B, new_high);
  analog_read(ANA_REG_7A, &val);
  val = SET_BITFIELD(val, REG_AUDPLL_FREQ_34_32, new_bit34_32) |
        REG_AUDPLL_FREQ_EN;
  analog_write(ANA_REG_7A, val);
}

void analog_aud_osc_clk_enable(bool enable) {
  uint16_t val;

  if (enable) {
    analog_read(ANA_REG_RF_C4, &val);
    val |= CODEC_RESAMPLE_CLK_BUF_PU;
    analog_write(ANA_REG_RF_C4, val);

    analog_read(ANA_REG_7A, &val);
    val |= REG_PU_OSC;
    analog_write(ANA_REG_7A, val);

    analog_read(ANA_REG_75, &val);
    val |= REG_CRYSTAL_SEL_LV;
    analog_write(ANA_REG_75, val);
#if 0
        analog_read(ANA_REG_174, &val);
        val |= CFG_TX_CLK_INV;
        analog_write(ANA_REG_174, val);
#endif
  } else {
#if 0
        analog_read(ANA_REG_174, &val);
        val &= ~CFG_TX_CLK_INV;
        analog_write(ANA_REG_174, val);
#endif
    analog_read(ANA_REG_75, &val);
    val &= ~REG_CRYSTAL_SEL_LV;
    analog_write(ANA_REG_75, val);

    analog_read(ANA_REG_7A, &val);
    val &= ~REG_PU_OSC;
    analog_write(ANA_REG_7A, val);

    analog_read(ANA_REG_RF_C4, &val);
    val &= ~CODEC_RESAMPLE_CLK_BUF_PU;
    analog_write(ANA_REG_RF_C4, val);
  }
}

void analog_aud_pll_open(enum ANA_AUD_PLL_USER_T user) {
  if (user >= ANA_AUD_PLL_USER_END) {
    return;
  }

#ifdef __AUDIO_RESAMPLE__
  if (user == ANA_AUD_PLL_USER_CODEC && hal_cmu_get_audio_resample_status()) {

    analog_aud_osc_clk_enable(true);
    return;
  }
#endif

  if (ana_aud_pll_map == 0) {
    hal_cmu_pll_enable(HAL_CMU_PLL_AUD, HAL_CMU_PLL_USER_AUD);
  }
  ana_aud_pll_map |= user;
}

void analog_aud_pll_close(enum ANA_AUD_PLL_USER_T user) {
  if (user >= ANA_AUD_PLL_USER_END) {
    return;
  }

#ifdef __AUDIO_RESAMPLE__
  if (user == ANA_AUD_PLL_USER_CODEC && hal_cmu_get_audio_resample_status()) {

    analog_aud_osc_clk_enable(false);
    return;
  }
#endif

  ana_aud_pll_map &= ~user;
  if (ana_aud_pll_map == 0) {
    hal_cmu_pll_disable(HAL_CMU_PLL_AUD, HAL_CMU_PLL_USER_AUD);
  }
}

static void analog_aud_enable_dac(uint32_t dac) {
  uint16_t val_6e;
  uint16_t val_70;
  uint16_t val_73;

  analog_read(ANA_REG_6E, &val_6e);
  analog_read(ANA_REG_70, &val_70);

  if (dac & (AUD_CHANNEL_MAP_CH0 | AUD_CHANNEL_MAP_CH1)) {
    val_6e |= REG_CODEC_TX_EAR_DR_EN | REG_CODEC_TX_EAR_ENBIAS;
    analog_write(ANA_REG_6E, val_6e);
    osDelay(1);
    val_70 |= CFG_TX_TREE_EN;
    analog_write(ANA_REG_70, val_70);
    osDelay(1);

    val_73 = 0;
    if (dac & AUD_CHANNEL_MAP_CH0) {
      val_73 |=
          REG_CODEC_TX_EN_EARPA_L | REG_CODEC_TX_EN_LCLK | REG_CODEC_TX_EN_LDAC;
    }
    if (dac & AUD_CHANNEL_MAP_CH1) {
      val_73 |= REG_CODEC_TX_EN_EARPA_R | REG_CODEC_TX_EN_RCLK |
                REG_CODEC_TX_EN_RDAC | REG_CODEC_TX_EN_LDAC;
    }
    val_73 |= REG_CODEC_TX_EN_DACLDO | REG_CODEC_TX_EN_LPPA;
    analog_write(ANA_REG_73, val_73);
    osDelay(1);
    val_73 |= REG_CODEC_TX_EN_S1PA;
    analog_write(ANA_REG_73, val_73);
    // Ensure 1ms delay before enabling dac_pa
    osDelay(1);
  } else {
    // Ensure 1ms delay after disabling dac_pa
    osDelay(1);
    analog_read(ANA_REG_73, &val_73);
    val_73 &= ~REG_CODEC_TX_EN_S1PA;
    analog_write(ANA_REG_73, val_73);
    osDelay(1);
    val_73 = 0;
    analog_write(ANA_REG_73, val_73);
    osDelay(1);

    val_70 &= ~CFG_TX_TREE_EN;
    analog_write(ANA_REG_70, val_70);
    osDelay(1);

    val_6e &= ~(REG_CODEC_TX_EAR_DR_EN | REG_CODEC_TX_EAR_ENBIAS);
    analog_write(ANA_REG_6E, val_6e);
  }
}

static void analog_aud_enable_dac_pa(uint32_t dac) {
  uint16_t val_73;

  analog_read(ANA_REG_73, &val_73);

  if (dac & (AUD_CHANNEL_MAP_CH0 | AUD_CHANNEL_MAP_CH1)) {
    val_73 |= REG_CODEC_TX_EN_S4PA;
    analog_write(ANA_REG_73, val_73);

#ifdef AUDIO_OUTPUT_DC_CALIB_ANA
    hal_codec_dac_sdm_reset_clear();
#endif
  } else {
#ifdef AUDIO_OUTPUT_DC_CALIB_ANA
    hal_codec_dac_sdm_reset_set();
#endif

    val_73 &= ~REG_CODEC_TX_EN_S4PA;
    analog_write(ANA_REG_73, val_73);
  }
}

static void analog_aud_enable_adc(enum ANA_CODEC_USER_T user,
                                  enum AUD_CHANNEL_MAP_T ch_map, bool en) {
  int i;
  uint16_t val_61, val_6c, val_16a;
  enum ANA_CODEC_USER_T old_map;
  bool set;
  bool global_update;

  ANALOG_DEBUG_TRACE(3, "[%s] user=%d ch_map=0x%x", __func__, user, ch_map);

  global_update = false;

  analog_read(ANA_REG_61, &val_61);
  analog_read(ANA_REG_16A, &val_16a);

  for (i = 0; i < MAX_ANA_MIC_CH_NUM; i++) {
    if (ch_map & (AUD_CHANNEL_MAP_CH0 << i)) {
      set = false;
      if (en) {
        if (adc_map[i] == 0) {
          set = true;
        }
        adc_map[i] |= user;
      } else {
        old_map = adc_map[i];
        adc_map[i] &= ~user;
        if (old_map != 0 && adc_map[i] == 0) {
          set = true;
        }
      }
      if (set) {
        global_update = true;
        if (i == 4) {
          if (adc_map[i]) {
            val_16a |= REG_CODEC_EN_ADCE;
          } else {
            val_16a &= ~REG_CODEC_EN_ADCE;
          }
        } else {
          if (adc_map[i]) {
            val_61 |= (REG_CODEC_EN_ADCA << i);
          } else {
            val_61 &= ~(REG_CODEC_EN_ADCA << i);
          }
        }
      }
    }
  }

  analog_write(ANA_REG_61, val_61);
  analog_write(ANA_REG_16A, val_16a);

  if (global_update) {
    for (i = 0; i < MAX_ANA_MIC_CH_NUM; i++) {
      if (adc_map[i]) {
        break;
      }
    }
    analog_read(ANA_REG_6C, &val_6c);
    if (i < MAX_ANA_MIC_CH_NUM) {
      val_6c |= REG_CODEC_RX_EN_VTOI;
    } else {
      val_6c &= ~REG_CODEC_RX_EN_VTOI;
    }
    analog_write(ANA_REG_6C, val_6c);
  }
}

static uint32_t db_to_adc_gain(int db) {
  int i;
  uint8_t cnt;
  const int8_t *list;

  list = adc_db;
  cnt = ARRAY_SIZE(adc_db);

  for (i = 0; i < cnt - 1; i++) {
    if (db < list[i + 1]) {
      break;
    }
  }

  if (i == cnt - 1) {
    return i;
  } else if (db * 2 < list[i] + list[i + 1]) {
    return i;
  } else {
    return i + 1;
  }
}

static int8_t get_chan_adc_gain(uint32_t i) {
  int8_t gain;

  gain = tgt_adc_db[i];

#ifdef DYN_ADC_GAIN
  if (adc_gain_offset[i] < 0 && -adc_gain_offset[i] > gain) {
    gain = 0;
  } else {
    gain += adc_gain_offset[i];
  }
#endif

  return gain;
}

static void analog_aud_set_adc_gain(enum AUD_IO_PATH_T input_path,
                                    enum AUD_CHANNEL_MAP_T ch_map) {
  int i;
  int gain;
  uint16_t gain_val;
  uint16_t val, val_16a;

  analog_read(ANA_REG_63, &val);
  if (ch_map & AUD_CHANNEL_MAP_CH4) {
    analog_read(ANA_REG_16A, &val_16a);
  } else {
    val_16a = 0;
  }

  for (i = 0; i < MAX_ANA_MIC_CH_NUM; i++) {
    if (ch_map & (AUD_CHANNEL_MAP_CH0 << i)) {
      if (0) {
#ifdef ANC_APP
#ifdef ANC_FF_ENABLED
      } else if ((ANC_FF_MIC_CH_L | ANC_FF_MIC_CH_R) &
                 (AUD_CHANNEL_MAP_CH0 << i)) {
        gain = get_chan_adc_gain(i);
#endif
#ifdef ANC_FB_ENABLED
      } else if ((ANC_FB_MIC_CH_L | ANC_FB_MIC_CH_R) &
                 (AUD_CHANNEL_MAP_CH0 << i)) {
        gain = get_chan_adc_gain(i);
#endif
#endif
      } else if (input_path == AUD_INPUT_PATH_LINEIN) {
        gain = LINEIN_ADC_GAIN_DB;
      } else {
        gain = get_chan_adc_gain(i);
      }
      gain_val = db_to_adc_gain(gain);
      if (i < MAX_ANA_MIC_CH_NUM - 1) {
        val = (val & ~(REG_CODEC_ADCA_GAIN_BIT_MASK << 3 * i)) |
              (REG_CODEC_ADCA_GAIN_BIT(gain_val) << 3 * i);
      } else {
        val_16a = SET_BITFIELD(val_16a, REG_CODEC_ADCE_GAIN_BIT, gain_val);
      }
    }
  }

  analog_write(ANA_REG_63, val);
  if (ch_map & AUD_CHANNEL_MAP_CH4) {
    analog_write(ANA_REG_16A, val_16a);
  }
}

#ifdef ANC_APP
void analog_aud_apply_anc_adc_gain_offset(enum ANC_TYPE_T type,
                                          int16_t offset_l, int16_t offset_r) {
  enum ANC_TYPE_T single_type;
  enum AUD_CHANNEL_MAP_T ch_map;
  uint32_t l, r;
  int8_t org_l, adj_l;
  int8_t org_r, adj_r;

  // qdb to db
  offset_l /= 4;
  offset_r /= 4;

  while (type) {
    l = get_msb_pos(type);
    single_type = (1 << l);
    type &= ~single_type;

    ch_map = 0;
    l = r = 32;
    if (0) {
#if defined(ANC_FF_MIC_CH_L) || defined(ANC_FF_MIC_CH_R)
    } else if (single_type == ANC_FEEDFORWARD) {
      ch_map |= ANC_FF_MIC_CH_L | ANC_FF_MIC_CH_R;
      l = get_msb_pos(ANC_FF_MIC_CH_L);
      r = get_msb_pos(ANC_FF_MIC_CH_R);
#endif
#if defined(ANC_FB_MIC_CH_L) || defined(ANC_FB_MIC_CH_R)
    } else if (single_type == ANC_FEEDBACK) {
      ch_map = ANC_FB_MIC_CH_L | ANC_FB_MIC_CH_R;
      l = get_msb_pos(ANC_FB_MIC_CH_L);
      r = get_msb_pos(ANC_FB_MIC_CH_R);
#endif
    } else {
      continue;
    }

    if ((l >= MAX_ANA_MIC_CH_NUM || adc_gain_offset[l] == offset_l) &&
        (r >= MAX_ANA_MIC_CH_NUM || adc_gain_offset[r] == offset_r)) {
      continue;
    }

    ANALOG_INFO_TRACE(0, "ana: apply anc adc gain offset: type=%d offset=%d/%d",
                      single_type, offset_l, offset_r);

    org_l = adj_l = 0;
    if (l < MAX_ANA_MIC_CH_NUM) {
      adc_gain_offset[l] = 0;
      if (offset_l) {
        org_l = adc_db[db_to_adc_gain(get_chan_adc_gain(l))];
        adc_gain_offset[l] = offset_l;
        adj_l = adc_db[db_to_adc_gain(get_chan_adc_gain(l))];
      }
    }

    org_r = adj_r = 0;
    if (r < MAX_ANA_MIC_CH_NUM) {
      adc_gain_offset[r] = 0;
      if (offset_r) {
        org_r = adc_db[db_to_adc_gain(get_chan_adc_gain(r))];
        adc_gain_offset[r] = offset_r;
        adj_r = adc_db[db_to_adc_gain(get_chan_adc_gain(r))];
      }
    }

    hal_codec_apply_anc_adc_gain_offset(single_type, (org_l - adj_l),
                                        (org_r - adj_r));
    analog_aud_set_adc_gain(AUD_INPUT_PATH_MAINMIC, ch_map);
  }
}
#endif

#ifdef DYN_ADC_GAIN
void analog_aud_apply_adc_gain_offset(enum AUD_CHANNEL_MAP_T ch_map,
                                      int16_t offset) {
  enum AUD_CHANNEL_MAP_T map;
  int i;

#ifdef ANC_APP
#ifdef ANC_FF_ENABLED
  ch_map &= ~(ANC_FF_MIC_CH_L | ANC_FF_MIC_CH_R);
#endif
#ifdef ANC_FB_ENABLED
  ch_map &= ~(ANC_FB_MIC_CH_L | ANC_FB_MIC_CH_R);
#endif
#endif

  if (ch_map) {
    map = ch_map;

    while (map) {
      i = get_msb_pos(map);
      map &= ~(1 << i);
      if (i < MAX_ANA_MIC_CH_NUM) {
        adc_gain_offset[i] = offset;
      }
    }

    ANALOG_INFO_TRACE(2, "ana: apply adc gain offset: ch_map=0x%X offset=%d",
                      ch_map, offset);

    analog_aud_set_adc_gain(AUD_INPUT_PATH_MAINMIC, ch_map);
  }
}
#endif

void analog_aud_set_dac_gain(int32_t v) {}

uint32_t analog_codec_get_dac_gain(void) { return 0; }

uint32_t analog_codec_dac_gain_to_db(int32_t gain) { return 0; }

int32_t analog_codec_dac_max_attn_db(void) { return 0; }

static int POSSIBLY_UNUSED dc_calib_checksum_valid(uint32_t efuse) {
  int i;
  uint32_t cnt = 0;
  uint32_t chksum_mask = (1 << (16 - DAC_DC_CALIB_BIT_WIDTH)) - 1;

  for (i = 0; i < DAC_DC_CALIB_BIT_WIDTH; i++) {
    if (efuse & (1 << i)) {
      cnt++;
    }
  }

  return (((~cnt) & chksum_mask) ==
          ((efuse >> DAC_DC_CALIB_BIT_WIDTH) & chksum_mask));
}

static int16_t dc_calib_val_decode(int16_t val) {
#ifdef AUDIO_OUTPUT_DC_CALIB_ANA
  uint32_t sign_bit = (1 << (DAC_DC_CALIB_BIT_WIDTH - 1));
  uint32_t num_mask = sign_bit - 1;

  if (val & sign_bit) {
    val = -(val & num_mask);
  }
#endif
  return val;
}

void analog_aud_get_dc_calib_value(int16_t *dc_l, int16_t *dc_r) {
  static const uint8_t EFUSE_PAGE_DIFF_1P7V[2] = {
      PMU_EFUSE_PAGE_DCCALIB2_L,
      PMU_EFUSE_PAGE_DCCALIB2_R,
  };
  static const uint8_t EFUSE_PAGE_DIFF_1P95V[2] = {
      PMU_EFUSE_PAGE_DCCALIB_L,
      PMU_EFUSE_PAGE_DCCALIB_R,
  };
  const uint8_t *page;
  uint16_t efuse;

  union DC_EFUSE_T {
    struct DC_VALUE_T {
      int16_t dc : DAC_DC_CALIB_BIT_WIDTH;
      uint16_t checksum : (16 - DAC_DC_CALIB_BIT_WIDTH);
    } val;
    uint16_t reg;
  };
  union DC_EFUSE_T dc;

  if (vcodec_mv >= 1900) {
    page = EFUSE_PAGE_DIFF_1P95V;
  } else {
    page = EFUSE_PAGE_DIFF_1P7V;
  }

  pmu_get_efuse(page[0], &efuse);
  if (dc_calib_checksum_valid(efuse)) {
    ANALOG_INFO_TRACE(1, "Dc calib L OK: 0x%04x", efuse);
    dc.reg = efuse;
    *dc_l = dc.val.dc;
  } else {
    ANALOG_INFO_TRACE(1, "Warning: Bad dc calib efuse L: 0x%04x", efuse);
    *dc_l = 0;
  }

  pmu_get_efuse(page[1], &efuse);
  if (dc_calib_checksum_valid(efuse)) {
    ANALOG_INFO_TRACE(1, "Dc calib R OK: 0x%04x", efuse);
    dc.reg = efuse;
    *dc_r = dc.val.dc;
  } else {
    ANALOG_INFO_TRACE(1, "Warning: Bad dc calib efuse R: 0x%04x", efuse);
    *dc_r = 0;
  }

  ANALOG_INFO_TRACE(2, "ANA: DC CALIB L=0x%04hX/%d R=0x%04hX/%d", *dc_l,
                    dc_calib_val_decode(*dc_l), *dc_r,
                    dc_calib_val_decode(*dc_r));

#if defined(ANA_DC_CALIB_L) || defined(ANA_DC_CALIB_R)
#ifdef ANA_DC_CALIB_L
  *dc_l = ANA_DC_CALIB_L;
#endif
#ifdef ANA_DC_CALIB_R
  *dc_r = ANA_DC_CALIB_R;
#endif
  ANALOG_INFO_TRACE(2, "ANA: OVERRIDE DC CALIB L=0x%04hX/%d R=0x%04hX/%d",
                    *dc_l, dc_calib_val_decode(*dc_l), *dc_r,
                    dc_calib_val_decode(*dc_r));
#endif

  return;
}

#ifdef AUDIO_OUTPUT_DC_CALIB_ANA
static void analog_aud_dc_calib_init(void) {
  uint16_t val;
  int16_t dc_l, dc_r;

  analog_aud_get_dc_calib_value(&dc_l, &dc_r);

  analog_read(ANA_REG_71, &val);
  val = SET_BITFIELD(val, REG_CODEC_TX_EAR_OFF_BITL, dc_l);
  analog_write(ANA_REG_71, val);

  analog_read(ANA_REG_72, &val);
  val = SET_BITFIELD(val, REG_CODEC_TX_EAR_OFF_BITR, dc_r);
  analog_write(ANA_REG_72, val);
}

static void analog_aud_dc_calib_enable(bool en) {
  uint16_t val;

  analog_read(ANA_REG_70, &val);
  val |= REG_CODEC_TX_EAR_OFFEN;
  analog_write(ANA_REG_70, val);
}
#endif

static void analog_aud_vcodec_enable(enum ANA_CODEC_USER_T user, bool en) {
  uint32_t lock;
  bool set = false;

  lock = int_lock();
  if (en) {
    if (vcodec_map == 0) {
      set = true;
    }
    vcodec_map |= user;
  } else {
    vcodec_map &= ~user;
    if (vcodec_map == 0) {
      set = true;
    }
  }
  int_unlock(lock);

  if (set) {
    pmu_codec_config(!!vcodec_map);
  }
}

static void analog_aud_enable_common_internal(enum ANA_CODEC_USER_T user,
                                              bool en) {
  uint32_t lock;
  uint16_t val_6b;
  bool set = false;

  lock = int_lock();
  if (en) {
    if (codec_common_map == 0) {
      set = true;
    }
    codec_common_map |= user;
  } else {
    codec_common_map &= ~user;
    if (codec_common_map == 0) {
      set = true;
    }
  }
  int_unlock(lock);

  if (set) {
    analog_read(ANA_REG_6B, &val_6b);
    if (codec_common_map) {
      val_6b |= REG_CODEC_EN_VCM;
    } else {
      val_6b &= ~(REG_CODEC_EN_VCM | REG_CODEC_VCM_EN_LPF);
    }
    if (codec_common_map) {
      // RTOS application startup time is long enougth for VCM charging
#if !(defined(VCM_ON) && defined(RTOS))
      // VCM fully stable time is about 60ms/1.95V or 150ms/1.7V
      // Quick startup:
      // 1) Disable VCM LPF and target to a higher voltage than the required one
      // 2) Wait for a short time when VCM is in quick charge (high voltage)
      // 3) Enable VCM LPF and target to the required VCM LPF voltage
      analog_write(ANA_REG_6B, SET_BITFIELD(val_6b, REG_CODEC_VCM_LOW_VCM, 0));
      uint32_t delay;

#if defined(VCM_CAP_100NF)
      if (vcodec_mv >= 1900) {
        delay = 6;
      } else {
        delay = 10;
      }
#else
      if (vcodec_mv >= 1900) {
        delay = 25;
      } else {
        delay = 100;
      }
#endif
      osDelay(delay);
#if 0
            // Target to a voltage near the required one
            analog_write(ANA_REG_6B, val_6b);
            osDelay(10);
#endif
#endif // !(VCM_ON && RTOS)
      val_6b |= REG_CODEC_VCM_EN_LPF;
    }
    analog_write(ANA_REG_6B, val_6b);
  }
}

static void analog_aud_enable_codec_common(enum ANA_CODEC_USER_T user,
                                           bool en) {
#ifndef VCM_ON
  analog_aud_enable_common_internal(user, en);
#endif
}

static void analog_aud_enable_adda_common(enum ANA_CODEC_USER_T user, bool en) {
  uint32_t lock;
  uint16_t val_6a, val_6b, val_74, val_7e;
  bool set = false;

  lock = int_lock();
  if (en) {
    if (adda_common_map == 0) {
      set = true;
    }
    adda_common_map |= user;
  } else {
    adda_common_map &= ~user;
    if (adda_common_map == 0) {
      set = true;
    }
  }
  int_unlock(lock);

  if (set) {
    analog_read(ANA_REG_6A, &val_6a);
    analog_read(ANA_REG_6B, &val_6b);
    if (vcodec_mv >= 1700) {
      analog_read(ANA_REG_74, &val_74);
    } else {
      val_74 = 0;
    }
    analog_read(ANA_REG_7E, &val_7e);
    if (adda_common_map) {
      val_6a |= REG_CODEC_EN_BIAS;
      analog_write(ANA_REG_6A, val_6a);
      if (vcodec_mv >= 1700) {
        val_74 |= REG_PU_TX_REGULATOR;
        analog_write(ANA_REG_74, val_74);
        hal_sys_timer_delay_us(10);
        val_74 &= ~REG_BYPASS_TX_REGULATOR;
        analog_write(ANA_REG_74, val_74);
      }
      val_6b |= REG_CODEC_EN_VCM_BUFFER;
      val_7e |= REG_PU_CLKMUX_LDO0P9;
    } else {
      val_6b &= ~REG_CODEC_EN_VCM_BUFFER;
      val_7e &= ~REG_PU_CLKMUX_LDO0P9;
      if (vcodec_mv >= 1700) {
        val_74 |= REG_BYPASS_TX_REGULATOR;
        analog_write(ANA_REG_74, val_74);
        val_74 &= ~REG_PU_TX_REGULATOR;
        analog_write(ANA_REG_74, val_74);
      }
      val_6a &= ~REG_CODEC_EN_BIAS;
      analog_write(ANA_REG_6A, val_6a);
    }
    analog_write(ANA_REG_6B, val_6b);
    analog_write(ANA_REG_7E, val_7e);
  }
}

static void analog_aud_enable_vmic(enum ANA_CODEC_USER_T user, uint32_t dev) {
  uint32_t lock;
  enum ANA_CODEC_USER_T old_map;
  bool set = false;
  int i;
  uint32_t pmu_map = 0;

  lock = int_lock();

  for (i = 0; i < MAX_ANA_MIC_CH_NUM; i++) {
    if (dev & (AUD_VMIC_MAP_VMIC1 << i)) {
      if (vmic_map[i] == 0) {
        set = true;
      }
      vmic_map[i] |= user;
    } else {
      old_map = vmic_map[i];
      vmic_map[i] &= ~user;
      if (old_map != 0 && vmic_map[i] == 0) {
        set = true;
      }
    }

    if (vmic_map[i]) {
      pmu_map |= (AUD_VMIC_MAP_VMIC1 << i);
    }
  }

  int_unlock(lock);

  if (set) {
    pmu_codec_mic_bias_enable(pmu_map);
#ifdef VOICE_DETECTOR_EN
    pmu_codec_mic_bias_lowpower_mode(pmu_map);
#endif
    if (pmu_map) {
      osDelay(1);
    }
  }
}

uint32_t analog_aud_get_max_dre_gain(void) {
  if (vcodec_mv >= 1900) {
    return 0x11;
  } else {
    return 0xF;
  }
}

int analog_reset(void) { return 0; }

void analog_open(void) {
  uint16_t val;

  val = REG_CODEC_ADCA_CH_SEL(1) | REG_CODEC_ADCB_CH_SEL(1) |
        REG_CODEC_ADCC_CH_SEL(1) | REG_CODEC_ADCD_CH_SEL(1);
  analog_write(ANA_REG_61, val);

  val = CFG_RESET_PGAA_DR | CFG_RESET_PGAB_DR | CFG_RESET_PGAC_DR |
        CFG_RESET_PGAD_DR;
  analog_write(ANA_REG_62, val);

  val = 0; // REG_CODEC_ADCA_GAIN_UPDATE | REG_CODEC_ADCB_GAIN_UPDATE |
           // REG_CODEC_ADCC_GAIN_UPDATE | REG_CODEC_ADCD_GAIN_UPDATE;
  analog_write(ANA_REG_63, val);

  val = REG_CODEC_ADC_IBSEL_REG(8) | REG_CODEC_ADC_IBSEL_VCOMP(8) |
        REG_CODEC_ADC_IBSEL_VREF(8) | REG_CODEC_ADC_LPFVCM_SW(7);
  analog_write(ANA_REG_67, val);

  val = REG_CODEC_ADC_OP1_IBIT(2) | REG_CODEC_ADC_VREF_SEL(4);
  analog_write(ANA_REG_68, val);

  val = REG_CODEC_BIAS_IBSEL(8) | REG_CODEC_BIAS_IBSEL_VOICE(8);
  if (vcodec_mv >= 1900) {
    val |= REG_CODEC_BIAS_IBSEL_TX(5);
  } else {
#ifdef LOW_CODEC_BIAS
    val |= REG_CODEC_BIAS_IBSEL_TX(1);
#else
    val |= REG_CODEC_BIAS_IBSEL_TX(3);
#endif
  }
  analog_write(ANA_REG_69, val);

  val = REG_CODEC_ADC_REG_VSEL(3) | REG_CODEC_BUF_LOWVCM(4) |
        REG_CODEC_EN_RX_EXT | REG_CODEC_EN_TX_EXT | REG_CODEC_DAC_CLK_EDGE_SEL;
  val |= REG_CODEC_EN_BIAS_LP;
  analog_write(ANA_REG_6A, val);

  uint16_t vcm, vcm_lpf;
  if (vcodec_mv >= 1900) {
    vcm = 7;
    vcm_lpf = 0xA;
  } else if (vcodec_mv >= 1800) {
    vcm = vcm_lpf = 7;
  } else {
    vcm = vcm_lpf = 7;
  }
  val = REG_CODEC_VCM_LOW_VCM(vcm) | REG_CODEC_VCM_LOW_VCM_LP(vcm) |
        REG_CODEC_VCM_LOW_VCM_LPF(vcm_lpf);
  analog_write(ANA_REG_6B, val);

  val = REG_CODEC_RX_VTOI_I_DAC2(4) | REG_CODEC_RX_VTOI_IDAC_SEL(8) |
        REG_CODEC_RX_VTOI_VCS_SEL(0x10);
  analog_write(ANA_REG_6C, val);

  if (vcodec_mv > 1900) {
    val = REG_CODEC_TX_DAC_VREF_L(9) | REG_CODEC_TX_DAC_VREF_R(9) |
          REG_CODEC_TX_EAR_CAS_BIT(3);
  } else if (vcodec_mv == 1900) {
    val = REG_CODEC_TX_DAC_VREF_L(0xA) | REG_CODEC_TX_DAC_VREF_R(0xA) |
          REG_CODEC_TX_EAR_CAS_BIT(3);
  } else {
    val = REG_CODEC_TX_DAC_VREF_L(2) | REG_CODEC_TX_DAC_VREF_R(2) |
          REG_CODEC_TX_EAR_CAS_BIT(1);
  }
  analog_write(ANA_REG_6D, val);

  val = REG_CODEC_TX_EAR_IBSEL(2);
#ifdef LOW_CODEC_BIAS
  if (vcodec_mv < 1900) {
    val = REG_CODEC_TX_EAR_IBSEL(0);
  }
#endif
  val |= REG_CODEC_TX_EAR_COMP_L(7) | REG_CODEC_TX_EAR_COMP_R(7) |
         REG_CODEC_TX_EAR_DR_ST(1) | REG_CODEC_TX_EAR_FBCAP(3);
  analog_write(ANA_REG_6E, val);

  val = REG_CODEC_TX_EAR_DRE_GAIN_L(0xF) | REG_CODEC_TX_EAR_DRE_GAIN_R(0xF) |
        DRE_GAIN_SEL_L | DRE_GAIN_SEL_R | REG_CODEC_TX_EAR_GAIN(1);
#ifdef DAC_DRE_GAIN_DC_UPDATE
  val |=
      REG_CODEC_TX_EAR_DRE_GAIN_L_UPDATE | REG_CODEC_TX_EAR_DRE_GAIN_R_UPDATE;
#endif
  analog_write(ANA_REG_6F, val);

  val = REG_CODEC_TX_EAR_OUTPUTSEL(1) | REG_CODEC_TX_EAR_SOFTSTART(8) |
        REG_CODEC_TX_EAR_OCEN | REG_CODEC_TX_EAR_LPBIAS;
  analog_write(ANA_REG_70, val);

  val = REG_DAC_LDO0P9_VSEL(2) | REG_BYPASS_TX_REGULATOR |
        REG_CODEC_TX_EAR_VCM_BIT(3) | REG_CODEC_TX_EAR_VCM_SEL;
  if (vcodec_mv >= 1900) {
    val |= REG_CODEC_TX_RVREF_CAP_BIT | REG_TX_REGULATOR_BIT(0xD);
  } else {
    val |= REG_TX_REGULATOR_BIT(4);
  }
  analog_write(ANA_REG_74, val);

  val = REG_CLKMUX_DVDD_SEL | REG_CLKMUX_LDO0P9_VSEL(2) |
        REG_AUDPLL_LDO_VREF(4) | REG_AUDPLL_LPF_BW_SEL;
  analog_write(ANA_REG_7E, val);

  // Optimize bottom noise, dig_codec_adcE_vref_sel[3:0] should be 0x4 ————by
  // jeff 20200916
  analog_read(ANA_REG_16E, &val);
  val = SET_BITFIELD(val, DIG_CODEC_ADCE_VREF_SEL, 0x4);
  analog_write(ANA_REG_16E, val);

#ifdef AUDIO_OUTPUT_DC_CALIB_ANA
  analog_aud_dc_calib_init();
  analog_aud_dc_calib_enable(true);
#endif

#ifdef VCM_ON
  analog_aud_enable_common_internal(ANA_CODEC_USER_DAC, true);
#endif
}

void analog_sleep(void) {
#ifdef VOICE_DETECTOR_EN
  if ((adda_common_map & ANA_CODEC_USER_VAD) &&
      (adc_map[4] & ANA_CODEC_USER_VAD) == 0) {
    uint16_t val;

    analog_read(ANA_REG_6B, &val);
    val = (val & ~REG_CODEC_EN_VCM_BUFFER) | REG_CODEC_LP_VCM;
    analog_write(ANA_REG_6B, val);
  }
#endif
}

void analog_wakeup(void) {
#ifdef VOICE_DETECTOR_EN
  if ((adda_common_map & ANA_CODEC_USER_VAD) &&
      (adc_map[4] & ANA_CODEC_USER_VAD) == 0) {
    uint16_t val;

    analog_read(ANA_REG_6B, &val);
    val = (val & ~REG_CODEC_LP_VCM) | REG_CODEC_EN_VCM_BUFFER;
    analog_write(ANA_REG_6B, val);
  }
#endif
}

void analog_aud_codec_anc_enable(enum ANC_TYPE_T type, bool en) {
  enum ANA_CODEC_USER_T user;
  enum AUD_CHANNEL_MAP_T ch_map;

  user = 0;
  ch_map = 0;
#if defined(ANC_FF_MIC_CH_L) || defined(ANC_FF_MIC_CH_R)
  if (type & ANC_FEEDFORWARD) {
    user |= ANA_CODEC_USER_ANC_FF;
    ch_map |= ANC_FF_MIC_CH_L | ANC_FF_MIC_CH_R;
  }
#endif
#if defined(ANC_FB_MIC_CH_L) || defined(ANC_FB_MIC_CH_R)
  if (type & ANC_FEEDFORWARD) {
    user |= ANA_CODEC_USER_ANC_FB;
    ch_map |= ANC_FB_MIC_CH_L | ANC_FB_MIC_CH_R;
  }
#endif

  ANALOG_DEBUG_TRACE(0, "%s: type=%d en=%d ch_map=0x%x", __func__, type, en,
                     ch_map);

  if (en) {
    analog_aud_enable_vmic(user, ANC_VMIC_CFG);
    analog_aud_enable_codec_common(user, true);
    analog_aud_enable_adda_common(user, true);
    analog_aud_set_adc_gain(AUD_INPUT_PATH_MAINMIC, ch_map);
    analog_aud_enable_adc(user, ch_map, true);
  } else {
    analog_aud_apply_anc_adc_gain_offset(type, 0, 0);
    analog_aud_enable_adc(user, ch_map, false);
    analog_aud_enable_adda_common(user, false);
    analog_aud_enable_codec_common(user, false);
    analog_aud_enable_vmic(user, 0);
  }
}

void analog_aud_codec_anc_boost(bool en,
                                ANALOG_ANC_BOOST_DELAY_FUNC delay_func) {
  uint16_t val;
  int ret;

  if (vcodec_mv >= 1800) {
    return;
  }

  if (delay_func == NULL) {
    delay_func = (ANALOG_ANC_BOOST_DELAY_FUNC)osDelay;
  }

  if (en) {
    // -2.1 dB
    hal_codec_set_anc_boost_gain_attn(0.78523563f);
    delay_func(1);
  }

  analog_read(ANA_REG_6B, &val);
  val &= ~REG_CODEC_VCM_EN_LPF;
  analog_write(ANA_REG_6B, val);
  osDelay(1);

  do {
    if (en) {
      ret = pmu_codec_volt_ramp_up();
    } else {
      ret = pmu_codec_volt_ramp_down();
    }
    delay_func(1);
  } while (ret);

  analog_read(ANA_REG_6B, &val);
  val |= REG_CODEC_VCM_EN_LPF;
  analog_write(ANA_REG_6B, val);

  if (!en) {
    delay_func(1);
    // 0 dB
    hal_codec_set_anc_boost_gain_attn(1.0f);
  }
}

void analog_aud_mickey_enable(bool en) {
  if (en) {
    analog_aud_vcodec_enable(ANA_CODEC_USER_MICKEY, true);
    analog_aud_enable_vmic(ANA_CODEC_USER_MICKEY, CFG_HW_AUD_MICKEY_DEV);
    analog_aud_enable_codec_common(ANA_CODEC_USER_MICKEY, true);
  } else {
    analog_aud_enable_codec_common(ANA_CODEC_USER_MICKEY, false);
    analog_aud_enable_vmic(ANA_CODEC_USER_MICKEY, 0);
    analog_aud_vcodec_enable(ANA_CODEC_USER_MICKEY, false);
  }
}

void analog_aud_codec_adc_enable(enum AUD_IO_PATH_T input_path,
                                 enum AUD_CHANNEL_MAP_T ch_map, bool en) {
  uint32_t dev;

  if (en) {
    dev = hal_codec_get_input_path_cfg(input_path);
    // Enable vmic first to overlap vmic stable time with codec vcm stable time
    analog_aud_enable_vmic(ANA_CODEC_USER_ADC, dev);
    analog_aud_enable_codec_common(ANA_CODEC_USER_ADC, true);
    analog_aud_enable_adda_common(ANA_CODEC_USER_ADC, true);
    analog_aud_set_adc_gain(input_path, ch_map);
    analog_aud_enable_adc(ANA_CODEC_USER_ADC, ch_map, true);
  } else {
    analog_aud_enable_adc(ANA_CODEC_USER_ADC, ch_map, false);
    analog_aud_enable_adda_common(ANA_CODEC_USER_ADC, false);
    analog_aud_enable_codec_common(ANA_CODEC_USER_ADC, false);
    analog_aud_enable_vmic(ANA_CODEC_USER_ADC, 0);
  }
}

static void analog_aud_codec_config_speaker(void) {
  bool en;

  if (ana_spk_req && !ana_spk_muted) {
    en = true;
  } else {
    en = false;
  }

  if (ana_spk_enabled != en) {
    ana_spk_enabled = en;
    if (en) {
      analog_aud_enable_dac_pa(CFG_HW_AUD_OUTPUT_PATH_SPEAKER_DEV);
    } else {
      analog_aud_enable_dac_pa(0);
    }
  }
}

void analog_aud_codec_speaker_enable(bool en) {
  ana_spk_req = en;
  analog_aud_codec_config_speaker();
}

void analog_aud_codec_dac_enable(bool en) {
  if (en) {
    analog_aud_enable_codec_common(ANA_CODEC_USER_DAC, true);
    analog_aud_enable_adda_common(ANA_CODEC_USER_DAC, true);
    pmu_codec_hppa_enable(1);
    analog_aud_enable_dac(CFG_HW_AUD_OUTPUT_PATH_SPEAKER_DEV);
#if !defined(AUDIO_OUTPUT_DC_CALIB_ANA) && !defined(AUDIO_OUTPUT_DC_CALIB)
    osDelay(1);
    analog_aud_codec_speaker_enable(true);
#endif
  } else {
#if !defined(AUDIO_OUTPUT_DC_CALIB_ANA) && !defined(AUDIO_OUTPUT_DC_CALIB)
    analog_aud_codec_speaker_enable(false);
    osDelay(1);
#endif
    analog_aud_enable_dac(0);
    pmu_codec_hppa_enable(0);
    analog_aud_enable_adda_common(ANA_CODEC_USER_DAC, false);
    analog_aud_enable_codec_common(ANA_CODEC_USER_DAC, false);
  }
}

void analog_aud_codec_open(void) {
  analog_aud_vcodec_enable(ANA_CODEC_USER_CODEC, true);

#ifdef _AUTO_SWITCH_POWER_MODE__
  // pmu_mode_change(PMU_POWER_MODE_DIG_DCDC);
#endif
}

void analog_aud_codec_close(void) {
  static const enum AUD_CHANNEL_MAP_T all_ch =
      AUD_CHANNEL_MAP_CH0 | AUD_CHANNEL_MAP_CH1 | AUD_CHANNEL_MAP_CH2 |
      AUD_CHANNEL_MAP_CH3 | AUD_CHANNEL_MAP_CH4;

  analog_aud_codec_speaker_enable(false);
  osDelay(1);
  analog_aud_codec_dac_enable(false);

  analog_aud_codec_adc_enable(AUD_IO_PATH_NULL, all_ch, false);

#ifdef _AUTO_SWITCH_POWER_MODE__
  // pmu_mode_change(PMU_POWER_MODE_ANA_DCDC);
#endif

  analog_aud_vcodec_enable(ANA_CODEC_USER_CODEC, false);
}

void analog_aud_codec_mute(void) {
#ifndef AUDIO_OUTPUT_DC_CALIB
  // analog_codec_tx_pa_gain_sel(0);
#endif

  ana_spk_muted = true;
  analog_aud_codec_config_speaker();
}

void analog_aud_codec_nomute(void) {
  ana_spk_muted = false;
  analog_aud_codec_config_speaker();

#ifndef AUDIO_OUTPUT_DC_CALIB
  // analog_aud_set_dac_gain(dac_gain);
#endif
}

int analog_debug_config_audio_output(bool diff) { return 0; }

int analog_debug_config_codec(uint16_t mv) {
#ifdef ANC_PROD_TEST
  int ret;

  ret = pmu_debug_config_codec(mv);
  if (ret) {
    return ret;
  }

  vcodec_mv = mv;
#endif
  return 0;
}

int analog_debug_config_low_power_adc(bool enable) { return 0; }

void analog_debug_config_anc_calib_mode(bool enable) {
  anc_calib_mode = enable;
}

bool analog_debug_get_anc_calib_mode(void) { return anc_calib_mode; }

int analog_debug_config_vad_mic(bool enable) { return 0; }

#ifdef VOICE_DETECTOR_EN

static void analog_aud_codec_vad_ini(void) {
#if 1
  unsigned short v;

#if 0
    //0x6a,0x0503
    analog_read(ANA_REG_6A, &v);
    v = SET_BITFIELD(v, REG_CODEC_ADC_REG_VSEL, 0x3);
    v = SET_BITFIELD(v, REG_CODEC_BUF_LOWVCM, 0x4);
    v |= REG_CODEC_EN_BIAS_LP;
    analog_write(ANA_REG_6A, v);

    //0x6b,0x3bbf
    analog_read(ANA_REG_6B, &v);
#if 0
    v = SET_BITFIELD(v, REG_CODEC_VCM_LOW_VCM, 0x7);
    v = SET_BITFIELD(v, REG_CODEC_VCM_LOW_VCM_LP, 0x7);
    v = SET_BITFIELD(v, REG_CODEC_VCM_LOW_VCM_LPF, 0x7);
    v &= ~REG_CODEC_EN_VCM_BUFFER;
#else
    v = SET_BITFIELD(v, REG_CODEC_VCM_LOW_VCM, 0x6);
    v = SET_BITFIELD(v, REG_CODEC_VCM_LOW_VCM_LP, 0x6);
    v = SET_BITFIELD(v, REG_CODEC_VCM_LOW_VCM_LPF, 0x6);
    v |= REG_CODEC_EN_VCM_BUFFER;
#endif
    analog_write(ANA_REG_6B, v);

    //0x74,0xc544
    analog_read(ANA_REG_74, &v);
    v &= ~REG_CODEC_TX_RVREF_CAP_BIT;
    v = SET_BITFIELD(v, REG_DAC_LDO0P9_VSEL, 0x2);
#if 0
    v |= REG_BYPASS_TX_REGULATOR;
    v &= ~REG_PU_TX_REGULATOR;
#else
    v &= ~REG_BYPASS_TX_REGULATOR;
    v |= REG_PU_TX_REGULATOR;
#endif
    v = SET_BITFIELD(v, REG_TX_REGULATOR_BIT, 0x5);
    v = SET_BITFIELD(v, REG_CODEC_TX_EAR_VCM_BIT, 0x2);
    v |= REG_CODEC_TX_EAR_VCM_SEL;
    analog_write(ANA_REG_74, v);
#endif

  // 0x173, 0x0805
  v = REG_VOICE_LDO_VBIT(5) | CFG_VOICE_DET_DELAY(8);
  analog_write(ANA_REG_173, v);

  // 0x17d,0x817f
  v = REG_CLK_GOAL_DIV_NUM(0x17f) | REG_COARSE_TUN_CODE_DR;
  analog_write(ANA_REG_17D, v);

#if 1
  // 0x171,0x1047
  v = CFG_VOICE_RESET | CFG_VOICE_PU_DELAY(4) | CFG_VOICE_PRECH_DELAY(0x7f);
  analog_write(ANA_REG_171, v);
#endif

  // 0x17a
  analog_read(ANA_REG_17A, &v);
  v = SET_BITFIELD(v, REG_VOICE_LOW_TUNE, 0x3);
  analog_write(ANA_REG_17A, v);

  // 0x161[15] = 1;   //cfg_reg_clkmux_dvdd_sel
  analog_read(ANA_REG_161, &v);
  v |= 1 << 15;
  analog_write(ANA_REG_161, v);

  // 0x170[15] = 1;   //cfg_voice2adcE
  analog_read(ANA_REG_170, &v);
  v = SET_BITFIELD(v, REG_VOICE_GAIN_A, 0x3);
  v = SET_BITFIELD(v, REG_VOICE_GAIN_B, 0x3);
  v = SET_BITFIELD(v, REG_VOICE_HIGH_TUNE_A, 0xa);
  v = SET_BITFIELD(v, REG_VOICE_HIGH_TUNE_B, 0x4);
  v |= CFG_VOICE2ADCE;
  analog_write(ANA_REG_170, v);

  osDelay(1);
#endif
}

static void analog_aud_codec_vad_fin(void) {
  unsigned short v;

  analog_read(ANA_REG_170, &v);
  v &= ~CFG_VOICE2ADCE;
  analog_write(ANA_REG_170, v);
}

static void analog_aud_codec_vad_trig_en(bool en) {
#if 1
  unsigned short v;
  uint32_t lock;

  lock = int_lock();
  analog_read(ANA_REG_171, &v);
  if (en)
    v |= CFG_VOICE_TRIG_ENABLE;
  else
    v &= ~CFG_VOICE_TRIG_ENABLE;

  analog_write(ANA_REG_171, v);

  int_unlock(lock);
#endif
}

static void analog_aud_codec_vad_pu(bool en) {
#if 1
  unsigned short v;
  uint32_t lock;

  lock = int_lock();
  analog_read(ANA_REG_171, &v);
  if (en)
    v |= CFG_VOICE_POWER_ON;
  else
    v &= ~CFG_VOICE_POWER_ON;

  analog_write(ANA_REG_171, v);
  int_unlock(lock);
#endif
}

void analog_aud_vad_enable(enum AUD_VAD_TYPE_T type, bool en) {
  if (type == AUD_VAD_TYPE_DIG) {
    uint32_t dev;
    enum AUD_CHANNEL_MAP_T ch_map;

    dev = hal_codec_get_input_path_cfg(AUD_INPUT_PATH_VADMIC);
    ch_map = dev & AUD_CHANNEL_MAP_ANA_ALL;
    analog_aud_enable_adc(ANA_CODEC_USER_VAD, ch_map, en);
  } else if (type == AUD_VAD_TYPE_MIX || type == AUD_VAD_TYPE_ANA) {
    if (en) {
      analog_aud_codec_vad_ini();
      analog_aud_codec_vad_pu(true);
      osDelay(1);
      analog_aud_codec_vad_trig_en(true);
      // pmu_codec_vad_save_power();
    } else {
      // pmu_codec_vad_restore_power();
      // Must power off before disabling trigger
      analog_aud_codec_vad_pu(false);
      osDelay(1);
      analog_aud_codec_vad_trig_en(false);
      analog_aud_codec_vad_fin();
    }
  }
}

void analog_aud_vad_adc_enable(bool en) {
  uint32_t dev;
  enum AUD_CHANNEL_MAP_T ch_map;

  dev = hal_codec_get_input_path_cfg(AUD_INPUT_PATH_VADMIC);
  ch_map = dev & AUD_CHANNEL_MAP_ANA_ALL;

  if (en) {
    // Enable vmic first to overlap vmic stable time with codec vcm stable time
    analog_aud_enable_vmic(ANA_CODEC_USER_VAD, dev);
    analog_aud_enable_codec_common(ANA_CODEC_USER_VAD, true);
    analog_aud_enable_adda_common(ANA_CODEC_USER_VAD, true);
    analog_aud_set_adc_gain(AUD_INPUT_PATH_VADMIC, ch_map);
  } else {
    analog_aud_enable_adda_common(ANA_CODEC_USER_VAD, false);
    analog_aud_enable_codec_common(ANA_CODEC_USER_VAD, false);
    analog_aud_enable_vmic(ANA_CODEC_USER_VAD, 0);
  }
}

#endif
