diff options
Diffstat (limited to 'chip/npcx/apm.c')
-rw-r--r-- | chip/npcx/apm.c | 694 |
1 files changed, 0 insertions, 694 deletions
diff --git a/chip/npcx/apm.c b/chip/npcx/apm.c deleted file mode 100644 index 4ab64774c1..0000000000 --- a/chip/npcx/apm.c +++ /dev/null @@ -1,694 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* NPCX-specific APM module for Chrome EC */ - -#include "apm_chip.h" -#include "common.h" -#include "registers.h" -#include "util.h" -#include "wov_chip.h" - -static struct apm_config apm_conf; -static struct apm_auto_gain_config apm_gain_conf; - - -static uint32_t apm_indirect_reg[][3] = { - {(NPCX_APM_BASE_ADDR + 0x034), (NPCX_APM_BASE_ADDR + 0x038)}, - {(NPCX_APM_BASE_ADDR + 0x04C), (NPCX_APM_BASE_ADDR + 0x050)}, - {(NPCX_APM_BASE_ADDR + 0x05C), (NPCX_APM_BASE_ADDR + 0x060)} -}; - -#define APM_CNTRL_REG 0 -#define APM_DATA_REG 1 - -/** - * Reads data indirect register. - * - * @param reg_offset - Indirect register APM_MIX_REG, APM_ADC_AGC_REG or - * APM_VAD_REG. - * @param indirect_addr - Indirect access address. - * @return The read data. - */ -static uint8_t apm_read_indirect_data(enum apm_indirect_reg_offset reg_offset, - uint8_t indirect_addr) -{ - /* Set the indirect access address. */ - SET_FIELD(REG8(apm_indirect_reg[reg_offset][APM_CNTRL_REG]), - NPCX_APM_CONTROL_ADD, indirect_addr); - - /* Read command. */ - CLEAR_BIT(REG8(apm_indirect_reg[reg_offset][APM_CNTRL_REG]), - NPCX_APM_CONTROL_LOAD); - - /* Get the data. */ - return REG8(apm_indirect_reg[reg_offset][APM_DATA_REG]); -} - -/** - * Writes data indirect register. - * - * @param reg_offset - Indirect register APM_MIX_REG, APM_ADC_AGC_REG or - * APM_VAD_REG. - * @param indirect_addr - Indirect access address. - * @param value - Written value. - * @return None - */ -static void apm_write_indirect_data(enum apm_indirect_reg_offset reg_offset, - uint8_t indirect_addr, uint8_t value) -{ - /* Set the data. */ - REG8(apm_indirect_reg[reg_offset][APM_DATA_REG]) = value; - - /* Set the indirect access address. */ - SET_FIELD(REG8(apm_indirect_reg[reg_offset][APM_CNTRL_REG]), - NPCX_APM_CONTROL_ADD, indirect_addr); - - /* Write command. */ - SET_BIT(REG8(apm_indirect_reg[reg_offset][APM_CNTRL_REG]), - NPCX_APM_CONTROL_LOAD); - CLEAR_BIT(REG8(apm_indirect_reg[reg_offset][APM_CNTRL_REG]), - NPCX_APM_CONTROL_LOAD); -} - -/** - * Sets the ADC DMIC rate. - * - * @param rate - ADC digital microphone rate - * @return None - */ -void apm_set_adc_dmic_config_l(enum apm_dmic_rate rate) -{ - if (rate == APM_DMIC_RATE_0_75) - SET_FIELD(NPCX_APM_CR_DMIC, NPCX_APM_CR_DMIC_ADC_DMIC_RATE, - APM_DMIC_RATE_3_0); - else if (rate == APM_DMIC_RATE_1_2) - SET_FIELD(NPCX_APM_CR_DMIC, NPCX_APM_CR_DMIC_ADC_DMIC_RATE, - APM_DMIC_RATE_2_4); - else - SET_FIELD(NPCX_APM_CR_DMIC, NPCX_APM_CR_DMIC_ADC_DMIC_RATE, - rate); -} - -/** - * Sets VAD DMIC rate. - * - * @param rate - VAD DMIC rate - * - * @return None - */ -void apm_set_vad_dmic_rate_l(enum apm_dmic_rate rate) -{ - uint8_t vad_data; - - vad_data = apm_read_indirect_data(APM_VAD_REG, APM_INDIRECT_VAD_0_REG); - - /* Set VAD_0 register. */ - if (rate == APM_DMIC_RATE_0_75) - SET_FIELD(vad_data, NPCX_VAD_0_VAD_DMIC_FREQ, - APM_DMIC_RATE_3_0); - else if (rate == APM_DMIC_RATE_1_2) - SET_FIELD(vad_data, NPCX_VAD_0_VAD_DMIC_FREQ, - APM_DMIC_RATE_2_4); - else - SET_FIELD(vad_data, NPCX_VAD_0_VAD_DMIC_FREQ, rate); - - apm_write_indirect_data(APM_VAD_REG, APM_INDIRECT_VAD_0_REG, vad_data); -} - -/*****************************************************************************/ -/* IC specific low-level driver */ - -/** - * Translates from ADC real value to frequency code - * - * @param adc_freq_val - ADC frequency. - * @return ADC frequency code, 0xFFFF in case of wrong value. - */ -static enum apm_adc_frequency apm_adc_freq_val_2_code(uint32_t adc_freq_val) -{ - enum apm_adc_frequency freq_code; - - switch (adc_freq_val) { - case 8000: - freq_code = APM_ADC_FREQ_8_000_KHZ; - break; - case 12000: - freq_code = APM_ADC_FREQ_12_000_KHZ; - break; - case 16000: - freq_code = APM_ADC_FREQ_16_000_KHZ; - break; - case 24000: - freq_code = APM_ADC_FREQ_24_000_KHZ; - break; - case 32000: - freq_code = APM_ADC_FREQ_32_000_KHZ; - break; - case 48000: - freq_code = APM_ADC_FREQ_48_000_KHZ; - break; - default: - freq_code = APM_ADC_FREQ_UNSUPPORTED; - break; - } - - return freq_code; -} - -/** - * Initiate APM module local parameters.. - * - * @param enable - enabled flag, 1 means enable - * @return None - */ -void apm_init(void) -{ - apm_conf.adc_ram_dmic_rate = APM_DMIC_RATE_0_75; - apm_conf.adc_i2s_dmic_rate = APM_DMIC_RATE_3_0; - apm_conf.gain_coupling = APM_ADC_CHAN_GAINS_INDEPENDENT; - apm_conf.left_chan_gain = 0; - apm_conf.right_chan_gain = 0; - - apm_gain_conf.stereo_enable = 0; - apm_gain_conf.agc_target = APM_ADC_MAX_TARGET_LEVEL_19_5; - apm_gain_conf.nois_gate_en = 0; - apm_gain_conf.nois_gate_thold = APM_MIN_NOISE_GET_THRESHOLD; - apm_gain_conf.hold_time = APM_HOLD_TIME_128; - apm_gain_conf.attack_time = APM_GAIN_RAMP_TIME_160; - apm_gain_conf.decay_time = APM_GAIN_RAMP_TIME_160; - apm_gain_conf.gain_max = APM_GAIN_VALUE_42_5; - apm_gain_conf.gain_min = APM_GAIN_VALUE_0_0; -} - -/** - * Enables/Disables APM module. - * - * @param enable - enabled flag, 1 means enable - * @return None - */ -void apm_enable(int enable) -{ - if (enable) { - CLEAR_BIT(NPCX_APM_CR_APM, NPCX_APM_CR_APM_PD); - - /* Work around that enable the AGC. */ - SET_FIELD(NPCX_APM_CR_APM, NPCX_APM_CR_APM_AGC_DIS, 0x00); - - } else - SET_BIT(NPCX_APM_CR_APM, NPCX_APM_CR_APM_PD); -} - -/** - * Enables/Disables voice activity detected interrupt. - * - * @param enable - enabled flag, 1 means enable - * @return APM interrupt mode. - */ -void apm_enable_vad_interrupt(int enable) -{ - wov_interrupt_enable(WOV_VAD_INT_INDX, enable); - wov_interrupt_enable(WOV_VAD_WAKE_INDX, enable); - if (enable) - CLEAR_BIT(NPCX_APM_IMR, NPCX_APM_IMR_VAD_DTC_MASK); - else - SET_BIT(NPCX_APM_IMR, NPCX_APM_IMR_VAD_DTC_MASK); -} - -/** - * Enable/Disable the WoV in the ADC. - * - * @param enable - enabled flag, 1 means enable - * @return None - */ -void apm_adc_wov_enable(int enable) -{ - if (enable) { - SET_FIELD(NPCX_APM_AICR_ADC, - NPCX_APM_AICR_ADC_ADC_AUDIOIF, 0x00); - } else { - SET_FIELD(NPCX_APM_AICR_ADC, - NPCX_APM_AICR_ADC_ADC_AUDIOIF, 0x03); - } -} - -/** - * Enables/Disables ADC. - * - * @param enable - enabled flag, 1 means enable - * @return None - */ -void apm_adc_enable(int enable) -{ - if (enable) { - CLEAR_BIT(NPCX_APM_AICR_ADC, NPCX_APM_AICR_ADC_PD_AICR_ADC); - SET_FIELD(NPCX_APM_AICR_ADC, - NPCX_APM_AICR_ADC_ADC_AUDIOIF, 0x00); - } else { - SET_BIT(NPCX_APM_AICR_ADC, NPCX_APM_AICR_ADC_PD_AICR_ADC); - SET_FIELD(NPCX_APM_AICR_ADC, - NPCX_APM_AICR_ADC_ADC_AUDIOIF, 0x03); - } -} - -/** - * sets the ADC frequency. - * - * @param adc_freq - ADC frequency. - * @return None - */ -void apm_adc_set_freq(enum apm_adc_frequency adc_freq) -{ - SET_FIELD(NPCX_APM_FCR_ADC, NPCX_APM_FCR_ADC_ADC_FREQ, adc_freq); -} - -/** - * Configures the ADC. - * - * @param hpf_enable - High pass filter enabled flag, 1 means enable - * @param filter_mode - ADC wind noise filter mode. - * @param adc_freq - ADC frequency. - * @return None - */ -void apm_adc_config(int hpf_enable, - enum apm_adc_wind_noise_filter_mode filter_mode, - enum apm_adc_frequency adc_freq) -{ - if (hpf_enable) - SET_BIT(NPCX_APM_FCR_ADC, NPCX_APM_FCR_ADC_ADC_HPF); - else - CLEAR_BIT(NPCX_APM_FCR_ADC, NPCX_APM_FCR_ADC_ADC_HPF); - - SET_FIELD(NPCX_APM_FCR_ADC, NPCX_APM_FCR_ADC_ADC_WNF, filter_mode); - - SET_FIELD(NPCX_APM_FCR_ADC, NPCX_APM_FCR_ADC_ADC_FREQ, adc_freq); -} - -/** - * Enables/Disables Digital Microphone. - * - * @param enable - enabled flag, 1 means enable - * @return None - */ -void apm_dmic_enable(int enable) -{ - if (enable) - CLEAR_BIT(NPCX_APM_CR_DMIC, NPCX_APM_CR_DMIC_PD_DMIC); - else - SET_BIT(NPCX_APM_CR_DMIC, NPCX_APM_CR_DMIC_PD_DMIC); -} - -/** - * Sets the RAM ADC DMIC rate. - * - * @param rate - ADC digital microphone rate - * @return None - */ -void apm_set_adc_ram_dmic_config(enum apm_dmic_rate rate) -{ - apm_conf.adc_ram_dmic_rate = rate; -} - -/** - * Gets the RAM ADC DMIC rate. - * - * @param None - * @return ADC digital microphone rate code. - */ -enum apm_dmic_rate apm_get_adc_ram_dmic_rate(void) -{ - return apm_conf.adc_ram_dmic_rate; -} - -/** - * Sets the ADC I2S DMIC rate. - * - * @param rate - ADC digital microphone rate - * @return None - */ -void apm_set_adc_i2s_dmic_config(enum apm_dmic_rate rate) -{ - apm_conf.adc_i2s_dmic_rate = rate; -} - -/** - * Gets the ADC I2S DMIC rate. - * - * @param None - * @return ADC digital microphone rate code. - */ -enum apm_dmic_rate apm_get_adc_i2s_dmic_rate(void) -{ - return apm_conf.adc_i2s_dmic_rate; -} -/** - * Configures Digital Mixer - * - * @param mix_left - Mixer left channel output selection on ADC path. - * @param mix_right - Mixer right channel output selection on ADC path. - * @return None - */ -void apm_digital_mixer_config(enum apm_dig_mix mix_left, - enum apm_dig_mix mix_right) -{ - uint8_t mix_2 = 0; - - SET_FIELD(mix_2, NPCX_APM_MIX_2_AIADCL_SEL, mix_left); - SET_FIELD(mix_2, NPCX_APM_MIX_2_AIADCR_SEL, mix_right); - - apm_write_indirect_data(APM_MIX_REG, APM_INDIRECT_MIX_2_REG, mix_2); -} - -/** - * Enables/Disables the VAD functionality. - * - * @param enable - enabled flag, 1 means enable - * @return None - */ -void apm_vad_enable(int enable) -{ - if (enable) - NPCX_APM_CR_VAD = 0x80; - else - NPCX_APM_CR_VAD = 0x00; -} - -/** - * Enables/Disables VAD ADC wakeup - * - * @param enable - 1 enable, 0 disable. - * - * @return None - */ -void apm_vad_adc_wakeup_enable(int enable) -{ - uint8_t vad_data; - - vad_data = apm_read_indirect_data(APM_VAD_REG, APM_INDIRECT_VAD_0_REG); - - if (enable) - SET_BIT(vad_data, NPCX_VAD_0_VAD_ADC_WAKEUP); - else - CLEAR_BIT(vad_data, NPCX_VAD_0_VAD_ADC_WAKEUP); - - apm_write_indirect_data(APM_VAD_REG, APM_INDIRECT_VAD_0_REG, vad_data); -} - -/** - * Sets VAD DMIC rate. - * - * @param rate - VAD DMIC rate - * - * @return None - */ -void apm_set_vad_dmic_rate(enum apm_dmic_rate rate) -{ - apm_conf.vad_dmic_rate = rate; -} - -/** - * Gets VAD DMIC rate. - * - * @param None - * - * @return ADC digital microphone rate code. - */ -enum apm_dmic_rate apm_get_vad_dmic_rate(void) -{ - return apm_conf.vad_dmic_rate; -} - -/** - * Sets VAD Input chanel. - * - * @param chan_src - Processed digital microphone channel - * selection. - * @return None - */ -void apm_set_vad_input_channel(enum apm_vad_in_channel_src chan_src) -{ - uint8_t vad_data; - - vad_data = apm_read_indirect_data(APM_VAD_REG, APM_INDIRECT_VAD_0_REG); - - SET_FIELD(vad_data, NPCX_VAD_0_VAD_INSEL, chan_src); - - apm_write_indirect_data(APM_VAD_REG, APM_INDIRECT_VAD_0_REG, vad_data); -} - -/** - * Sets VAD sensitivity. - * - * @param sensitivity_db - VAD sensitivity in db. - * @return None - */ -void apm_set_vad_sensitivity(uint8_t sensitivity_db) -{ - uint8_t vad_data; - - vad_data = apm_read_indirect_data(APM_VAD_REG, APM_INDIRECT_VAD_1_REG); - - SET_FIELD(vad_data, NPCX_VAD_1_VAD_POWER_SENS, sensitivity_db); - - apm_write_indirect_data(APM_VAD_REG, APM_INDIRECT_VAD_1_REG, vad_data); -} - -/** - * Gets VAD sensitivity. - * - * @param None. - * @return VAD sensitivity in db - */ -uint8_t apm_get_vad_sensitivity(void) -{ - uint8_t vad_data; - - vad_data = apm_read_indirect_data(APM_VAD_REG, APM_INDIRECT_VAD_1_REG); - - return GET_FIELD(vad_data, NPCX_VAD_1_VAD_POWER_SENS); -} - -/** - * Restarts VAD functionality. - * - * @param None - * @return None - */ -void apm_vad_restart(void) -{ - SET_BIT(NPCX_APM_CR_VAD_CMD, NPCX_APM_CR_VAD_CMD_VAD_RESTART); -} - -/** - * Restarts VAD functionality. - * - * @param gain_coupling - ADC digital gain coupling (independent or - * rigth tracks left). - * @param left_chan_gain - Left channel ADC digital gain programming value. - * @param right_chan_gain - Right channel ADC digital gain programming value. - * @return EC_ERROR_INVAL or EC_SUCCESS - */ -enum ec_error_list apm_adc_gain_config(enum apm_adc_gain_coupling gain_coupling, - uint8_t left_chan_gain, uint8_t right_chan_gain) -{ - /* Check parameters validity. */ - if ((left_chan_gain > 0x2B) || (right_chan_gain > 0x2B)) - return EC_ERROR_INVAL; - - /* - * Store the parameters in order to use them in case the function - * was called prioe calling to wov_set_mode. - */ - apm_conf.gain_coupling = gain_coupling; - apm_conf.left_chan_gain = left_chan_gain; - apm_conf.right_chan_gain = right_chan_gain; - - /* Set gain coupling.*/ - if (gain_coupling == APM_ADC_CHAN_GAINS_INDEPENDENT) - CLEAR_BIT(NPCX_APM_GCR_ADCL, NPCX_APM_GCR_ADCL_LRGID); - else - SET_BIT(NPCX_APM_GCR_ADCL, NPCX_APM_GCR_ADCL_LRGID); - - /* set channels gains. */ - SET_FIELD(NPCX_APM_GCR_ADCL, NPCX_APM_GCR_ADCL_GIDL, left_chan_gain); - SET_FIELD(NPCX_APM_GCR_ADCR, NPCX_APM_GCR_ADCR_GIDR, right_chan_gain); - - return EC_SUCCESS; -} - -/** - * Enables/Disables the automatic gain. - * - * @param enable - enabled flag, 1 means enable - * @return None - */ -void apm_auto_gain_cntrl_enable(int enable) -{ - if (enable) - NPCX_APM_CR_ADC_AGC = 0x80; - else - NPCX_APM_CR_ADC_AGC = 0x00; -} - -/** - * Enables/Disables the automatic gain. - * - * @param gain_cfg - struct of apm auto gain config - * @return EC_ERROR_INVAL or EC_SUCCESS - */ -enum ec_error_list apm_adc_auto_gain_config( - struct apm_auto_gain_config *gain_cfg) -{ - uint8_t gain_data = 0; - - /* Check parameters validity. */ - - if (gain_cfg->gain_min > gain_cfg->gain_max) - return EC_ERROR_INVAL; - - /* - * Store the parameters in order to use them in case the function - * was called prioe calling to wov_set_mode. - */ - apm_gain_conf.stereo_enable = gain_cfg->stereo_enable; - apm_gain_conf.agc_target = gain_cfg->agc_target; - apm_gain_conf.nois_gate_en = gain_cfg->nois_gate_en; - apm_gain_conf.nois_gate_thold = gain_cfg->nois_gate_thold; - apm_gain_conf.hold_time = gain_cfg->hold_time; - apm_gain_conf.attack_time = gain_cfg->attack_time; - apm_gain_conf.decay_time = gain_cfg->decay_time; - apm_gain_conf.gain_max = gain_cfg->gain_max; - apm_gain_conf.gain_min = gain_cfg->gain_min; - - /* Set the parameters. */ - - if (gain_cfg->stereo_enable) - CLEAR_BIT(gain_data, NPCX_ADC_AGC_0_AGC_STEREO); - else - SET_BIT(gain_data, NPCX_ADC_AGC_0_AGC_STEREO); - - SET_FIELD(gain_data, NPCX_ADC_AGC_0_AGC_TARGET, gain_cfg->agc_target); - - apm_write_indirect_data(APM_ADC_AGC_REG, APM_INDIRECT_ADC_AGC_0_REG, - gain_data); - - gain_data = 0; - - if (gain_cfg->nois_gate_en) - SET_BIT(gain_data, NPCX_ADC_AGC_1_NG_EN); - else - CLEAR_BIT(gain_data, NPCX_ADC_AGC_1_NG_EN); - SET_FIELD(gain_data, NPCX_ADC_AGC_1_NG_THR, gain_cfg->nois_gate_thold); - SET_FIELD(gain_data, NPCX_ADC_AGC_1_HOLD, gain_cfg->hold_time); - - apm_write_indirect_data(APM_ADC_AGC_REG, APM_INDIRECT_ADC_AGC_1_REG, - gain_data); - - gain_data = 0; - - SET_FIELD(gain_data, NPCX_ADC_AGC_2_ATK, gain_cfg->attack_time); - SET_FIELD(gain_data, NPCX_ADC_AGC_2_DCY, gain_cfg->decay_time); - - apm_write_indirect_data(APM_ADC_AGC_REG, APM_INDIRECT_ADC_AGC_2_REG, - gain_data); - - gain_data = 0; - - SET_FIELD(gain_data, NPCX_ADC_AGC_3_AGC_MAX, gain_cfg->gain_max); - - apm_write_indirect_data(APM_ADC_AGC_REG, APM_INDIRECT_ADC_AGC_3_REG, - gain_data); - - gain_data = 0; - - SET_FIELD(gain_data, NPCX_ADC_AGC_4_AGC_MIN, gain_cfg->gain_min); - - apm_write_indirect_data(APM_ADC_AGC_REG, APM_INDIRECT_ADC_AGC_4_REG, - gain_data); - - return EC_SUCCESS; -} - -/** - * Sets APM mode (enables & disables APN sub modules accordingly - * to the APM mode). - * - * @param apm_mode - APM mode, DEFAULT, DETECTION, RECORD or INDEPENDENT modes. - * @return None - */ -void apm_set_mode(enum wov_modes wov_mode) -{ - apm_enable(0); - - switch (wov_mode) { - case WOV_MODE_OFF: - apm_enable_vad_interrupt(0); - apm_dmic_enable(0); - apm_adc_enable(0); - apm_vad_enable(0); - wov_apm_active(0); - break; - - case WOV_MODE_VAD: - apm_clear_vad_detected_bit(); - wov_apm_active(1); - apm_dmic_enable(1); - apm_adc_wov_enable(1); - apm_set_vad_dmic_rate_l(apm_conf.vad_dmic_rate); - apm_set_vad_sensitivity(wov_conf.sensitivity_db); - apm_enable_vad_interrupt(1); - apm_vad_restart(); - apm_vad_enable(1); - break; - - case WOV_MODE_RAM: - case WOV_MODE_I2S: - case WOV_MODE_RAM_AND_I2S: - wov_apm_active(1); - apm_vad_enable(0); - apm_enable_vad_interrupt(0); - if (wov_mode == WOV_MODE_RAM) - apm_set_adc_dmic_config_l(apm_conf.adc_ram_dmic_rate); - else - apm_set_adc_dmic_config_l(apm_conf.adc_i2s_dmic_rate); - apm_dmic_enable(1); - apm_adc_enable(1); - break; - - default: - apm_set_vad_dmic_rate_l(APM_DMIC_RATE_1_0); - apm_set_adc_dmic_config_l(APM_DMIC_RATE_1_0); - apm_vad_enable(0); - apm_enable_vad_interrupt(0); - apm_dmic_enable(0); - apm_adc_enable(0); - wov_apm_active(0); - break; - } - - apm_adc_gain_config(apm_conf.gain_coupling, - apm_conf.left_chan_gain, - apm_conf.right_chan_gain); - - apm_adc_auto_gain_config(&apm_gain_conf); - - apm_adc_set_freq(apm_adc_freq_val_2_code(wov_conf.sample_per_sec)); - - if (wov_mode != WOV_MODE_OFF) - apm_enable(1); -} - -/** - * Clears VAD detected bit in IFR register. - * - * @param None - * @return None. - */ -void apm_clear_vad_detected_bit(void) -{ - apm_vad_enable(0); - - APM_CLEAR_VAD_INTERRUPT; -} |