esp_i2s: use actual channel count for BCLK calculation

The I2S BCLK frequency is calculated as:
  bclk = sample_rate * total_slot * data_width

Previously, total_slot was always taken from the static config
(esp_i2s0_config / esp_i2s1_config), which is hardcoded to 2.
This is correct for mono and stereo, but wrong for TDM modes
with more than 2 channels (e.g. 4-channel recording with ES7210).

With 4 channels but total_slot=2, the BCLK is only half of what
it should be, causing the actual sample rate to be half of the
requested rate (e.g. requesting 16 kHz actually samples at 8 kHz).

Replace priv->config->total_slot with MAX(priv->channels, 2) in
all three BCLK calculation sites (i2s_check_mclkfrequency and
i2s_set_clock for both master and slave paths). The MIN of 2
preserves the I2S protocol requirement that at least 2 slots
exist even for mono, while correctly scaling for multi-channel
TDM configurations.

Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
This commit is contained in:
wangjianyu3
2026-03-30 15:22:53 +08:00
committed by Xiang Xiao
parent 3b1aac55a8
commit c100e9a9e8
+5 -5
View File
@@ -26,6 +26,8 @@
#include <nuttx/config.h>
#include <sys/param.h>
#include <assert.h>
#include <debug.h>
#include <errno.h>
@@ -288,8 +290,6 @@
# define I2S_RCC_ATOMIC()
#endif
#define MIN(x, y) ((x) < (y) ? (x) : (y))
/****************************************************************************
* Private Types
****************************************************************************/
@@ -2012,7 +2012,7 @@ static int32_t i2s_check_mclkfrequency(struct esp_i2s_s *priv)
{
uint32_t mclk_freq;
uint32_t mclk_multiple = priv->mclk_multiple;
uint32_t bclk = priv->rate * priv->config->total_slot * priv->data_width;
uint32_t bclk = priv->rate * MAX(priv->channels, 2) * priv->data_width;
int i;
/* If the master clock is divisible by both the sample rate and the bit
@@ -2146,7 +2146,7 @@ static void i2s_set_clock(struct esp_i2s_s *priv)
if (priv->config->role == I2S_ROLE_MASTER)
{
bclk = priv->rate * priv->config->total_slot *
bclk = priv->rate * MAX(priv->channels, 2) *
priv->config->data_width;
mclk = priv->mclk_freq;
bclk_div = mclk / bclk;
@@ -2156,7 +2156,7 @@ static void i2s_set_clock(struct esp_i2s_s *priv)
/* For slave mode, mclk >= bclk * 8, so fix bclk_div to 2 first */
bclk_div = 8;
bclk = priv->rate * priv->config->total_slot *
bclk = priv->rate * MAX(priv->channels, 2) *
priv->config->data_width;
mclk = bclk * bclk_div;
}