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