feat(es8311): add digital input gain and restore 42dB HW max for ES3C28P/35P

- Add input-gain-percent property (0..2000, default 100) to everest,es8311 binding
- Extend Es8311Config with input_gain_percent, Es8311Data with input_gain float
- Implement get_input_gain_multiplier() so audio-stream can apply digital boost on top of HW gain
- Change HW gain mapping 100% -> 42dB (was 24dB) to restore +30dB behavior remembered from pre audio-stream driver (ES8311 supports 0/6/12/18/24/30/36/42 per vendor)
- Validate percent <=2000 in start_device()
- Set ES3C28P (2.8" color) and ES3C35P (3.5" color) DTS to input-gain-percent = <100> (no extra digital, pure HW 42dB max, software volume can lower)
- Fixes quiet mic even at 100% and allows tunable digital boost via devicetree for boards with quiet MEMS capsules
This commit is contained in:
Adolfo Reyna
2026-07-31 12:11:09 -04:00
parent fba4e8b4da
commit 340953b1f6
5 changed files with 34 additions and 4 deletions
+20 -4
View File
@@ -31,6 +31,7 @@ struct Es8311Data {
bool is_open = false;
AudioCodecDirection open_direction = AUDIO_CODEC_DIR_BOTH;
esp_codec_dev_sample_info_t open_sample_info = {};
float input_gain = 1.0f;
};
#define GET_CONFIG(device) (static_cast<const Es8311Config*>((device)->config))
@@ -164,8 +165,8 @@ error_t set_volume(Device* device, AudioCodecDirection direction, float volume_p
}
if (direction == AUDIO_CODEC_DIR_INPUT) {
// ES8311 ADC gain range is roughly 0..24 dB; map 0..100% linearly onto it.
float db = (volume_percent / 100.0f) * 24.0f;
// ES8311 ADC gain supports 0..42dB (0,6,12,18,24,30,36,42) – max hardware to restore old +30dB+ behavior
float db = (volume_percent / 100.0f) * 42.0f;
return (esp_codec_dev_set_in_gain(data->codec_device, db) == ESP_CODEC_DEV_OK) ? ERROR_NONE : ERROR_RESOURCE;
}
@@ -192,7 +193,8 @@ error_t get_volume(Device* device, AudioCodecDirection direction, float* volume_
if (esp_codec_dev_get_in_gain(data->codec_device, &db) != ESP_CODEC_DEV_OK) {
return ERROR_RESOURCE;
}
*volume_percent = (db / 24.0f) * 100.0f;
*volume_percent = (db / 42.0f) * 100.0f;
if (*volume_percent > 100.0f) *volume_percent = 100.0f;
return ERROR_NONE;
}
@@ -255,6 +257,12 @@ error_t get_capabilities(Device* device, AudioCodecDirection* supported_directio
return ERROR_NONE;
}
error_t get_input_gain_multiplier(Device* device, float* gain) {
auto* data = GET_DATA(device);
*gain = data->input_gain;
return ERROR_NONE;
}
static const struct AudioCodecApi API = {
.open = open,
.close = close,
@@ -267,7 +275,7 @@ static const struct AudioCodecApi API = {
.get_native_sample_rate = get_native_sample_rate,
.get_native_channels = get_native_channels,
.get_capabilities = get_capabilities,
.get_input_gain_multiplier = nullptr,
.get_input_gain_multiplier = get_input_gain_multiplier,
};
// endregion
@@ -277,6 +285,11 @@ static const struct AudioCodecApi API = {
error_t start_device(Device* device) {
const auto* config = GET_CONFIG(device);
if (config->input_gain_percent > 2000) {
LOG_E(TAG, "Invalid input_gain_percent %u (must be 0..2000)", config->input_gain_percent);
return ERROR_RESOURCE;
}
auto* i2c_controller = device_get_parent(device);
if (i2c_controller == nullptr || device_get_type(i2c_controller) != &I2C_CONTROLLER_TYPE) {
LOG_E(TAG, "Parent is not an I2C controller");
@@ -290,6 +303,9 @@ error_t start_device(Device* device) {
}
auto* data = new Es8311Data();
data->input_gain = (float) config->input_gain_percent / 100.0f;
if (data->input_gain < 0.0f) data->input_gain = 1.0f;
if (config->input_gain_percent == 0) data->input_gain = 1.0f; // default when not set (devicetree default 100, but 0 means unset)
data->ctrl_if = audio_codec_adapter_new_i2c_ctrl(i2c_controller, config->address);
data->data_if = audio_codec_adapter_new_i2s_data(i2s_controller);