From 8cc7476735dd3f9f9e3f5b1356eadc4ef40c23b4 Mon Sep 17 00:00:00 2001 From: Dana Conrad Date: Sun, 3 Dec 2023 15:07:26 -0600 Subject: ErosQ Native ES9018K2M: Add digital filters capability Setting not yet hidden for older hardware revision. Change-Id: Iaaa5727e63c38de578a6bbc73498ae1073180e65 --- apps/features.txt | 4 +- firmware/drivers/audio/es9018k2m.c | 48 ++++++++++++++++++++-- firmware/export/config/erosqnative.h | 2 + firmware/export/es9018k2m.h | 14 ++++++- .../erosqnative/audiohw-erosqnative.c | 10 ++++- 5 files changed, 70 insertions(+), 8 deletions(-) diff --git a/apps/features.txt b/apps/features.txt index 1356d20e34..a43172932f 100644 --- a/apps/features.txt +++ b/apps/features.txt @@ -186,7 +186,7 @@ depth_3d #endif /* This should be AUDIOHW_HAVE_FILTER_ROLL_OFF but that is only defined later */ -#if defined(DX50) || defined(HAVE_DF1704_CODEC) || defined(HAVE_PCM1792_CODEC) || defined(HAVE_CS4398) || defined(HAVE_WM8740) || defined(HAVE_ES9018) || defined(HAVE_XDUOO_LINUX_CODEC) || defined(HAVE_FIIO_LINUX_CODEC) || defined(HAVE_AK4376) || defined(HAVE_ES9218) +#if defined(DX50) || defined(HAVE_DF1704_CODEC) || defined(HAVE_PCM1792_CODEC) || defined(HAVE_CS4398) || defined(HAVE_WM8740) || defined(HAVE_ES9018)|| defined(HAVE_EROS_QN_CODEC) || defined(HAVE_XDUOO_LINUX_CODEC) || defined(HAVE_FIIO_LINUX_CODEC) || defined(HAVE_AK4376) || defined(HAVE_ES9218) filter_roll_off #endif @@ -195,7 +195,7 @@ filter_roll_off dac_power_mode #endif -#if defined(HAVE_ES9018) +#if defined(HAVE_ES9018) || defined(HAVE_EROS_QN_CODEC) es9018 #endif diff --git a/firmware/drivers/audio/es9018k2m.c b/firmware/drivers/audio/es9018k2m.c index e19cf6e8a9..3f14aaea39 100644 --- a/firmware/drivers/audio/es9018k2m.c +++ b/firmware/drivers/audio/es9018k2m.c @@ -55,15 +55,20 @@ static int vol_tenthdb2hw(const int tdb) * static uint8_t reg4_automute_time = 0x00; // Automute time. Default = disabled * static uint8_t reg5_automute_level = 0x68; // Automute level. Default is some level * static uint8_t reg6_deemphasis = 0x4A; // Deemphasis. Default = disabled - * static uint8_t reg7_general_settings = 0x80; // General settings. Default sharp fir, pcm iir and unmuted + */ +static uint8_t reg7_general_settings = 0x80; // General settings. Default sharp fir, pcm iir and unmuted +/* * static uint8_t reg8_gpio_configuration = 0x10; // GPIO configuration * static uint8_t reg10_master_mode_control = 0x05; // Master Mode Control. Default value: master mode off * static uint8_t reg11_channel_mapping = 0x02; // Channel Mapping. Default stereo is Ch1=left, Ch2=right * static uint8_t reg12_dpll_settings = 0x5A; // DPLL Settings. Default = 5 for I2S, A for DSD * static uint8_t reg13_thd_comp = 0x40; // THD Compensation * static uint8_t reg14_softstart_settings = 0x8A; // Soft Start Settings - * static uint8_t reg21_gpio_input_selection = 0x00; // Oversampling filter. Default: oversampling ON */ +static uint8_t reg21_gpio_input_selection = 0x00; // Oversampling filter. Default: oversampling ON + +#define bitSet(value, bit) ((value) |= (1UL << (bit))) +#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) static uint8_t vol_reg_l = ES9018K2M_REG15_VOLUME_L; static uint8_t reg15_vol_l = 0; @@ -95,7 +100,7 @@ i2c_descriptor vol_desc_r = { .next = NULL, }; -void es9018k2m_set_volume(int vol_l, int vol_r) +void es9018k2m_set_volume_async(int vol_l, int vol_r) { /* Queue writes to the DAC's volume. * Note that this needs to be done asynchronously. From testing, calling @@ -106,6 +111,43 @@ void es9018k2m_set_volume(int vol_l, int vol_r) i2c_async_queue(ES9018K2M_BUS, TIMEOUT_NOBLOCK, I2C_Q_ADD, 0, &vol_desc_r); } +void es9018k2m_set_filter_roll_off(int value) +{ + /* Note: the ihifi800 implementation manipulates + * bit 0 of reg21, but I think that is incorrect? + * Bit 2 is the bypass for the IIR digital filters, + * Whereas Bit 0 is the oversampling filter, which + * the datasheet seems to say should be left on. */ + + /* 0 = "Sharp" / Fast Rolloff (Default) + 1 = Slow Rolloff + 2 = "Short" / Minimum Phase + 3 = Bypass */ + switch(value) + { + case 0: + bitClear(reg7_general_settings, 5); + bitClear(reg7_general_settings, 6); + bitClear(reg21_gpio_input_selection, 2); + break; + case 1: + bitSet(reg7_general_settings, 5); + bitClear(reg7_general_settings, 6); + bitClear(reg21_gpio_input_selection, 2); + break; + case 2: + bitClear(reg7_general_settings, 5); + bitSet(reg7_general_settings, 6); + bitClear(reg21_gpio_input_selection, 2); + break; + case 3: + bitSet(reg21_gpio_input_selection, 2); + break; + } + es9018k2m_write_reg(ES9018K2M_REG7_GENERAL_SETTINGS, reg7_general_settings); + es9018k2m_write_reg(ES9018K2M_REG21_GPIO_INPUT_SELECT, reg21_gpio_input_selection); +} + /* returns I2C_STATUS_OK upon success, I2C_STATUS_* errors upon error */ int es9018k2m_write_reg(uint8_t reg, uint8_t val) { diff --git a/firmware/export/config/erosqnative.h b/firmware/export/config/erosqnative.h index c71f7ade49..4f87282f1f 100644 --- a/firmware/export/config/erosqnative.h +++ b/firmware/export/config/erosqnative.h @@ -63,6 +63,8 @@ #define HAVE_EROS_QN_CODEC #define HAVE_SW_TONE_CONTROLS #define HAVE_SW_VOLUME_CONTROL +#define AUDIOHW_CAPS (FILTER_ROLL_OFF_CAP) +#define AUDIOHW_HAVE_SHORT_ROLL_OFF /* use high-bitdepth volume scaling */ #define PCM_NATIVE_BITDEPTH 24 diff --git a/firmware/export/es9018k2m.h b/firmware/export/es9018k2m.h index 035a607030..2824fed505 100644 --- a/firmware/export/es9018k2m.h +++ b/firmware/export/es9018k2m.h @@ -25,6 +25,13 @@ //====================================================================================== // ES9018K2M support stuff +// Implement audiohw_* functions in audiohw-*.c. These functions are utilities which +// may be used there. + +// AUDIOHW_SETTING(VOLUME, *) not set here, probably best to put it in device-specific *_codec.h +#ifdef AUDIOHW_HAVE_SHORT_ROLL_OFF +AUDIOHW_SETTING(FILTER_ROLL_OFF, "", 0, 1, 0, 3, 0) +#endif #ifndef ES9018K2M_VOLUME_MIN # define ES9018K2M_VOLUME_MIN -1270 @@ -50,8 +57,11 @@ #define ES9018K2M_REG16_VOLUME_R 16 #define ES9018K2M_REG21_GPIO_INPUT_SELECT 21 -/* writes volume levels to DAC over I2C */ -void es9018k2m_set_volume(int vol_l, int vol_r); +/* writes volume levels to DAC over I2C, asynchronously */ +void es9018k2m_set_volume_async(int vol_l, int vol_r); + +/* write filter roll-off setting to DAC over I2C, synchronously */ +void es9018k2m_set_filter_roll_off(int value); /* writes a single register */ /* returns I2C_STATUS_OK upon success, I2C_STATUS_* errors upon error */ diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/audiohw-erosqnative.c b/firmware/target/mips/ingenic_x1000/erosqnative/audiohw-erosqnative.c index 1e3e7f0b7f..df97aba0c8 100644 --- a/firmware/target/mips/ingenic_x1000/erosqnative/audiohw-erosqnative.c +++ b/firmware/target/mips/ingenic_x1000/erosqnative/audiohw-erosqnative.c @@ -162,7 +162,7 @@ void audiohw_set_volume(int vol_l, int vol_r) /* set software volume just below unity due to * DAC offset. We don't want to overflow the PCM system. */ pcm_set_master_volume(-1, -1); - es9018k2m_set_volume(l, r); + es9018k2m_set_volume_async(l, r); } else /* PCM5102A */ { @@ -171,4 +171,12 @@ void audiohw_set_volume(int vol_l, int vol_r) pcm_set_master_volume(l, r); } +} + +void audiohw_set_filter_roll_off(int value) +{ + if (es9018k2m_present_flag) + { + es9018k2m_set_filter_roll_off(value); + } } \ No newline at end of file -- cgit v1.2.3