diff --git a/drivers/audio/CMakeLists.txt b/drivers/audio/CMakeLists.txt index 71410a6f31d36..76d4d1bffe031 100644 --- a/drivers/audio/CMakeLists.txt +++ b/drivers/audio/CMakeLists.txt @@ -16,5 +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_CODEC_AW88298 aw88298.c) -zephyr_library_sources_ifdef(CONFIG_AUDIO_CODEC_ES7210 es7210.c) zephyr_library_sources_ifdef(CONFIG_AUDIO_DMIC_AMBIQ_PDM dmic_ambiq_pdm.c) +zephyr_library_sources_ifdef(CONFIG_AUDIO_DMIC_ES7210 dmic_es7210.c) diff --git a/drivers/audio/Kconfig b/drivers/audio/Kconfig index cb92edc0f26e0..b13ecee8034d3 100644 --- a/drivers/audio/Kconfig +++ b/drivers/audio/Kconfig @@ -37,7 +37,6 @@ source "subsys/logging/Kconfig.template.log_config" source "drivers/audio/Kconfig.aw88298" source "drivers/audio/Kconfig.cs43l22" -source "drivers/audio/Kconfig.es7210" source "drivers/audio/Kconfig.max98091" source "drivers/audio/Kconfig.pcm1681" source "drivers/audio/Kconfig.tas6422dac" @@ -69,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_es7210" endif # AUDIO_DMIC diff --git a/drivers/audio/Kconfig.dmic_es7210 b/drivers/audio/Kconfig.dmic_es7210 new file mode 100644 index 0000000000000..d16febdbe671a --- /dev/null +++ b/drivers/audio/Kconfig.dmic_es7210 @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: Apache-2.0 + +config AUDIO_DMIC_ES7210 +bool "Everest Semiconductor ES7210 digital microphone" +depends on I2C +depends on I2S +depends on DT_HAS_EVEREST_ES7210_DMIC_ENABLED +help + Enable support for the Everest Semiconductor ES7210 audio ADC as a + digital microphone source. The driver configures the converter over + I2C and streams audio over an I2S interface. + +config ES7210_DMIC_I2S_TIMEOUT_MS +int "I2S read timeout (ms)" +depends on AUDIO_DMIC_ES7210 +default 2000 +help + Timeout, in milliseconds, used for I2S read operations performed + by the ES7210 digital microphone driver. diff --git a/drivers/audio/Kconfig.es7210 b/drivers/audio/Kconfig.es7210 deleted file mode 100644 index a66ed79c9bd46..0000000000000 --- a/drivers/audio/Kconfig.es7210 +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -config AUDIO_CODEC_ES7210 -bool "Everest Semiconductor ES7210 audio ADC" -depends on I2C -select AUDIO -depends on DT_HAS_EVEREST_ES7210_ENABLED -help - Enable driver support for the Everest Semiconductor ES7210 - quad-channel audio analog-to-digital converter. This device - provides the front microphones on the M5Stack CoreS3 family. diff --git a/drivers/audio/dmic_es7210.c b/drivers/audio/dmic_es7210.c new file mode 100644 index 0000000000000..97217693ce9c4 --- /dev/null +++ b/drivers/audio/dmic_es7210.c @@ -0,0 +1,764 @@ +/* + * Copyright (c) 2025 The Zephyr Authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT everest_es7210_dmic + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "es7210.h" + +LOG_MODULE_REGISTER(es7210_dmic, CONFIG_AUDIO_DMIC_LOG_LEVEL); + +struct es7210_dmic_codec_config { + struct i2c_dt_spec i2c; + uint32_t mclk_freq; + uint8_t mic_select; + uint8_t mic_gain; +}; + +struct es7210_dmic_codec_data { + uint8_t clock_off_value; + uint8_t mic_select; + uint8_t mic_gain; + uint32_t mclk; + uint32_t sample_rate; + bool muted; + bool started; +}; + +struct es7210_dmic_config { + const struct device *i2s_dev; + i2s_opt_t i2s_options; + uint8_t data_format; + bool bit_clk_inverted; + int32_t timeout_ms; + struct es7210_dmic_codec_config codec; +}; + +struct es7210_dmic_data { + enum dmic_state state; + struct k_mem_slab *mem_slab; + size_t block_size; + uint32_t pcm_rate; + uint8_t pcm_width; + uint8_t num_channels; + struct es7210_dmic_codec_data codec; +}; + +static inline const struct es7210_dmic_config *dev_cfg(const struct device *dev) +{ + return dev->config; +} + +static inline struct es7210_dmic_data *dev_data(const struct device *dev) +{ + return dev->data; +} + +static int es7210_write_reg(const struct device *dev, uint8_t reg, uint8_t val) +{ + const struct es7210_dmic_config *conf = dev_cfg(dev); + int ret = i2c_reg_write_byte_dt(&conf->codec.i2c, reg, val); + + if (ret < 0) { + LOG_ERR("Failed to write reg 0x%02x", reg); + } + + return ret; +} + +static int es7210_read_reg(const struct device *dev, uint8_t reg, uint8_t *val) +{ + const struct es7210_dmic_config *conf = dev_cfg(dev); + int ret = i2c_reg_read_byte_dt(&conf->codec.i2c, reg, val); + + if (ret < 0) { + LOG_ERR("Failed to read reg 0x%02x", reg); + } + + return ret; +} + +static int es7210_update_bits(const struct device *dev, uint8_t reg, uint8_t mask, uint8_t value) +{ + uint8_t cur; + int ret = es7210_read_reg(dev, reg, &cur); + + if (ret < 0) { + return ret; + } + + uint8_t new_val = (cur & ~mask) | (value & mask); + + if (new_val == cur) { + return 0; + } + + return es7210_write_reg(dev, reg, new_val); +} + +struct es7210_coeff { + uint32_t mclk; + uint32_t lrck; + uint8_t adc_div; + uint8_t dll; + uint8_t doubler; + uint8_t osr; + uint8_t lrck_h; + uint8_t lrck_l; +}; + +static const struct es7210_coeff es7210_clk_coeffs[] = { + {12288000U, 8000U, 0x03, 0x01, 0x00, 0x20, 0x06, 0x00}, + {16384000U, 8000U, 0x04, 0x01, 0x00, 0x20, 0x08, 0x00}, + {19200000U, 8000U, 0x1e, 0x00, 0x01, 0x28, 0x09, 0x60}, + {4096000U, 8000U, 0x01, 0x01, 0x00, 0x20, 0x02, 0x00}, + {11289600U, 11025U, 0x02, 0x01, 0x00, 0x20, 0x01, 0x00}, + {12288000U, 12000U, 0x02, 0x01, 0x00, 0x20, 0x04, 0x00}, + {19200000U, 12000U, 0x14, 0x00, 0x01, 0x28, 0x06, 0x40}, + {4096000U, 16000U, 0x01, 0x01, 0x01, 0x20, 0x01, 0x00}, + {19200000U, 16000U, 0x0a, 0x00, 0x00, 0x1e, 0x04, 0x80}, + {16384000U, 16000U, 0x02, 0x01, 0x00, 0x20, 0x04, 0x00}, + {12288000U, 16000U, 0x03, 0x01, 0x01, 0x20, 0x03, 0x00}, + {11289600U, 22050U, 0x01, 0x01, 0x00, 0x20, 0x02, 0x00}, + {12288000U, 24000U, 0x01, 0x01, 0x00, 0x20, 0x02, 0x00}, + {19200000U, 24000U, 0x0a, 0x00, 0x01, 0x28, 0x03, 0x20}, + {12288000U, 32000U, 0x03, 0x00, 0x00, 0x20, 0x01, 0x80}, + {16384000U, 32000U, 0x01, 0x01, 0x00, 0x20, 0x02, 0x00}, + {19200000U, 32000U, 0x05, 0x00, 0x00, 0x1e, 0x02, 0x58}, + {11289600U, 44100U, 0x01, 0x01, 0x01, 0x20, 0x01, 0x00}, + {12288000U, 48000U, 0x01, 0x01, 0x01, 0x20, 0x01, 0x00}, + {19200000U, 48000U, 0x05, 0x00, 0x01, 0x28, 0x01, 0x90}, + {16384000U, 64000U, 0x01, 0x01, 0x00, 0x20, 0x01, 0x00}, + {19200000U, 64000U, 0x05, 0x00, 0x01, 0x1e, 0x01, 0x2c}, + {11289600U, 88200U, 0x01, 0x01, 0x01, 0x20, 0x00, 0x80}, + {12288000U, 96000U, 0x01, 0x01, 0x01, 0x20, 0x00, 0x80}, + {19200000U, 96000U, 0x05, 0x00, 0x01, 0x28, 0x00, 0xC8}, +}; + +static const struct es7210_coeff *es7210_find_coeff(uint32_t mclk, uint32_t lrck) +{ + for (size_t i = 0U; i < ARRAY_SIZE(es7210_clk_coeffs); i++) { + if (es7210_clk_coeffs[i].mclk == mclk && es7210_clk_coeffs[i].lrck == lrck) { + return &es7210_clk_coeffs[i]; + } + } + + return NULL; +} + +static int es7210_reset(const struct device *dev) +{ + int ret = es7210_write_reg(dev, ES7210_RESET_REG00, 0xFF); + + if (ret < 0) { + return ret; + } + + k_msleep(5); + + ret = es7210_write_reg(dev, ES7210_RESET_REG00, 0x41); + if (ret < 0) { + return ret; + } + + k_msleep(2); + + return 0; +} + +static int es7210_config_sample_rate(const struct device *dev, uint32_t mclk, uint32_t lrck) +{ + const struct es7210_coeff *coeff = es7210_find_coeff(mclk, lrck); + + if (coeff == NULL) { + LOG_ERR("Unsupported sample rate %u Hz with MCLK %u Hz", lrck, mclk); + return -EINVAL; + } + + int ret = es7210_write_reg(dev, ES7210_MAINCLK_REG02, + coeff->adc_div | (coeff->doubler << 6) | (coeff->dll << 7)); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_OSR_REG07, coeff->osr); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_LRCK_DIVH_REG04, coeff->lrck_h); + if (ret < 0) { + return ret; + } + + return es7210_write_reg(dev, ES7210_LRCK_DIVL_REG05, coeff->lrck_l); +} + +static int es7210_config_format(const struct device *dev, i2s_fmt_t format, uint8_t word_size) +{ + uint8_t reg; + int ret = es7210_read_reg(dev, ES7210_SDP_INTERFACE1_REG11, ®); + + if (ret < 0) { + return ret; + } + + reg &= ~0x03U; + + switch (format & I2S_FMT_DATA_FORMAT_MASK) { + case I2S_FMT_DATA_FORMAT_I2S: + break; + case I2S_FMT_DATA_FORMAT_LEFT_JUSTIFIED: + case I2S_FMT_DATA_FORMAT_RIGHT_JUSTIFIED: + reg |= 0x01; + break; + default: + LOG_ERR("Unsupported I2S data format 0x%08x", format); + return -ENOTSUP; + } + + reg &= ~0xE0U; + + switch (word_size) { + case 16U: + reg |= 0x60; + break; + case 24U: + reg |= 0x00; + break; + case 32U: + reg |= 0x80; + break; + default: + LOG_WRN("Unsupported word size %u bits, falling back to 16 bits", word_size); + reg |= 0x60; + break; + } + + return es7210_write_reg(dev, ES7210_SDP_INTERFACE1_REG11, reg); +} + +static int es7210_apply_gain(const struct device *dev) +{ + struct es7210_dmic_data *data = dev_data(dev); + uint8_t gain = MIN(data->codec.mic_gain, ES7210_MAX_GAIN_STEP) & 0x0FU; + uint8_t value = 0x10 | gain; + int ret = es7210_write_reg(dev, ES7210_MIC1_GAIN_REG43, value); + + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_MIC2_GAIN_REG44, value); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_MIC3_GAIN_REG45, 0x00); + if (ret < 0) { + return ret; + } + + return es7210_write_reg(dev, ES7210_MIC4_GAIN_REG46, 0x00); +} + +static int es7210_apply_mute(const struct device *dev, bool mute) +{ + uint8_t mask = 0x03; + uint8_t value = mute ? mask : 0x00; + int ret = es7210_update_bits(dev, ES7210_ADC34_MUTERANGE_REG14, mask, value); + + if (ret < 0) { + return ret; + } + + return es7210_update_bits(dev, ES7210_ADC12_MUTERANGE_REG15, mask, value); +} + +static int es7210_start_stream(const struct device *dev) +{ + struct es7210_dmic_data *data = dev_data(dev); + int ret = es7210_write_reg(dev, ES7210_CLOCK_OFF_REG01, data->codec.clock_off_value); + + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_POWER_DOWN_REG06, 0x00); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_ANALOG_REG40, 0x42); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_MIC1_POWER_REG47, 0x00); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_MIC2_POWER_REG48, 0x00); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_MIC3_POWER_REG49, 0x00); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_MIC4_POWER_REG4A, 0x00); + if (ret < 0) { + return ret; + } + + uint8_t mic12 = (data->codec.mic_select & (ES7210_MIC1_BIT | ES7210_MIC2_BIT)) ? 0x00 : 0xFF; + uint8_t mic34 = (data->codec.mic_select & (ES7210_MIC3_BIT | ES7210_MIC4_BIT)) ? 0x00 : 0xFF; + + ret = es7210_write_reg(dev, ES7210_MIC12_POWER_REG4B, mic12); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_MIC34_POWER_REG4C, mic34); + if (ret < 0) { + return ret; + } + + data->codec.started = true; + + return 0; +} + +static int es7210_stop_stream(const struct device *dev) +{ + int ret = es7210_write_reg(dev, ES7210_MIC1_POWER_REG47, 0xFF); + + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_MIC2_POWER_REG48, 0xFF); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_MIC3_POWER_REG49, 0xFF); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_MIC4_POWER_REG4A, 0xFF); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_MIC12_POWER_REG4B, 0xFF); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_MIC34_POWER_REG4C, 0xFF); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_ANALOG_REG40, 0xC0); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_CLOCK_OFF_REG01, 0x1F); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_POWER_DOWN_REG06, 0x07); + if (ret < 0) { + return ret; + } + + dev_data(dev)->codec.started = false; + + return 0; +} + +static i2s_fmt_t es7210_dmic_format_from_idx(uint8_t idx) +{ + switch (idx) { + case 1: + return I2S_FMT_DATA_FORMAT_LEFT_JUSTIFIED; + case 2: + return I2S_FMT_DATA_FORMAT_RIGHT_JUSTIFIED; + case 0: + default: + return I2S_FMT_DATA_FORMAT_I2S; + } +} + +static int es7210_dmic_configure(const struct device *dev, struct dmic_cfg *cfg) +{ + const struct es7210_dmic_config *conf = dev_cfg(dev); + struct es7210_dmic_data *data = dev_data(dev); + struct pcm_stream_cfg *stream = &cfg->streams[0]; + i2s_fmt_t format; + struct i2s_config i2s_cfg; + uint32_t mclk; + int ret; + + if (cfg->channel.req_num_streams == 0U) { + return -EINVAL; + } + + if (cfg->channel.req_num_streams > 1U) { + return -ENOTSUP; + } + + if (stream->pcm_rate == 0U || stream->pcm_width == 0U || stream->block_size == 0U || + stream->mem_slab == NULL) { + return -EINVAL; + } + + data->mem_slab = stream->mem_slab; + data->block_size = stream->block_size; + data->pcm_rate = stream->pcm_rate; + data->pcm_width = stream->pcm_width; + data->num_channels = cfg->channel.req_num_chan; + + format = es7210_dmic_format_from_idx(conf->data_format); + if (conf->bit_clk_inverted) { + format |= I2S_FMT_BIT_CLK_INV; + } + + mclk = conf->codec.mclk_freq; + if (mclk == 0U) { + mclk = stream->pcm_rate * 256U; + } + + data->codec.mclk = mclk; + data->codec.sample_rate = stream->pcm_rate; + data->codec.mic_select = conf->codec.mic_select; + data->codec.mic_gain = conf->codec.mic_gain; + data->codec.clock_off_value = 0x14; + data->codec.muted = false; + + ret = es7210_reset(dev); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_CLOCK_OFF_REG01, 0x1F); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_POWER_DOWN_REG06, 0x00); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_TIME_CONTROL0_REG09, 0x30); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_TIME_CONTROL1_REG0A, 0x30); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_ADC34_HPF2_REG20, 0x0A); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_ADC34_HPF1_REG21, 0x2A); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_ADC12_HPF2_REG22, 0x0A); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_ADC12_HPF1_REG23, 0x2A); + if (ret < 0) { + return ret; + } + + uint8_t mode = 0x10; + uint32_t master_mask = I2S_OPT_FRAME_CLK_MASTER | I2S_OPT_BIT_CLK_MASTER; + uint32_t opt = conf->i2s_options & master_mask; + + if (opt == master_mask) { + mode |= 0x01; + } else if (opt != 0U) { + LOG_ERR("Inconsistent master configuration (options: 0x%08x)", conf->i2s_options); + return -EINVAL; + } + + ret = es7210_write_reg(dev, ES7210_MODE_CONFIG_REG08, mode); + if (ret < 0) { + return ret; + } + + ret = es7210_config_sample_rate(dev, data->codec.mclk, stream->pcm_rate); + if (ret < 0) { + return ret; + } + + ret = es7210_config_format(dev, format, stream->pcm_width); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_ANALOG_REG40, 0x42); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_MIC12_BIAS_REG41, 0x70); + if (ret < 0) { + return ret; + } + + ret = es7210_write_reg(dev, ES7210_MIC34_BIAS_REG42, 0x70); + if (ret < 0) { + return ret; + } + + ret = es7210_apply_gain(dev); + if (ret < 0) { + return ret; + } + + ret = es7210_apply_mute(dev, data->codec.muted); + if (ret < 0) { + return ret; + } + + ret = es7210_stop_stream(dev); + if (ret < 0) { + return ret; + } + + i2s_cfg.word_size = stream->pcm_width; + i2s_cfg.channels = cfg->channel.req_num_chan; + i2s_cfg.format = format; + i2s_cfg.options = conf->i2s_options; + i2s_cfg.frame_clk_freq = stream->pcm_rate; + i2s_cfg.mem_slab = stream->mem_slab; + i2s_cfg.block_size = stream->block_size; + i2s_cfg.timeout = conf->timeout_ms; + + ret = i2s_configure(conf->i2s_dev, I2S_DIR_RX, &i2s_cfg); + if (ret < 0) { + LOG_ERR("Failed to configure I2S RX (%d)", ret); + return ret; + } + + cfg->channel.act_num_chan = cfg->channel.req_num_chan; + cfg->channel.act_chan_map_lo = cfg->channel.req_chan_map_lo; + cfg->channel.act_chan_map_hi = cfg->channel.req_chan_map_hi; + cfg->channel.act_num_streams = 1U; + + data->state = DMIC_STATE_CONFIGURED; + + return 0; +} + +static int es7210_dmic_trigger(const struct device *dev, enum dmic_trigger cmd) +{ + const struct es7210_dmic_config *conf = dev_cfg(dev); + struct es7210_dmic_data *data = dev_data(dev); + int ret = 0; + + switch (cmd) { + case DMIC_TRIGGER_START: + if (data->state != DMIC_STATE_CONFIGURED && data->state != DMIC_STATE_PAUSED) { + return -EIO; + } + + ret = es7210_start_stream(dev); + if (ret < 0) { + return ret; + } + + ret = i2s_trigger(conf->i2s_dev, I2S_DIR_RX, I2S_TRIGGER_START); + if (ret < 0) { + es7210_stop_stream(dev); + return ret; + } + + data->state = DMIC_STATE_ACTIVE; + break; + + case DMIC_TRIGGER_STOP: + if (data->state != DMIC_STATE_ACTIVE && data->state != DMIC_STATE_PAUSED) { + return 0; + } + + ret = i2s_trigger(conf->i2s_dev, I2S_DIR_RX, I2S_TRIGGER_STOP); + if (ret < 0) { + return ret; + } + + ret = es7210_stop_stream(dev); + if (ret < 0) { + return ret; + } + data->state = DMIC_STATE_CONFIGURED; + break; + + case DMIC_TRIGGER_PAUSE: + if (data->state != DMIC_STATE_ACTIVE) { + return 0; + } + + ret = i2s_trigger(conf->i2s_dev, I2S_DIR_RX, I2S_TRIGGER_STOP); + if (ret < 0) { + return ret; + } + + ret = es7210_stop_stream(dev); + if (ret < 0) { + return ret; + } + data->state = DMIC_STATE_PAUSED; + break; + + case DMIC_TRIGGER_RELEASE: + if (data->state != DMIC_STATE_PAUSED) { + return -EIO; + } + + ret = es7210_start_stream(dev); + if (ret < 0) { + return ret; + } + + ret = i2s_trigger(conf->i2s_dev, I2S_DIR_RX, I2S_TRIGGER_START); + if (ret < 0) { + es7210_stop_stream(dev); + return ret; + } + + data->state = DMIC_STATE_ACTIVE; + break; + + case DMIC_TRIGGER_RESET: + i2s_trigger(conf->i2s_dev, I2S_DIR_RX, I2S_TRIGGER_DROP); + es7210_stop_stream(dev); + data->state = DMIC_STATE_CONFIGURED; + break; + + default: + return -EINVAL; + } + + return ret; +} + +static int es7210_dmic_read(const struct device *dev, uint8_t stream, void **buffer, size_t *size, + int32_t timeout) +{ + const struct es7210_dmic_config *conf = dev_cfg(dev); + struct es7210_dmic_data *data = dev_data(dev); + int ret; + size_t block_size; + + ARG_UNUSED(stream); + + if (data->state != DMIC_STATE_ACTIVE && data->state != DMIC_STATE_PAUSED) { + return -EIO; + } + + if ((timeout != SYS_FOREVER_MS) && (timeout != conf->timeout_ms)) { + LOG_DBG("Unsupported timeout %d ms", timeout); + } + + ret = i2s_read(conf->i2s_dev, buffer, &block_size); + if (ret < 0) { + return ret; + } + + if (size != NULL) { + *size = block_size; + } + + return 0; +} + +static const struct _dmic_ops es7210_dmic_api = { + .configure = es7210_dmic_configure, + .trigger = es7210_dmic_trigger, + .read = es7210_dmic_read, +}; + +static int es7210_dmic_init(const struct device *dev) +{ + const struct es7210_dmic_config *conf = dev_cfg(dev); + struct es7210_dmic_data *data = dev_data(dev); + + if (!device_is_ready(conf->i2s_dev)) { + LOG_ERR("I2S device is not ready"); + return -ENODEV; + } + + if (!device_is_ready(conf->codec.i2c.bus)) { + LOG_ERR("ES7210 control bus is not ready"); + return -ENODEV; + } + + data->state = DMIC_STATE_INITIALIZED; + + return 0; +} + +#define ES7210_DMIC_OPTIONS(inst) \ + ((DT_INST_PROP(inst, bit_clock_master) ? I2S_OPT_BIT_CLK_SLAVE : I2S_OPT_BIT_CLK_MASTER) | \ + (DT_INST_PROP(inst, frame_clock_master) ? I2S_OPT_FRAME_CLK_SLAVE \ + : I2S_OPT_FRAME_CLK_MASTER)) + +#define ES7210_DMIC_CODEC_NODE(inst) DT_INST_PHANDLE(inst, codec) \ + +#define ES7210_DMIC_INIT(inst) \ + static struct es7210_dmic_data es7210_dmic_data_##inst; \ + static const struct es7210_dmic_config es7210_dmic_config_##inst = { \ + .i2s_dev = DEVICE_DT_GET(DT_INST_BUS(inst)), \ + .i2s_options = ES7210_DMIC_OPTIONS(inst), \ + .data_format = DT_INST_ENUM_IDX_OR(inst, data_format, 0), \ + .bit_clk_inverted = DT_INST_PROP_OR(inst, bit_clock_inverted, false), \ + .timeout_ms = \ + DT_INST_PROP_OR(inst, timeout_ms, CONFIG_ES7210_DMIC_I2S_TIMEOUT_MS), \ + .codec = { \ + .i2c = I2C_DT_SPEC_GET(ES7210_DMIC_CODEC_NODE(inst)), \ + .mclk_freq = \ + DT_PROP_OR(ES7210_DMIC_CODEC_NODE(inst), mclk_frequency, 0), \ + .mic_select = \ + DT_PROP_OR(ES7210_DMIC_CODEC_NODE(inst), \ + mic_select, ES7210_MIC1_BIT | ES7210_MIC2_BIT), \ + .mic_gain = DT_PROP_OR(ES7210_DMIC_CODEC_NODE(inst), mic_gain, 11), \ + }, \ + }; \ + DEVICE_DT_INST_DEFINE(inst, es7210_dmic_init, NULL, &es7210_dmic_data_##inst, \ + &es7210_dmic_config_##inst, POST_KERNEL, \ + CONFIG_AUDIO_DMIC_INIT_PRIORITY, &es7210_dmic_api); + +DT_INST_FOREACH_STATUS_OKAY(ES7210_DMIC_INIT) diff --git a/drivers/audio/es7210.c b/drivers/audio/es7210.c deleted file mode 100644 index 91c7f3abe0152..0000000000000 --- a/drivers/audio/es7210.c +++ /dev/null @@ -1,649 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include - -#include "es7210.h" - -LOG_MODULE_REGISTER(everest_es7210, CONFIG_AUDIO_CODEC_LOG_LEVEL); - -#define DT_DRV_COMPAT everest_es7210 - -struct es7210_config { - struct i2c_dt_spec i2c; - uint32_t mclk_freq; - uint8_t mic_select; - uint8_t mic_gain; -}; - -struct es7210_data { - uint8_t clock_off_value; - uint8_t mic_select; - uint8_t mic_gain; - uint32_t mclk; - uint32_t sample_rate; - bool muted; - bool started; -}; - -struct es7210_coeff { - uint32_t mclk; - uint32_t lrck; - uint8_t adc_div; - uint8_t dll; - uint8_t doubler; - uint8_t osr; - uint8_t lrck_h; - uint8_t lrck_l; -}; - -static const struct es7210_coeff es7210_clk_coeffs[] = { - {12288000U, 8000U, 0x03, 0x01, 0x00, 0x20, 0x06, 0x00}, - {16384000U, 8000U, 0x04, 0x01, 0x00, 0x20, 0x08, 0x00}, - {19200000U, 8000U, 0x1e, 0x00, 0x01, 0x28, 0x09, 0x60}, - {4096000U, 8000U, 0x01, 0x01, 0x00, 0x20, 0x02, 0x00}, - {11289600U, 11025U, 0x02, 0x01, 0x00, 0x20, 0x01, 0x00}, - {12288000U, 12000U, 0x02, 0x01, 0x00, 0x20, 0x04, 0x00}, - {19200000U, 12000U, 0x14, 0x00, 0x01, 0x28, 0x06, 0x40}, - {4096000U, 16000U, 0x01, 0x01, 0x01, 0x20, 0x01, 0x00}, - {19200000U, 16000U, 0x0a, 0x00, 0x00, 0x1e, 0x04, 0x80}, - {16384000U, 16000U, 0x02, 0x01, 0x00, 0x20, 0x04, 0x00}, - {12288000U, 16000U, 0x03, 0x01, 0x01, 0x20, 0x03, 0x00}, - {11289600U, 22050U, 0x01, 0x01, 0x00, 0x20, 0x02, 0x00}, - {12288000U, 24000U, 0x01, 0x01, 0x00, 0x20, 0x02, 0x00}, - {19200000U, 24000U, 0x0a, 0x00, 0x01, 0x28, 0x03, 0x20}, - {12288000U, 32000U, 0x03, 0x00, 0x00, 0x20, 0x01, 0x80}, - {16384000U, 32000U, 0x01, 0x01, 0x00, 0x20, 0x02, 0x00}, - {19200000U, 32000U, 0x05, 0x00, 0x00, 0x1e, 0x02, 0x58}, - {11289600U, 44100U, 0x01, 0x01, 0x01, 0x20, 0x01, 0x00}, - {12288000U, 48000U, 0x01, 0x01, 0x01, 0x20, 0x01, 0x00}, - {19200000U, 48000U, 0x05, 0x00, 0x01, 0x28, 0x01, 0x90}, - {16384000U, 64000U, 0x01, 0x01, 0x00, 0x20, 0x01, 0x00}, - {19200000U, 64000U, 0x05, 0x00, 0x01, 0x1e, 0x01, 0x2c}, - {11289600U, 88200U, 0x01, 0x01, 0x01, 0x20, 0x00, 0x80}, - {12288000U, 96000U, 0x01, 0x01, 0x01, 0x20, 0x00, 0x80}, - {19200000U, 96000U, 0x05, 0x00, 0x01, 0x28, 0x00, 0xC8}, -}; - -static inline const struct es7210_config *dev_cfg(const struct device *dev) -{ - return dev->config; -} - -static inline struct es7210_data *dev_data(const struct device *dev) -{ - return dev->data; -} - -static int es7210_write_reg(const struct device *dev, uint8_t reg, uint8_t val) -{ - int ret = i2c_reg_write_byte_dt(&dev_cfg(dev)->i2c, reg, val); - - if (ret < 0) { - LOG_ERR("Failed to write reg 0x%02x", reg); - } - - return ret; -} - -static int es7210_read_reg(const struct device *dev, uint8_t reg, uint8_t *val) -{ - int ret = i2c_reg_read_byte_dt(&dev_cfg(dev)->i2c, reg, val); - - if (ret < 0) { - LOG_ERR("Failed to read reg 0x%02x", reg); - } - - return ret; -} - -static int es7210_update_bits(const struct device *dev, uint8_t reg, uint8_t mask, uint8_t value) -{ - uint8_t cur; - int ret = es7210_read_reg(dev, reg, &cur); - - if (ret < 0) { - return ret; - } - - uint8_t new_val = (cur & ~mask) | (value & mask); - - if (new_val == cur) { - return 0; - } - - return es7210_write_reg(dev, reg, new_val); -} - -static const struct es7210_coeff *es7210_find_coeff(uint32_t mclk, uint32_t lrck) -{ - for (size_t i = 0U; i < ARRAY_SIZE(es7210_clk_coeffs); i++) { - if (es7210_clk_coeffs[i].mclk == mclk && es7210_clk_coeffs[i].lrck == lrck) { - return &es7210_clk_coeffs[i]; - } - } - - return NULL; -} - -static int es7210_reset(const struct device *dev) -{ - int ret = es7210_write_reg(dev, ES7210_RESET_REG00, 0xFF); - - if (ret < 0) { - return ret; - } - - k_msleep(5); - - ret = es7210_write_reg(dev, ES7210_RESET_REG00, 0x41); - if (ret < 0) { - return ret; - } - - k_msleep(2); - - return 0; -} - -static int es7210_config_sample_rate(const struct device *dev, uint32_t mclk, uint32_t lrck) -{ - const struct es7210_coeff *coeff = es7210_find_coeff(mclk, lrck); - - if (coeff == NULL) { - LOG_ERR("Unsupported sample rate %u Hz with MCLK %u Hz", lrck, mclk); - return -EINVAL; - } - - int ret = es7210_write_reg(dev, ES7210_MAINCLK_REG02, - coeff->adc_div | (coeff->doubler << 6) | (coeff->dll << 7)); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_OSR_REG07, coeff->osr); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_LRCK_DIVH_REG04, coeff->lrck_h); - if (ret < 0) { - return ret; - } - - return es7210_write_reg(dev, ES7210_LRCK_DIVL_REG05, coeff->lrck_l); -} - -static int es7210_config_format(const struct device *dev, audio_dai_cfg_t *cfg) -{ - uint8_t reg; - int ret = es7210_read_reg(dev, ES7210_SDP_INTERFACE1_REG11, ®); - - if (ret < 0) { - return ret; - } - - reg &= ~0x03U; - - switch (cfg->i2s.format & I2S_FMT_DATA_FORMAT_MASK) { - case I2S_FMT_DATA_FORMAT_I2S: - break; - case I2S_FMT_DATA_FORMAT_LEFT_JUSTIFIED: - case I2S_FMT_DATA_FORMAT_RIGHT_JUSTIFIED: - reg |= 0x01; - break; - default: - LOG_ERR("Unsupported I2S data format 0x%08x", cfg->i2s.format); - return -ENOTSUP; - } - - reg &= ~0xE0U; - - switch (cfg->i2s.word_size) { - case 16U: - reg |= 0x60; - break; - case 24U: - reg |= 0x00; - break; - case 32U: - reg |= 0x80; - break; - default: - LOG_WRN("Unsupported word size %u bits, falling back to 16 bits", - cfg->i2s.word_size); - reg |= 0x60; - break; - } - - return es7210_write_reg(dev, ES7210_SDP_INTERFACE1_REG11, reg); -} - -static int es7210_apply_gain(const struct device *dev) -{ - struct es7210_data *data = dev_data(dev); - uint8_t gain = MIN(data->mic_gain, ES7210_MAX_GAIN_STEP) & 0x0FU; - uint8_t value = 0x10 | gain; - int ret = es7210_write_reg(dev, ES7210_MIC1_GAIN_REG43, value); - - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC2_GAIN_REG44, value); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC3_GAIN_REG45, 0x00); - if (ret < 0) { - return ret; - } - - return es7210_write_reg(dev, ES7210_MIC4_GAIN_REG46, 0x00); -} - -static int es7210_apply_mute(const struct device *dev, bool mute) -{ - uint8_t mask = 0x03; - uint8_t value = mute ? mask : 0x00; - int ret = es7210_update_bits(dev, ES7210_ADC34_MUTERANGE_REG14, mask, value); - - if (ret < 0) { - return ret; - } - - return es7210_update_bits(dev, ES7210_ADC12_MUTERANGE_REG15, mask, value); -} - -static int es7210_start_stream(const struct device *dev) -{ - struct es7210_data *data = dev_data(dev); - int ret = es7210_write_reg(dev, ES7210_CLOCK_OFF_REG01, data->clock_off_value); - - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_POWER_DOWN_REG06, 0x00); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_ANALOG_REG40, 0x42); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC1_POWER_REG47, 0x00); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC2_POWER_REG48, 0x00); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC3_POWER_REG49, 0x00); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC4_POWER_REG4A, 0x00); - if (ret < 0) { - return ret; - } - - uint8_t mic12 = (data->mic_select & (ES7210_MIC1_BIT | ES7210_MIC2_BIT)) ? 0x00 : 0xFF; - uint8_t mic34 = (data->mic_select & (ES7210_MIC3_BIT | ES7210_MIC4_BIT)) ? 0x00 : 0xFF; - - ret = es7210_write_reg(dev, ES7210_MIC12_POWER_REG4B, mic12); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC34_POWER_REG4C, mic34); - if (ret < 0) { - return ret; - } - - data->started = true; - - return 0; -} - -static int es7210_stop_stream(const struct device *dev) -{ - int ret = es7210_write_reg(dev, ES7210_MIC1_POWER_REG47, 0xFF); - - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC2_POWER_REG48, 0xFF); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC3_POWER_REG49, 0xFF); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC4_POWER_REG4A, 0xFF); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC12_POWER_REG4B, 0xFF); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC34_POWER_REG4C, 0xFF); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_ANALOG_REG40, 0xC0); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_CLOCK_OFF_REG01, 0x1F); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_POWER_DOWN_REG06, 0x07); - if (ret < 0) { - return ret; - } - - dev_data(dev)->started = false; - - return 0; -} - -static int es7210_configure(const struct device *dev, struct audio_codec_cfg *cfg) -{ - const struct es7210_config *conf = dev_cfg(dev); - struct es7210_data *data = dev_data(dev); - - if (cfg->dai_type != AUDIO_DAI_TYPE_I2S) { - return -ENOTSUP; - } - - if (cfg->dai_cfg.i2s.frame_clk_freq == 0U) { - LOG_ERR("Frame clock frequency must be provided"); - return -EINVAL; - } - - uint32_t mclk = cfg->mclk_freq ? cfg->mclk_freq : conf->mclk_freq; - - if (mclk == 0U) { - mclk = cfg->dai_cfg.i2s.frame_clk_freq * 256U; - } - - int ret = es7210_reset(dev); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_CLOCK_OFF_REG01, 0x1F); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_POWER_DOWN_REG06, 0x00); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_TIME_CONTROL0_REG09, 0x30); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_TIME_CONTROL1_REG0A, 0x30); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_ADC34_HPF2_REG20, 0x0A); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_ADC34_HPF1_REG21, 0x2A); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_ADC12_HPF2_REG22, 0x0A); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_ADC12_HPF1_REG23, 0x2A); - if (ret < 0) { - return ret; - } - - uint8_t mode = 0x10; - uint32_t master_mask = I2S_OPT_FRAME_CLK_MASTER | I2S_OPT_BIT_CLK_MASTER; - uint32_t opt = cfg->dai_cfg.i2s.options & master_mask; - - if (opt == master_mask) { - mode |= 0x01; - } else if (opt != 0U) { - LOG_ERR("Inconsistent master configuration (options: 0x%08x)", - cfg->dai_cfg.i2s.options); - return -EINVAL; - } - - ret = es7210_write_reg(dev, ES7210_MODE_CONFIG_REG08, mode); - if (ret < 0) { - return ret; - } - - ret = es7210_config_sample_rate(dev, mclk, cfg->dai_cfg.i2s.frame_clk_freq); - if (ret < 0) { - return ret; - } - - ret = es7210_config_format(dev, &cfg->dai_cfg); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_ANALOG_REG40, 0x42); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC12_BIAS_REG41, 0x70); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC34_BIAS_REG42, 0x70); - if (ret < 0) { - return ret; - } - - data->mic_gain = MIN(conf->mic_gain, ES7210_MAX_GAIN_STEP); - ret = es7210_apply_gain(dev); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC1_POWER_REG47, 0x00); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC2_POWER_REG48, 0x00); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC3_POWER_REG49, 0x00); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC4_POWER_REG4A, 0x00); - if (ret < 0) { - return ret; - } - - data->mic_select = conf->mic_select; - uint8_t mic12 = (data->mic_select & (ES7210_MIC1_BIT | ES7210_MIC2_BIT)) ? 0x00 : 0xFF; - uint8_t mic34 = (data->mic_select & (ES7210_MIC3_BIT | ES7210_MIC4_BIT)) ? 0x00 : 0xFF; - - ret = es7210_write_reg(dev, ES7210_MIC12_POWER_REG4B, mic12); - if (ret < 0) { - return ret; - } - - ret = es7210_write_reg(dev, ES7210_MIC34_POWER_REG4C, mic34); - if (ret < 0) { - return ret; - } - - data->clock_off_value = 0x14; - ret = es7210_write_reg(dev, ES7210_CLOCK_OFF_REG01, data->clock_off_value); - if (ret < 0) { - return ret; - } - - data->muted = false; - data->mclk = mclk; - data->sample_rate = cfg->dai_cfg.i2s.frame_clk_freq; - - ret = es7210_apply_mute(dev, data->muted); - if (ret < 0) { - return ret; - } - - return es7210_start_stream(dev); -} - -static void es7210_start_output(const struct device *dev) -{ - int ret = es7210_start_stream(dev); - - if (ret < 0) { - LOG_ERR("Failed to start ES7210: %d", ret); - } -} - -static void es7210_stop_output(const struct device *dev) -{ - int ret = es7210_stop_stream(dev); - - if (ret < 0) { - LOG_ERR("Failed to stop ES7210: %d", ret); - } -} - -static int es7210_set_property(const struct device *dev, audio_property_t property, - audio_channel_t channel, audio_property_value_t val) -{ - struct es7210_data *data = dev_data(dev); - - ARG_UNUSED(channel); - - switch (property) { - case AUDIO_PROPERTY_INPUT_VOLUME: - if (val.vol < 0) { - data->mic_gain = 0U; - } else if (val.vol > ES7210_MAX_GAIN_STEP) { - data->mic_gain = ES7210_MAX_GAIN_STEP; - } else { - data->mic_gain = (uint8_t)val.vol; - } - - if (!data->started) { - return 0; - } - - return es7210_apply_gain(dev); - - case AUDIO_PROPERTY_INPUT_MUTE: - data->muted = val.mute; - if (!data->started) { - return 0; - } - - return es7210_apply_mute(dev, data->muted); - - default: - return -ENOTSUP; - } -} - -static int es7210_apply_properties(const struct device *dev) -{ - int ret = es7210_apply_gain(dev); - - if (ret < 0) { - return ret; - } - - return es7210_apply_mute(dev, dev_data(dev)->muted); -} - -static int es7210_clear_errors(const struct device *dev) -{ - ARG_UNUSED(dev); - return 0; -} - -static int es7210_register_error_callback(const struct device *dev, audio_codec_error_callback_t cb) -{ - ARG_UNUSED(dev); - ARG_UNUSED(cb); - return -ENOTSUP; -} - -static int es7210_route_input(const struct device *dev, audio_channel_t channel, uint32_t input) -{ - ARG_UNUSED(dev); - ARG_UNUSED(channel); - ARG_UNUSED(input); - return 0; -} - -static const struct audio_codec_api es7210_driver_api = { - .configure = es7210_configure, - .start_output = es7210_start_output, - .stop_output = es7210_stop_output, - .set_property = es7210_set_property, - .apply_properties = es7210_apply_properties, - .clear_errors = es7210_clear_errors, - .register_error_callback = es7210_register_error_callback, - .route_input = es7210_route_input, -}; - -#define ES7210_INIT(inst) \ - static struct es7210_data es7210_data_##inst; \ - static const struct es7210_config es7210_config_##inst = { \ - .i2c = I2C_DT_SPEC_INST_GET(inst), \ - .mclk_freq = DT_INST_PROP_OR(inst, mclk_frequency, 0), \ - .mic_select = \ - DT_INST_PROP_OR(inst, mic_select, ES7210_MIC1_BIT | ES7210_MIC2_BIT), \ - .mic_gain = DT_INST_PROP_OR(inst, mic_gain, 11), \ - }; \ - DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &es7210_data_##inst, &es7210_config_##inst, \ - POST_KERNEL, CONFIG_AUDIO_CODEC_INIT_PRIORITY, &es7210_driver_api); - -DT_INST_FOREACH_STATUS_OKAY(ES7210_INIT) diff --git a/dts/bindings/audio/everest,es7210-dmic.yaml b/dts/bindings/audio/everest,es7210-dmic.yaml new file mode 100644 index 0000000000000..5710f541b700b --- /dev/null +++ b/dts/bindings/audio/everest,es7210-dmic.yaml @@ -0,0 +1,46 @@ +# Copyright 2025 The Zephyr Authors +# SPDX-License-Identifier: Apache-2.0 + +description: Everest Semiconductor ES7210 digital microphone (I2S) + +compatible: "everest,es7210-dmic" + +include: i2s-device.yaml + +properties: + codec: + type: phandle + required: true + description: | + Phandle to a node describing the ES7210 control interface. + The DMIC driver uses the phandle to access the I2C registers and + optional clock and microphone configuration properties. + + bit-clock-master: + type: boolean + description: > + Set when the ES7210 provides the I2S bit clock. If unset the SoC drives + the clock. + + frame-clock-master: + type: boolean + description: > + Set when the ES7210 provides the I2S frame clock. If unset the SoC drives + the clock. + + bit-clock-inverted: + type: boolean + description: Invert the I2S bit clock polarity. + + data-format: + type: string + enum: + - i2s + - left-justified + - right-justified + description: I2S data format provided by the ES7210. + + timeout-ms: + type: int + default: 2000 + description: Timeout in milliseconds used for I2S read operations. diff --git a/samples/drivers/i2s/i2s_codec/boards/m5stack_cores3_esp32s3_procpu.conf b/samples/drivers/i2s/i2s_codec/boards/m5stack_cores3_esp32s3_procpu.conf new file mode 100644 index 0000000000000..a6e42e9a33ef6 --- /dev/null +++ b/samples/drivers/i2s/i2s_codec/boards/m5stack_cores3_esp32s3_procpu.conf @@ -0,0 +1,3 @@ +CONFIG_USE_DMIC=y +CONFIG_DMIC_CHANNELS=2 +CONFIG_AUDIO_DMIC_ES7210=y diff --git a/samples/drivers/i2s/i2s_codec/boards/m5stack_cores3_esp32s3_procpu.overlay b/samples/drivers/i2s/i2s_codec/boards/m5stack_cores3_esp32s3_procpu.overlay index 85b2f7d530590..ebb64f7d68dbf 100644 --- a/samples/drivers/i2s/i2s_codec/boards/m5stack_cores3_esp32s3_procpu.overlay +++ b/samples/drivers/i2s/i2s_codec/boards/m5stack_cores3_esp32s3_procpu.overlay @@ -5,19 +5,26 @@ */ / { - aliases { - i2s-codec-tx = &i2s1; - }; + aliases { + i2s-codec-tx = &i2s1; + }; }; audio_codec: &aw88298 { - status = "okay"; + status = "okay"; }; &i2s1 { - status = "okay"; + status = "okay"; + + dmic_dev: es7210_dmic@0 { + compatible = "everest,es7210-dmic"; + reg = <0>; + status = "okay"; + codec = <&es7210>; + }; }; &dma { - status = "okay"; + status = "okay"; };