diff --git a/boards/nxp/frdm_mcxn236/board.c b/boards/nxp/frdm_mcxn236/board.c index 53d2052a78331..d18db0d484276 100644 --- a/boards/nxp/frdm_mcxn236/board.c +++ b/boards/nxp/frdm_mcxn236/board.c @@ -1,5 +1,5 @@ /* - * Copyright 2024 NXP + * Copyright 2024-2025 NXP * SPDX-License-Identifier: Apache-2.0 */ #include @@ -103,7 +103,9 @@ void board_early_init_hook(void) CLOCK_SetupExtClocking(BOARD_XTAL0_CLK_HZ); -#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(sai0)) || DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(sai1)) +#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(sai0)) || \ + DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(sai1)) || \ + DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(micfil)) /* < Set up PLL1 */ const pll_setup_t pll1_Setup = { .pllctrl = SCG_SPLLCTRL_SOURCE(1U) | SCG_SPLLCTRL_SELI(3U) | @@ -111,12 +113,13 @@ void board_early_init_hook(void) .pllndiv = SCG_SPLLNDIV_NDIV(25U), .pllpdiv = SCG_SPLLPDIV_PDIV(10U), .pllmdiv = SCG_SPLLMDIV_MDIV(256U), - .pllRate = 24576000U}; + .pllRate = 24576000U + }; /* Configure PLL1 to the desired values */ CLOCK_SetPLL1Freq(&pll1_Setup); - /* Set PLL1 CLK0 divider to value 1 */ - CLOCK_SetClkDiv(kCLOCK_DivPLL1Clk0, 1U); + /* Set PLL1 CLK0 divider to value 2, then the clock is 12288000Hz. */ + CLOCK_SetClkDiv(kCLOCK_DivPLL1Clk0, 2U); #endif #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexcomm0)) @@ -160,6 +163,7 @@ void board_early_init_hook(void) #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio0)) CLOCK_EnableClock(kCLOCK_Gpio0); + CLOCK_EnableClock(kCLOCK_Port0); #endif #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio1)) @@ -339,6 +343,15 @@ void board_early_init_hook(void) CLOCK_EnableClock(kCLOCK_Sai1); #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(micfil), okay) + CLOCK_SetClkDiv(kCLOCK_DivMicfilFClk, 1U); + CLOCK_AttachClk(kPLL1_CLK0_to_MICFILF); + CLOCK_EnableClock(kCLOCK_Micfil); + + PORT0->PCR[16] = 0x00001900; + PORT0->PCR[17] = 0x00001900; +#endif + /* Set SystemCoreClock variable. */ SystemCoreClock = CLOCK_INIT_CORE_CLOCK; } diff --git a/boards/nxp/frdm_mcxn236/frdm_mcxn236-pinctrl.dtsi b/boards/nxp/frdm_mcxn236/frdm_mcxn236-pinctrl.dtsi index c9256f0919f02..8faf060716d2e 100644 --- a/boards/nxp/frdm_mcxn236/frdm_mcxn236-pinctrl.dtsi +++ b/boards/nxp/frdm_mcxn236/frdm_mcxn236-pinctrl.dtsi @@ -1,5 +1,5 @@ /* - * Copyright 2024 NXP + * Copyright 2024-2025 NXP * SPDX-License-Identifier: Apache-2.0 */ @@ -8,8 +8,8 @@ &pinctrl { pinmux_flexcomm0_lpuart: pinmux_flexcomm0_lpuart { group0 { - pinmux = , - ; + pinmux = , + ; slew-rate = "fast"; drive-strength = "low"; input-enable; @@ -227,10 +227,33 @@ , , , + , ; drive-strength = "high"; slew-rate = "fast"; input-enable; }; }; + + pinmux_flexcomm2_i2c: pinmux_flexcomm2_i2c { + group0 { + pinmux = , + ; + slew-rate = "fast"; + drive-strength = "low"; + input-enable; + bias-pull-up; + drive-open-drain; + }; + }; + + pinmux_micfil: pinmux_micfil { + group0 { + pinmux = , + ; + drive-strength = "high"; + slew-rate = "fast"; + input-enable; + }; + }; }; diff --git a/boards/nxp/frdm_mcxn236/frdm_mcxn236.dts b/boards/nxp/frdm_mcxn236/frdm_mcxn236.dts index 6375c643dc2e8..d05a5d99fdcf8 100644 --- a/boards/nxp/frdm_mcxn236/frdm_mcxn236.dts +++ b/boards/nxp/frdm_mcxn236/frdm_mcxn236.dts @@ -175,6 +175,19 @@ &flexcomm2_lpi2c2 { status = "okay"; + pinctrl-0 = <&pinmux_flexcomm2_i2c>; + pinctrl-names = "default"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + + audio_codec: da7212@1a { + compatible = "dialog,da7212"; + reg = <0x1a>; + clocks = <&syscon MCUX_SAI1_CLK>; + clock-source = "MCLK"; + clock-names = "mclk"; + }; }; &flexcomm3 { @@ -427,3 +440,9 @@ dvp_20pin_interface: &video_sdma {}; pinctrl-0 = <&pinmux_sai1>; pinctrl-names = "default"; }; + +&micfil { + status = "okay"; + pinctrl-0 = <&pinmux_micfil>; + pinctrl-names = "default"; +}; diff --git a/drivers/audio/CMakeLists.txt b/drivers/audio/CMakeLists.txt index bca0f07b86e25..f70c78cbfc114 100644 --- a/drivers/audio/CMakeLists.txt +++ b/drivers/audio/CMakeLists.txt @@ -16,3 +16,5 @@ zephyr_library_sources_ifdef(CONFIG_AUDIO_CODEC_CS43L22 cs43l22.c) zephyr_library_sources_ifdef(CONFIG_AUDIO_CODEC_PCM1681 pcm1681.c) zephyr_library_sources_ifdef(CONFIG_AUDIO_CODEC_MAX98091 max98091.c) zephyr_library_sources_ifdef(CONFIG_AUDIO_DMIC_AMBIQ_PDM dmic_ambiq_pdm.c) +zephyr_library_sources_ifdef(CONFIG_AUDIO_CODEC_DA7212 da7212.c) +zephyr_library_sources_ifdef(CONFIG_AUDIO_DMIC_NXP_MICFIL dmic_nxp_micfil.c) diff --git a/drivers/audio/Kconfig b/drivers/audio/Kconfig index 78fb303988055..396aa2c3e59c6 100644 --- a/drivers/audio/Kconfig +++ b/drivers/audio/Kconfig @@ -43,6 +43,7 @@ source "drivers/audio/Kconfig.tlv320aic3110" source "drivers/audio/Kconfig.tlv320dac" source "drivers/audio/Kconfig.wm8904" source "drivers/audio/Kconfig.wm8962" +source "drivers/audio/Kconfig.da7212" endif # AUDIO_CODEC @@ -67,6 +68,7 @@ source "drivers/audio/Kconfig.mpxxdtyy" source "drivers/audio/Kconfig.dmic_pdm_nrfx" source "drivers/audio/Kconfig.dmic_mcux" source "drivers/audio/Kconfig.dmic_ambiq_pdm" +source "drivers/audio/Kconfig.dmic_nxp_micfil" endif # AUDIO_DMIC diff --git a/drivers/audio/Kconfig.da7212 b/drivers/audio/Kconfig.da7212 new file mode 100644 index 0000000000000..d2d3e21259350 --- /dev/null +++ b/drivers/audio/Kconfig.da7212 @@ -0,0 +1,10 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +config AUDIO_CODEC_DA7212 + bool "Dialog DA7212 codec support" + default y + select I2C + depends on DT_HAS_DIALOG_DA7212_ENABLED + help + Enable support for the Dialog DA7212 audio codec. diff --git a/drivers/audio/Kconfig.dmic_nxp_micfil b/drivers/audio/Kconfig.dmic_nxp_micfil new file mode 100644 index 0000000000000..e3832846ae589 --- /dev/null +++ b/drivers/audio/Kconfig.dmic_nxp_micfil @@ -0,0 +1,22 @@ +# Copyright 2025 NXP +# +# SPDX-License-Identifier: Apache-2.0 + +config AUDIO_DMIC_NXP_MICFIL + bool "NXP MICFIL driver" + default y + depends on DT_HAS_NXP_MICFIL_ENABLED + select HAS_MCUX + select CLOCK_CONTROL + help + Enable NXP MICFIL driver. + +if AUDIO_DMIC_NXP_MICFIL + +config DMIC_NXP_MICFIL_QUEUE_SIZE + int "Message queue depth" + default 4 + help + Depth of the message queue used to pass filled buffers to the app. + +endif # AUDIO_DMIC_NXP_MICFIL diff --git a/drivers/audio/da7212.c b/drivers/audio/da7212.c new file mode 100644 index 0000000000000..7c2de4db99348 --- /dev/null +++ b/drivers/audio/da7212.c @@ -0,0 +1,676 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "da7212.h" + +LOG_MODULE_REGISTER(dialog_da7212, CONFIG_AUDIO_CODEC_LOG_LEVEL); + +#define DT_DRV_COMPAT dialog_da7212 +#define DEV_CFG(dev) ((const struct da7212_driver_config *const)dev->config) + +struct da7212_driver_config { + struct i2c_dt_spec i2c; + int clock_source; + const struct device *mclk_dev; + clock_control_subsys_t mclk_name; +}; + +static inline void da7212_write_reg(const struct device *dev, uint8_t reg, uint8_t val) +{ + const struct da7212_driver_config *const dev_cfg = DEV_CFG(dev); + uint8_t data[2] = {reg, val}; + int ret; + + ret = i2c_write(dev_cfg->i2c.bus, data, sizeof(data), dev_cfg->i2c.addr); + + if (ret != 0) { + LOG_ERR("i2c write to codec error %d (reg 0x%02x)", ret, reg); + } + + LOG_DBG("REG:%02u VAL:%#02x", reg, val); +} + +static inline void da7212_read_reg(const struct device *dev, uint8_t reg, uint8_t *val) +{ + const struct da7212_driver_config *const dev_cfg = DEV_CFG(dev); + + int ret; + + ret = i2c_write_read(dev_cfg->i2c.bus, dev_cfg->i2c.addr, + ®, sizeof(reg), val, sizeof(*val)); + + if (ret != 0) { + LOG_ERR("i2c read from codec error %d (reg 0x%02x)", ret, reg); + } else { + LOG_DBG("REG:%02u VAL:%#02x", reg, *val); + } +} + +static inline void da7212_update_reg(const struct device *dev, uint8_t reg, + uint8_t mask, uint8_t val) +{ + uint8_t cur, newv; + + da7212_read_reg(dev, reg, &cur); + LOG_DBG("read %#x = %x", reg, cur); + + /* Apply mask to update only selected bits */ + newv = (cur & (uint8_t)~mask) | (val & mask); + + LOG_DBG("write %#x = %x", reg, newv); + da7212_write_reg(dev, reg, newv); +} + +static void da7212_soft_reset(const struct device *dev) +{ + da7212_write_reg(dev, DIALOG7212_CIF_CTRL, + (uint8_t)DIALOG7212_CIF_CTRL_CIF_REG_SOFT_RESET_MASK); +} + +static int da7212_clock_mode_config(const struct device *dev, audio_dai_cfg_t *cfg) +{ + uint8_t val = 0; + + /* Master mode => DAI_CLK_EN = 1 (BCLK/WCLK output). + * Slave mode => DAI_CLK_EN = 0 (BCLK/WCLK input) + */ + if ((cfg->i2s.options & I2S_OPT_FRAME_CLK_SLAVE) == 0) { + da7212_update_reg(dev, DIALOG7212_DAI_CLK_MODE, + DIALOG7212_DAI_CLK_EN_MASK, DIALOG7212_DAI_CLK_EN_MASK); + + /* DAI master mode BCLK number per WCLK period */ + switch (cfg->i2s.word_size) { + case 16: + val = DIALOG7212_DAI_BCLKS_PER_WCLK_BCLK32; + break; + case 32: + val = DIALOG7212_DAI_BCLKS_PER_WCLK_BCLK64; + break; + case 64: + val = DIALOG7212_DAI_BCLKS_PER_WCLK_BCLK128; + break; + case 128: + val = DIALOG7212_DAI_BCLKS_PER_WCLK_BCLK256; + break; + default: + LOG_ERR("Word size %d not supported", cfg->i2s.word_size); + return -EINVAL; + } + + da7212_update_reg(dev, DIALOG7212_DAI_CLK_MODE, + (uint8_t)DIALOG7212_DAI_BCLKS_PER_WCLK_MASK, val); + } else { + da7212_update_reg(dev, DIALOG7212_DAI_CLK_MODE, + DIALOG7212_DAI_CLK_EN_MASK, 0); + } + + return 0; +} + +static int da7212_dac_input_config(const struct device *dev, audio_route_t route) +{ + if ((route == AUDIO_ROUTE_PLAYBACK) || (route == AUDIO_ROUTE_PLAYBACK_CAPTURE)) { + /* Route DAI input to DAC outputs (playback path) */ + da7212_write_reg(dev, DIALOG7212_DIG_ROUTING_DAC, + (uint8_t)(DIALOG7212_DIG_ROUTING_DAC_R_RSC_DAC_R | + DIALOG7212_DIG_ROUTING_DAC_L_RSC_DAC_L)); + } else { + /* Route ADC input to DAC outputs (bypass path) */ + da7212_write_reg(dev, DIALOG7212_DIG_ROUTING_DAC, + (uint8_t)(DIALOG7212_DIG_ROUTING_DAC_R_RSC_ADC_R_OUTPUT | + DIALOG7212_DIG_ROUTING_DAC_L_RSC_ADC_L_OUTPUT)); + } + + return 0; +} + +static int da7212_protocol_config(const struct device *dev, audio_dai_type_t dai_type) +{ + uint8_t proto; + + switch (dai_type) { + case AUDIO_DAI_TYPE_I2S: + proto = DIALOG7212_DAI_FORMAT_I2S_MODE; + break; + case AUDIO_DAI_TYPE_LEFT_JUSTIFIED: + proto = DIALOG7212_DAI_FORMAT_LEFT_JUSTIFIED; + break; + case AUDIO_DAI_TYPE_RIGHT_JUSTIFIED: + proto = DIALOG7212_DAI_FORMAT_RIGTH_JUSTIFIED; + break; + case AUDIO_DAI_TYPE_PCMA: + proto = DIALOG7212_DAI_FORMAT_DSP_MODE; /* Map to DSP mode */ + break; + case AUDIO_DAI_TYPE_PCMB: + proto = DIALOG7212_DAI_FORMAT_DSP_MODE; /* Map to DSP mode */ + break; + default: + return -EINVAL; + } + + /* Keep DAI enabled flag set */ + da7212_update_reg(dev, DIALOG7212_DAI_CTRL, + (uint8_t)(DIALOG7212_DAI_FORMAT_MASK), proto); + LOG_DBG("Codec protocol: %#x", proto); + + return 0; +} + +static int da7212_audio_format_config(const struct device *dev, audio_dai_cfg_t *cfg) +{ + uint8_t val = 0; + + /* Sample rate */ + switch (cfg->i2s.frame_clk_freq) { + case 8000: + val = DIALOG7212_SR_8KHZ; + break; + case 11025: + val = DIALOG7212_SR_11_025KHZ; + break; + case 12000: + val = DIALOG7212_SR_12KHZ; + break; + case 16000: + val = DIALOG7212_SR_16KHZ; + break; + case 22050: + val = DIALOG7212_SR_22KHZ; + break; + case 24000: + val = DIALOG7212_SR_24KHZ; + break; + case 32000: + val = DIALOG7212_SR_32KHZ; + break; + case 44100: + val = DIALOG7212_SR_44_1KHZ; + break; + case 48000: + val = DIALOG7212_SR_48KHZ; + break; + case 88200: + val = DIALOG7212_SR_88_2KHZ; + break; + case 96000: + val = DIALOG7212_SR_96KHZ; + break; + default: + LOG_WRN("Invalid codec sample rate: %d", cfg->i2s.frame_clk_freq); + return -EINVAL; + } + da7212_write_reg(dev, DIALOG7212_SR, val); + + /* Word length */ + switch (cfg->i2s.word_size) { + case 16: + val = DIALOG7212_DAI_WORD_LENGTH_16B; + break; + case 20: + val = DIALOG7212_DAI_WORD_LENGTH_20B; + break; + case 24: + val = DIALOG7212_DAI_WORD_LENGTH_24B; + break; + case 32: + val = DIALOG7212_DAI_WORD_LENGTH_32B; + break; + default: + LOG_ERR("Word size %d not supported", cfg->i2s.word_size); + return -EINVAL; + } + da7212_update_reg(dev, DIALOG7212_DAI_CTRL, + (uint8_t)DIALOG7212_DAI_WORD_LENGTH_MASK, val); + + return 0; +} + +static int da7212_out_update(const struct device *dev, audio_channel_t channel, + uint8_t reg, uint8_t val) +{ + switch (channel) { + case AUDIO_CHANNEL_FRONT_LEFT: + case AUDIO_CHANNEL_HEADPHONE_LEFT: + da7212_write_reg(dev, reg, val); + return 0; + case AUDIO_CHANNEL_FRONT_RIGHT: + case AUDIO_CHANNEL_HEADPHONE_RIGHT: + da7212_write_reg(dev, reg + 1U, val); /* R gain is next register for HP */ + return 0; + case AUDIO_CHANNEL_ALL: + da7212_write_reg(dev, reg, val); + da7212_write_reg(dev, reg + 1U, val); + return 0; + default: + return -EINVAL; + } +} + +static int da7212_out_volume_config(const struct device *dev, + audio_channel_t channel, int volume) +{ + uint8_t vol = (uint8_t)CLAMP(volume, 0, 0x3F); + + /* DIALOG7212_HP_L_GAIN at 0x48, DIALOG7212_HP_R_GAIN at 0x49 */ + return da7212_out_update(dev, channel, DIALOG7212_HP_L_GAIN, vol); +} + +/* Mute by setting MUTE bit, keep HP_L_AMP_EN bit set */ +static int da7212_out_mute_config(const struct device *dev, + audio_channel_t channel, bool mute) +{ + /* Keep amp enabled while toggling mute: + * 0xC0 (EN|MUTE) to mute + * 0x80 (EN) to unmute + */ + uint8_t regValue = mute ? 0xC0U : 0x80U; + + switch (channel) { + case AUDIO_CHANNEL_FRONT_LEFT: + case AUDIO_CHANNEL_HEADPHONE_LEFT: + da7212_update_reg(dev, DIALOG7212_HP_L_CTRL, 0xC0U, regValue); + return 0; + case AUDIO_CHANNEL_FRONT_RIGHT: + case AUDIO_CHANNEL_HEADPHONE_RIGHT: + da7212_update_reg(dev, DIALOG7212_HP_R_CTRL, 0xC0U, regValue); + return 0; + case AUDIO_CHANNEL_ALL: + da7212_update_reg(dev, DIALOG7212_HP_L_CTRL, 0xC0U, regValue); + da7212_update_reg(dev, DIALOG7212_HP_R_CTRL, 0xC0U, regValue); + da7212_update_reg(dev, DIALOG7212_LINE_CTRL, 0xC0U, regValue); + return 0; + default: + return -EINVAL; + } +} + +static int da7212_in_update(const struct device *dev, audio_channel_t channel, + uint8_t reg_gain, uint8_t gain) +{ + switch (channel) { + case AUDIO_CHANNEL_FRONT_LEFT: + da7212_write_reg(dev, reg_gain, gain); + return 0; + case AUDIO_CHANNEL_FRONT_RIGHT: + da7212_write_reg(dev, reg_gain + 1U, gain); + return 0; + case AUDIO_CHANNEL_ALL: + da7212_write_reg(dev, reg_gain, gain); + da7212_write_reg(dev, reg_gain + 1U, gain); + return 0; + default: + return -EINVAL; + } +} + +static int da7212_in_volume_config(const struct device *dev, + audio_channel_t channel, int volume) +{ + uint8_t vol = (uint8_t)CLAMP(volume, 0, 0x7F); + + /* DIALOG7212_ADC_L_GAIN at 0x36, DIALOG7212_ADC_R_GAIN at 0x37 */ + return da7212_in_update(dev, channel, DIALOG7212_ADC_L_GAIN, vol); +} + +static int da7212_in_mute_config(const struct device *dev, + audio_channel_t channel, bool mute) +{ + uint8_t reg = (channel == AUDIO_CHANNEL_FRONT_RIGHT) ? + DIALOG7212_ADC_R_CTRL : DIALOG7212_ADC_L_CTRL; + + /* Keep ADC enabled while toggling mute: + * 0xC0 (EN|MUTE) to mute + * 0x80 (EN) to unmute + */ + uint8_t regValue = mute ? 0xC0U : 0x80U; + + if (channel == AUDIO_CHANNEL_ALL) { + da7212_update_reg(dev, DIALOG7212_ADC_L_CTRL, 0xC0U, regValue); + da7212_update_reg(dev, DIALOG7212_ADC_R_CTRL, 0xC0U, regValue); + return 0; + } + + da7212_update_reg(dev, reg, 0xC0U, regValue); + + return 0; +} + +static int da7212_route_input(const struct device *dev, + audio_channel_t channel, uint32_t input) +{ + uint8_t l_sel, r_sel; + + switch (input) { + case 0: /* AUX */ + l_sel = DIALOG7212_MIXIN_L_SELECT_AUX_L_SEL_MASK; + r_sel = DIALOG7212_MIXIN_R_SELECT_AUX_R_SEL_MASK; + break; + default: + /* For other inputs, keep AUX as default to have a working path */ + l_sel = DIALOG7212_MIXIN_L_SELECT_AUX_L_SEL_MASK; + r_sel = DIALOG7212_MIXIN_R_SELECT_AUX_R_SEL_MASK; + break; + } + + switch (channel) { + case AUDIO_CHANNEL_FRONT_LEFT: + da7212_write_reg(dev, DIALOG7212_MIXIN_L_SELECT, l_sel); + break; + case AUDIO_CHANNEL_FRONT_RIGHT: + da7212_write_reg(dev, DIALOG7212_MIXIN_R_SELECT, r_sel); + break; + case AUDIO_CHANNEL_ALL: + da7212_write_reg(dev, DIALOG7212_MIXIN_L_SELECT, l_sel); + da7212_write_reg(dev, DIALOG7212_MIXIN_R_SELECT, r_sel); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int da7212_route_output(const struct device *dev, + audio_channel_t channel, uint32_t output) +{ + /* Route DACs to mixers by default */ + ARG_UNUSED(output); + + da7212_write_reg(dev, DIALOG7212_MIXOUT_L_SELECT, + (uint8_t)DIALOG7212_MIXOUT_L_SELECT_DAC_L_MASK); + da7212_write_reg(dev, DIALOG7212_MIXOUT_R_SELECT, + (uint8_t)DIALOG7212_MIXOUT_R_SELECT_DAC_R_MASK); + + return 0; +} + +static void da7212_configure_output(const struct device *dev) +{ + /* Power charge pump */ + da7212_write_reg(dev, DIALOG7212_CP_CTRL, + (uint8_t)(DIALOG7212_CP_CTRL_EN_MASK | + DIALOG7212_CP_CTRL_SMALL_SWIT_CH_FREQ_EN_MASK | + DIALOG7212_CP_CTRL_MCHANGE_OUTPUT | + DIALOG7212_CP_CTRL_MOD_CPVDD_1 | + DIALOG7212_CP_CTRL_ANALOG_VLL_LV_BOOSTS_CP)); + + /* Route DAC to MixOut */ + da7212_write_reg(dev, DIALOG7212_MIXOUT_L_SELECT, + (uint8_t)DIALOG7212_MIXOUT_L_SELECT_DAC_L_MASK); + da7212_write_reg(dev, DIALOG7212_MIXOUT_R_SELECT, + (uint8_t)DIALOG7212_MIXOUT_R_SELECT_DAC_R_MASK); + + /* Enable DACs with ramp */ + da7212_write_reg(dev, DIALOG7212_DAC_L_CTRL, + (uint8_t)(DIALOG7212_DAC_L_CTRL_ADC_EN_MASK | + DIALOG7212_DAC_L_CTRL_ADC_RAMP_EN_MASK)); + da7212_write_reg(dev, DIALOG7212_DAC_R_CTRL, + (uint8_t)(DIALOG7212_DAC_R_CTRL_ADC_EN_MASK | + DIALOG7212_DAC_R_CTRL_ADC_RAMP_EN_MASK)); + + /* Enable HP amps, ZC and OE */ + da7212_write_reg(dev, DIALOG7212_HP_L_CTRL, + (uint8_t)(DIALOG7212_HP_L_CTRL_AMP_EN_MASK | + DIALOG7212_HP_L_CTRL_AMP_RAMP_EN_MASK | + DIALOG7212_HP_L_CTRL_AMP_ZC_EN_MASK | + DIALOG7212_HP_L_CTRL_AMP_OE_MASK)); + da7212_write_reg(dev, DIALOG7212_HP_R_CTRL, + (uint8_t)(DIALOG7212_HP_R_CTRL_AMP_EN_MASK | + DIALOG7212_HP_R_CTRL_AMP_RAMP_EN_MASK | + DIALOG7212_HP_R_CTRL_AMP_ZC_EN_MASK | + DIALOG7212_HP_R_CTRL_AMP_OE_MASK)); + + /* Enable MixOut amplifiers and mixing into HP */ + da7212_write_reg(dev, DIALOG7212_MIXOUT_L_CTRL, + (uint8_t)(DIALOG7212_MIXOUT_L_CTRL_AMP_EN_MASK | + DIALOG7212_MIXOUT_L_CTRL_AMP_SOFT_MIX_EN_MASK | + DIALOG7212_MIXOUT_L_CTRL_AMP_MIX_EN_MASK)); + da7212_write_reg(dev, DIALOG7212_MIXOUT_R_CTRL, + (uint8_t)(DIALOG7212_MIXOUT_R_CTRL_AMP_EN_MASK | + DIALOG7212_MIXOUT_R_CTRL_AMP_SOFT_MIX_EN_MASK | + DIALOG7212_MIXOUT_R_CTRL_AMP_MIX_EN_MASK)); + + /* Configure DAC gain to 0x67. */ + da7212_write_reg(dev, DIALOG7212_DAC_L_GAIN, (uint8_t)(0x67)); + da7212_write_reg(dev, DIALOG7212_DAC_R_GAIN, (uint8_t)(0x67)); + + /* Set default HP volume and unmute */ + da7212_out_volume_config(dev, AUDIO_CHANNEL_ALL, DIALOG7212_HP_DEFAULT_GAIN); + da7212_out_mute_config(dev, AUDIO_CHANNEL_ALL, false); +} + +static void da7212_configure_input(const struct device *dev) +{ + /* Route AUX to MIXIN L/R (0x01 on both) */ + da7212_write_reg(dev, DIALOG7212_MIXIN_L_SELECT, + (uint8_t)DIALOG7212_MIXIN_L_SELECT_AUX_L_SEL_MASK); + da7212_write_reg(dev, DIALOG7212_MIXIN_R_SELECT, + (uint8_t)DIALOG7212_MIXIN_R_SELECT_AUX_R_SEL_MASK); + + /* Charge pump control = 0xFD + * EN | SMALL_SWIT_CH_FREQ_EN | MCHANGE_OUTPUT | MOD_CPVDD_1 | ANALOG_VLL_LV_BOOSTS_CP + */ + da7212_write_reg(dev, DIALOG7212_CP_CTRL, + (uint8_t)(DIALOG7212_CP_CTRL_EN_MASK | + DIALOG7212_CP_CTRL_SMALL_SWIT_CH_FREQ_EN_MASK | + DIALOG7212_CP_CTRL_MCHANGE_OUTPUT | + DIALOG7212_CP_CTRL_MOD_CPVDD_1 | + DIALOG7212_CP_CTRL_ANALOG_VLL_LV_BOOSTS_CP)); + + /* AUX_L_CTRL = 0xB4: AMP_EN | AMP_RAMP_EN | AMP_ZC_EN | AMP_ZC_SEL_INPUT_AUX_L_IF */ + da7212_write_reg(dev, DIALOG7212_AUX_L_CTRL, + (uint8_t)(DIALOG7212_AUX_L_CTRL_AMP_EN_MASK | + DIALOG7212_AUX_L_CTRL_AMP_RAMP_EN_MASK | + DIALOG7212_AUX_L_CTRL_AMP_ZC_EN_MASK | + DIALOG7212_AUX_L_CTRL_AMP_ZC_SEL_INPUT_AUX_L_IF)); + + /* AUX_R_CTRL = 0xB0: AMP_EN | AMP_RAMP_EN | AMP_ZC_EN */ + da7212_write_reg(dev, DIALOG7212_AUX_R_CTRL, + (uint8_t)(DIALOG7212_AUX_R_CTRL_AMP_EN_MASK | + DIALOG7212_AUX_R_CTRL_AMP_RAMP_EN_MASK | + DIALOG7212_AUX_R_CTRL_AMP_ZC_EN_MASK)); + + /* MIC_1_CTRL = 0x04 (MIC_1_P), MIC_2_CTRL = 0x04 (MIC_2_P) */ + da7212_write_reg(dev, DIALOG7212_MIC_1_CTRL, + (uint8_t)DIALOG7212_MIC_1_CTRL_AMP_IN_SEL_MIC_1_P); + da7212_write_reg(dev, DIALOG7212_MIC_2_CTRL, + (uint8_t)DIALOG7212_MIC_2_CTRL_AMP_IN_SEL_MIC_2_P); + + /* MIXIN_L/R_CTRL = 0x88: AMP_EN | AMP_MIX_EN */ + da7212_write_reg(dev, DIALOG7212_MIXIN_L_CTRL, + (uint8_t)(DIALOG7212_MIXIN_L_CTRL_AMP_EN_MASK | + DIALOG7212_MIXIN_L_CTRL_AMP_MIX_EN_MASK)); + da7212_write_reg(dev, DIALOG7212_MIXIN_R_CTRL, + (uint8_t)(DIALOG7212_MIXIN_R_CTRL_AMP_EN_MASK | + DIALOG7212_MIXIN_R_CTRL_AMP_MIX_EN_MASK)); + + /* ADC_L_CTRL = 0xA0: ADC_EN | ADC_RAMP_EN (mirror to R for stereo) */ + da7212_write_reg(dev, DIALOG7212_ADC_L_CTRL, + (uint8_t)(DIALOG7212_ADC_L_CTRL_ADC_EN_MASK | + DIALOG7212_ADC_L_CTRL_ADC_RAMP_EN_MASK)); + da7212_write_reg(dev, DIALOG7212_ADC_R_CTRL, + (uint8_t)(DIALOG7212_ADC_R_CTRL_ADC_EN_MASK | + DIALOG7212_ADC_R_CTRL_ADC_RAMP_EN_MASK)); + + /* GAIN_RAMP_CTRL = 0x02: NR_MUL_16 */ + da7212_write_reg(dev, DIALOG7212_GAIN_RAMP_CTRL, + (uint8_t)DIALOG7212_GAIN_RAMP_CTRL_RATE_NR_MUL_16); + + /* PC_COUNT = 0x02: RESYNC */ + da7212_write_reg(dev, DIALOG7212_PC_COUNT, + (uint8_t)DIALOG7212_PC_COUNT_RESYNC_MASK); + + /* CP_DELAY = 0x95: LIMITER_AUT | TAU_DELAY_4MS | FCONTROL_0HZ_OR_1MHZ */ + da7212_write_reg(dev, DIALOG7212_CP_DELAY, + (uint8_t)(DIALOG7212_CP_DELAY_ON_OFF_LIMITER_AUT | + DIALOG7212_CP_DELAY_TAU_DELAY_4MS | + DIALOG7212_CP_DELAY_FCONTROL_0HZ_OR_1MHZ)); + + /* Set default ADC volume and unmute */ + da7212_in_volume_config(dev, AUDIO_CHANNEL_ALL, DIALOG7212_HP_DEFAULT_GAIN); + da7212_in_mute_config(dev, AUDIO_CHANNEL_ALL, false); +} + +static int da7212_configure(const struct device *dev, struct audio_codec_cfg *cfg) +{ + const struct da7212_driver_config *const dev_cfg = DEV_CFG(dev); + + if (cfg->dai_type >= AUDIO_DAI_TYPE_INVALID) { + LOG_ERR("dai_type not supported"); + return -EINVAL; + } + + if (cfg->dai_route == AUDIO_ROUTE_BYPASS) { + return 0; + } + + if (dev_cfg->clock_source == 0) { + int err = clock_control_on(dev_cfg->mclk_dev, dev_cfg->mclk_name); + + if (err < 0) { + LOG_ERR("MCLK clock source enable fail: %d", err); + } + err = clock_control_get_rate(dev_cfg->mclk_dev, dev_cfg->mclk_name, + &cfg->mclk_freq); + if (err < 0) { + LOG_ERR("MCLK clock source freq acquire fail: %d", err); + } + } + + da7212_soft_reset(dev); + + /* DAI right/left output stream comes from ADC right/left. + * Not used in AUDIO_ROUTE_PLAYBACK routing. + */ + da7212_write_reg(dev, DIALOG7212_DIG_ROUTING_DAI, + (uint8_t)DIALOG7212_DIG_ROUTING_DAI_R_SRC_ADC_RIGHT); + da7212_write_reg(dev, DIALOG7212_DIG_ROUTING_DAI, + (uint8_t)DIALOG7212_DIG_ROUTING_DAI_L_SRC_ADC_LEFT); + + /* Set default sample rate to 16kHz */ + da7212_write_reg(dev, DIALOG7212_SR, + (uint8_t)DIALOG7212_SR_16KHZ); + + /* Enable voltage reference and bias */ + da7212_write_reg(dev, DIALOG7212_REFERENCES, + (uint8_t)DIALOG7212_REFERENCES_BIAS_EN_MASK); + + /* Keep PLL disable, use MCLK as system clock. */ + da7212_write_reg(dev, DIALOG7212_PLL_FRAC_TOP, 0); + da7212_write_reg(dev, DIALOG7212_PLL_FRAC_BOT, 0); + da7212_write_reg(dev, DIALOG7212_PLL_INTEGER, 0x20); + da7212_write_reg(dev, DIALOG7212_PLL_CTRL, 0x0); + + /* Set default clock mode to slave, BCLK number per WCLK = 64 */ + da7212_write_reg(dev, DIALOG7212_DAI_CLK_MODE, + (uint8_t)DIALOG7212_DAI_BCLKS_PER_WCLK_BCLK64); + + /* Enable DAI, set default word length to 16 bits, I2S format, + * output enabled + */ + da7212_write_reg(dev, DIALOG7212_DAI_CTRL, + (uint8_t)(DIALOG7212_DAI_EN_MASK | + DIALOG7212_DAI_OE_MASK | + DIALOG7212_DAI_WORD_LENGTH_16B | + DIALOG7212_DAI_FORMAT_I2S_MODE)); + + /* Route DAC to MixOut by default */ + da7212_write_reg(dev, DIALOG7212_DIG_ROUTING_DAC, + (uint8_t)(DIALOG7212_DIG_ROUTING_DAC_R_RSC_DAC_R | + DIALOG7212_DIG_ROUTING_DAC_L_RSC_DAC_L)); + + /* Clock mode configuration */ + da7212_clock_mode_config(dev, &cfg->dai_cfg); + /* DAC input configuration */ + da7212_dac_input_config(dev, cfg->dai_route); + /* Protocol configuration */ + da7212_protocol_config(dev, cfg->dai_type); + /* Sample rate, word length configuration */ + da7212_audio_format_config(dev, &cfg->dai_cfg); + + switch (cfg->dai_route) { + case AUDIO_ROUTE_PLAYBACK: + da7212_configure_output(dev); + break; + case AUDIO_ROUTE_CAPTURE: + da7212_configure_input(dev); + break; + case AUDIO_ROUTE_PLAYBACK_CAPTURE: + da7212_configure_output(dev); + da7212_configure_input(dev); + break; + default: + break; + } + + return 0; +} + +static void da7212_start_output(const struct device *dev) +{ + ARG_UNUSED(dev); +} + +static void da7212_stop_output(const struct device *dev) +{ + ARG_UNUSED(dev); +} + +static int da7212_set_property(const struct device *dev, audio_property_t property, + audio_channel_t channel, audio_property_value_t val) +{ + switch (property) { + case AUDIO_PROPERTY_OUTPUT_VOLUME: + return da7212_out_volume_config(dev, channel, val.vol); + case AUDIO_PROPERTY_OUTPUT_MUTE: + return da7212_out_mute_config(dev, channel, val.mute); + case AUDIO_PROPERTY_INPUT_VOLUME: + return da7212_in_volume_config(dev, channel, val.vol); + case AUDIO_PROPERTY_INPUT_MUTE: + return da7212_in_mute_config(dev, channel, val.mute); + default: + break; + } + + return -EINVAL; +} + +static int da7212_apply_properties(const struct device *dev) +{ + /* Nothing special: gains written immediately */ + return 0; +} + +static const struct audio_codec_api da7212_driver_api = { + .configure = da7212_configure, + .start_output = da7212_start_output, + .stop_output = da7212_stop_output, + .set_property = da7212_set_property, + .apply_properties = da7212_apply_properties, + .route_input = da7212_route_input, + .route_output = da7212_route_output, +}; + +#define DA7212_INIT(n) \ + static const struct da7212_driver_config da7212_device_config_##n = { \ + .i2c = I2C_DT_SPEC_INST_GET(n), \ + .clock_source = DT_INST_ENUM_IDX(n, clock_source), \ + .mclk_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_NAME(n, mclk)), \ + .mclk_name = (clock_control_subsys_t)DT_INST_CLOCKS_CELL_BY_NAME(n, \ + mclk, name)}; \ + \ + DEVICE_DT_INST_DEFINE(n, NULL, NULL, NULL, &da7212_device_config_##n, \ + POST_KERNEL, CONFIG_AUDIO_CODEC_INIT_PRIORITY, &da7212_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(DA7212_INIT) diff --git a/drivers/audio/da7212.h b/drivers/audio/da7212.h new file mode 100644 index 0000000000000..c2b81fd7555ff --- /dev/null +++ b/drivers/audio/da7212.h @@ -0,0 +1,1162 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_AUDIO_DIALOG7212_H_ +#define ZEPHYR_DRIVERS_AUDIO_DIALOG7212_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/*! @brief da7212 volume setting range */ +#define DA7212_HEADPHONE_MAX_VOLUME_VALUE 0x3FU +#define DIALOG7212_HP_DEFAULT_GAIN 0x3FU + +/*! @brief Status registers */ +#define DIALOG7212_STATUS1 0x02 +#define DIALOG7212_PLL_STATUS 0x03 +#define DIALOG7212_AUX_L_GAIN_STATUS 0x04 +#define DIALOG7212_AUX_R_GAIN_STATUS 0x05 +#define DIALOG7212_MIC_1_GAIN_STATUS 0x06 +#define DIALOG7212_MIC_2_GAIN_STATUS 0x07 +#define DIALOG7212_MIXIN_L_GAIN_STATUS 0x08 +#define DIALOG7212_MIXIN_R_GAIN_STATUS 0x09 +#define DIALOG7212_ADC_L_GAIN_STATUS 0x0A +#define DIALOG7212_ADC_R_GAIN_STATUS 0x0B +#define DIALOG7212_DAC_L_GAIN_STATUS 0x0C +#define DIALOG7212_DAC_R_GAIN_STATUS 0x0D +#define DIALOG7212_HP_L_GAIN_STATUS 0x0E +#define DIALOG7212_HP_R_GAIN_STATUS 0x0F +#define DIALOG7212_LINE_GAIN_STATUS 0x10 + +/*! @brief System Initialisation Registers */ +#define DIALOG7212_CIF_CTRL 0x1d +#define DIALOG7212_DIG_ROUTING_DAI 0x21 +#define DIALOG7212_SR 0x22 +#define DIALOG7212_REFERENCES 0x23 +#define DIALOG7212_PLL_FRAC_TOP 0x24 +#define DIALOG7212_PLL_FRAC_BOT 0x25 +#define DIALOG7212_PLL_INTEGER 0x26 +#define DIALOG7212_PLL_CTRL 0x27 +#define DIALOG7212_DAI_CLK_MODE 0x28 +#define DIALOG7212_DAI_CTRL 0x29 +#define DIALOG7212_DIG_ROUTING_DAC 0x2A +#define DIALOG7212_ALC_CTRL1 0x2B + +/*! @brief Input Gain/ Select Filter Registers */ +#define DIALOG7212_AUX_L_GAIN 0x30 +#define DIALOG7212_AUX_R_GAIN 0x31 +#define DIALOG7212_MIXIN_L_SELECT 0x32 +#define DIALOG7212_MIXIN_R_SELECT 0x33 +#define DIALOG7212_MIXIN_L_GAIN 0x34 +#define DIALOG7212_MIXIN_R_GAIN 0x35 +#define DIALOG7212_ADC_L_GAIN 0x36 +#define DIALOG7212_ADC_R_GAIN 0x37 +#define DIALOG7212_ADC_FILTERS1 0x38 +#define DIALOG7212_MIC_1_GAIN 0x39 +#define DIALOG7212_MIC_2_GAIN 0x3A + +/*! @brief Output Gain/ Select Filter Registers */ +#define DIALOG7212_DAC_FILTERS5 0x40 +#define DIALOG7212_DAC_FILTERS2 0x41 +#define DIALOG7212_DAC_FILTERS3 0x42 +#define DIALOG7212_DAC_FILTERS4 0x43 +#define DIALOG7212_DAC_FILTERS1 0x44 +#define DIALOG7212_DAC_L_GAIN 0x45 +#define DIALOG7212_DAC_R_GAIN 0x46 +#define DIALOG7212_CP_CTRL 0x47 +#define DIALOG7212_HP_L_GAIN 0x48 +#define DIALOG7212_HP_R_GAIN 0x49 +#define DIALOG7212_LINE_GAIN 0x4A +#define DIALOG7212_MIXOUT_L_SELECT 0x4B +#define DIALOG7212_MIXOUT_R_SELECT 0x4C + +/*! @brief System Controller Registers(1) */ +#define DIALOG7212_SYSTEM_MODES_INPUT 0x50 +#define DIALOG7212_SYSTEM_MODES_OUTPUT 0x51 + +/*! @brief Control Registers(2) */ +#define DIALOG7212_AUX_L_CTRL 0x60 +#define DIALOG7212_AUX_R_CTRL 0x61 +#define DIALOG7212_MICBIAS_CTRL 0x62 +#define DIALOG7212_MIC_1_CTRL 0x63 +#define DIALOG7212_MIC_2_CTRL 0x64 +#define DIALOG7212_MIXIN_L_CTRL 0x65 +#define DIALOG7212_MIXIN_R_CTRL 0x66 +#define DIALOG7212_ADC_L_CTRL 0x67 +#define DIALOG7212_ADC_R_CTRL 0x68 +#define DIALOG7212_DAC_L_CTRL 0x69 +#define DIALOG7212_DAC_R_CTRL 0x6A +#define DIALOG7212_HP_L_CTRL 0x6B +#define DIALOG7212_HP_R_CTRL 0x6C +#define DIALOG7212_LINE_CTRL 0x6D +#define DIALOG7212_MIXOUT_L_CTRL 0x6E +#define DIALOG7212_MIXOUT_R_CTRL 0x6F + +/*! @brief Configuration Registers */ +#define DIALOG7212_LDO_CTRL 0x90 +#define DIALOG7212_GAIN_RAMP_CTRL 0x92 +#define DIALOG7212_MIC_CONFIG 0x93 +#define DIALOG7212_PC_COUNT 0x94 +#define DIALOG7212_CP_VOL_THRESHOLD1 0x95 +#define DIALOG7212_CP_DELAY 0x96 +#define DIALOG7212_CP_DETECTOR 0x97 +#define DIALOG7212_DAI_OFFSET 0x98 +#define DIALOG7212_DIG_CTRL 0x99 +#define DIALOG7212_ALC_CTRL2 0x9A +#define DIALOG7212_ALC_CTRL3 0x9B +#define DIALOG7212_ALC_NOISE 0x9C +#define DIALOG7212_ALC_TARGET_MIN 0x9D +#define DIALOG7212_ALC_TARGET_MAX 0x9E +#define DIALOG7212_ALC_GAIN_LIMITS 0x9F +#define DIALOG7212_ALC_ANA_GAIN_LIMITS 0xA0 +#define DIALOG7212_ALC_ANTICLIP_CTRL 0xA1 +#define DIALOG7212_ALC_ANTICLIP_LEVEL 0xA2 +#define DIALOG7212_DAC_NG_SETUP_TIME 0xAF +#define DIALOG7212_DAC_NG_OFF_THRESH 0xB0 +#define DIALOG7212_DAC_NG_ON_THRESH 0xB1 +#define DIALOG7212_DAC_NG_CTRL 0xB2 +/* #define DIALOG7212_DAC_NG_SPARE 0xB3 */ + +/*! @brief Tone Generation & Beep Registers */ +#define DIALOG7212_TONE_GEN_CFG1 0xB4 +#define DIALOG7212_TONE_GEN_CFG2 0xB5 +#define DIALOG7212_TONE_GEN_CYCLES 0xB6 +#define DIALOG7212_TONE_GEN_FREQ1_L 0xB7 +#define DIALOG7212_TONE_GEN_FREQ1_U 0xB8 +#define DIALOG7212_TONE_GEN_FREQ2_L 0xB9 +#define DIALOG7212_TONE_GEN_FREQ2_U 0xBA +#define DIALOG7212_TONE_GEN_ON_PER 0xBB +#define DIALOG7212_TONE_GEN_OFF_PER 0xBC + +/*! @brief System Controller Registers(2) */ +#define DIALOG7212_SYSTEM_STATUS 0xE0 +#define DIALOG7212_SYSTEM_ACTIVE 0xFD + +/********** Driver DA7212 Macros **********/ + +/*! @brief Status registers mask/shift */ +/* DIALOG7212_PLL_STATUS 0x03*/ +#define DIALOG7212_PLL_STATUS_BYPASS_ACTIVE_MASK (1U << 3) +#define DIALOG7212_PLL_STATUS_MCLK_STATUS_MASK (1U << 2) +#define DIALOG7212_PLL_STATUS_SRM_LOCK_MASK (1U << 1) +#define DIALOG7212_PLL_STATUS_LOCK_MASK (1U << 0) + +/* DIALOG7212_AUX_L_GAIN_STATUS 0x04*/ +#define DIALOG7212_AUX_L_AMP_GAIN_STATUS_MASK (0x3F) +#define DIALOG7212_AUX_L_AMP_GAIN_STATUS_SHIFT (0U) +#define DIALOG7212_AUX_L_AMP_GAIN_STATUS(x) \ + ((x) << DIALOG7212_AUX_L_AMP_GAIN_STATUS_SHIFT) + +/* DIALOG7212_AUX_R_GAIN_STATUS 0x05*/ +#define DIALOG7212_AUX_R_AMP_GAIN_STATUS_MASK (0x3F) +#define DIALOG7212_AUX_R_AMP_GAIN_STATUS_SHIFT (0U) +#define DIALOG7212_AUX_R_AMP_GAIN_STATUS(x) \ + ((x) << DIALOG7212_AUX_R_AMP_GAIN_STATUS_SHIFT) + +/* DIALOG7212_MIC_1_GAIN_STATUS 0x06*/ +#define DIALOG7212_MIC_1_AMP_GAIN_STATUS_MASK (0x07) +#define DIALOG7212_MIC_1_AMP_GAIN_STATUS_SHIFT (0U) +#define DIALOG7212_MIC_1_AMP_GAIN_STATUS(x) \ + ((x) << DIALOG7212_MIC_1_AMP_GAIN_STATUS_SHIFT) + +/* DIALOG7212_MIC_2_GAIN_STATUS 0x07*/ +#define DIALOG7212_MIC_2_AMP_GAIN_STATUS_MASK (0x07) +#define DIALOG7212_MIC_2_AMP_GAIN_STATUS_SHIFT (0U) +#define DIALOG7212_MIC_2_AMP_GAIN_STATUS(x) \ + ((x) << DIALOG7212_MIC_2_AMP_GAIN_STATUS_SHIFT) + +/* DIALOG7212_MIXIN_L_GAIN_STATUS 0x08*/ +#define DIALOG7212_MIXIN_L_AMP_GAIN_STATUS_MASK (0x0F) +#define DIALOG7212_MIXIN_L_AMP_GAIN_STATUS_SHIFT (0U) +#define DIALOG7212_MIXIN_L_AMP_GAIN_STATUS(x) \ + ((x) << DIALOG7212_MIXIN_L_AMP_GAIN_STATUS_SHIFT) + +/* DIALOG7212_MIXIN_R_GAIN_STATUS 0x09*/ +#define DIALOG7212_MIXIN_R_AMP_GAIN_STATUS_MASK (0x0F) +#define DIALOG7212_MIXIN_R_AMP_GAIN_STATUS_SHIFT (0U) +#define DIALOG7212_MIXIN_R_AMP_GAIN_STATUS(x) \ + ((x) << DIALOG7212_MIXIN_R_AMP_GAIN_STATUS_SHIFT) + +/* DIALOG7212_ADC_L_GAIN_STATUS 0x0A*/ +#define DIALOG7212_ADC_L_GAIN_STATUS_MASK (0x7F) +#define DIALOG7212_ADC_L_GAIN_STATUS_SHIFT (0U) +#define DIALOG7212_ADC_L_GAIN_STATUS_VAL(x) \ + ((x) << DIALOG7212_ADC_L_GAIN_STATUS_SHIFT) + +/* DIALOG7212_ADC_R_GAIN_STATUS 0x0B*/ +#define DIALOG7212_ADC_R_GAIN_STATUS_MASK (0x7F) +#define DIALOG7212_ADC_R_GAIN_STATUS_SHIFT (0U) +#define DIALOG7212_ADC_R_GAIN_STATUS_VAL(x) \ + ((x) << DIALOG7212_ADC_R_GAIN_STATUS_SHIFT) + +/* DIALOG7212_DAC_L_GAIN_STATUS 0x0C*/ +#define DIALOG7212_DAC_L_GAIN_STATUS_MASK (0x7F) +#define DIALOG7212_DAC_L_GAIN_STATUS_SHIFT (0U) +#define DIALOG7212_DAC_L_GAIN_STATUS_VAL(x) \ + ((x) << DIALOG7212_DAC_L_GAIN_STATUS_SHIFT) + +/* DIALOG7212_DAC_R_GAIN_STATUS 0x0D*/ +#define DIALOG7212_DAC_R_GAIN_STATUS_MASK (0x7F) +#define DIALOG7212_DAC_R_GAIN_STATUS_SHIFT (0U) +#define DIALOG7212_DAC_R_GAIN_STATUS_VAL(x) \ + ((x) << DIALOG7212_DAC_R_GAIN_STATUS_SHIFT) + +/* DIALOG7212_HP_L_GAIN_STATUS 0x0E*/ +#define DIALOG7212_HP_L_AMP_GAIN_STATUS_MASK (0x3F) +#define DIALOG7212_HP_L_AMP_GAIN_STATUS_SHIFT (0U) +#define DIALOG7212_HP_L_AMP_GAIN_STATUS(x) \ + ((x) << DIALOG7212_HP_L_AMP_GAIN_STATUS_SHIFT) + +/* DIALOG7212_HP_R_GAIN_STATUS 0x0F*/ +#define DIALOG7212_HP_R_AMP_GAIN_STATUS_MASK (0x3F) +#define DIALOG7212_HP_R_AMP_GAIN_STATUS_SHIFT (0U) +#define DIALOG7212_HP_R_AMP_GAIN_STATUS(x) \ + ((x) << DIALOG7212_HP_R_AMP_GAIN_STATUS_SHIFT) + +/* DIALOG7212_LINE_GAIN_STATUS 0x10*/ +#define DIALOG7212_LINE_AMP_GAIN_STATUS_MASK (0x3F) +#define DIALOG7212_LINE_AMP_GAIN_STATUS_SHIFT (0U) +#define DIALOG7212_LINE_AMP_GAIN_STATUS(x) \ + ((x) << DIALOG7212_LINE_AMP_GAIN_STATUS_SHIFT) + +/*! @brief System Initialisation Registers mask/shift */ +/* DIALOG7212_CIF_CTRL 0x1d */ +#define DIALOG7212_CIF_CTRL_CIF_REG_SOFT_RESET_MASK (1U << 7) +#define DIALOG7212_CIF_CTRL_CIF_I2C_WRITE_MODE_MASK (1U << 0) + +/* DIALOG7212_DIG_ROUTING_DAI 0x21 */ +#define DIALOG7212_DIG_ROUTING_DAI_R_SRC_MASK (0x30) +#define DIALOG7212_DIG_ROUTING_DAI_R_SRC_SHIFT (4U) +#define DIALOG7212_DIG_ROUTING_DAI_R_SRC_ADC_LEFT \ + (0U << DIALOG7212_DIG_ROUTING_DAI_R_SRC_SHIFT) +#define DIALOG7212_DIG_ROUTING_DAI_R_SRC_ADC_RIGHT \ + (1U << DIALOG7212_DIG_ROUTING_DAI_R_SRC_SHIFT) +#define DIALOG7212_DIG_ROUTING_DAI_R_SRC_DAI_LEFT \ + (2U << DIALOG7212_DIG_ROUTING_DAI_R_SRC_SHIFT) +#define DIALOG7212_DIG_ROUTING_DAI_R_SRC_DAI_RIGHT \ + (3U << DIALOG7212_DIG_ROUTING_DAI_R_SRC_SHIFT) +#define DIALOG7212_DIG_ROUTING_DAI_L_SRC_MASK (0x03) +#define DIALOG7212_DIG_ROUTING_DAI_L_SRC_SHIFT (4U) +#define DIALOG7212_DIG_ROUTING_DAI_L_SRC_ADC_LEFT \ + (0U << DIALOG7212_DIG_ROUTING_DAI_L_SRC_SHIFT) +#define DIALOG7212_DIG_ROUTING_DAI_L_SRC_ADC_RIGHT \ + (1U << DIALOG7212_DIG_ROUTING_DAI_L_SRC_SHIFT) +#define DIALOG7212_DIG_ROUTING_DAI_L_SRC_DAI_LEFT \ + (2U << DIALOG7212_DIG_ROUTING_DAI_L_SRC_SHIFT) +#define DIALOG7212_DIG_ROUTING_DAI_L_SRC_DAI_RIGHT \ + (3U << DIALOG7212_DIG_ROUTING_DAI_L_SRC_SHIFT) + +/* DIALOG7212_SR 0x22 */ +#define DIALOG7212_SR_MASK (0x0F) +#define DIALOG7212_SR_SHIFT (0U) +#define DIALOG7212_SR_8KHZ (1U << DIALOG7212_SR_SHIFT) +#define DIALOG7212_SR_11_025KHZ (2U << DIALOG7212_SR_SHIFT) +#define DIALOG7212_SR_12KHZ (3U << DIALOG7212_SR_SHIFT) +#define DIALOG7212_SR_16KHZ (5U << DIALOG7212_SR_SHIFT) +#define DIALOG7212_SR_22KHZ (6U << DIALOG7212_SR_SHIFT) +#define DIALOG7212_SR_24KHZ (7U << DIALOG7212_SR_SHIFT) +#define DIALOG7212_SR_32KHZ (9U << DIALOG7212_SR_SHIFT) +#define DIALOG7212_SR_44_1KHZ (10U << DIALOG7212_SR_SHIFT) +#define DIALOG7212_SR_48KHZ (11U << DIALOG7212_SR_SHIFT) +#define DIALOG7212_SR_88_2KHZ (14U << DIALOG7212_SR_SHIFT) +#define DIALOG7212_SR_96KHZ (15U << DIALOG7212_SR_SHIFT) + +/* DIALOG7212_REFERENCES 0x23 */ +#define DIALOG7212_REFERENCES_VMID_FAST_DISCHARGE_MASK (1U << 5) +#define DIALOG7212_REFERENCES_VMID_FAST_CHARGE_MASK (1U << 4) +#define DIALOG7212_REFERENCES_BIAS_EN_MASK (1U << 3) + +/* DIALOG7212_PLL_FRAC_TOP 0x24 */ +#define DIALOG7212_PLL_FBDIV_FRAC_TOP_MASK (0x1F) +#define DIALOG7212_PLL_FBDIV_FRAC_TOP_SHIFT (0U) +#define DIALOG7212_PLL_FBDIV_FRAC_TOP(x) \ + ((x) << DIALOG7212_PLL_FBDIV_FRAC_TOP_SHIFT) + +/* DIALOG7212_PLL_FRAC_BOT 0x25 */ +#define DIALOG7212_PLL_FBDIV_FRAC_BOT_MASK (0xFF) +#define DIALOG7212_PLL_FBDIV_FRAC_BOT_SHIFT (0U) +#define DIALOG7212_PLL_FBDIV_FRAC_BOT(x) \ + ((x) << DIALOG7212_PLL_FBDIV_FRAC_BOT_SHIFT) + +/* DIALOG7212_PLL_INTEGER 0x26 */ +#define DIALOG7212_PLL_FBDIV_INTEGER_MASK (0xFF) +#define DIALOG7212_PLL_FBDIV_INTEGER_SHIFT (0U) +#define DIALOG7212_PLL_FBDIV_INTEGER_BOT(x) \ + ((x) << DIALOG7212_PLL_FBDIV_INTEGER_SHIFT) + +/* DIALOG7212_PLL_CTRL 0x27 */ +#define DIALOG7212_PLL_EN_MASK (1U << 7) +#define DIALOG7212_PLL_SRM_EN_MASK (1U << 6) +#define DIALOG7212_PLL_32K_MODE_MASK (1U << 5) +#define DIALOG7212_PLL_MCLKSQR_EN_MASK (1U << 4) +#define DIALOG7212_PLL_INDIV_MASK (0x06) +#define DIALOG7212_PLL_INDIV_SHIFT (2U) +#define DIALOG7212_PLL_INDIV_2_10MHZ (0U << DIALOG7212_PLL_INDIV_SHIFT) +#define DIALOG7212_PLL_INDIV_10_20MHZ (1U << DIALOG7212_PLL_INDIV_SHIFT) +#define DIALOG7212_PLL_INDIV_20_40MHZ (2U << DIALOG7212_PLL_INDIV_SHIFT) +#define DIALOG7212_PLL_INDIV_40_80MHZ (3U << DIALOG7212_PLL_INDIV_SHIFT) + +/* DIALOG7212_DAI_CLK_MODE 0x28 */ +#define DIALOG7212_DAI_CLK_EN_MASK (1U << 7) +#define DIALOG7212_DAI_WCLK_POL_MASK (1U << 3) +#define DIALOG7212_DAI_CLK_POL_MASK (1U << 2) +#define DIALOG7212_DAI_BCLKS_PER_WCLK_MASK (0x03) +#define DIALOG7212_DAI_BCLKS_PER_WCLK_SHIFT (0U) +#define DIALOG7212_DAI_BCLKS_PER_WCLK_BCLK32 \ + (0U << DIALOG7212_DAI_BCLKS_PER_WCLK_SHIFT) +#define DIALOG7212_DAI_BCLKS_PER_WCLK_BCLK64 \ + (1U << DIALOG7212_DAI_BCLKS_PER_WCLK_SHIFT) +#define DIALOG7212_DAI_BCLKS_PER_WCLK_BCLK128 \ + (2U << DIALOG7212_DAI_BCLKS_PER_WCLK_SHIFT) +#define DIALOG7212_DAI_BCLKS_PER_WCLK_BCLK256 \ + (3U << DIALOG7212_DAI_BCLKS_PER_WCLK_SHIFT) + +/* DIALOG7212_DAI_CTRL 0x29 */ +#define DIALOG7212_DAI_EN_MASK (1U << 7) +#define DIALOG7212_DAI_OE_MASK (1U << 6) +#define DIALOG7212_DAI_TDM_MODE_EN_MASK (1U << 5) +#define DIALOG7212_DAI_MONO_MODE_MASK (1U << 4) +#define DIALOG7212_DAI_WORD_LENGTH_MASK (0xC) +#define DIALOG7212_DAI_WORD_LENGTH_SHIFT (2U) +#define DIALOG7212_DAI_WORD_LENGTH_16B \ + (0U << DIALOG7212_DAI_WORD_LENGTH_SHIFT) +#define DIALOG7212_DAI_WORD_LENGTH_20B \ + (1U << DIALOG7212_DAI_WORD_LENGTH_SHIFT) +#define DIALOG7212_DAI_WORD_LENGTH_24B \ + (2U << DIALOG7212_DAI_WORD_LENGTH_SHIFT) +#define DIALOG7212_DAI_WORD_LENGTH_32B \ + (3U << DIALOG7212_DAI_WORD_LENGTH_SHIFT) +#define DIALOG7212_DAI_FORMAT_MASK (0x03) +#define DIALOG7212_DAI_FORMAT_SHIFT (0U) +#define DIALOG7212_DAI_FORMAT_I2S_MODE \ + (0U << DIALOG7212_DAI_FORMAT_SHIFT) +#define DIALOG7212_DAI_FORMAT_LEFT_JUSTIFIED \ + (1U << DIALOG7212_DAI_FORMAT_SHIFT) +#define DIALOG7212_DAI_FORMAT_RIGTH_JUSTIFIED \ + (2U << DIALOG7212_DAI_FORMAT_SHIFT) +#define DIALOG7212_DAI_FORMAT_DSP_MODE \ + (3U << DIALOG7212_DAI_FORMAT_SHIFT) + +/* DIALOG7212_DIG_ROUTING_DAC 0x2A */ +#define DIALOG7212_DIG_ROUTING_DAC_R_MONO_MASK (1U << 7) +#define DIALOG7212_DIG_ROUTING_DAC_R_RSC_MASK (0x30) +#define DIALOG7212_DIG_ROUTING_DAC_R_RSC_SHIFT (4U) +#define DIALOG7212_DIG_ROUTING_DAC_R_RSC_ADC_L_OUTPUT \ + (0U << DIALOG7212_DIG_ROUTING_DAC_R_RSC_SHIFT) +#define DIALOG7212_DIG_ROUTING_DAC_R_RSC_ADC_R_OUTPUT \ + (1U << DIALOG7212_DIG_ROUTING_DAC_R_RSC_SHIFT) +#define DIALOG7212_DIG_ROUTING_DAC_R_RSC_DAC_L \ + (2U << DIALOG7212_DIG_ROUTING_DAC_R_RSC_SHIFT) +#define DIALOG7212_DIG_ROUTING_DAC_R_RSC_DAC_R \ + (3U << DIALOG7212_DIG_ROUTING_DAC_R_RSC_SHIFT) +#define DIALOG7212_DIG_ROUTING_DAC_L_MONO_MASK (1U << 3) +#define DIALOG7212_DIG_ROUTING_DAC_L_RSC_MASK (0x03) +#define DIALOG7212_DIG_ROUTING_DAC_L_RSC_SHIFT (0U) +#define DIALOG7212_DIG_ROUTING_DAC_L_RSC_ADC_L_OUTPUT \ + (0U << DIALOG7212_DIG_ROUTING_DAC_L_RSC_SHIFT) +#define DIALOG7212_DIG_ROUTING_DAC_L_RSC_ADC_R_OUTPUT \ + (1U << DIALOG7212_DIG_ROUTING_DAC_L_RSC_SHIFT) +#define DIALOG7212_DIG_ROUTING_DAC_L_RSC_DAC_L \ + (2U << DIALOG7212_DIG_ROUTING_DAC_L_RSC_SHIFT) +#define DIALOG7212_DIG_ROUTING_DAC_L_RSC_DAC_R \ + (3U << DIALOG7212_DIG_ROUTING_DAC_L_RSC_SHIFT) + +/* DIALOG7212_ALC_CTRL1 0x2B */ +#define DIALOG7212_ALC_R_EN_MASK (1U << 7) +#define DIALOG7212_ALC_CALIB_OVERFLOW_MASK (1U << 5) +#define DIALOG7212_ALC_AUTO_CALIB_EN_MASK (1U << 4) +#define DIALOG7212_ALC_L_EN_MASK (1U << 3) +#define DIALOG7212_ALC_CALIB_MODE_MASK (1U << 2) +#define DIALOG7212_ALC_SYNC_MODE_MASK (1U << 1) +#define DIALOG7212_ALC_OFFSET_EN_MASK (1U << 0) + +/*! @brief Input Gain/ Select Filter Registers mask/shift */ +/* DIALOG7212_AUX_L_GAIN 0x30 */ +#define DIALOG7212_AUX_L_AMP_GAIN_MASK (0x3F) +#define DIALOG7212_AUX_L_AMP_GAIN_SHIFT (0U) +#define DIALOG7212_AUX_L_AMP_GAIN(x) \ + ((x) << DIALOG7212_AUX_L_AMP_GAIN_SHIFT) + +/* DIALOG7212_AUX_R_GAIN 0x31 */ +#define DIALOG7212_AUX_R_AMP_GAIN_MASK (0x3F) +#define DIALOG7212_AUX_R_AMP_GAIN_SHIFT (0U) +#define DIALOG7212_AUX_R_AMP_GAIN(x) \ + ((x) << DIALOG7212_AUX_R_AMP_GAIN_SHIFT) + +/* DIALOG7212_MIXIN_L_SELECT 0x32 */ +#define DIALOG7212_MIXIN_L_SELECT_DMIC_L_EN_MASK (1U << 7) +#define DIALOG7212_MIXIN_L_SELECT_MIXING_R_MASK (1U << 3) +#define DIALOG7212_MIXIN_L_SELECT_MIC2_SEL_MASK (1U << 2) +#define DIALOG7212_MIXIN_L_SELECT_MIC1_SEL_MASK (1U << 1) +#define DIALOG7212_MIXIN_L_SELECT_AUX_L_SEL_MASK (1U << 0) + +/* DIALOG7212_MIXIN_R_SELECT 0x33 */ +#define DIALOG7212_MIXIN_R_SELECT_DMIC_R_EN_MASK (1U << 7) +#define DIALOG7212_MIXIN_R_SELECT_MIXING_L_MASK (1U << 3) +#define DIALOG7212_MIXIN_R_SELECT_MIC2_SEL_MASK (1U << 2) +#define DIALOG7212_MIXIN_R_SELECT_MIC1_SEL_MASK (1U << 1) +#define DIALOG7212_MIXIN_R_SELECT_AUX_R_SEL_MASK (1U << 0) + +/* DIALOG7212_MIXIN_L_GAIN 0x34 */ +#define DIALOG7212_MIXIN_L_AMP_GAIN_MASK (0x0F) +#define DIALOG7212_MIXIN_L_AMP_GAIN_SHIFT (0U) +#define DIALOG7212_MIXIN_L_AMP_GAIN(x) \ + ((x) << DIALOG7212_MIXIN_L_AMP_GAIN_SHIFT) + +/* DIALOG7212_MIXIN_R_GAIN 0x35 */ +#define DIALOG7212_MIXIN_R_AMP_GAIN_MASK (0x0F) +#define DIALOG7212_MIXIN_R_AMP_GAIN_SHIFT (0U) +#define DIALOG7212_MIXIN_R_AMP_GAIN(x) \ + ((x) << DIALOG7212_MIXIN_R_AMP_GAIN_SHIFT) + +/* DIALOG7212_ADC_L_GAIN 0x36 */ +#define DIALOG7212_ADC_L_DIGITAL_GAIN_MASK (0x7F) +#define DIALOG7212_ADC_L_DIGITAL_GAIN_SHIFT (0U) +#define DIALOG7212_ADC_L_DIGITAL_GAIN(x) \ + ((x) << DIALOG7212_ADC_L_DIGITAL_GAIN_SHIFT) + +/* DIALOG7212_ADC_R_GAIN 0x37 */ +#define DIALOG7212_ADC_R_DIGITAL_GAIN_MASK (0x7F) +#define DIALOG7212_ADC_R_DIGITAL_GAIN_SHIFT (0U) +#define DIALOG7212_ADC_R_DIGITAL_GAIN(x) \ + ((x) << DIALOG7212_ADC_R_DIGITAL_GAIN_SHIFT) + +/* DIALOG7212_ADC_FILTERS1 0x38 */ +#define DIALOG7212_ADC_FILTERS1_ADC_HPF_EN_MASK (1U << 7) +#define DIALOG7212_ADC_FILTERS1_ADC_AUDIO_HPF_CORNER_MASK (0x30) +#define DIALOG7212_ADC_FILTERS1_ADC_AUDIO_HPF_CORNER_SHIFT (5U) +#define DIALOG7212_ADC_FILTERS1_ADC_AUDIO_HPF_CORNER_2HZ \ + (0U << DIALOG7212_ADC_FILTERS1_ADC_AUDIO_HPF_CORNER_SHIFT) +#define DIALOG7212_ADC_FILTERS1_ADC_AUDIO_HPF_CORNER_4HZ \ + (1U << DIALOG7212_ADC_FILTERS1_ADC_AUDIO_HPF_CORNER_SHIFT) +#define DIALOG7212_ADC_FILTERS1_ADC_AUDIO_HPF_CORNER_8HZ \ + (2U << DIALOG7212_ADC_FILTERS1_ADC_AUDIO_HPF_CORNER_SHIFT) +#define DIALOG7212_ADC_FILTERS1_ADC_AUDIO_HPF_CORNER_16HZ \ + (3U << DIALOG7212_ADC_FILTERS1_ADC_AUDIO_HPF_CORNER_SHIFT) +#define DIALOG7212_ADC_FILTERS1_ADC_VOICE_EN_MASK (1U << 3) +#define DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_MASK (0x07) +#define DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_SHIFT (0U) +#define DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_2_5HZ \ + (0U << DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_SHIFT) +#define DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_25HZ \ + (1U << DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_SHIFT) +#define DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_50HZ \ + (2U << DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_SHIFT) +#define DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_100HZ \ + (3U << DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_SHIFT) +#define DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_150HZ \ + (4U << DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_SHIFT) +#define DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_200HZ \ + (5U << DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_SHIFT) +#define DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_300HZ \ + (6U << DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_SHIFT) +#define DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_400HZ \ + (7U << DIALOG7212_ADC_FILTERS1_ADC_VOICE_HPF_CORNER_SHIFT) + +/* DIALOG7212_MIC_1_GAIN 0x39 */ +#define DIALOG7212_MIC_1_AMP_GAIN_MASK (0x07) +#define DIALOG7212_MIC_1_AMP_GAIN_SHIFT (0U) +#define DIALOG7212_MIC_1_AMP_GAIN_N6DB (0U << DIALOG7212_MIC_1_AMP_GAIN_SHIFT) +#define DIALOG7212_MIC_1_AMP_GAIN_0DB (1U << DIALOG7212_MIC_1_AMP_GAIN_SHIFT) +#define DIALOG7212_MIC_1_AMP_GAIN_P6DB (2U << DIALOG7212_MIC_1_AMP_GAIN_SHIFT) +#define DIALOG7212_MIC_1_AMP_GAIN_P12DB (3U << DIALOG7212_MIC_1_AMP_GAIN_SHIFT) +#define DIALOG7212_MIC_1_AMP_GAIN_P18DB (4U << DIALOG7212_MIC_1_AMP_GAIN_SHIFT) +#define DIALOG7212_MIC_1_AMP_GAIN_P24DB (5U << DIALOG7212_MIC_1_AMP_GAIN_SHIFT) +#define DIALOG7212_MIC_1_AMP_GAIN_P30DB (6U << DIALOG7212_MIC_1_AMP_GAIN_SHIFT) +#define DIALOG7212_MIC_1_AMP_GAIN_P36DB (7U << DIALOG7212_MIC_1_AMP_GAIN_SHIFT) + +/* DIALOG7212_MIC_2_GAIN 0x3A */ +#define DIALOG7212_MIC_2_AMP_GAIN_MASK (0x07) +#define DIALOG7212_MIC_2_AMP_GAIN_SHIFT (0U) +#define DIALOG7212_MIC_2_AMP_GAIN_N6DB (0U << DIALOG7212_MIC_2_AMP_GAIN_SHIFT) +#define DIALOG7212_MIC_2_AMP_GAIN_0DB (1U << DIALOG7212_MIC_2_AMP_GAIN_SHIFT) +#define DIALOG7212_MIC_2_AMP_GAIN_P6DB (2U << DIALOG7212_MIC_2_AMP_GAIN_SHIFT) +#define DIALOG7212_MIC_2_AMP_GAIN_P12DB (3U << DIALOG7212_MIC_2_AMP_GAIN_SHIFT) +#define DIALOG7212_MIC_2_AMP_GAIN_P18DB (4U << DIALOG7212_MIC_2_AMP_GAIN_SHIFT) +#define DIALOG7212_MIC_2_AMP_GAIN_P24DB (5U << DIALOG7212_MIC_2_AMP_GAIN_SHIFT) +#define DIALOG7212_MIC_2_AMP_GAIN_P30DB (6U << DIALOG7212_MIC_2_AMP_GAIN_SHIFT) +#define DIALOG7212_MIC_2_AMP_GAIN_P36DB (7U << DIALOG7212_MIC_2_AMP_GAIN_SHIFT) + +/*! @brief Output Gain/ Select Filter Registers mask/shift */ +/* DIALOG7212_DAC_FILTERS5 0x40 */ +#define DIALOG7212_DAC_FILTERS5_SOFTMUTE_EN_MASK (1U << 7) +#define DIALOG7212_DAC_FILTERS5_SOFTMUTE_RATE_MASK (0x07) +#define DIALOG7212_DAC_FILTERS5_SOFTMUTE_RATE_SHIFT (4U) +#define DIALOG7212_DAC_FILTERS5_SOFTMUTE_RATE_1 \ + (0U << DIALOG7212_DAC_FILTERS5_SOFTMUTE_RATE_SHIFT) +#define DIALOG7212_DAC_FILTERS5_SOFTMUTE_RATE_2 \ + (1U << DIALOG7212_DAC_FILTERS5_SOFTMUTE_RATE_SHIFT) +#define DIALOG7212_DAC_FILTERS5_SOFTMUTE_RATE_4 \ + (2U << DIALOG7212_DAC_FILTERS5_SOFTMUTE_RATE_SHIFT) +#define DIALOG7212_DAC_FILTERS5_SOFTMUTE_RATE_8 \ + (3U << DIALOG7212_DAC_FILTERS5_SOFTMUTE_RATE_SHIFT) +#define DIALOG7212_DAC_FILTERS5_SOFTMUTE_RATE_16 \ + (4U << DIALOG7212_DAC_FILTERS5_SOFTMUTE_RATE_SHIFT) +#define DIALOG7212_DAC_FILTERS5_SOFTMUTE_RATE_32 \ + (5U << DIALOG7212_DAC_FILTERS5_SOFTMUTE_RATE_SHIFT) +#define DIALOG7212_DAC_FILTERS5_SOFTMUTE_RATE_64 \ + (6U << DIALOG7212_DAC_FILTERS5_SOFTMUTE_RATE_SHIFT) + +/* DIALOG7212_DAC_FILTERS2 0x41 */ +#define DIALOG7212_DAC_FILTERS2_EQ_BAND2_MASK (0xF0) +#define DIALOG7212_DAC_FILTERS2_EQ_BAND2_SHIFT (4U) +#define DIALOG7212_DAC_FILTERS2_EQ_BAND2(x) \ + ((x) << DIALOG7212_DAC_FILTERS2_EQ_BAND2_SHIFT) +#define DIALOG7212_DAC_FILTERS2_EQ_BAND1_MASK (0x0F) +#define DIALOG7212_DAC_FILTERS2_EQ_BAND1_SHIFT (0U) +#define DIALOG7212_DAC_FILTERS2_EQ_BAND1(x) \ + ((x) << DIALOG7212_DAC_FILTERS2_EQ_BAND1_SHIFT) + +/* DIALOG7212_DAC_FILTERS3 0x42 */ +#define DIALOG7212_DAC_FILTERS3_EQ_BAND4_MASK (0xF0) +#define DIALOG7212_DAC_FILTERS3_EQ_BAND4_SHIFT (4U) +#define DIALOG7212_DAC_FILTERS3_EQ_BAND4(x) \ + ((x) << DIALOG7212_DAC_FILTERS2_EQ_BAND4_SHIFT) +#define DIALOG7212_DAC_FILTERS3_EQ_BAND3_MASK (0x0F) +#define DIALOG7212_DAC_FILTERS3_EQ_BAND3_SHIFT (0U) +#define DIALOG7212_DAC_FILTERS3_EQ_BAND3(x) \ + ((x) << DIALOG7212_DAC_FILTERS2_EQ_BAND3_SHIFT) + +/* DIALOG7212_DAC_FILTERS4 0x43 */ +#define DIALOG7212_DAC_FILTERS4_EQ_EN_MASK (1U << 7) +#define DIALOG7212_DAC_FILTERS4_EQ_BAND5_MASK (0x0F) +#define DIALOG7212_DAC_FILTERS4_EQ_BAND5_SHIFT (0U) +#define DIALOG7212_DAC_FILTERS4_EQ_BAND5(x) \ + ((x) << DIALOG7212_DAC_FILTERS2_EQ_BAND5_SHIFT) + +/* DIALOG7212_DAC_FILTERS1 0x44 */ +#define DIALOG7212_DAC_FILTERS1_HPF_EN_MASK (1U << 7) +#define DIALOG7212_DAC_FILTERS1_DAC_AUDIO_HPF_CORNER_MASK (0x30) +#define DIALOG7212_DAC_FILTERS1_DAC_AUDIO_HPF_CORNER_SHIFT (5U) +#define DIALOG7212_DAC_FILTERS1_DAC_AUDIO_HPF_CORNER_2HZ \ + (0U << DIALOG7212_DAC_FILTERS1_DAC_AUDIO_HPF_CORNER_SHIFT) +#define DIALOG7212_DAC_FILTERS1_DAC_AUDIO_HPF_CORNER_4HZ \ + (1U << DIALOG7212_DAC_FILTERS1_DAC_AUDIO_HPF_CORNER_SHIFT) +#define DIALOG7212_DAC_FILTERS1_DAC_AUDIO_HPF_CORNER_8HZ \ + (2U << DIALOG7212_DAC_FILTERS1_DAC_AUDIO_HPF_CORNER_SHIFT) +#define DIALOG7212_DAC_FILTERS1_DAC_AUDIO_HPF_CORNER_16HZ \ + (3U << DIALOG7212_DAC_FILTERS1_DAC_AUDIO_HPF_CORNER_SHIFT) +#define DIALOG7212_DAC_FILTERS1_DAC_VOICE_EN_MASK (1U << 3) +#define DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_MASK (0x07) +#define DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_SHIFT (0U) +#define DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_2_5HZ \ + (0U << DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_SHIFT) +#define DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_25HZ \ + (1U << DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_SHIFT) +#define DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_50HZ \ + (2U << DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_SHIFT) +#define DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_100HZ \ + (3U << DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_SHIFT) +#define DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_150HZ \ + (4U << DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_SHIFT) +#define DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_200HZ \ + (5U << DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_SHIFT) +#define DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_300HZ \ + (6U << DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_SHIFT) +#define DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_400HZ \ + (7U << DIALOG7212_DAC_FILTERS1_DAC_VOICE_HPF_CORNER_SHIFT) + +/* DIALOG7212_DAC_L_GAIN 0x45 */ +#define DIALOG7212_DAC_L_DIGITAL_GAIN_MASK (0x7F) +#define DIALOG7212_DAC_L_DIGITAL_GAIN_SHIFT (0U) +#define DIALOG7212_DAC_L_DIGITAL_GAIN(x) \ + ((x) << DIALOG7212_DAC_L_DIGITAL_GAIN_SHIFT) + +/* DIALOG7212_DAC_R_GAIN 0x46 */ +#define DIALOG7212_DAC_R_DIGITAL_GAIN_MASK (0x7F) +#define DIALOG7212_DAC_R_DIGITAL_GAIN_SHIFT (0U) +#define DIALOG7212_DAC_R_DIGITAL_GAIN(x) \ + ((x) << DIALOG7212_DAC_R_DIGITAL_GAIN_SHIFT) + +/* DIALOG7212_CP_CTRL 0x47 */ +#define DIALOG7212_CP_CTRL_EN_MASK (1U << 7) +#define DIALOG7212_CP_CTRL_SMALL_SWIT_CH_FREQ_EN_MASK (1U << 6) +#define DIALOG7212_CP_CTRL_MCHANGE_MASK (0x30) +#define DIALOG7212_CP_CTRL_MCHANGE_SHIFT (4U) +#define DIALOG7212_CP_CTRL_MCHANGE_CP_MOD \ + (0U << DIALOG7212_CP_CTRL_MCHANGE_SHIFT) +#define DIALOG7212_CP_CTRL_MCHANGE_PGA \ + (1U << DIALOG7212_CP_CTRL_MCHANGE_SHIFT) +#define DIALOG7212_CP_CTRL_MCHANGE_DAC \ + (2U << DIALOG7212_CP_CTRL_MCHANGE_SHIFT) +#define DIALOG7212_CP_CTRL_MCHANGE_OUTPUT \ + (3U << DIALOG7212_CP_CTRL_MCHANGE_SHIFT) +#define DIALOG7212_CP_CTRL_MOD_MASK (0x0C) +#define DIALOG7212_CP_CTRL_MOD_SHIFT (2U) +#define DIALOG7212_CP_CTRL_MOD_STANDBY \ + (0U << DIALOG7212_CP_CTRL_MOD_SHIFT) +#define DIALOG7212_CP_CTRL_MOD_CPVDD_2 \ + (2U << DIALOG7212_CP_CTRL_MOD_SHIFT) +#define DIALOG7212_CP_CTRL_MOD_CPVDD_1 \ + (3U << DIALOG7212_CP_CTRL_MOD_SHIFT) +#define DIALOG7212_CP_CTRL_ANALOG_VLL_MASK (0x03) +#define DIALOG7212_CP_CTRL_ANALOG_VLL_SHIFT (0U) +#define DIALOG7212_CP_CTRL_ANALOG_VLL_NO_FEEDBACK \ + (0U << DIALOG7212_CP_CTRL_ANALOG_VLL_SHIFT) +#define DIALOG7212_CP_CTRL_ANALOG_VLL_LV_BOOSTS_CP \ + (1U << DIALOG7212_CP_CTRL_ANALOG_VLL_SHIFT) +#define DIALOG7212_CP_CTRL_ANALOG_VLL_LV_RESTART_CP \ + (2U << DIALOG7212_CP_CTRL_ANALOG_VLL_SHIFT) + +/* DIALOG7212_HP_L_GAIN 0x48 */ +#define DIALOG7212_HP_L_AMP_GAIN_MASK (0x3F) +#define DIALOG7212_HP_L_AMP_GAIN_SHIFT (0U) +#define DIALOG7212_HP_L_AMP_GAIN(x) \ + ((x) << DIALOG7212_HP_L_AMP_GAIN_SHIFT) + +/* DIALOG7212_HP_R_GAIN 0x49 */ +#define DIALOG7212_HP_R_AMP_GAIN_MASK (0x3F) +#define DIALOG7212_HP_R_AMP_GAIN_SHIFT (0U) +#define DIALOG7212_HP_R_AMP_GAIN(x) \ + ((x) << DIALOG7212_HP_R_AMP_GAIN_SHIFT) + +/* DIALOG7212_LINE_GAIN 0x4A */ +#define DIALOG7212_LINE_AMP_GAIN_MASK (0x3F) +#define DIALOG7212_LINE_AMP_GAIN_SHIFT (0U) +#define DIALOG7212_LINE_AMP_GAIN(x) \ + ((x) << DIALOG7212_LINE_AMP_GAIN_SHIFT) + +/* DIALOG7212_MIXOUT_L_SELECT 0x4B */ +#define DIALOG7212_MIXOUT_L_SELECT_MIXIN_R_INV_MASK (1U << 6) +#define DIALOG7212_MIXOUT_L_SELECT_MIXIN_L_INV_MASK (1U << 5) +#define DIALOG7212_MIXOUT_L_SELECT_AUX_L_INV_MASK (1U << 4) +#define DIALOG7212_MIXOUT_L_SELECT_DAC_L_MASK (1U << 3) +#define DIALOG7212_MIXOUT_L_SELECT_MIXIN_R_MASK (1U << 2) +#define DIALOG7212_MIXOUT_L_SELECT_MIXIN_L_MASK (1U << 1) +#define DIALOG7212_MIXOUT_L_SELECT_AUX_L_MASK (1U << 0) + +/* DIALOG7212_MIXOUT_R_SELECT 0x4C */ +#define DIALOG7212_MIXOUT_R_SELECT_MIXIN_L_INV_MASK (1U << 6) +#define DIALOG7212_MIXOUT_R_SELECT_MIXIN_R_INV_MASK (1U << 5) +#define DIALOG7212_MIXOUT_R_SELECT_AUX_R_INV_MASK (1U << 4) +#define DIALOG7212_MIXOUT_R_SELECT_DAC_R_MASK (1U << 3) +#define DIALOG7212_MIXOUT_R_SELECT_MIXIN_L_MASK (1U << 2) +#define DIALOG7212_MIXOUT_R_SELECT_MIXIN_R_MASK (1U << 1) +#define DIALOG7212_MIXOUT_R_SELECT_AUX_R_MASK (1U << 0) + +/*! @brief System Controller Registers(1) mask/shift */ +/* DIALOG7212_SYSTEM_MODES_INPUT 0x50 */ +#define DIALOG7212_SYSTEM_MODES_INPUT_ADC_R_MASK (1U << 7) +#define DIALOG7212_SYSTEM_MODES_INPUT_ADC_L_MASK (1U << 6) +#define DIALOG7212_SYSTEM_MODES_INPUT_MIXIN_R_MASK (1U << 5) +#define DIALOG7212_SYSTEM_MODES_INPUT_MIXIN_L_MASK (1U << 4) +#define DIALOG7212_SYSTEM_MODES_INPUT_MIC_2_MASK (1U << 3) +#define DIALOG7212_SYSTEM_MODES_INPUT_MIC_1_MASK (1U << 2) +#define DIALOG7212_SYSTEM_MODES_INPUT_MIC_BIAS_MASK (1U << 1) +#define DIALOG7212_SYSTEM_MODES_INPUT_MODE_SUBMIT_MASK (1U << 0) + +/* DIALOG7212_SYSTEM_MODES_OUTPUT 0x51 */ +#define DIALOG7212_SYSTEM_MODES_OUTPUT_DAC_R_MASK (1U << 7) +#define DIALOG7212_SYSTEM_MODES_OUTPUT_DAC_L_MASK (1U << 6) +#define DIALOG7212_SYSTEM_MODES_OUTPUT_HP_R_MASK (1U << 5) +#define DIALOG7212_SYSTEM_MODES_OUTPUT_HP_L_MASK (1U << 4) +#define DIALOG7212_SYSTEM_MODES_OUTPUT_LINE_MASK (1U << 3) +#define DIALOG7212_SYSTEM_MODES_OUTPUT_AUX_R_MASK (1U << 2) +#define DIALOG7212_SYSTEM_MODES_OUTPUT_AUX_L_MASK (1U << 1) +#define DIALOG7212_SYSTEM_MODES_OUTPUT_MODE_SUBMIT_MASK (1U << 0) + +/*****************Control Registers(2)********************/ +/* DIALOG7212_AUX_L_CTRL 0x60 */ +#define DIALOG7212_AUX_L_CTRL_AMP_EN_MASK (1U << 7) +#define DIALOG7212_AUX_L_CTRL_AMP_MUTE_EN_MASK (1U << 6) +#define DIALOG7212_AUX_L_CTRL_AMP_RAMP_EN_MASK (1U << 5) +#define DIALOG7212_AUX_L_CTRL_AMP_ZC_EN_MASK (1U << 4) +#define DIALOG7212_AUX_L_CTRL_AMP_ZC_SEL_MASK (0x0C) +#define DIALOG7212_AUX_L_CTRL_AMP_ZC_SEL_SHIFT (2U) +#define DIALOG7212_AUX_L_CTRL_AMP_ZC_SEL_INPUT_AUX_L \ + (0U << DIALOG7212_AUX_L_CTRL_AMP_ZC_SEL_SHIFT) +#define DIALOG7212_AUX_L_CTRL_AMP_ZC_SEL_INPUT_AUX_L_IF \ + (1U << DIALOG7212_AUX_L_CTRL_AMP_ZC_SEL_SHIFT) +#define DIALOG7212_AUX_L_CTRL_AMP_ZC_SEL_NO_ZC_POSSBLE \ + (2U << DIALOG7212_AUX_L_CTRL_AMP_ZC_SEL_SHIFT) +#define DIALOG7212_AUX_L_CTRL_AMP_ZC_SEL_OUTPUT_AUX_L \ + (3U << DIALOG7212_AUX_L_CTRL_AMP_ZC_SEL_SHIFT) + +/* DIALOG7212_AUX_R_CTRL 0x61 */ +#define DIALOG7212_AUX_R_CTRL_AMP_EN_MASK (1U << 7) +#define DIALOG7212_AUX_R_CTRL_AMP_MUTE_EN_MASK (1U << 6) +#define DIALOG7212_AUX_R_CTRL_AMP_RAMP_EN_MASK (1U << 5) +#define DIALOG7212_AUX_R_CTRL_AMP_ZC_EN_MASK (1U << 4) +#define DIALOG7212_AUX_R_CTRL_AMP_ZC_SEL_MASK (0x0C) +#define DIALOG7212_AUX_R_CTRL_AMP_ZC_SEL_SHIFT (2U) +#define DIALOG7212_AUX_R_CTRL_AMP_ZC_SEL_INPUT_AUX_R \ + (0U << DIALOG7212_AUX_R_CTRL_AMP_ZC_SEL_SHIFT) +#define DIALOG7212_AUX_R_CTRL_AMP_ZC_SEL_INPUT_AUX_R_IF \ + (1U << DIALOG7212_AUX_R_CTRL_AMP_ZC_SEL_SHIFT) +#define DIALOG7212_AUX_R_CTRL_AMP_ZC_SEL_NO_ZC_POSSBLE \ + (2U << DIALOG7212_AUX_R_CTRL_AMP_ZC_SEL_SHIFT) +#define DIALOG7212_AUX_R_CTRL_AMP_ZC_SEL_OUTPUT_AUX_R \ + (3U << DIALOG7212_AUX_R_CTRL_AMP_ZC_SEL_SHIFT) + +/* DIALOG7212_MICBIAS_CTRL 0x62 */ +#define DIALOG7212_MICBIAS_CTRL_MICBIAS2_EN_MASK (1U << 7) +#define DIALOG7212_MICBIAS_CTRL_MICBIAS2_LEVEL_MASK (0x30) +#define DIALOG7212_MICBIAS_CTRL_MICBIAS2_SHIFT (4U) +#define DIALOG7212_MICBIAS_CTRL_MICBIAS2_1_6V \ + (0U << DIALOG7212_MICBIAS_CTRL_MICBIAS2_SHIFT) +#define DIALOG7212_MICBIAS_CTRL_MICBIAS2_2_2V \ + (1U << DIALOG7212_MICBIAS_CTRL_MICBIAS2_SHIFT) +#define DIALOG7212_MICBIAS_CTRL_MICBIAS2_2_5V \ + (2U << DIALOG7212_MICBIAS_CTRL_MICBIAS2_SHIFT) +#define DIALOG7212_MICBIAS_CTRL_MICBIAS2_3_0V \ + (3U << DIALOG7212_MICBIAS_CTRL_MICBIAS2_SHIFT) +#define DIALOG7212_MICBIAS_CTRL_MICBIAS1_EN_MASK (1U << 3) +#define DIALOG7212_MICBIAS_CTRL_MICBIAS1_LEVEL_MASK (0x03) +#define DIALOG7212_MICBIAS_CTRL_MICBIAS1_SHIFT (0U) +#define DIALOG7212_MICBIAS_CTRL_MICBIAS1_1_6V \ + (0U << DIALOG7212_MICBIAS_CTRL_MICBIAS1_SHIFT) +#define DIALOG7212_MICBIAS_CTRL_MICBIAS1_2_2V \ + (1U << DIALOG7212_MICBIAS_CTRL_MICBIAS1_SHIFT) +#define DIALOG7212_MICBIAS_CTRL_MICBIAS1_2_5V \ + (2U << DIALOG7212_MICBIAS_CTRL_MICBIAS1_SHIFT) +#define DIALOG7212_MICBIAS_CTRL_MICBIAS1_3_0V \ + (3U << DIALOG7212_MICBIAS_CTRL_MICBIAS1_SHIFT) + +/* DIALOG7212_MIC_1_CTRL 0x63 */ +#define DIALOG7212_MIC_1_CTRL_AMP_EN_MASK (1U << 7) +#define DIALOG7212_MIC_1_CTRL_AMP_MUTE_EN_MASK (1U << 6) +#define DIALOG7212_MIC_1_CTRL_AMP_IN_SEL_MASK (0x0C) +#define DIALOG7212_MIC_1_CTRL_AMP_IN_SEL_SHIFT (2U) +#define DIALOG7212_MIC_1_CTRL_AMP_IN_SEL_DIFFERENTIAL \ + (0U << DIALOG7212_MIC_1_CTRL_AMP_IN_SEL_SHIFT) +#define DIALOG7212_MIC_1_CTRL_AMP_IN_SEL_MIC_1_P \ + (1U << DIALOG7212_MIC_1_CTRL_AMP_IN_SEL_SHIFT) +#define DIALOG7212_MIC_1_CTRL_AMP_IN_SEL_MIC_1_N \ + (2U << DIALOG7212_MIC_1_CTRL_AMP_IN_SEL_SHIFT) + +/* DIALOG7212_MIC_2_CTRL 0x64 */ +#define DIALOG7212_MIC_2_CTRL_AMP_EN_MASK (1U << 7) +#define DIALOG7212_MIC_2_CTRL_AMP_MUTE_EN_MASK (1U << 6) +#define DIALOG7212_MIC_2_CTRL_AMP_IN_SEL_MASK (0x0C) +#define DIALOG7212_MIC_2_CTRL_AMP_IN_SEL_SHIFT (2U) +#define DIALOG7212_MIC_2_CTRL_AMP_IN_SEL_DIFFERENTIAL \ + (0U << DIALOG7212_MIC_2_CTRL_AMP_IN_SEL_SHIFT) +#define DIALOG7212_MIC_2_CTRL_AMP_IN_SEL_MIC_2_P \ + (1U << DIALOG7212_MIC_2_CTRL_AMP_IN_SEL_SHIFT) +#define DIALOG7212_MIC_2_CTRL_AMP_IN_SEL_MIC_2_N \ + (2U << DIALOG7212_MIC_2_CTRL_AMP_IN_SEL_SHIFT) + +/* DIALOG7212_MIXIN_L_CTRL 0x65 */ +#define DIALOG7212_MIXIN_L_CTRL_AMP_EN_MASK (1U << 7) +#define DIALOG7212_MIXIN_L_CTRL_AMP_MUTE_EN_MASK (1U << 6) +#define DIALOG7212_MIXIN_L_CTRL_AMP_RAMP_EN_MASK (1U << 5) +#define DIALOG7212_MIXIN_L_CTRL_AMP_ZC_EN_MASK (1U << 4) +#define DIALOG7212_MIXIN_L_CTRL_AMP_MIX_EN_MASK (1U << 3) + +/* DIALOG7212_MIXIN_R_CTRL 0x66 */ +#define DIALOG7212_MIXIN_R_CTRL_AMP_EN_MASK (1U << 7) +#define DIALOG7212_MIXIN_R_CTRL_AMP_MUTE_EN_MASK (1U << 6) +#define DIALOG7212_MIXIN_R_CTRL_AMP_RAMP_EN_MASK (1U << 5) +#define DIALOG7212_MIXIN_R_CTRL_AMP_ZC_EN_MASK (1U << 4) +#define DIALOG7212_MIXIN_R_CTRL_AMP_MIX_EN_MASK (1U << 3) + +/* DIALOG7212_ADC_L_CTRL 0x67 */ +#define DIALOG7212_ADC_L_CTRL_ADC_EN_MASK (1U << 7) +#define DIALOG7212_ADC_L_CTRL_ADC_MUTE_EN_MASK (1U << 6) +#define DIALOG7212_ADC_L_CTRL_ADC_RAMP_EN_MASK (1U << 5) + +/* DIALOG7212_ADC_R_CTRL 0x68 */ +#define DIALOG7212_ADC_R_CTRL_ADC_EN_MASK (1U << 7) +#define DIALOG7212_ADC_R_CTRL_ADC_MUTE_EN_MASK (1U << 6) +#define DIALOG7212_ADC_R_CTRL_ADC_RAMP_EN_MASK (1U << 5) + +/* DIALOG7212_DAC_L_CTRL 0x69 */ +#define DIALOG7212_DAC_L_CTRL_ADC_EN_MASK (1U << 7) +#define DIALOG7212_DAC_L_CTRL_ADC_MUTE_EN_MASK (1U << 6) +#define DIALOG7212_DAC_L_CTRL_ADC_RAMP_EN_MASK (1U << 5) + +/* DIALOG7212_DAC_R_CTRL 0x6A */ +#define DIALOG7212_DAC_R_CTRL_ADC_EN_MASK (1U << 7) +#define DIALOG7212_DAC_R_CTRL_ADC_MUTE_EN_MASK (1U << 6) +#define DIALOG7212_DAC_R_CTRL_ADC_RAMP_EN_MASK (1U << 5) + +/* DIALOG7212_HP_L_CTRL 0x6B */ +#define DIALOG7212_HP_L_CTRL_AMP_EN_MASK (1U << 7) +#define DIALOG7212_HP_L_CTRL_AMP_MUTE_EN_MASK (1U << 6) +#define DIALOG7212_HP_L_CTRL_AMP_RAMP_EN_MASK (1U << 5) +#define DIALOG7212_HP_L_CTRL_AMP_ZC_EN_MASK (1U << 4) +#define DIALOG7212_HP_L_CTRL_AMP_OE_MASK (1U << 3) +#define DIALOG7212_HP_L_CTRL_AMP_MIN_GAIN_EN_MASK (1U << 2) + +/* DIALOG7212_HP_R_CTRL 0x6C */ +#define DIALOG7212_HP_R_CTRL_AMP_EN_MASK (1U << 7) +#define DIALOG7212_HP_R_CTRL_AMP_MUTE_EN_MASK (1U << 6) +#define DIALOG7212_HP_R_CTRL_AMP_RAMP_EN_MASK (1U << 5) +#define DIALOG7212_HP_R_CTRL_AMP_ZC_EN_MASK (1U << 4) +#define DIALOG7212_HP_R_CTRL_AMP_OE_MASK (1U << 3) +#define DIALOG7212_HP_R_CTRL_AMP_MIN_GAIN_EN_MASK (1U << 2) + +/* DIALOG7212_LINE_CTRL 0x6D */ +#define DIALOG7212_LINE_CTRL_AMP_EN_MASK (1U << 7) +#define DIALOG7212_LINE_CTRL_AMP_MUTE_EN_MASK (1U << 6) +#define DIALOG7212_LINE_CTRL_AMP_RAMP_EN_MASK (1U << 5) +#define DIALOG7212_LINE_CTRL_AMP_OE_MASK (1U << 3) +#define DIALOG7212_LINE_CTRL_AMP_MIN_GAIN_EN_MASK (1U << 2) + +/* DIALOG7212_MIXOUT_L_CTRL 0x6E */ +#define DIALOG7212_MIXOUT_L_CTRL_AMP_EN_MASK (1U << 7) +#define DIALOG7212_MIXOUT_L_CTRL_AMP_SOFT_MIX_EN_MASK (1U << 4) +#define DIALOG7212_MIXOUT_L_CTRL_AMP_MIX_EN_MASK (1U << 3) + +/* DIALOG7212_MIXOUT_R_CTRL 0x6F */ +#define DIALOG7212_MIXOUT_R_CTRL_AMP_EN_MASK (1U << 7) +#define DIALOG7212_MIXOUT_R_CTRL_AMP_SOFT_MIX_EN_MASK (1U << 4) +#define DIALOG7212_MIXOUT_R_CTRL_AMP_MIX_EN_MASK (1U << 3) + +/*! @brief Configuration Registers mask/shift */ +/* DIALOG7212_LDO_CTRL 0x90 */ +#define DIALOG7212_LDO_CTRL_EN_MASK (1U << 7) +#define DIALOG7212_LDO_CTRL_LEVEL_SELECT_MASK (0x30) +#define DIALOG7212_LDO_CTRL_LEVEL_SELECT_SHIFT (4U) +#define DIALOG7212_LDO_CTRL_LEVEL_SELECT_1_05V \ + (0U << DIALOG7212_LDO_CTRL_LEVEL_SELECT_SHIFT) +#define DIALOG7212_LDO_CTRL_LEVEL_SELECT_1_10V \ + (1U << DIALOG7212_LDO_CTRL_LEVEL_SELECT_SHIFT) +#define DIALOG7212_LDO_CTRL_LEVEL_SELECT_1_20V \ + (2U << DIALOG7212_LDO_CTRL_LEVEL_SELECT_SHIFT) +#define DIALOG7212_LDO_CTRL_LEVEL_SELECT_1_40V \ + (3U << DIALOG7212_LDO_CTRL_LEVEL_SELECT_SHIFT) + +/* DIALOG7212_GAIN_RAMP_CTRL 0x92 */ +#define DIALOG7212_GAIN_RAMP_CTRL_RATE_MASK (0x03) +#define DIALOG7212_GAIN_RAMP_CTRL_RATE_SHIFT (0U) +#define DIALOG7212_GAIN_RAMP_CTRL_RATE_NR_DIV_8 \ + (0U << DIALOG7212_GAIN_RAMP_CTRL_RATE_SHIFT) +#define DIALOG7212_GAIN_RAMP_CTRL_RATE_NR_DIV_16 \ + (1U << DIALOG7212_GAIN_RAMP_CTRL_RATE_SHIFT) +#define DIALOG7212_GAIN_RAMP_CTRL_RATE_NR_MUL_16 \ + (2U << DIALOG7212_GAIN_RAMP_CTRL_RATE_SHIFT) +#define DIALOG7212_GAIN_RAMP_CTRL_RATE_NR_MUL_32 \ + (3U << DIALOG7212_GAIN_RAMP_CTRL_RATE_SHIFT) + +/* DIALOG7212_MIC_CONFIG 0x93 */ +#define DIALOG7212_MIC_CONFIG_DMIC_CLK_RATE_MASK (1U << 2) +#define DIALOG7212_MIC_CONFIG_DMIC_SAMPLEPHASE_MASK (1U << 1) +#define DIALOG7212_MIC_CONFIG_DMIC_DATA_SEL_MASK (1U << 0) + +/* DIALOG7212_PC_COUNT 0x94 */ +#define DIALOG7212_PC_COUNT_RESYNC_MASK (1U << 1) +#define DIALOG7212_PC_COUNT_FREERU_MASK (1U << 0) + +/* DIALOG7212_CP_VOL_THRESHOLD1 0x95 */ +#define DIALOG7212_CP_VOL_THRESHOLD1_VDD2_MASK (0x3F) +#define DIALOG7212_CP_VOL_THRESHOLD1_VDD2_SHIFT (0U) +#define DIALOG7212_CP_VOL_THRESHOLD1_VDD2(x) \ + ((x) << DIALOG7212_CP_VOL_THRESHOLD1_VDD2_SHIFT) + +/* DIALOG7212_CP_DELAY 0x96 */ +#define DIALOG7212_CP_DELAY_ON_OFF_MASK (0xC0) +#define DIALOG7212_CP_DELAY_ON_OFF_SHIFT (6U) +#define DIALOG7212_CP_DELAY_ON_OFF_LIMITER_ON \ + (0U << DIALOG7212_CP_DELAY_ON_OFF_SHIFT) +#define DIALOG7212_CP_DELAY_ON_OFF_LIMITER_OFF \ + (1U << DIALOG7212_CP_DELAY_ON_OFF_SHIFT) +#define DIALOG7212_CP_DELAY_ON_OFF_LIMITER_AUT \ + (2U << DIALOG7212_CP_DELAY_ON_OFF_SHIFT) +#define DIALOG7212_CP_DELAY_TAU_DELAY_MASK (0x38) +#define DIALOG7212_CP_DELAY_TAU_DELAY_SHIFT (3U) +#define DIALOG7212_CP_DELAY_TAU_DELAY_0MS \ + (0U << DIALOG7212_CP_DELAY_TAU_DELAY_SHIFT) +#define DIALOG7212_CP_DELAY_TAU_DELAY_2MS \ + (1U << DIALOG7212_CP_DELAY_TAU_DELAY_SHIFT) +#define DIALOG7212_CP_DELAY_TAU_DELAY_4MS \ + (2U << DIALOG7212_CP_DELAY_TAU_DELAY_SHIFT) +#define DIALOG7212_CP_DELAY_TAU_DELAY_16MS \ + (3U << DIALOG7212_CP_DELAY_TAU_DELAY_SHIFT) +#define DIALOG7212_CP_DELAY_TAU_DELAY_64MS \ + (4U << DIALOG7212_CP_DELAY_TAU_DELAY_SHIFT) +#define DIALOG7212_CP_DELAY_TAU_DELAY_128MS \ + (5U << DIALOG7212_CP_DELAY_TAU_DELAY_SHIFT) +#define DIALOG7212_CP_DELAY_TAU_DELAY_256MS \ + (6U << DIALOG7212_CP_DELAY_TAU_DELAY_SHIFT) +#define DIALOG7212_CP_DELAY_TAU_DELAY_512MS \ + (7U << DIALOG7212_CP_DELAY_TAU_DELAY_SHIFT) +#define DIALOG7212_CP_DELAY_FCONTROL_MASK (0x07) +#define DIALOG7212_CP_DELAY_FCONTROL_SHIFT (0U) +#define DIALOG7212_CP_DELAY_FCONTROL_1MHZ \ + (0U << DIALOG7212_CP_DELAY_FCONTROL_SHIFT) +#define DIALOG7212_CP_DELAY_FCONTROL_500KHZ \ + (1U << DIALOG7212_CP_DELAY_FCONTROL_SHIFT) +#define DIALOG7212_CP_DELAY_FCONTROL_250KHZ \ + (2U << DIALOG7212_CP_DELAY_FCONTROL_SHIFT) +#define DIALOG7212_CP_DELAY_FCONTROL_125KHZ \ + (3U << DIALOG7212_CP_DELAY_FCONTROL_SHIFT) +#define DIALOG7212_CP_DELAY_FCONTROL_63KHZ \ + (4U << DIALOG7212_CP_DELAY_FCONTROL_SHIFT) +#define DIALOG7212_CP_DELAY_FCONTROL_0HZ_OR_1MHZ \ + (5U << DIALOG7212_CP_DELAY_FCONTROL_SHIFT) + +/* DIALOG7212_CP_DETECTOR 0x97 */ +#define DIALOG7212_CP_DETECTOR_DROP_MASK (0x03) +#define DIALOG7212_CP_DETECTOR_DROP_SHIFT (0U) +#define DIALOG7212_CP_DETECTOR_DROP_25MV \ + (0U << DIALOG7212_CP_DETECTOR_DROP_SHIFT) +#define DIALOG7212_CP_DETECTOR_DROP_50MV \ + (1U << DIALOG7212_CP_DETECTOR_DROP_SHIFT) +#define DIALOG7212_CP_DETECTOR_DROP_75MV \ + (2U << DIALOG7212_CP_DETECTOR_DROP_SHIFT) +#define DIALOG7212_CP_DETECTOR_DROP_100MV \ + (3U << DIALOG7212_CP_DETECTOR_DROP_SHIFT) + +/* DIALOG7212_DAI_OFFSET 0x98 */ +#define DIALOG7212_DAI_OFFSET_MASK (0xFF) +#define DIALOG7212_DAI_OFFSET_SHIFT (0U) +#define DIALOG7212_DAI_OFFSET_VAL(x) \ + (x << DIALOG7212_DAI_OFFSET_SHIFT) + +/* DIALOG7212_DIG_CTRL 0x99 */ +#define DIALOG7212_DIG_CTRL_R_INV_MASK (1U << 7) +#define DIALOG7212_DIG_CTRL_L_INV_MASK (1U << 3) + +/* DIALOG7212_ALC_CTRL2 0x9A */ +#define DIALOG7212_ALC_CTRL2_RELEASE_MASK (0xF0) +#define DIALOG7212_ALC_CTRL2_RELEASE_SHIFT (4U) +#define DIALOG7212_ALC_CTRL2_RELEASE(x) \ + ((x) << DIALOG7212_ALC_CTRL2_RELEASE_SHIFT) +#define DIALOG7212_ALC_CTRL2_ATTACK_MASK (0x0F) +#define DIALOG7212_ALC_CTRL2_ATTACK_SHIFT (0U) +#define DIALOG7212_ALC_CTRL2_ATTACK(x) \ + ((x) << DIALOG7212_ALC_CTRL2_RELEASE_SHIFT) + +/* DIALOG7212_ALC_CTRL3 0x9B */ +#define DIALOG7212_ALC_CTRL3_INTEG_RELEASE_MASK (0xC0) +#define DIALOG7212_ALC_CTRL3_INTEG_RELEASE_SHIFT (6U) +#define DIALOG7212_ALC_CTRL3_INTEG_RELEASE_1DIV4 \ + (0U << DIALOG7212_ALC_CTRL3_INTEG_RELEASE_SHIFT) +#define DIALOG7212_ALC_CTRL3_INTEG_RELEASE_1DIV16 \ + (1U << DIALOG7212_ALC_CTRL3_INTEG_RELEASE_SHIFT) +#define DIALOG7212_ALC_CTRL3_INTEG_RELEASE_1DIV256 \ + (2U << DIALOG7212_ALC_CTRL3_INTEG_RELEASE_SHIFT) +#define DIALOG7212_ALC_CTRL3_INTEG_ATTACK_MASK (0x30) +#define DIALOG7212_ALC_CTRL3_INTEG_ATTACK_SHIFT (4U) +#define DIALOG7212_ALC_CTRL3_INTEG_ATTACK_1DIV4 \ + (0U << DIALOG7212_ALC_CTRL3_INTEG_ATTACK_SHIFT) +#define DIALOG7212_ALC_CTRL3_INTEG_ATTACK_1DIV16 \ + (1U << DIALOG7212_ALC_CTRL3_INTEG_ATTACK_SHIFT) +#define DIALOG7212_ALC_CTRL3_INTEG_ATTACK_1DIV256 \ + (2U << DIALOG7212_ALC_CTRL3_INTEG_ATTACK_SHIFT) +#define DIALOG7212_ALC_CTRL3_HOLD_MASK (0x0F) +#define DIALOG7212_ALC_CTRL3_HOLD_SHIFT (0U) +#define DIALOG7212_ALC_CTRL3_HOLD(x) \ + ((x) << DIALOG7212_ALC_CTRL3_HOLD_SHIFT) + +/* DIALOG7212_ALC_NOISE 0x9C */ +#define DIALOG7212_ALC_NOISE_MASK (0x3F) +#define DIALOG7212_ALC_NOISE_SHIFT (0U) +#define DIALOG7212_ALC_NOISE_VAL(x) ((x) << DIALOG7212_ALC_NOISE_SHIFT) + +/* DIALOG7212_ALC_TARGET_MIN 0x9D */ +#define DIALOG7212_ALC_TARGET_MIN_THRESHOLD_MIN_MASK (0x3F) +#define DIALOG7212_ALC_TARGET_MIN_THRESHOLD_MIN_SHIFT (0U) +#define DIALOG7212_ALC_TARGET_MIN_THRESHOLD_MIN(x) \ + ((x) << DIALOG7212_ALC_TARGET_MIN_THRESHOLD_MIN_SHIFT) + +/* DIALOG7212_ALC_TARGET_MAX 0x9E */ +#define DIALOG7212_ALC_TARGET_MAX_THRESHOLD_MAX_MASK (0x3F) +#define DIALOG7212_ALC_TARGET_MAX_THRESHOLD_MAX_SHIFT (0U) +#define DIALOG7212_ALC_TARGET_MAX_THRESHOLD_MAX(x) \ + ((x) << DIALOG7212_ALC_TARGET_MAX_THRESHOLD_MIN_SHIFT) + +/* DIALOG7212_ALC_GAIN_LIMITS 0x9F */ +#define DIALOG7212_ALC_GAIN_LIMITS_GAIN_MAX_MASK (0xF0) +#define DIALOG7212_ALC_GAIN_LIMITS_GAIN_MAX_SHIFT (4U) +#define DIALOG7212_ALC_GAIN_LIMITS_GAIN_MAX(x) \ + ((x) << DIALOG7212_ALC_GAIN_LIMITS_GAIN_MAX_SHIFT) +#define DIALOG7212_ALC_GAIN_LIMITS_ATTEN_MAX_MASK (0x0F) +#define DIALOG7212_ALC_GAIN_LIMITS_ATTEN_MAX_SHIFT (0U) +#define DIALOG7212_ALC_GAIN_LIMITS_ATTEN_MAX(x) \ + ((x) << DIALOG7212_ALC_GAIN_LIMITS_ATTEN_MAX_SHIFT) + +/* DIALOG7212_ALC_ANA_GAIN_LIMITS 0xA0 */ +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MAX_MASK (0x70) +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MAX_SHIFT (4U) +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MAX_0DB \ + (1U << DIALOG7212_ALC_ANA_GAIN_LIMITS_MAX_SHIFT) +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MAX_6DB \ + (2U << DIALOG7212_ALC_ANA_GAIN_LIMITS_MAX_SHIFT) +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MAX_12DB \ + (3U << DIALOG7212_ALC_ANA_GAIN_LIMITS_MAX_SHIFT) +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MAX_18DB \ + (4U << DIALOG7212_ALC_ANA_GAIN_LIMITS_MAX_SHIFT) +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MAX_24DB \ + (5U << DIALOG7212_ALC_ANA_GAIN_LIMITS_MAX_SHIFT) +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MAX_30DB \ + (6U << DIALOG7212_ALC_ANA_GAIN_LIMITS_MAX_SHIFT) +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MAX_36DB \ + (7U << DIALOG7212_ALC_ANA_GAIN_LIMITS_MAX_SHIFT) +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MIN_MASK (0x07) +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MIN_SHIFT (0U) +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MIN_0DB \ + (1U << DIALOG7212_ALC_ANA_GAIN_LIMITS_MIN_SHIFT) +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MIN_6DB \ + (2U << DIALOG7212_ALC_ANA_GAIN_LIMITS_MIN_SHIFT) +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MIN_12DB \ + (3U << DIALOG7212_ALC_ANA_GAIN_LIMITS_MIN_SHIFT) +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MIN_18DB \ + (4U << DIALOG7212_ALC_ANA_GAIN_LIMITS_MIN_SHIFT) +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MIN_24DB \ + (5U << DIALOG7212_ALC_ANA_GAIN_LIMITS_MIN_SHIFT) +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MIN_30DB \ + (6U << DIALOG7212_ALC_ANA_GAIN_LIMITS_MIN_SHIFT) +#define DIALOG7212_ALC_ANA_GAIN_LIMITS_MIN_36DB \ + (7U << DIALOG7212_ALC_ANA_GAIN_LIMITS_MIN_SHIFT) + +/* DIALOG7212_ALC_ANTICLIP_CTRL 0xA1 */ +#define DIALOG7212_ALC_ANTICLIP_CTRL_EN_MASK (1U << 7) + +/* DIALOG7212_ALC_ANTICLIP_LEVEL 0xA2 */ +#define DIALOG7212_ALC_ANTICLIP_LEVEL_MASK (0x7F) +#define DIALOG7212_ALC_ANTICLIP_LEVEL_SHIFT (0U) +#define DIALOG7212_ALC_ANTICLIP_LEVEL_VAL(x) \ + ((x) << DIALOG7212_ALC_ANTICLIP_LEVEL_SHIFT) + +/* DIALOG7212_DAC_NG_SETUP_TIME 0xAF */ +#define DIALOG7212_DAC_NG_SETUP_TIME_RAMPDN_RATE_MASK (1U << 3) +#define DIALOG7212_DAC_NG_SETUP_TIME_RAMPUP_RATE_MASK (1U << 2) +#define DIALOG7212_DAC_NG_SETUP_TIME_MASK (0x03) +#define DIALOG7212_DAC_NG_SETUP_TIME_SHIFT (0U) +#define DIALOG7212_DAC_NG_SETUP_TIME_256 \ + (1U << DIALOG7212_DAC_NG_SETUP_TIME_SHIFT) +#define DIALOG7212_DAC_NG_SETUP_TIME_512 \ + (2U << DIALOG7212_DAC_NG_SETUP_TIME_SHIFT) +#define DIALOG7212_DAC_NG_SETUP_TIME_1024 \ + (3U << DIALOG7212_DAC_NG_SETUP_TIME_SHIFT) +#define DIALOG7212_DAC_NG_SETUP_TIME_2048 \ + (4U << DIALOG7212_DAC_NG_SETUP_TIME_SHIFT) + +/* DIALOG7212_DAC_NG_OFF_THRESH 0xB0 */ +#define DIALOG7212_DAC_NG_OFF_THRESHOLD_MASK (0x07) +#define DIALOG7212_DAC_NG_OFF_THRESHOLD_SHIFT (0U) +#define DIALOG7212_DAC_NG_OFF_THRESHOLD_N90DB \ + (0U << DIALOG7212_DAC_NG_OFF_THRESHOLD_SHIFT) +#define DIALOG7212_DAC_NG_OFF_THRESHOLD_N84DB \ + (1U << DIALOG7212_DAC_NG_OFF_THRESHOLD_SHIFT) +#define DIALOG7212_DAC_NG_OFF_THRESHOLD_N78DB \ + (2U << DIALOG7212_DAC_NG_OFF_THRESHOLD_SHIFT) +#define DIALOG7212_DAC_NG_OFF_THRESHOLD_N72DB \ + (3U << DIALOG7212_DAC_NG_OFF_THRESHOLD_SHIFT) +#define DIALOG7212_DAC_NG_OFF_THRESHOLD_N66DB \ + (4U << DIALOG7212_DAC_NG_OFF_THRESHOLD_SHIFT) +#define DIALOG7212_DAC_NG_OFF_THRESHOLD_N60DB \ + (5U << DIALOG7212_DAC_NG_OFF_THRESHOLD_SHIFT) +#define DIALOG7212_DAC_NG_OFF_THRESHOLD_N54DB \ + (6U << DIALOG7212_DAC_NG_OFF_THRESHOLD_SHIFT) +#define DIALOG7212_DAC_NG_OFF_THRESHOLD_N48DB \ + (7U << DIALOG7212_DAC_NG_OFF_THRESHOLD_SHIFT) + +/* DIALOG7212_DAC_NG_ON_THRESH 0xB1 */ +#define DIALOG7212_DAC_NG_ON_THRESHOLD_MASK (0x07) +#define DIALOG7212_DAC_NG_ON_THRESHOLD_SHIFT (0U) +#define DIALOG7212_DAC_NG_ON_THRESHOLD_N90DB \ + (0U << DIALOG7212_DAC_NG_ON_THRESHOLD_SHIFT) +#define DIALOG7212_DAC_NG_ON_THRESHOLD_N84DB \ + (1U << DIALOG7212_DAC_NG_ON_THRESHOLD_SHIFT) +#define DIALOG7212_DAC_NG_ON_THRESHOLD_N78DB \ + (2U << DIALOG7212_DAC_NG_ON_THRESHOLD_SHIFT) +#define DIALOG7212_DAC_NG_ON_THRESHOLD_N72DB \ + (3U << DIALOG7212_DAC_NG_ON_THRESHOLD_SHIFT) +#define DIALOG7212_DAC_NG_ON_THRESHOLD_N66DB \ + (4U << DIALOG7212_DAC_NG_ON_THRESHOLD_SHIFT) +#define DIALOG7212_DAC_NG_ON_THRESHOLD_N60DB \ + (5U << DIALOG7212_DAC_NG_ON_THRESHOLD_SHIFT) +#define DIALOG7212_DAC_NG_ON_THRESHOLD_N54DB \ + (6U << DIALOG7212_DAC_NG_ON_THRESHOLD_SHIFT) +#define DIALOG7212_DAC_NG_ON_THRESHOLD_N48DB \ + (7U << DIALOG7212_DAC_NG_ON_THRESHOLD_SHIFT) + +/* DIALOG7212_DAC_NG_CTRL 0xB2 */ +#define DIALOG7212_DAC_NG_CTRL_EN_MASK (1U << 7) + +/*! @brief Tone Generation & Beep Registers mask/shift */ +/* DIALOG7212_TONE_GEN_CFG1 0xB4 */ +#define DIALOG7212_TONE_GEN_CFG1_START_STOPN_MASK (1U << 7) +#define DIALOG7212_TONE_GEN_CFG1_DMTF_EN_MASK (1U << 4) +#define DIALOG7212_TONE_GEN_CFG1_DMTF_REG_MASK (0x0F) +#define DIALOG7212_TONE_GEN_CFG1_DMTF_REG_SHIFT (0U) +#define DIALOG7212_TONE_GEN_CFG1_DMTF_REG(x) \ + ((x) << DIALOG7212_TONE_GEN_CFG1_DMTF_REG_SHIFT) + +/* DIALOG7212_TONE_GEN_CFG2 0xB5 */ +#define DIALOG7212_TONE_GEN_CFG2_GAIN_MASK (0xF0) +#define DIALOG7212_TONE_GEN_CFG2_GAIN_SHIFT (4U) +#define DIALOG7212_TONE_GEN_CFG2_GAIN(x) \ + ((x) << DIALOG7212_TONE_GEN_CFG2_GAIN_SHIFT) +#define DIALOG7212_TONE_GEN_CFG2_SWG_SEL_MASK (0x03) +#define DIALOG7212_TONE_GEN_CFG2_SWG_SEL_SHIFT (0U) +#define DIALOG7212_TONE_GEN_CFG2_SWG_SEL_SUM__BOTH \ + (0U << DIALOG7212_TONE_GEN_CFG2_SWG_SEL_SHIFT) +#define DIALOG7212_TONE_GEN_CFG2_SWG_SEL_SWG1_ONLY \ + (1U << DIALOG7212_TONE_GEN_CFG2_SWG_SEL_SHIFT) +#define DIALOG7212_TONE_GEN_CFG2_SWG_SEL_SWG2_ONLY \ + (2U << DIALOG7212_TONE_GEN_CFG2_SWG_SEL_SHIFT) +#define DIALOG7212_TONE_GEN_CFG2_SWG_SEL_SUM_BOTH \ + (3U << DIALOG7212_TONE_GEN_CFG2_SWG_SEL_SHIFT) + +/* DIALOG7212_TONE_GEN_CYCLES 0xB6 */ +#define DIALOG7212_TONE_GEN_CYCLES_BEEP_CYCLES_MASK (0x07) +#define DIALOG7212_TONE_GEN_CYCLES_BEEP_CYCLES_SHIFT (0U) +#define DIALOG7212_TONE_GEN_CYCLES_BEEP_CYCLES_1 \ + (0U << DIALOG7212_TONE_GEN_CYCLES_BEEP_CYCLES_SHIFT) +#define DIALOG7212_TONE_GEN_CYCLES_BEEP_CYCLES_2 \ + (1U << DIALOG7212_TONE_GEN_CYCLES_BEEP_CYCLES_SHIFT) +#define DIALOG7212_TONE_GEN_CYCLES_BEEP_CYCLES_4 \ + (2U << DIALOG7212_TONE_GEN_CYCLES_BEEP_CYCLES_SHIFT) +#define DIALOG7212_TONE_GEN_CYCLES_BEEP_CYCLES_8 \ + (3U << DIALOG7212_TONE_GEN_CYCLES_BEEP_CYCLES_SHIFT) +#define DIALOG7212_TONE_GEN_CYCLES_BEEP_CYCLES_16 \ + (4U << DIALOG7212_TONE_GEN_CYCLES_BEEP_CYCLES_SHIFT) +#define DIALOG7212_TONE_GEN_CYCLES_BEEP_CYCLES_32 \ + (5U << DIALOG7212_TONE_GEN_CYCLES_BEEP_CYCLES_SHIFT) +#define DIALOG7212_TONE_GEN_CYCLES_BEEP_CYCLES_INFINITE \ + (6U << DIALOG7212_TONE_GEN_CYCLES_BEEP_CYCLES_SHIFT) + +/* DIALOG7212_TONE_GEN_FREQ1_L 0xB7 */ +#define DIALOG7212_TONE_GEN_FREQ1_L_MASK (0xFF) +#define DIALOG7212_TONE_GEN_FREQ1_L_SHIFT (0U) +#define DIALOG7212_TONE_GEN_FREQ1_L_VAL(x) \ + ((x) << DIALOG7212_TONE_GEN_FREQ1_L_SHIFT) + +/* DIALOG7212_TONE_GEN_FREQ1_U 0xB8 */ +#define DIALOG7212_TONE_GEN_FREQ1_U_MASK (0xFF) +#define DIALOG7212_TONE_GEN_FREQ1_U_SHIFT (0U) +#define DIALOG7212_TONE_GEN_FREQ1_U_VAL(x) \ + ((x) << DIALOG7212_TONE_GEN_FREQ1_U_SHIFT) + +/* DIALOG7212_TONE_GEN_FREQ2_L 0xB9 */ +#define DIALOG7212_TONE_GEN_FREQ2_L_MASK (0xFF) +#define DIALOG7212_TONE_GEN_FREQ2_L_SHIFT (0U) +#define DIALOG7212_TONE_GEN_FREQ2_L_VAL(x) \ + ((x) << DIALOG7212_TONE_GEN_FREQ2_L_SHIFT) + +/* DIALOG7212_TONE_GEN_FREQ2_U 0xBA */ +#define DIALOG7212_TONE_GEN_FREQ2_U_MASK (0xFF) +#define DIALOG7212_TONE_GEN_FREQ2_U_SHIFT (0U) +#define DIALOG7212_TONE_GEN_FREQ2_U_VAL(x) \ + ((x) << DIALOG7212_TONE_GEN_FREQ2_U_SHIFT) + +/* DIALOG7212_TONE_GEN_ON_PER 0xBB */ +#define DIALOG7212_TONE_GEN_ON_PER_BEEP_ON_PER_MASK (0x3F) +#define DIALOG7212_TONE_GEN_ON_PER_BEEP_ON_PER_SHIFT (0U) +#define DIALOG7212_TONE_GEN_ON_PER_BEEP_ON_PER(x) \ + ((x) << DIALOG7212_TONE_GEN_ON_PER_BEEP_ON_PER_SHIFT) + +/* DIALOG7212_TONE_GEN_OFF_PER 0xBC */ +#define DIALOG7212_TONE_GEN_OFF_PER_BEEP_OFF_PER_MASK (0x3F) +#define DIALOG7212_TONE_GEN_OFF_PER_BEEP_OFF_PER_SHIFT (0U) +#define DIALOG7212_TONE_GEN_OFF_PER_BEEP_OFF_PER(x) \ + ((x) << DIALOG7212_TONE_GEN_OFF_PER_BEEP_OFF_PER_SHIFT) + +/*! @brief System Controller Registers(2) */ +/* DIALOG7212_SYSTEM_STATUS 0xE0 */ +#define DIALOG7212_SYSTEM_STATUS_SC2_BUSY_MASK (1U << 1) +#define DIALOG7212_SYSTEM_STATUS_SC1_BUSY_MASK (1U << 0) + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_DRIVERS_AUDIO_DIALOG7212_H_ */ diff --git a/drivers/audio/dmic_nxp_micfil.c b/drivers/audio/dmic_nxp_micfil.c new file mode 100644 index 0000000000000..094a86cf4a059 --- /dev/null +++ b/drivers/audio/dmic_nxp_micfil.c @@ -0,0 +1,630 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(dmic_nxp_micfil, CONFIG_AUDIO_DMIC_LOG_LEVEL); + +#define DT_DRV_COMPAT nxp_micfil + +struct nxp_micfil_cfg { + PDM_Type *base; + uint8_t quality_mode; + uint8_t fifo_watermark; + uint8_t cic_decimation_rate; + uint8_t chan_dc_cutoff[4]; /* dc remover cutoff frequency. */ + uint8_t chan_gain[4]; /* decimation filter gain. */ + uint8_t ch_enabled_mask; + uint32_t sample_rate; /* MICFIL sample rate */ + const struct device *clock_dev; + clock_control_subsys_t clock_name; + void (*irq_config_func)(const struct device *dev); +}; + +struct nxp_micfil_drv_data { + const struct device *dev; + PDM_Type *base; + struct k_msgq *rx_msg_queue; + volatile enum dmic_state state; + uint8_t hw_chan[4]; /* Requested hardware channel order, maximun 4 channels. */ + uint8_t channels; /* Current active channels count */ + uint8_t sample_bytes; /* bytes per sample (4 for 32bits). */ + uint16_t block_size; + struct k_mem_slab *mem_slab; + void *active_buf; /* Current active buffer */ + uint16_t write_off; /* Bytes written into active_buf */ + uint8_t fifo_wm; /* FIFO watermark */ +}; + +static int nxp_micfil_configure(const struct device *dev, struct dmic_cfg *cfg_in) +{ + struct nxp_micfil_drv_data *data = dev->data; + const struct nxp_micfil_cfg *cfg = dev->config; + struct pdm_chan_cfg *chan = &cfg_in->channel; + struct pcm_stream_cfg *stream = &cfg_in->streams[0]; + uint8_t act = 0U; + uint8_t micfil_idx; + enum pdm_lr lr; + + if (data->state == DMIC_STATE_ACTIVE) { + return -EBUSY; + } + + if (stream->pcm_rate == 0U || stream->pcm_width == 0U || + stream->mem_slab == NULL || stream->block_size == 0U) { + return -EINVAL; + } + + /* NXP MICFIL FIFO data width is 32-bit, only the 24 more significant bits + * have information, and the other bits are always 0. We output 32-bit PCM + * to keep alignment and simplify processing. + */ + if (!(stream->pcm_width == 32U)) { + LOG_ERR("Unsupported pcm width %u", stream->pcm_width); + return -EINVAL; + } + + if (chan->req_num_streams != 1U) { + LOG_ERR("Only 1 stream supported"); + return -EINVAL; + } + + /* Basic channel count sanity and support limit */ + if ((chan->req_num_chan == 0U) || (chan->req_num_chan > ARRAY_SIZE(data->hw_chan))) { + LOG_ERR("Unsupported number of channels: %u", chan->req_num_chan); + return -ENOTSUP; + } + + /* Parse the requested logical channels and build HW channel list. */ + for (uint8_t index = 0U; index < chan->req_num_chan; index++) { + dmic_parse_channel_map(chan->req_chan_map_lo, chan->req_chan_map_hi, + index, &micfil_idx, &lr); + + /* New mapping model: + * - The micfil number in the map is used directly as the DMIC channel number, + * which corresponds to the hardware DATACH index. + * - The lr value selects which side (Left/Right) that DMIC channel represents + * within its stereo pair; adjacency/consecutiveness is validated later. + */ + uint8_t hw_chan = micfil_idx; + + if (hw_chan >= ARRAY_SIZE(data->hw_chan)) { + LOG_ERR("Requested hw channel index %u exceeds supported %u", + hw_chan, (uint32_t)ARRAY_SIZE(data->hw_chan)); + return -EINVAL; + } + + if ((cfg->ch_enabled_mask & BIT(hw_chan)) == 0U) { + LOG_ERR("Requested hw channel %u not enabled in DT", hw_chan); + return -EINVAL; + } + + /* Avoid duplicates */ + for (uint8_t i = 0U; i < act; i++) { + if (data->hw_chan[i] == hw_chan) { + LOG_ERR("Duplicate channel request for hw channel %u", hw_chan); + return -EINVAL; + } + } + + data->hw_chan[act++] = hw_chan; + } + + /* Ensure no extra mappings beyond req_num_chan are set */ + for (uint8_t index = chan->req_num_chan; index < 16U; index++) { + uint32_t chan_map; + + if (index < 8U) { + chan_map = (chan->req_chan_map_lo >> (index * 4U)) & 0xFU; + } else { + chan_map = (chan->req_chan_map_hi >> ((index - 8U) * 4U)) & 0xFU; + } + if (chan_map != 0U) { + LOG_ERR("Extra mapping present for logical channel %u", index); + return -EINVAL; + } + } + + /* Validate adjacency for each stereo pair (L/R in any order) + * New model requires paired dmics to use consecutive DMIC channel numbers + * (e.g., 0/1, 2/3, ...), not the same micfil number. This preserves the API + * constraint that L and R are adjacent while allowing explicit control + * over which channel number is Left/Right. + */ + for (uint8_t index = 0U; index + 1U < chan->req_num_chan; index += 2U) { + uint8_t micfil0, micfil1; + enum pdm_lr lr0, lr1; + + dmic_parse_channel_map(chan->req_chan_map_lo, chan->req_chan_map_hi, + index, &micfil0, &lr0); + dmic_parse_channel_map(chan->req_chan_map_lo, chan->req_chan_map_hi, + index + 1U, &micfil1, &lr1); + + if (lr0 == lr1) { + LOG_ERR("Pair %u/%u has same L/R selection", index, index + 1U); + return -EINVAL; + } + /* Require consecutive DMIC channel numbers within a pair (e.g., 0/1, 2/3). + * Enforce that the smaller of the two is even to avoid crossing pairs (e.g., 1/2). + */ + uint8_t minp = MIN(micfil0, micfil1); + uint8_t maxp = MAX(micfil0, micfil1); + + if (!((maxp == (uint8_t)(minp + 1U)) && ((minp & 0x1U) == 0U))) { + LOG_ERR("Pair %u/%u must map to consecutive DMIC channels.", + index, index + 1U); + return -EINVAL; + } + } + + if (act == 0U) { + LOG_ERR("No channels requested"); + return -EINVAL; + } + + data->channels = act; + data->sample_bytes = stream->pcm_width / 8U; + data->block_size = stream->block_size; + data->mem_slab = stream->mem_slab; + + /* Validate block_size alignment to complete frames */ + uint32_t frame_bytes = (uint32_t)data->channels * (uint32_t)data->sample_bytes; + + if ((data->block_size % frame_bytes) != 0U) { + LOG_ERR("block_size %u not aligned to frame size %u (channels=%u)", + data->block_size, (uint32_t)frame_bytes, data->channels); + return -EINVAL; + } + + /* Populate act_* fields according to accepted configuration */ + chan->act_num_streams = 1U; + chan->act_num_chan = chan->req_num_chan; + chan->act_chan_map_lo = chan->req_chan_map_lo; + chan->act_chan_map_hi = chan->req_chan_map_hi; + + data->state = DMIC_STATE_CONFIGURED; + + return 0; +} + +static int nxp_micfil_trigger(const struct device *dev, enum dmic_trigger cmd) +{ + struct nxp_micfil_drv_data *data = dev->data; + + switch (cmd) { + case DMIC_TRIGGER_START: + case DMIC_TRIGGER_RELEASE: { + /* Check if we are in a state that can be started/released */ + if (!(data->state == DMIC_STATE_CONFIGURED || + data->state == DMIC_STATE_PAUSED)) { + return -EIO; + } + void *buf = NULL; + + if (k_mem_slab_alloc(data->mem_slab, &buf, K_NO_WAIT) != 0) { + return -ENOMEM; + } + data->active_buf = buf; + data->write_off = 0; + + /* Clear any pending status before enabling data interrupts */ + uint32_t st = data->base->FIFO_STAT; + + if (st) { + data->base->FIFO_STAT = st; + } + + st = data->base->STAT; + + if (st) { + data->base->STAT = st; + } + + /* Enable data FIFO watermark interrupts only (DISEL=2). */ + data->base->CTRL_1 = ((data->base->CTRL_1 & ~PDM_CTRL_1_DISEL_MASK) | + PDM_CTRL_1_DISEL(2U)); + + /* Enable the requested channels */ + for (uint8_t index = 0; index < data->channels; index++) { + data->base->CTRL_1 |= BIT(data->hw_chan[index]); + } + + /* Enable MICFIL. */ + data->base->CTRL_1 |= PDM_CTRL_1_PDMIEN_MASK; + + data->state = DMIC_STATE_ACTIVE; + + break; + } + + case DMIC_TRIGGER_PAUSE: + case DMIC_TRIGGER_STOP: + case DMIC_TRIGGER_RESET: { + /* Check if we are in a state that can be stopped/paused/reset */ + if (data->state == DMIC_STATE_ACTIVE || data->state == DMIC_STATE_PAUSED || + data->state == DMIC_STATE_ERROR) { + /* Disable MICFIL */ + data->base->CTRL_1 &= ~PDM_CTRL_1_PDMIEN_MASK; + + /* Disable the requested channels */ + for (uint8_t index = 0; index < data->channels; index++) { + data->base->CTRL_1 &= ~(BIT(data->hw_chan[index])); + } + + /* Disable fifo interrupts. */ + data->base->CTRL_1 &= ~PDM_CTRL_1_DISEL_MASK; + + /* Set state early so any in-flight ISR bails out */ + data->state = (cmd == DMIC_TRIGGER_RESET) ? DMIC_STATE_UNINIT : + DMIC_STATE_CONFIGURED; + + /* Clear any pending status flags */ + uint32_t st = data->base->FIFO_STAT; + + if (st) { + data->base->FIFO_STAT = st; + } + + st = data->base->STAT; + + if (st) { + data->base->STAT = st; + } + } + + /* Free active buffer if any */ + if (data->active_buf) { + void *tmp = data->active_buf; + + data->active_buf = NULL; + k_mem_slab_free(data->mem_slab, tmp); + } + + /* Drain and free any queued buffers that were filled + * but not yet read to avoid leaks. + */ + if (data->rx_msg_queue) { + void *queued; + + while (k_msgq_get(data->rx_msg_queue, &queued, K_NO_WAIT) == 0) { + k_mem_slab_free(data->mem_slab, queued); + } + } + break; + } + + default: + return -EINVAL; + } + + return 0; +} + +static int nxp_micfil_read(const struct device *dev, uint8_t stream, + void **buffer, size_t *size, int32_t timeout) +{ + struct nxp_micfil_drv_data *data = dev->data; + + ARG_UNUSED(stream); + + /* Check if we are in a state that can read */ + if (!(data->state == DMIC_STATE_ACTIVE || + data->state == DMIC_STATE_PAUSED)) { + return -EIO; + } + + /* Get the filled buffer from the queue */ + int ret = k_msgq_get(data->rx_msg_queue, buffer, SYS_TIMEOUT_MS(timeout)); + + if (ret == 0) { + *size = data->block_size; + return 0; + } + + /* Fallback: if active but no IRQ-produced data arrived within timeout, + * return a zero-filled block so API semantics (non-timeout) are satisfied. + */ + if (data->state == DMIC_STATE_ACTIVE) { + void *buf = NULL; + static uint32_t last_warn_ms; + + if (k_mem_slab_alloc(data->mem_slab, &buf, K_NO_WAIT) != 0) { + return ret; /* original error */ + } + /* Provide silence */ + (void)memset(buf, 0, data->block_size); + + uint32_t now = k_uptime_get_32(); + + if ((now - last_warn_ms) > 1000U) { + LOG_ERR("DMIC fallback: no IRQ data yet, returning silence\n"); + last_warn_ms = now; + } + + *buffer = buf; + *size = data->block_size; + + return 0; + } + + return ret; +} + +static void nxp_micfil_isr(const void *arg) +{ + const struct device *dev = (const struct device *)arg; + struct nxp_micfil_drv_data *data = dev->data; + + /* Clear status flags */ + uint32_t state = data->base->FIFO_STAT; + + if (state) { + data->base->FIFO_STAT = state; + } + + state = data->base->STAT; + + if (state) { + data->base->STAT = state; + } + + /* Check if we are in a state that can read */ + if (!data->active_buf || data->state != DMIC_STATE_ACTIVE) { + return; + } + + /* Read data from all enabled channels */ + uint8_t *dst = (uint8_t *)data->active_buf; + /* Each frame is channels * sample_bytes. Hardware returns 32-bit samples in DATACH[]. + * We output little-endian 32-bit PCM: LSB first, 4 bytes per sample. + */ + uint16_t frame_bytes = (uint16_t)(data->channels * data->sample_bytes); + /* Calculate how many complete frames are left in the current block that can be + * written. This limits the maximum number of frames that this ISR can take from + * the hardware FIFO to avoid write overflow and maintain frame alignment. + */ + uint16_t frames_remaining = (uint16_t)((data->block_size - data->write_off) / frame_bytes); + /* Read up to fifo_wm frames. */ + uint16_t frames_to_read = (uint16_t)data->fifo_wm; + + /* Adjust if more frames than remaining in buffer */ + if (frames_to_read > frames_remaining) { + frames_to_read = frames_remaining; + } + + /* Read frames from all active channels' FIFO. */ + for (uint16_t frame = 0; frame < frames_to_read; frame++) { + for (uint8_t chan = 0; chan < data->channels; chan++) { + /* Read one 32-bit sample from the selected hardware channel FIFO. */ + uint8_t hw = data->hw_chan[chan]; + volatile uint32_t raw_data = data->base->DATACH[hw]; + + dst[data->write_off + 0] = (uint8_t)(raw_data & 0xFFU); + dst[data->write_off + 1] = (uint8_t)((raw_data >> 8U) & 0xFFU); + dst[data->write_off + 2] = (uint8_t)((raw_data >> 16U) & 0xFFU); + dst[data->write_off + 3] = (uint8_t)((raw_data >> 24U) & 0xFFU); + + data->write_off += 4; + } + } + + /* Check if active buffer is full. Hand off to queue and rotate buffers safely. */ + if (data->write_off >= data->block_size) { + void *completed = data->active_buf; + void *new_buf = NULL; + + /* Allocate next buffer first to avoid using a freed buffer */ + if (k_mem_slab_alloc(data->mem_slab, &new_buf, K_NO_WAIT) != 0) { + /* No memory available: enter error state and stop capturing */ + data->active_buf = NULL; + data->state = DMIC_STATE_ERROR; + + /* Disable MICFIL */ + data->base->CTRL_1 &= ~PDM_CTRL_1_PDMIEN_MASK; + + /* Disable the requested channels */ + for (uint8_t index = 0; index < data->channels; index++) { + data->base->CTRL_1 &= ~(BIT(data->hw_chan[index])); + } + + /* Disable fifo interrupts. */ + data->base->CTRL_1 &= ~PDM_CTRL_1_DISEL_MASK; + return; + } + + /* Try to enqueue the completed buffer. If queue is full, free it. */ + if (k_msgq_put(data->rx_msg_queue, &completed, K_NO_WAIT) != 0) { + k_mem_slab_free(data->mem_slab, completed); + } + + /* Switch to the new active buffer */ + data->active_buf = new_buf; + data->write_off = 0; + } +} + +static int nxp_micfil_init(const struct device *dev) +{ + const struct nxp_micfil_cfg *cfg = dev->config; + struct nxp_micfil_drv_data *data = dev->data; + uint32_t clk_rate = 0U; + int ret; + + data->dev = dev; + data->base = cfg->base; + + if (cfg->clock_dev != NULL) { + ret = clock_control_on(cfg->clock_dev, cfg->clock_name); + if (ret) { + LOG_ERR("Device clock turn on failed"); + return ret; + } + + ret = clock_control_get_rate(cfg->clock_dev, cfg->clock_name, &clk_rate); + if (ret < 0) { + LOG_WRN("Device clock rate not available (%d)", ret); + } + } + + if (cfg->irq_config_func) { + cfg->irq_config_func(dev); + } + + /* MICFIL initialization. */ + /* Ensure module is enabled and interface/interrupts/channels + * are disabled before config. + */ + data->base->CTRL_1 &= ~(PDM_CTRL_1_MDIS_MASK | PDM_CTRL_1_PDMIEN_MASK | + PDM_CTRL_1_ERREN_MASK); + /* TODO: Use DT property instead of hardcoding channel numbers. */ + for (uint8_t ch = 0U; ch < 4U; ch++) { + data->base->CTRL_1 &= ~BIT(ch); + } + + /* Wait until all filters stopped if supported. */ + while ((data->base->STAT & PDM_STAT_BSY_FIL_MASK) != 0U) { + } + + /* Do a software reset pulse before configuration. */ + data->base->CTRL_1 |= PDM_CTRL_1_SRES_MASK; + + /* Configure quality mode, CIC decimation rate. */ + data->base->CTRL_2 &= ~(PDM_CTRL_2_QSEL_MASK | PDM_CTRL_2_CICOSR_MASK); + data->base->CTRL_2 |= PDM_CTRL_2_QSEL(cfg->quality_mode) | + PDM_CTRL_2_CICOSR(cfg->cic_decimation_rate); + + /* Configure FIFO watermark. */ + data->base->FIFO_CTRL = (data->base->FIFO_CTRL & ~PDM_FIFO_CTRL_FIFOWMK_MASK) | + PDM_FIFO_CTRL_FIFOWMK(cfg->fifo_watermark); + + /* Cache fifo watermark for ISR. */ + data->fifo_wm = cfg->fifo_watermark; + + /* MICFIL channels initialization. */ + /* Configure DC remover cutoff per hardware channel. */ + for (uint8_t ch = 0U; ch < ARRAY_SIZE(cfg->chan_dc_cutoff); ch++) { + uint32_t mask = PDM_DC_CTRL_DCCONFIG0_MASK << (ch * 2U); + uint32_t val = (cfg->chan_dc_cutoff[ch] & PDM_DC_CTRL_DCCONFIG0_MASK) << (ch * 2U); + + data->base->DC_OUT_CTRL = ((data->base->DC_OUT_CTRL & ~mask) | val); + } + + /* Configure decimation-filter-gain per hardware channel. */ + for (uint8_t ch = 0U; ch < ARRAY_SIZE(cfg->chan_gain); ch++) { + uint32_t mask = PDM_RANGE_CTRL_RANGEADJ0_MASK << (ch * 4U); + uint32_t val = (cfg->chan_gain[ch] & PDM_RANGE_CTRL_RANGEADJ0_MASK) << (ch * 4U); + + data->base->RANGE_CTRL = ((data->base->RANGE_CTRL & ~mask) | val); + } + + /* Configure clock divider if clock rate and sample rate are known. */ + if (clk_rate != 0U && cfg->sample_rate != 0U) { + uint32_t osr_reg_max = (PDM_CTRL_2_CICOSR_MASK >> PDM_CTRL_2_CICOSR_SHIFT); + + if (cfg->cic_decimation_rate > osr_reg_max) { + LOG_ERR("CIC decimation rate %u exceeds max %u", + cfg->cic_decimation_rate, (uint32_t)osr_reg_max); + return -EINVAL; + } + + /* Real OSR per MCUX SDK: (max + 1 - programmed). */ + uint32_t real_osr = osr_reg_max + 1U - (uint32_t)cfg->cic_decimation_rate; + uint32_t micfil_clock_rate = cfg->sample_rate * real_osr * 8U; + + if (clk_rate < micfil_clock_rate) { + LOG_ERR("Clock rate %u too low for sample rate %u (OSR=%u)", + clk_rate, cfg->sample_rate, real_osr); + return -EINVAL; + } + + uint32_t reg_div = clk_rate / micfil_clock_rate; + + if (reg_div == 0U) { + reg_div = 1U; + } + + uint32_t clkdiv_max = (PDM_CTRL_2_CLKDIV_MASK >> PDM_CTRL_2_CLKDIV_SHIFT); + + if (reg_div > clkdiv_max) { + LOG_WRN("CLKDIV %u exceeds max %u, clamping", reg_div, clkdiv_max); + reg_div = clkdiv_max; + } + + data->base->CTRL_2 = (data->base->CTRL_2 & (~PDM_CTRL_2_CLKDIV_MASK)) | + PDM_CTRL_2_CLKDIV(reg_div); + + LOG_INF("MICFIL clk=%uHz sample=%u OSR=%u div=%u wm=%u", + clk_rate, cfg->sample_rate, real_osr, reg_div, cfg->fifo_watermark); + } else { + LOG_WRN("Clock rate or sample rate is zero, cannot set clock divider"); + } + + data->state = DMIC_STATE_INITIALIZED; + + return 0; +} + +static const struct _dmic_ops dmic_ops = { + .configure = nxp_micfil_configure, + .trigger = nxp_micfil_trigger, + .read = nxp_micfil_read, +}; + +#define NXP_MICFIL_IRQ_CONFIG(inst) \ + static void _CONCAT(irq_config, inst)(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(inst), DT_INST_IRQ(inst, priority), \ + nxp_micfil_isr, DEVICE_DT_INST_GET(inst), 0); \ + irq_enable(DT_INST_IRQN(inst)); \ + } + +/* Build per-hardware-channel DC cutoff array from DT child nodes. */ +#define DC_CUTOFF_ITEM(node_id) [DT_REG_ADDR(node_id)] = \ + DT_PROP(node_id, dc_remover_cutoff_freq), +/* Build per-hardware-channel OUT gain array from DT child nodes. */ +#define OUT_GAIN_ITEM(node_id) [DT_REG_ADDR(node_id)] = \ + DT_PROP_OR(node_id, decimation_filter_gain, 0), +/* Build bitmask of enabled channels by OR-ing BIT(reg) per child. */ +#define CH_BIT(node_id) | BIT(DT_REG_ADDR(node_id)) + +#define NXP_MICFIL_DEFINE(inst) \ + K_MSGQ_DEFINE(nxp_micfil_msgq##inst, sizeof(void *), \ + CONFIG_DMIC_NXP_MICFIL_QUEUE_SIZE, 4); \ + \ + NXP_MICFIL_IRQ_CONFIG(inst) \ + \ + static struct nxp_micfil_drv_data _CONCAT(data, inst) = { \ + .rx_msg_queue = &nxp_micfil_msgq##inst, \ + .state = DMIC_STATE_UNINIT, \ + }; \ + \ + static const struct nxp_micfil_cfg _CONCAT(cfg, inst) = { \ + .base = (PDM_Type *)DT_INST_REG_ADDR(inst), \ + .quality_mode = DT_INST_PROP(inst, quality_mode), \ + .fifo_watermark = DT_INST_PROP(inst, fifo_watermark), \ + .cic_decimation_rate = DT_INST_PROP(inst, cic_decimation_rate), \ + .chan_dc_cutoff = { DT_INST_FOREACH_CHILD_STATUS_OKAY(inst, \ + DC_CUTOFF_ITEM) }, \ + .chan_gain = { DT_INST_FOREACH_CHILD_STATUS_OKAY(inst, OUT_GAIN_ITEM) },\ + .ch_enabled_mask = (0 DT_INST_FOREACH_CHILD_STATUS_OKAY(inst, CH_BIT)), \ + .sample_rate = DT_INST_PROP(inst, sample_rate), \ + .clock_dev = DEVICE_DT_GET_OR_NULL(DT_INST_CLOCKS_CTLR(inst)), \ + .clock_name = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(inst, name), \ + .irq_config_func = _CONCAT(irq_config, inst), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, nxp_micfil_init, NULL, &_CONCAT(data, inst), \ + &_CONCAT(cfg, inst), POST_KERNEL, \ + CONFIG_AUDIO_DMIC_INIT_PRIORITY, &dmic_ops); + +DT_INST_FOREACH_STATUS_OKAY(NXP_MICFIL_DEFINE) diff --git a/drivers/clock_control/clock_control_mcux_syscon.c b/drivers/clock_control/clock_control_mcux_syscon.c index bbf192d0e0f78..211f970c42493 100644 --- a/drivers/clock_control/clock_control_mcux_syscon.c +++ b/drivers/clock_control/clock_control_mcux_syscon.c @@ -176,6 +176,10 @@ static int mcux_lpc_syscon_clock_control_on(const struct device *dev, } #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(micfil), okay) + CLOCK_EnableClock(kCLOCK_Micfil); +#endif + return 0; } @@ -611,6 +615,12 @@ static int mcux_lpc_syscon_clock_control_get_subsys_rate(const struct device *de *rate = CLOCK_GetLpspiClkFreq(1); break; #endif /* defined(CONFIG_SPI_NXP_LPSPI) */ + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(micfil), okay) + case MCUX_MICFIL_CLK: + *rate = CLOCK_GetMicfilClkFreq(); + break; +#endif } return 0; diff --git a/dts/arm/nxp/nxp_mcxn23x_common.dtsi b/dts/arm/nxp/nxp_mcxn23x_common.dtsi index 75a7160e2226c..b58f70ba9f2f6 100644 --- a/dts/arm/nxp/nxp_mcxn23x_common.dtsi +++ b/dts/arm/nxp/nxp_mcxn23x_common.dtsi @@ -985,6 +985,48 @@ nxp,rx-dma-channel = <3>; status = "disabled"; }; + + micfil: micfil@10c000 { + compatible = "nxp,micfil"; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <48 0>; + reg = <0x10c000 0x1000>; + clocks = <&syscon MCUX_MICFIL_CLK>; + status = "disabled"; + quality-mode = <1>; + cic-decimation-rate = <0>; + fifo-watermark = <15>; + sample-rate = <16000>; + + channel0: micfil-channel@0 { + reg = <0>; + status = "disabled"; + dc-remover-cutoff-freq = <2>; + decimation-filter-gain = <4>; + }; + + channel1: micfil-channel@1 { + reg = <1>; + status = "disabled"; + dc-remover-cutoff-freq = <2>; + decimation-filter-gain = <4>; + }; + + channel2: micfil-channel@2 { + reg = <2>; + status = "disabled"; + dc-remover-cutoff-freq = <2>; + decimation-filter-gain = <4>; + }; + + channel3: micfil-channel@3 { + reg = <3>; + status = "disabled"; + dc-remover-cutoff-freq = <2>; + decimation-filter-gain = <4>; + }; + }; }; &systick { diff --git a/dts/bindings/audio/dialog,da7212.yaml b/dts/bindings/audio/dialog,da7212.yaml new file mode 100644 index 0000000000000..a4f5ba9ff58cc --- /dev/null +++ b/dts/bindings/audio/dialog,da7212.yaml @@ -0,0 +1,31 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: Dialog DA7212 audio codec + +include: [i2c-device.yaml] + +compatible: "dialog,da7212" + +properties: + reg: + required: true + clock-source: + type: string + default: "MCLK" + description: | + Codec's internal clock (SYSCLK) source selection. Available options: + - "MCLK": external MCLK supplied by host + enum: + - "MCLK" + + clocks: + type: phandle-array + required: true + description: Phandle to the clock providing the codec MCLK input + clock-names: + type: string-array + required: true + description: Must contain "mclk" matching the MCLK input + enum: + - mclk diff --git a/dts/bindings/audio/nxp,pdm.yaml b/dts/bindings/audio/nxp,pdm.yaml new file mode 100644 index 0000000000000..715665bfb49e2 --- /dev/null +++ b/dts/bindings/audio/nxp,pdm.yaml @@ -0,0 +1,87 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP PDM Microphone Interface (MICFIL) + +compatible: "nxp,micfil" + +include: + - base.yaml + - pinctrl-device.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + clocks: + required: true + + quality-mode: + type: int + enum: [0, 1, 4, 5, 6, 7] + default: 0 + description: | + Decimation filter quality mode. + 0 = Medium, default value, PoR reset value of register + 1 = High + 4 = VeryLow2 + 5 = VeryLow1 + 6 = VeryLow0 + 7 = Low + + cic-decimation-rate: + type: int + description: | + CIC filter decimation rate setting, + range is SoC specific, may [0, 15] or [8, 31] + The final OSR = (16 - cic-decimation-rate) + CIC decimation rate = 2 * OSR; If HQ, VLQ0 mode. + CIC decimation rate = OSR; If other modes. + 0: CIC oversampling rate = 0, default value, PoR reset value + 1: CIC oversampling rate = 1 + ... + 15: CIC oversampling rate = 15 + + fifo-watermark: + type: int + description: | + FIFO watermark level (implementation defined, typically 7), + range is SoC specific, may [0, 7] or [0, 15]. + Default is PoR reset value of register. + + sample-rate: + type: int + enum: [8000, 12000, 16000, 24000, 32000, 48000, 96000] + description: | + Sample rate in Hz. + +child-binding: + description: | + NXP MICFIL channel. Can be used to configure DC remover cutoff frequency and gain + include: + - name: base.yaml + property-allowlist: + - reg + properties: + reg: + required: true + dc-remover-cutoff-freq: + type: int + enum: [0, 1, 2, 3] + default: 0 + description: | + DC remover cutoff frequency in Hz + 0: 20Hz (FS=48KHz), default value, PoR reset value + 1: 13.3Hz (FS=48KHz) + 2: 40Hz (FS=48KHz) + 3: DC remover is bypassed + + decimation-filter-gain: + type: int + default: 0 + description: | + Decimation filter gain setting, range: [0, 15]. + Default is PoR reset value of register. diff --git a/dts/bindings/vendor-prefixes.txt b/dts/bindings/vendor-prefixes.txt index 21fe4c83139d9..41abc3d4e96ac 100644 --- a/dts/bindings/vendor-prefixes.txt +++ b/dts/bindings/vendor-prefixes.txt @@ -176,6 +176,7 @@ devantech Devantech, Ltd. dfi DFI Inc. dfrobot DFRobot dh DH electronics GmbH +dialog Dialog Semiconductor difrnce Shenzhen Yagu Electronic Technology Co., Ltd. digi Digi International Inc. digilent Digilent, Inc. diff --git a/include/zephyr/audio/dmic.h b/include/zephyr/audio/dmic.h index 9cf89ff1aaa77..bb46e008ddde3 100644 --- a/include/zephyr/audio/dmic.h +++ b/include/zephyr/audio/dmic.h @@ -81,13 +81,13 @@ struct pdm_io_cfg { *@{ */ /** Minimum clock frequency supported by the mic */ - uint32_t min_pdm_clk_freq; + uint32_t min_pdm_clk_freq; /** Maximum clock frequency supported by the mic */ - uint32_t max_pdm_clk_freq; + uint32_t max_pdm_clk_freq; /** Minimum duty cycle in % supported by the mic */ - uint8_t min_pdm_clk_dc; + uint8_t min_pdm_clk_dc; /** Maximum duty cycle in % supported by the mic */ - uint8_t max_pdm_clk_dc; + uint8_t max_pdm_clk_dc; /** * @} */ @@ -97,11 +97,11 @@ struct pdm_io_cfg { * @{ */ /** Bit mask to optionally invert PDM clock */ - uint8_t pdm_clk_pol; + uint8_t pdm_clk_pol; /** Bit mask to optionally invert mic data */ - uint8_t pdm_data_pol; + uint8_t pdm_data_pol; /** Collection of clock skew values for each PDM port */ - uint32_t pdm_clk_skew; + uint32_t pdm_clk_skew; /** * @} */ @@ -115,13 +115,13 @@ struct pdm_io_cfg { */ struct pcm_stream_cfg { /** PCM sample rate of stream */ - uint32_t pcm_rate; + uint32_t pcm_rate; /** PCM sample width of stream */ - uint8_t pcm_width; + uint8_t pcm_width; /** PCM sample block size per transfer */ - uint16_t block_size; + uint16_t block_size; /** SLAB for DMIC driver to allocate buffers for stream */ - struct k_mem_slab *mem_slab; + struct k_mem_slab *mem_slab; }; /** @@ -150,26 +150,26 @@ struct pdm_chan_cfg { * @name Requested channel map * @{ */ - uint32_t req_chan_map_lo; /**< Channels 0 to 7 */ - uint32_t req_chan_map_hi; /**< Channels 8 to 15 */ + uint32_t req_chan_map_lo; /**< Channels 0 to 7 */ + uint32_t req_chan_map_hi; /**< Channels 8 to 15 */ /** @} */ /** * @name Actual channel map that the driver could configure * @{ */ - uint32_t act_chan_map_lo; /**< Channels 0 to 7 */ - uint32_t act_chan_map_hi; /**< Channels 8 to 15 */ + uint32_t act_chan_map_lo; /**< Channels 0 to 7 */ + uint32_t act_chan_map_hi; /**< Channels 8 to 15 */ /** @} */ /** Requested number of channels */ - uint8_t req_num_chan; + uint8_t req_num_chan; /** Actual number of channels that the driver could configure */ - uint8_t act_num_chan; + uint8_t act_num_chan; /** Requested number of streams for each channel */ - uint8_t req_num_streams; + uint8_t req_num_streams; /** Actual number of streams that the driver could configure */ - uint8_t act_num_streams; + uint8_t act_num_streams; }; /** diff --git a/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h b/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h index a48085bb2db65..e7674c41483f2 100644 --- a/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h +++ b/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h @@ -1,4 +1,5 @@ /* + * Copyright 2020-2025 NXP * Copyright 2020-2025 NXP * * SPDX-License-Identifier: Apache-2.0 @@ -134,4 +135,6 @@ #define MCUX_OPAMP2_CLK MCUX_LPC_CLK_ID(0x18, 0x02) #define MCUX_OPAMP3_CLK MCUX_LPC_CLK_ID(0x18, 0x03) +#define MCUX_MICFIL_CLK MCUX_LPC_CLK_ID(0x18, 0x00) + #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_MCUX_LPC_SYSCON_H_ */ diff --git a/samples/drivers/i2s/i2s_codec/Kconfig b/samples/drivers/i2s/i2s_codec/Kconfig index f5edd389f1bba..827049d3d53c6 100644 --- a/samples/drivers/i2s/i2s_codec/Kconfig +++ b/samples/drivers/i2s/i2s_codec/Kconfig @@ -25,6 +25,24 @@ config USE_CODEC_CLOCK to generate those. If not selected, the I2S peripheral will generate them and the codec will be expected to consume them. +config EXTRA_BLOCKS + int "Extra block size" + default 32 + help + Count of DMIC channels to capture and process. + +config SAMPLE_WIDTH + int "Sample bit width" + default 16 + help + Sample bit width of the system. + +config BYTES_PER_SAMPLE + int "Bytes per sample" + default 2 + help + Bytes per sample of the system. + config USE_DMIC bool "Use DMIC as an audio input" diff --git a/samples/drivers/i2s/i2s_codec/boards/frdm_mcxn236.conf b/samples/drivers/i2s/i2s_codec/boards/frdm_mcxn236.conf new file mode 100644 index 0000000000000..1b143f42deb79 --- /dev/null +++ b/samples/drivers/i2s/i2s_codec/boards/frdm_mcxn236.conf @@ -0,0 +1,14 @@ +# Copyright 2025 NXP +# +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_DMA_TCD_QUEUE_SIZE=4 +CONFIG_AUDIO_CODEC_DA7212=y +CONFIG_SAMPLE_FREQ=16000 +CONFIG_I2S_INIT_BUFFERS=1 +CONFIG_USE_CODEC_CLOCK=y +CONFIG_USE_DMIC=y +CONFIG_DMIC_CHANNELS=1 +CONFIG_EXTRA_BLOCKS=10 +CONFIG_SAMPLE_WIDTH=32 +CONFIG_BYTES_PER_SAMPLE=4 diff --git a/samples/drivers/i2s/i2s_codec/boards/frdm_mcxn236.overlay b/samples/drivers/i2s/i2s_codec/boards/frdm_mcxn236.overlay new file mode 100644 index 0000000000000..48695caef2f59 --- /dev/null +++ b/samples/drivers/i2s/i2s_codec/boards/frdm_mcxn236.overlay @@ -0,0 +1,26 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + i2s-codec-tx = &sai1; + i2s-tx = &sai1; + }; +}; + +&sai1 { + mclk-output; +}; + +dmic_dev: &micfil { + channel0: micfil-channel@0 { + status = "okay"; + }; + + channel1: micfil-channel@1 { + status = "okay"; + }; +}; diff --git a/samples/drivers/i2s/i2s_codec/sample.yaml b/samples/drivers/i2s/i2s_codec/sample.yaml index 1fdc2a97322ea..c4d79a3e95828 100644 --- a/samples/drivers/i2s/i2s_codec/sample.yaml +++ b/samples/drivers/i2s/i2s_codec/sample.yaml @@ -10,6 +10,7 @@ tests: - mimxrt1060_evk/mimxrt1062/qspi - mimxrt1180_evk/mimxrt1189/cm33 - mimxrt1180_evk/mimxrt1189/cm7 + - frdm_mcxn236 harness: console harness_config: type: one_line diff --git a/samples/drivers/i2s/i2s_codec/src/main.c b/samples/drivers/i2s/i2s_codec/src/main.c index edef0c9f07994..b71b560fa7b58 100644 --- a/samples/drivers/i2s/i2s_codec/src/main.c +++ b/samples/drivers/i2s/i2s_codec/src/main.c @@ -19,8 +19,8 @@ #define I2S_CODEC_TX DT_ALIAS(i2s_codec_tx) #define SAMPLE_FREQUENCY CONFIG_SAMPLE_FREQ -#define SAMPLE_BIT_WIDTH (16U) -#define BYTES_PER_SAMPLE sizeof(int16_t) +#define SAMPLE_BIT_WIDTH CONFIG_SAMPLE_WIDTH +#define BYTES_PER_SAMPLE CONFIG_BYTES_PER_SAMPLE #if CONFIG_USE_DMIC #define NUMBER_OF_CHANNELS CONFIG_DMIC_CHANNELS #else @@ -32,7 +32,7 @@ #define TIMEOUT (2000U) #define BLOCK_SIZE (BYTES_PER_SAMPLE * SAMPLES_PER_BLOCK) -#define BLOCK_COUNT (INITIAL_BLOCKS + 32) +#define BLOCK_COUNT (INITIAL_BLOCKS + CONFIG_EXTRA_BLOCKS) K_MEM_SLAB_DEFINE_IN_SECT_STATIC(mem_slab, __nocache, BLOCK_SIZE, BLOCK_COUNT, 4); diff --git a/samples/drivers/i2s/i2s_codec/src/sine.h b/samples/drivers/i2s/i2s_codec/src/sine.h index 99dfd1d0e90fe..a367e0a12dc74 100644 --- a/samples/drivers/i2s/i2s_codec/src/sine.h +++ b/samples/drivers/i2s/i2s_codec/src/sine.h @@ -4,19 +4,16 @@ * SPDX-License-Identifier: Apache-2.0 */ - #ifndef SINE_H_ - #define SINE_H_ +#ifndef SINE_H_ +#define SINE_H_ -#if CONFIG_NOCACHE_MEMORY -#define __NOCACHE __attribute__((__section__(".nocache"))) -#elif defined(CONFIG_DT_DEFINED_NOCACHE) -#define __NOCACHE __attribute__((__section__(CONFIG_DT_DEFINED_NOCACHE_NAME))) -#else /* CONFIG_NOCACHE_MEMORY */ -#define __NOCACHE -#endif /* CONFIG_NOCACHE_MEMORY */ - -unsigned char __16kHz16bit_stereo_sine_pcm[] __NOCACHE; -unsigned char __16kHz16bit_stereo_sine_pcm[] = { +/* + * Keep the PCM data in flash to avoid large RAM usage. + * If a platform requires DMA-readable RAM buffers, copy + * chunks of this table into a small nocache TX buffer + * at runtime instead of keeping the entire table in RAM. + */ +static const unsigned char __16kHz16bit_stereo_sine_pcm[] = { 0x00, 0x00, 0x00, 0x00, 0x08, 0x0b, 0x08, 0x0b, 0xbb, 0x15, 0xbb, 0x15, 0xc9, 0x1f, 0xc9, 0x1f, 0xe4, 0x28, 0xe4, 0x28, 0xc8, 0x30, 0xc8, 0x30, 0x38, 0x37, 0x38, 0x37, 0x03, 0x3c, 0x03, 0x3c, 0x04, 0x3f, 0x04, 0x3f, 0x25, 0x40, 0x25, 0x40, 0x5d, 0x3f, 0x5d, 0x3f, 0xb1, @@ -444,6 +441,6 @@ unsigned char __16kHz16bit_stereo_sine_pcm[] = { 0xa3, 0xc0, 0xa3, 0xc0, 0xdb, 0xbf, 0xdb, 0xbf, 0xfc, 0xc0, 0xfc, 0xc0, 0xfd, 0xc3, 0xfd, 0xc3, 0xc8, 0xc8, 0xc8, 0xc8, 0x38, 0xcf, 0x38, 0xcf, 0x1c, 0xd7, 0x1c, 0xd7, 0x37, 0xe0, 0x37, 0xe0, 0x45, 0xea, 0x45, 0xea, 0xf8, 0xf4, 0xf8, 0xf4}; -const unsigned int __16kHz16bit_stereo_sine_pcm_len = sizeof(__16kHz16bit_stereo_sine_pcm); +static const unsigned int __16kHz16bit_stereo_sine_pcm_len = sizeof(__16kHz16bit_stereo_sine_pcm); #endif /* SINE_H_ */