You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/10/26 16:09:11 UTC
[incubator-nuttx] 04/04: xtensa/esp32: add i2s_mclkfrequency to set master clock on I2S
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 0bf7afad253a16b81c6c5712c453dd759f758d41
Author: Tiago Medicci Serrano <ti...@espressif.com>
AuthorDate: Sun Oct 23 10:41:42 2022 -0300
xtensa/esp32: add i2s_mclkfrequency to set master clock on I2S
---
arch/xtensa/src/esp32/esp32_i2s.c | 62 +++++++++++++++++++++++++++++++++------
1 file changed, 53 insertions(+), 9 deletions(-)
diff --git a/arch/xtensa/src/esp32/esp32_i2s.c b/arch/xtensa/src/esp32/esp32_i2s.c
index ee907050f0..830b25b728 100644
--- a/arch/xtensa/src/esp32/esp32_i2s.c
+++ b/arch/xtensa/src/esp32/esp32_i2s.c
@@ -242,6 +242,7 @@ struct esp32_i2s_s
sem_t exclsem; /* Assures mutually exclusive access */
uint32_t rate; /* I2S actual configured sample-rate */
uint32_t data_width; /* I2S actual configured data_width */
+ uint32_t mclk_freq; /* I2S actual master clock */
int cpuint; /* I2S interrupt ID */
uint8_t cpu; /* CPU ID */
spinlock_t lock; /* Device specific lock. */
@@ -305,13 +306,15 @@ static void i2s_tx_schedule(struct esp32_i2s_s *priv,
/* I2S methods (and close friends) */
+static uint32_t esp32_i2s_mclkfrequency(struct i2s_dev_s *dev,
+ uint32_t frequency);
static uint32_t esp32_i2s_txsamplerate(struct i2s_dev_s *dev,
- uint32_t rate);
+ uint32_t rate);
static uint32_t esp32_i2s_txdatawidth(struct i2s_dev_s *dev, int bits);
static int esp32_i2s_send(struct i2s_dev_s *dev,
- struct ap_buffer_s *apb,
- i2s_callback_t callback, void *arg,
- uint32_t timeout);
+ struct ap_buffer_s *apb,
+ i2s_callback_t callback, void *arg,
+ uint32_t timeout);
/****************************************************************************
* Private Data
@@ -319,9 +322,10 @@ static int esp32_i2s_send(struct i2s_dev_s *dev,
static const struct i2s_ops_s g_i2sops =
{
- .i2s_txsamplerate = esp32_i2s_txsamplerate,
- .i2s_txdatawidth = esp32_i2s_txdatawidth,
- .i2s_send = esp32_i2s_send,
+ .i2s_txsamplerate = esp32_i2s_txsamplerate,
+ .i2s_txdatawidth = esp32_i2s_txdatawidth,
+ .i2s_send = esp32_i2s_send,
+ .i2s_mclkfrequency = esp32_i2s_mclkfrequency,
};
#ifdef CONFIG_ESP32_I2S0
@@ -395,7 +399,7 @@ static const struct esp32_i2s_config_s esp32_i2s1_config =
.data_width = CONFIG_ESP32_I2S1_DATA_BIT_WIDTH,
.rate = CONFIG_ESP32_I2S1_SAMPLE_RATE,
.total_slot = 2,
- .mclk_multiple = I2S_MCLK_MULTIPLE_384,
+ .mclk_multiple = I2S_MCLK_MULTIPLE_256,
.tx_en = I2S1_TX_ENABLED,
.rx_en = I2S1_RX_ENABLED,
#ifdef CONFIG_ESP32_I2S1_MCLK
@@ -1132,6 +1136,10 @@ static void i2s_configure(struct esp32_i2s_s *priv)
modifyreg32(I2S_FIFO_CONF_REG(priv->config->port), 0,
I2S_TX_FIFO_MOD_FORCE_EN);
+ esp32_i2s_mclkfrequency((struct i2s_dev_s *)priv,
+ (priv->config->rate *
+ priv->config->mclk_multiple));
+
esp32_i2s_txsamplerate((struct i2s_dev_s *)priv, priv->config->rate);
}
@@ -1225,6 +1233,42 @@ static int esp32_i2s_interrupt(int irq, void *context, void *arg)
return 0;
}
+/****************************************************************************
+ * Name: esp32_i2s_mclkfrequency
+ *
+ * Description:
+ * Set the master clock frequency. Usually, the MCLK is a multiple of the
+ * sample rate. Most of the audio codecs require setting specific MCLK
+ * frequency according to the sample rate.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * frequency - The I2S master clock's frequency
+ *
+ * Returned Value:
+ * Returns the resulting master clock or a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static uint32_t esp32_i2s_mclkfrequency(struct i2s_dev_s *dev,
+ uint32_t frequency)
+{
+ struct esp32_i2s_s *priv = (struct esp32_i2s_s *)dev;
+
+ /* Check if the master clock frequency is beyond the highest possible
+ * value and return an error.
+ */
+
+ if (frequency >= (I2S_LL_BASE_CLK / 2))
+ {
+ return -EINVAL;
+ }
+
+ priv->mclk_freq = frequency;
+
+ return frequency;
+}
+
/****************************************************************************
* Name: esp32_i2s_txsamplerate
*
@@ -1276,7 +1320,7 @@ static uint32_t esp32_i2s_txsamplerate(struct i2s_dev_s *dev, uint32_t rate)
if (priv->config->role == I2S_ROLE_MASTER)
{
bclk = rate * priv->config->total_slot * priv->data_width;
- mclk = rate * priv->config->mclk_multiple;
+ mclk = priv->mclk_freq;
bclk_div = mclk / bclk;
}
else