mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 11:56:10 +08:00
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:
@@ -26,6 +26,8 @@
|
|||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -288,8 +290,6 @@
|
|||||||
# define I2S_RCC_ATOMIC()
|
# define I2S_RCC_ATOMIC()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Types
|
* Private Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -2012,7 +2012,7 @@ static int32_t i2s_check_mclkfrequency(struct esp_i2s_s *priv)
|
|||||||
{
|
{
|
||||||
uint32_t mclk_freq;
|
uint32_t mclk_freq;
|
||||||
uint32_t mclk_multiple = priv->mclk_multiple;
|
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;
|
int i;
|
||||||
|
|
||||||
/* If the master clock is divisible by both the sample rate and the bit
|
/* 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)
|
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;
|
priv->config->data_width;
|
||||||
mclk = priv->mclk_freq;
|
mclk = priv->mclk_freq;
|
||||||
bclk_div = mclk / bclk;
|
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 */
|
/* For slave mode, mclk >= bclk * 8, so fix bclk_div to 2 first */
|
||||||
|
|
||||||
bclk_div = 8;
|
bclk_div = 8;
|
||||||
bclk = priv->rate * priv->config->total_slot *
|
bclk = priv->rate * MAX(priv->channels, 2) *
|
||||||
priv->config->data_width;
|
priv->config->data_width;
|
||||||
mclk = bclk * bclk_div;
|
mclk = bclk * bclk_div;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user