You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/06/05 18:54:27 UTC

[incubator-nuttx] branch master updated (d065bbe -> 36f54e2)

This is an automated email from the ASF dual-hosted git repository.

acassis pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git.


    from d065bbe  audio/pcm_decode.c: Fix #endif position when excluding stop and pause/resume.
     new 8da4b02  drivers/audio: Add CS4344 driver.
     new d001c82  boards/arm/stm32/olimex-stm32-p407: Add support for the CS4344 audio driver.
     new 36f54e2  Fix PR1201 nxstyle issues.

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../configs/{nsh => audio}/defconfig               |  16 +-
 boards/arm/stm32/olimex-stm32-p407/include/board.h |  18 +
 boards/arm/stm32/olimex-stm32-p407/src/Make.defs   |   4 +
 .../olimex-stm32-p407/src/olimex-stm32-p407.h      |  34 +
 .../stm32/olimex-stm32-p407/src/stm32_bringup.c    |  10 +
 .../arm/stm32/olimex-stm32-p407/src/stm32_cs4344.c | 170 +++++
 drivers/audio/Kconfig                              |  33 +
 drivers/audio/Make.defs                            |   4 +
 drivers/audio/{wm8776.c => cs4344.c}               | 835 ++++++++++-----------
 drivers/audio/cs4344.h                             |  98 +++
 include/nuttx/audio/cs4344.h                       | 141 ++++
 11 files changed, 926 insertions(+), 437 deletions(-)
 copy boards/arm/stm32/olimex-stm32-p407/configs/{nsh => audio}/defconfig (82%)
 create mode 100644 boards/arm/stm32/olimex-stm32-p407/src/stm32_cs4344.c
 copy drivers/audio/{wm8776.c => cs4344.c} (59%)
 create mode 100644 drivers/audio/cs4344.h
 create mode 100644 include/nuttx/audio/cs4344.h


[incubator-nuttx] 01/03: drivers/audio: Add CS4344 driver.

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 8da4b02350da5b0fe9dee1f70ce7f2b5730a89a7
Author: Ouss4 <ab...@gmail.com>
AuthorDate: Wed Jun 3 15:45:26 2020 +0100

    drivers/audio: Add CS4344 driver.
---
 drivers/audio/Kconfig        |   33 +
 drivers/audio/Make.defs      |    4 +
 drivers/audio/cs4344.c       | 1370 ++++++++++++++++++++++++++++++++++++++++++
 drivers/audio/cs4344.h       |   98 +++
 include/nuttx/audio/cs4344.h |  141 +++++
 5 files changed, 1646 insertions(+)

diff --git a/drivers/audio/Kconfig b/drivers/audio/Kconfig
index 735718a..610109c 100644
--- a/drivers/audio/Kconfig
+++ b/drivers/audio/Kconfig
@@ -165,6 +165,39 @@ config CS43L22_CLKDEBUG
 
 endif # AUDIO_CS43L22
 
+config AUDIO_CS4344
+	bool "CS4344 audio chip"
+	default n
+	depends on AUDIO
+	---help---
+		Select to enable support for the CS4344 Audio codec by Cirrus Logic.
+		This chip is a lower level audio chip.. basically
+		an exotic D-to-A.  It includes no built-in support for audio CODECS.
+
+if AUDIO_CS4344
+
+config CS4344_INFLIGHT
+	int "CS4344 maximum in-flight audio buffers"
+	default 2
+
+config CS4344_MSG_PRIO
+	int "CS4344 message priority"
+	default 1
+
+config CS4344_BUFFER_SIZE
+	int "CS4344 preferred buffer size"
+	default 8192
+
+config CS4344_NUM_BUFFERS
+	int "CS4344 preferred number of buffers"
+	default 4
+
+config CS4344_WORKER_STACKSIZE
+	int "CS4344 worker thread stack size"
+	default 768
+
+endif # AUDIO_CS4344
+
 config AUDIO_WM8776
 	bool "WM8776 audio chip"
 	default n
diff --git a/drivers/audio/Make.defs b/drivers/audio/Make.defs
index a3b607c..b0c0535 100644
--- a/drivers/audio/Make.defs
+++ b/drivers/audio/Make.defs
@@ -58,6 +58,10 @@ endif
 endif
 endif
 
+ifeq ($(CONFIG_AUDIO_CS4344),y)
+CSRCS += cs4344.c
+endif
+
 ifeq ($(CONFIG_AUDIO_WM8904),y)
 CSRCS += wm8904.c
 ifeq ($(CONFIG_WM8904_REGDUMP),y)
diff --git a/drivers/audio/cs4344.c b/drivers/audio/cs4344.c
new file mode 100644
index 0000000..0c2619b
--- /dev/null
+++ b/drivers/audio/cs4344.c
@@ -0,0 +1,1370 @@
+/****************************************************************************
+ * drivers/audio/cs4344.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <fixedmath.h>
+#include <queue.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/mqueue.h>
+#include <nuttx/clock.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/fs/ioctl.h>
+#include <nuttx/audio/i2s.h>
+#include <nuttx/audio/audio.h>
+#include <nuttx/audio/cs4344.h>
+#include <nuttx/lib/math.h>
+
+#include "cs4344.h"
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int  cs4344_takesem(FAR sem_t *sem);
+static int  cs4344_forcetake(FAR sem_t *sem);
+#define     cs4344_givesem(s) nxsem_post(s)
+
+static void cs4344_setdatawidth(FAR struct cs4344_dev_s *priv);
+static void cs4344_setbitrate(FAR struct cs4344_dev_s *priv);
+
+/* Audio lower half methods (and close friends) */
+
+static int  cs4344_getcaps(FAR struct audio_lowerhalf_s *dev, int type,
+                            FAR struct audio_caps_s *caps);
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int  cs4344_configure(FAR struct audio_lowerhalf_s *dev,
+                              FAR void *session,
+                              FAR const struct audio_caps_s *caps);
+#else
+static int  cs4344_configure(FAR struct audio_lowerhalf_s *dev,
+                              FAR const struct audio_caps_s *caps);
+#endif
+static int  cs4344_shutdown(FAR struct audio_lowerhalf_s *dev);
+static void cs4344_senddone(FAR struct i2s_dev_s *i2s,
+                             FAR struct ap_buffer_s *apb, FAR void *arg,
+                             int result);
+static void cs4344_returnbuffers(FAR struct cs4344_dev_s *priv);
+static int  cs4344_sendbuffer(FAR struct cs4344_dev_s *priv);
+
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int  cs4344_start(FAR struct audio_lowerhalf_s *dev,
+                          FAR void *session);
+#else
+static int  cs4344_start(FAR struct audio_lowerhalf_s *dev);
+#endif
+#ifndef CONFIG_AUDIO_EXCLUDE_STOP
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int  cs4344_stop(FAR struct audio_lowerhalf_s *dev,
+                         FAR void *session);
+#else
+static int  cs4344_stop(FAR struct audio_lowerhalf_s *dev);
+#endif
+#endif
+#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int  cs4344_pause(FAR struct audio_lowerhalf_s *dev,
+                          FAR void *session);
+static int  cs4344_resume(FAR struct audio_lowerhalf_s *dev,
+                           FAR void *session);
+#else
+static int  cs4344_pause(FAR struct audio_lowerhalf_s *dev);
+static int  cs4344_resume(FAR struct audio_lowerhalf_s *dev);
+#endif
+#endif
+static int  cs4344_enqueuebuffer(FAR struct audio_lowerhalf_s *dev,
+                                  FAR struct ap_buffer_s *apb);
+static int  cs4344_cancelbuffer(FAR struct audio_lowerhalf_s *dev,
+                                 FAR struct ap_buffer_s *apb);
+static int  cs4344_ioctl(FAR struct audio_lowerhalf_s *dev, int cmd,
+                          unsigned long arg);
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int  cs4344_reserve(FAR struct audio_lowerhalf_s *dev,
+                           FAR void **session);
+#else
+static int  cs4344_reserve(FAR struct audio_lowerhalf_s *dev);
+#endif
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int  cs4344_release(FAR struct audio_lowerhalf_s *dev,
+                            FAR void *session);
+#else
+static int  cs4344_release(FAR struct audio_lowerhalf_s *dev);
+#endif
+
+static void *cs4344_workerthread(pthread_addr_t pvarg);
+
+/* Initialization */
+
+static void cs4344_reset(FAR struct cs4344_dev_s *priv);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct audio_ops_s g_audioops =
+{
+  cs4344_getcaps,       /* getcaps */
+  cs4344_configure,     /* configure */
+  cs4344_shutdown,      /* shutdown */
+  cs4344_start,         /* start */
+#ifndef CONFIG_AUDIO_EXCLUDE_STOP
+  cs4344_stop,          /* stop */
+#endif
+#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
+  cs4344_pause,         /* pause */
+  cs4344_resume,        /* resume */
+#endif
+  NULL,                  /* allocbuffer */
+  NULL,                  /* freebuffer */
+  cs4344_enqueuebuffer, /* enqueue_buffer */
+  cs4344_cancelbuffer,  /* cancel_buffer */
+  cs4344_ioctl,         /* ioctl */
+  NULL,                  /* read */
+  NULL,                  /* write */
+  cs4344_reserve,       /* reserve */
+  cs4344_release        /* release */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cs4344_takesem
+ *
+ * Description:
+ *  Take a semaphore count, handling the nasty EINTR return if we are
+ *  interrupted by a signal.
+ *
+ ****************************************************************************/
+
+static int cs4344_takesem(FAR sem_t *sem)
+{
+  return nxsem_wait_uninterruptible(sem);
+}
+
+/****************************************************************************
+ * Name: cs4344_forcetake
+ *
+ * Description:
+ *   This is just another wrapper but this one continues even if the thread
+ *   is canceled.  This must be done in certain conditions where were must
+ *   continue in order to clean-up resources.
+ *
+ ****************************************************************************/
+
+static int cs4344_forcetake(FAR sem_t *sem)
+{
+  int result;
+  int ret = OK;
+
+  do
+    {
+      result = nxsem_wait_uninterruptible(sem);
+
+      /* The only expected error would -ECANCELED meaning that the
+       * parent thread has been canceled.  We have to continue and
+       * terminate the poll in this case.
+       */
+
+      DEBUGASSERT(result == OK || result == -ECANCELED);
+      if (ret == OK && result < 0)
+        {
+          /* Remember the first failure */
+
+          ret = result;
+        }
+    }
+  while (result < 0);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: cs4344_setdatawidth
+ *
+ * Description:
+ *   Set the 8- or 16-bit data modes
+ *
+ ****************************************************************************/
+
+static void cs4344_setdatawidth(FAR struct cs4344_dev_s *priv)
+{
+  if (priv->bpsamp == 16)
+    {
+      /* Reset default default setting */
+
+      priv->i2s->ops->i2s_txdatawidth(priv->i2s, 16);
+    }
+  else
+    {
+      /* This should select 8-bit with no companding */
+
+      priv->i2s->ops->i2s_txdatawidth(priv->i2s, 8);
+    }
+}
+
+/****************************************************************************
+ * Name: cs4344_setbitrate
+ *
+ ****************************************************************************/
+
+static void cs4344_setbitrate(FAR struct cs4344_dev_s *priv)
+{
+  DEBUGASSERT(priv);
+
+  priv->i2s->ops->i2s_txsamplerate(priv->i2s, priv->samprate);
+
+  audinfo("sample rate=%u nchannels=%u bpsamp=%u\n",
+          priv->samprate, priv->nchannels, priv->bpsamp);
+}
+
+/****************************************************************************
+ * Name: cs4344_getcaps
+ *
+ * Description:
+ *   Get the audio device capabilities
+ *
+ ****************************************************************************/
+
+static int cs4344_getcaps(FAR struct audio_lowerhalf_s *dev, int type,
+                           FAR struct audio_caps_s *caps)
+{
+  /* Validate the structure */
+
+  DEBUGASSERT(caps && caps->ac_len >= sizeof(struct audio_caps_s));
+  audinfo("type=%d ac_type=%d\n", type, caps->ac_type);
+
+  /* Fill in the caller's structure based on requested info */
+
+  caps->ac_format.hw  = 0;
+  caps->ac_controls.w = 0;
+
+  switch (caps->ac_type)
+    {
+      /* Caller is querying for the types of units we support */
+
+      case AUDIO_TYPE_QUERY:
+
+        /* Provide our overall capabilities.  The interfacing software
+         * must then call us back for specific info for each capability.
+         */
+
+        caps->ac_channels = 2;       /* Stereo output */
+
+        switch (caps->ac_subtype)
+          {
+            case AUDIO_TYPE_QUERY:
+
+              /* We don't decode any formats!  Only something above us in
+               * the audio stream can perform decoding on our behalf.
+               */
+
+              /* The types of audio units we implement */
+
+              caps->ac_controls.b[0] =
+                AUDIO_TYPE_OUTPUT | AUDIO_TYPE_FEATURE |
+                AUDIO_TYPE_PROCESSING;
+              break;
+
+            case AUDIO_FMT_MIDI:
+
+              /* We only support Format 0 */
+
+              caps->ac_controls.b[0] = AUDIO_SUBFMT_END;
+              break;
+
+            default:
+              caps->ac_controls.b[0] = AUDIO_SUBFMT_END;
+              break;
+          }
+
+        break;
+
+      /* Provide capabilities of our OUTPUT unit */
+
+      case AUDIO_TYPE_OUTPUT:
+
+        caps->ac_channels = 2;
+
+        switch (caps->ac_subtype)
+          {
+            case AUDIO_TYPE_QUERY:
+
+              /* Report the Sample rates we support */
+
+              caps->ac_controls.b[0] =
+                AUDIO_SAMP_RATE_8K | AUDIO_SAMP_RATE_11K |
+                AUDIO_SAMP_RATE_16K | AUDIO_SAMP_RATE_22K |
+                AUDIO_SAMP_RATE_32K | AUDIO_SAMP_RATE_44K |
+                AUDIO_SAMP_RATE_48K;
+              break;
+
+            case AUDIO_FMT_MP3:
+            case AUDIO_FMT_WMA:
+            case AUDIO_FMT_PCM:
+              break;
+
+            default:
+              break;
+          }
+
+        break;
+
+      /* Provide capabilities of our FEATURE units */
+
+      case AUDIO_TYPE_FEATURE:
+
+        /* If the sub-type is UNDEF, then report the Feature Units we
+         * support.
+         */
+
+        if (caps->ac_subtype == AUDIO_FU_UNDEF)
+          {
+            /* Fill in the ac_controls section with the Feature Units we
+             * have.
+             */
+
+            caps->ac_controls.b[0] = AUDIO_FU_VOLUME | AUDIO_FU_BASS |
+                                     AUDIO_FU_TREBLE;
+            caps->ac_controls.b[1] = AUDIO_FU_BALANCE >> 8;
+          }
+        else
+          {
+            /* TODO:  Do we need to provide specific info for the Feature
+             * Units, such as volume setting ranges, etc.?
+             */
+          }
+
+        break;
+
+      /* Provide capabilities of our PROCESSING unit */
+
+      case AUDIO_TYPE_PROCESSING:
+
+        switch (caps->ac_subtype)
+          {
+            case AUDIO_PU_UNDEF:
+
+              /* Provide the type of Processing Units we support */
+
+              caps->ac_controls.b[0] = AUDIO_PU_STEREO_EXTENDER;
+              break;
+
+            case AUDIO_PU_STEREO_EXTENDER:
+
+              /* Provide capabilities of our Stereo Extender */
+
+              caps->ac_controls.b[0] =
+                AUDIO_STEXT_ENABLE | AUDIO_STEXT_WIDTH;
+              break;
+
+            default:
+
+              /* Other types of processing uint we don't support */
+
+              break;
+          }
+        break;
+
+      /* All others we don't support */
+
+      default:
+
+        /* Zero out the fields to indicate no support */
+
+        caps->ac_subtype = 0;
+        caps->ac_channels = 0;
+
+        break;
+    }
+
+  /* Return the length of the audio_caps_s struct for validation of
+   * proper Audio device type.
+   */
+
+  return caps->ac_len;
+}
+
+/****************************************************************************
+ * Name: cs4344_configure
+ *
+ * Description:
+ *   Configure the audio device for the specified  mode of operation.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int
+cs4344_configure(FAR struct audio_lowerhalf_s *dev,
+                  FAR void *session, FAR const struct audio_caps_s *caps)
+#else
+static int
+cs4344_configure(FAR struct audio_lowerhalf_s *dev,
+                  FAR const struct audio_caps_s *caps)
+#endif
+{
+  FAR struct cs4344_dev_s *priv = (FAR struct cs4344_dev_s *)dev;
+  int ret = OK;
+
+  DEBUGASSERT(priv != NULL && caps != NULL);
+  audinfo("ac_type: %d\n", caps->ac_type);
+
+  /* Process the configure operation */
+
+  switch (caps->ac_type)
+    {
+    case AUDIO_TYPE_FEATURE:
+      audinfo("  AUDIO_TYPE_FEATURE\n");
+
+      /* Process based on Feature Unit */
+
+      switch (caps->ac_format.hw)
+        {
+        default:
+          auderr("    ERROR: Unrecognized feature unit\n");
+          ret = -ENOTTY;
+          break;
+        }
+        break;
+
+    case AUDIO_TYPE_OUTPUT:
+      {
+        audinfo("  AUDIO_TYPE_OUTPUT:\n");
+        audinfo("    Number of channels: %u\n", caps->ac_channels);
+        audinfo("    Sample rate:        %u\n", caps->ac_controls.hw[0]);
+        audinfo("    Sample width:       %u\n", caps->ac_controls.b[2]);
+
+        /* Verify that all of the requested values are supported */
+
+        ret = -ERANGE;
+        if (caps->ac_channels != 1 && caps->ac_channels != 2)
+          {
+            auderr("ERROR: Unsupported number of channels: %d\n",
+                   caps->ac_channels);
+            break;
+          }
+
+        if (caps->ac_controls.b[2] != 8 && caps->ac_controls.b[2] != 16)
+          {
+            auderr("ERROR: Unsupported bits per sample: %d\n",
+                   caps->ac_controls.b[2]);
+            break;
+          }
+
+        /* Save the current stream configuration */
+
+        priv->samprate  = caps->ac_controls.hw[0];
+        priv->nchannels = caps->ac_channels;
+        priv->bpsamp    = caps->ac_controls.b[2];
+
+        /* Reconfigure the FLL to support the resulting number or channels,
+         * bits per sample, and bitrate.
+         */
+
+        cs4344_setdatawidth(priv);
+        cs4344_setbitrate(priv);
+        ret = OK;
+      }
+      break;
+
+    case AUDIO_TYPE_PROCESSING:
+      break;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: cs4344_shutdown
+ *
+ * Description:
+ *   Shutdown the CS4344 chip and put it in the lowest power state possible.
+ *
+ ****************************************************************************/
+
+static int cs4344_shutdown(FAR struct audio_lowerhalf_s *dev)
+{
+  FAR struct cs4344_dev_s *priv = (FAR struct cs4344_dev_s *)dev;
+
+  DEBUGASSERT(priv);
+
+  /* Now issue a software reset. This puts all CS4344 registers back in
+   * their default state.
+   */
+
+  cs4344_reset(priv);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: cs4344_senddone
+ *
+ * Description:
+ *   This is the I2S callback function that is invoked when the transfer
+ *   completes.
+ *
+ ****************************************************************************/
+
+static void
+cs4344_senddone(FAR struct i2s_dev_s *i2s,
+                 FAR struct ap_buffer_s *apb, FAR void *arg, int result)
+{
+  FAR struct cs4344_dev_s *priv = (FAR struct cs4344_dev_s *)arg;
+  struct audio_msg_s msg;
+  irqstate_t flags;
+  int ret;
+
+  DEBUGASSERT(i2s && priv && priv->running && apb);
+  audinfo("apb=%p inflight=%d result=%d\n", apb, priv->inflight, result);
+
+  /* We do not place any restriction on the context in which this function
+   * is called.  It may be called from an interrupt handler.  Therefore, the
+   * doneq and in-flight values might be accessed from the interrupt level.
+   * Not the best design.  But we will use interrupt controls to protect
+   * against that possibility.
+   */
+
+  flags = enter_critical_section();
+
+  /* Add the completed buffer to the end of our doneq.  We do not yet
+   * decrement the reference count.
+   */
+
+  dq_addlast((FAR dq_entry_t *)apb, &priv->doneq);
+
+  /* And decrement the number of buffers in-flight */
+
+  DEBUGASSERT(priv->inflight > 0);
+  priv->inflight--;
+
+  /* Save the result of the transfer */
+
+  /* REVISIT:  This can be overwritten */
+
+  priv->result = result;
+  leave_critical_section(flags);
+
+  /* Now send a message to the worker thread, informing it that there are
+   * buffers in the done queue that need to be cleaned up.
+   */
+
+  msg.msg_id = AUDIO_MSG_COMPLETE;
+  ret = nxmq_send(priv->mq, (FAR const char *)&msg, sizeof(msg),
+                  CONFIG_CS4344_MSG_PRIO);
+  if (ret < 0)
+    {
+      auderr("ERROR: nxmq_send failed: %d\n", ret);
+    }
+}
+
+/****************************************************************************
+ * Name: cs4344_returnbuffers
+ *
+ * Description:
+ *   This function is called after the complete of one or more data
+ *   transfers.  This function will empty the done queue and release our
+ *   reference to each buffer.
+ *
+ ****************************************************************************/
+
+static void cs4344_returnbuffers(FAR struct cs4344_dev_s *priv)
+{
+  FAR struct ap_buffer_s *apb;
+  irqstate_t flags;
+
+  /* The doneq and in-flight values might be accessed from the interrupt
+   * level in some implementations.  Not the best design.  But we will
+   * use interrupt controls to protect against that possibility.
+   */
+
+  flags = enter_critical_section();
+  while (dq_peek(&priv->doneq) != NULL)
+    {
+      /* Take the next buffer from the queue of completed transfers */
+
+      apb = (FAR struct ap_buffer_s *)dq_remfirst(&priv->doneq);
+      leave_critical_section(flags);
+
+      audinfo("Returning: apb=%p curbyte=%d nbytes=%d flags=%04x\n",
+              apb, apb->curbyte, apb->nbytes, apb->flags);
+
+      /* Are we returning the final buffer in the stream? */
+
+      if ((apb->flags & AUDIO_APB_FINAL) != 0)
+        {
+          /* Both the pending and the done queues should be empty and there
+           * should be no buffers in-flight.
+           */
+
+          DEBUGASSERT(dq_empty(&priv->doneq) && dq_empty(&priv->pendq) &&
+                      priv->inflight == 0);
+
+          /* Set the terminating flag.  This will, eventually, cause the
+           * worker thread to exit (if it is not already terminating).
+           */
+
+          audinfo("Terminating\n");
+          priv->terminating = true;
+        }
+
+      /* Release our reference to the audio buffer */
+
+      apb_free(apb);
+
+      /* Send the buffer back up to the previous level. */
+
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+      priv->dev.upper(priv->dev.priv, AUDIO_CALLBACK_DEQUEUE, apb, OK, NULL);
+#else
+      priv->dev.upper(priv->dev.priv, AUDIO_CALLBACK_DEQUEUE, apb, OK);
+#endif
+      flags = enter_critical_section();
+    }
+
+  leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Name: cs4344_sendbuffer
+ *
+ * Description:
+ *   Start the transfer an audio buffer to the CS4344 via I2S.  This
+ *   will not wait for the transfer to complete but will return immediately.
+ *   the wmd8904_senddone called will be invoked when the transfer
+ *   completes, stimulating the worker thread to call this function again.
+ *
+ ****************************************************************************/
+
+static int cs4344_sendbuffer(FAR struct cs4344_dev_s *priv)
+{
+  FAR struct ap_buffer_s *apb;
+  irqstate_t flags;
+  uint32_t timeout;
+  int shift;
+  int ret;
+
+  /* Loop while there are audio buffers to be sent and we have few than
+   * CONFIG_CS4344_INFLIGHT then "in-flight"
+   *
+   * The 'inflight' value might be modified from the interrupt level in some
+   * implementations.  We will use interrupt controls to protect against
+   * that possibility.
+   *
+   * The 'pendq', on the other hand, is protected via a semaphore.  Let's
+   * hold the semaphore while we are busy here and disable the interrupts
+   * only while accessing 'inflight'.
+   */
+
+  ret = cs4344_takesem(&priv->pendsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  while (priv->inflight < CONFIG_CS4344_INFLIGHT &&
+         dq_peek(&priv->pendq) != NULL && !priv->paused)
+    {
+      /* Take next buffer from the queue of pending transfers */
+
+      apb = (FAR struct ap_buffer_s *)dq_remfirst(&priv->pendq);
+      audinfo("Sending apb=%p, size=%d inflight=%d\n",
+              apb, apb->nbytes, priv->inflight);
+
+      /* Increment the number of buffers in-flight before sending in order
+       * to avoid a possible race condition.
+       */
+
+      flags = enter_critical_section();
+      priv->inflight++;
+      leave_critical_section(flags);
+
+      /* Send the entire audio buffer via I2S.  What is a reasonable timeout
+       * to use?  This would depend on the bit rate and size of the buffer.
+       *
+       * Samples in the buffer (samples):
+       *   = buffer_size * 8 / bpsamp                           samples
+       * Sample rate (samples/second):
+       *   = samplerate * nchannels
+       * Expected transfer time (seconds):
+       *   = (buffer_size * 8) / bpsamp / samplerate / nchannels
+       *
+       * We will set the timeout about twice that.
+       *
+       * NOTES:
+       * - The multiplier of 8 becomes 16000 for 2x and units of
+       *   milliseconds.
+       * - 16000 is a approximately 16384 (1 << 14), bpsamp is either
+       *   (1 << 3) or (1 << 4), and nchannels is either (1 << 0) or
+       *   (1 << 1).  So this can be simplifies to (milliseconds):
+       *
+       *   = (buffer_size << shift) / samplerate
+       */
+
+      shift  = (priv->bpsamp == 8) ? 14 - 3 : 14 - 4;
+      shift -= (priv->nchannels > 1) ? 1 : 0;
+
+      timeout = MSEC2TICK(((uint32_t)(apb->nbytes - apb->curbyte) << shift) /
+                           (uint32_t)priv->samprate);
+
+      ret = I2S_SEND(priv->i2s, apb, cs4344_senddone, priv, timeout);
+      if (ret < 0)
+        {
+          auderr("ERROR: I2S_SEND failed: %d\n", ret);
+          break;
+        }
+    }
+
+  cs4344_givesem(&priv->pendsem);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: cs4344_start
+ *
+ * Description:
+ *   Start the configured operation (audio streaming, volume enabled, etc.).
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int cs4344_start(FAR struct audio_lowerhalf_s *dev,
+           FAR void *session)
+#else
+static int cs4344_start(FAR struct audio_lowerhalf_s *dev)
+#endif
+{
+  FAR struct cs4344_dev_s *priv = (FAR struct cs4344_dev_s *)dev;
+  struct sched_param sparam;
+  struct mq_attr attr;
+  pthread_attr_t tattr;
+  FAR void *value;
+  int ret;
+
+  audinfo("Entry\n");
+
+  /* Create a message queue for the worker thread */
+
+  snprintf(priv->mqname, sizeof(priv->mqname), "/tmp/%X", priv);
+
+  attr.mq_maxmsg  = 16;
+  attr.mq_msgsize = sizeof(struct audio_msg_s);
+  attr.mq_curmsgs = 0;
+  attr.mq_flags   = 0;
+
+  priv->mq = mq_open(priv->mqname, O_RDWR | O_CREAT, 0644, &attr);
+  if (priv->mq == NULL)
+    {
+      /* Error creating message queue! */
+
+      auderr("ERROR: Couldn't allocate message queue\n");
+      return -ENOMEM;
+    }
+
+  /* Join any old worker thread we had created to prevent a memory leak */
+
+  if (priv->threadid != 0)
+    {
+      audinfo("Joining old thread\n");
+      pthread_join(priv->threadid, &value);
+    }
+
+  /* Start our thread for sending data to the device */
+
+  pthread_attr_init(&tattr);
+  sparam.sched_priority = sched_get_priority_max(SCHED_FIFO) - 3;
+  pthread_attr_setschedparam(&tattr, &sparam);
+  pthread_attr_setstacksize(&tattr, CONFIG_CS4344_WORKER_STACKSIZE);
+
+  audinfo("Starting worker thread\n");
+  ret = pthread_create(&priv->threadid, &tattr, cs4344_workerthread,
+                       (pthread_addr_t)priv);
+  if (ret != OK)
+    {
+      auderr("ERROR: pthread_create failed: %d\n", ret);
+    }
+  else
+    {
+      pthread_setname_np(priv->threadid, "cs4344");
+      audinfo("Created worker thread\n");
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: cs4344_stop
+ *
+ * Description:
+ *   Stop the configured operation (audio streaming, volume disabled, etc.).
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_AUDIO_EXCLUDE_STOP
+#  ifdef CONFIG_AUDIO_MULTI_SESSION
+static int cs4344_stop(FAR struct audio_lowerhalf_s *dev, FAR void *session)
+#  else
+static int cs4344_stop(FAR struct audio_lowerhalf_s *dev)
+#  endif
+{
+  FAR struct cs4344_dev_s *priv = (FAR struct cs4344_dev_s *)dev;
+  struct audio_msg_s term_msg;
+  FAR void *value;
+
+  /* Send a message to stop all audio streaming */
+
+  term_msg.msg_id = AUDIO_MSG_STOP;
+  term_msg.u.data = 0;
+  nxmq_send(priv->mq, (FAR const char *)&term_msg, sizeof(term_msg),
+            CONFIG_CS4344_MSG_PRIO);
+
+  /* Join the worker thread */
+
+  pthread_join(priv->threadid, &value);
+  priv->threadid = 0;
+
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: cs4344_pause
+ *
+ * Description:
+ *   Pauses the playback.
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
+#  ifdef CONFIG_AUDIO_MULTI_SESSION
+static int cs4344_pause(FAR struct audio_lowerhalf_s *dev,
+                         FAR void *session)
+#  else
+static int cs4344_pause(FAR struct audio_lowerhalf_s *dev)
+#  endif
+{
+  FAR struct cs4344_dev_s *priv = (FAR struct cs4344_dev_s *)dev;
+
+  if (priv->running && !priv->paused)
+    {
+      /* Disable interrupts to prevent us from suppling any more data */
+
+      priv->paused = true;
+    }
+
+  return OK;
+}
+#endif /* CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME */
+
+/****************************************************************************
+ * Name: cs4344_resume
+ *
+ * Description:
+ *   Resumes the playback.
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
+#  ifdef CONFIG_AUDIO_MULTI_SESSION
+static int cs4344_resume(FAR struct audio_lowerhalf_s *dev,
+                          FAR void *session)
+#  else
+static int cs4344_resume(FAR struct audio_lowerhalf_s *dev)
+#  endif
+{
+  FAR struct cs4344_dev_s *priv = (FAR struct cs4344_dev_s *)dev;
+
+  if (priv->running && priv->paused)
+    {
+      priv->paused = false;
+
+      /* Enable interrupts to allow sampling data */
+
+      cs4344_sendbuffer(priv);
+    }
+
+  return OK;
+}
+#endif /* CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME */
+
+/****************************************************************************
+ * Name: cs4344_enqueuebuffer
+ *
+ * Description:
+ *   Enqueue an Audio Pipeline Buffer for playback/ processing.
+ *
+ ****************************************************************************/
+
+static int cs4344_enqueuebuffer(FAR struct audio_lowerhalf_s *dev,
+                                 FAR struct ap_buffer_s *apb)
+{
+  FAR struct cs4344_dev_s *priv = (FAR struct cs4344_dev_s *)dev;
+  struct audio_msg_s term_msg;
+  int ret;
+
+  audinfo("Enqueueing: apb=%p curbyte=%d nbytes=%d flags=%04x\n",
+          apb, apb->curbyte, apb->nbytes, apb->flags);
+
+  ret = cs4344_takesem(&priv->pendsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Take a reference on the new audio buffer */
+
+  apb_reference(apb);
+
+  /* Add the new buffer to the tail of pending audio buffers */
+
+  apb->flags |= AUDIO_APB_OUTPUT_ENQUEUED;
+  dq_addlast(&apb->dq_entry, &priv->pendq);
+  cs4344_givesem(&priv->pendsem);
+
+  /* Send a message to the worker thread indicating that a new buffer has
+   * been enqueued.  If mq is NULL, then the playing has not yet started.
+   * In that case we are just "priming the pump" and we don't need to send
+   * any message.
+   */
+
+  ret = OK;
+  if (priv->mq != NULL)
+    {
+      term_msg.msg_id  = AUDIO_MSG_ENQUEUE;
+      term_msg.u.data = 0;
+
+      ret = nxmq_send(priv->mq, (FAR const char *)&term_msg,
+                      sizeof(term_msg), CONFIG_CS4344_MSG_PRIO);
+      if (ret < 0)
+        {
+          auderr("ERROR: nxmq_send failed: %d\n", ret);
+        }
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: cs4344_cancelbuffer
+ *
+ * Description:
+ *   Called when an enqueued buffer is being cancelled.
+ *
+ ****************************************************************************/
+
+static int cs4344_cancelbuffer(FAR struct audio_lowerhalf_s *dev,
+                                FAR struct ap_buffer_s *apb)
+{
+  audinfo("apb=%p\n", apb);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: cs4344_ioctl
+ *
+ * Description:
+ *   Perform a device ioctl
+ *
+ ****************************************************************************/
+
+static int cs4344_ioctl(FAR struct audio_lowerhalf_s *dev, int cmd,
+                         unsigned long arg)
+{
+  int ret = OK;
+#ifdef CONFIG_AUDIO_DRIVER_SPECIFIC_BUFFERS
+  FAR struct ap_buffer_info_s *bufinfo;
+#endif
+
+  /* Deal with ioctls passed from the upper-half driver */
+
+  switch (cmd)
+    {
+      /* Check for AUDIOIOC_HWRESET ioctl.  This ioctl is passed straight
+       * through from the upper-half audio driver.
+       */
+
+      case AUDIOIOC_HWRESET:
+        {
+          audinfo("AUDIOIOC_HWRESET:\n");
+        }
+        break;
+
+       /* Report our preferred buffer size and quantity */
+
+#ifdef CONFIG_AUDIO_DRIVER_SPECIFIC_BUFFERS
+      case AUDIOIOC_GETBUFFERINFO:
+        {
+          audinfo("AUDIOIOC_GETBUFFERINFO:\n");
+          bufinfo              = (FAR struct ap_buffer_info_s *)arg;
+          bufinfo->buffer_size = CONFIG_CS4344_BUFFER_SIZE;
+          bufinfo->nbuffers    = CONFIG_CS4344_NUM_BUFFERS;
+        }
+        break;
+#endif
+
+      default:
+        ret = -ENOTTY;
+        audinfo("Ignored\n");
+        break;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: cs4344_reserve
+ *
+ * Description:
+ *   Reserves a session (the only one we have).
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int
+cs4344_reserve(FAR struct audio_lowerhalf_s *dev, FAR void **session)
+#else
+static int cs4344_reserve(FAR struct audio_lowerhalf_s *dev)
+#endif
+{
+  FAR struct cs4344_dev_s *priv = (FAR struct cs4344_dev_s *)dev;
+  int ret = OK;
+
+  /* Borrow the APBQ semaphore for thread sync */
+
+  ret = cs4344_takesem(&priv->pendsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  if (priv->reserved)
+    {
+      ret = -EBUSY;
+    }
+  else
+    {
+      /* Initialize the session context */
+
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+     *session           = NULL;
+#endif
+      priv->inflight    = 0;
+      priv->running     = false;
+      priv->paused      = false;
+#ifndef CONFIG_AUDIO_EXCLUDE_STOP
+      priv->terminating = false;
+#endif
+      priv->reserved    = true;
+    }
+
+  cs4344_givesem(&priv->pendsem);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: cs4344_release
+ *
+ * Description:
+ *   Releases the session (the only one we have).
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int cs4344_release(FAR struct audio_lowerhalf_s *dev,
+                           FAR void *session)
+#else
+static int cs4344_release(FAR struct audio_lowerhalf_s *dev)
+#endif
+{
+  FAR struct cs4344_dev_s *priv = (FAR struct cs4344_dev_s *)dev;
+  FAR void *value;
+  int ret;
+
+  /* Join any old worker thread we had created to prevent a memory leak */
+
+  if (priv->threadid != 0)
+    {
+      pthread_join(priv->threadid, &value);
+      priv->threadid = 0;
+    }
+
+  /* Borrow the APBQ semaphore for thread sync */
+
+  ret = cs4344_forcetake(&priv->pendsem);
+
+  /* Really we should free any queued buffers here */
+
+  priv->reserved = false;
+  cs4344_givesem(&priv->pendsem);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: cs4344_workerthread
+ *
+ *  This is the thread that feeds data to the chip and keeps the audio
+ *  stream going.
+ *
+ ****************************************************************************/
+
+static void *cs4344_workerthread(pthread_addr_t pvarg)
+{
+  FAR struct cs4344_dev_s *priv = (struct cs4344_dev_s *)pvarg;
+  struct audio_msg_s msg;
+  FAR struct ap_buffer_s *apb;
+  int msglen;
+  unsigned int prio;
+
+  audinfo("Entry\n");
+
+#ifndef CONFIG_AUDIO_EXCLUDE_STOP
+  priv->terminating = false;
+#endif
+
+/* Mark ourself as running and make sure that CS4344 interrupts are
+ * enabled.
+ */
+
+  priv->running = true;
+
+  /* Loop as long as we are supposed to be running and as long as we have
+   * buffers in-flight.
+   */
+
+  while (priv->running || priv->inflight > 0)
+    {
+      /* Check if we have been asked to terminate.  We have to check if we
+       * still have buffers in-flight.  If we do, then we can't stop until
+       * birds come back to roost.
+       */
+
+      if (priv->terminating && priv->inflight <= 0)
+        {
+          /* We are IDLE.  Break out of the loop and exit. */
+
+          break;
+        }
+      else
+        {
+          /* Check if we can send more audio buffers to the CS4344 */
+
+          cs4344_sendbuffer(priv);
+        }
+
+      /* Wait for messages from our message queue */
+
+      msglen = nxmq_receive(priv->mq, (FAR char *)&msg, sizeof(msg), &prio);
+
+      /* Handle the case when we return with no message */
+
+      if (msglen < sizeof(struct audio_msg_s))
+        {
+          auderr("ERROR: Message too small: %d\n", msglen);
+          continue;
+        }
+
+      /* Process the message */
+
+      switch (msg.msg_id)
+        {
+          /* The ISR has requested more data.  We will catch this case at
+           * the top of the loop.
+           */
+
+          case AUDIO_MSG_DATA_REQUEST:
+            audinfo("AUDIO_MSG_DATA_REQUEST\n");
+            break;
+
+          /* Stop the playback */
+
+#ifndef CONFIG_AUDIO_EXCLUDE_STOP
+          case AUDIO_MSG_STOP:
+
+            /* Indicate that we are terminating */
+
+            audinfo("AUDIO_MSG_STOP: Terminating\n");
+            priv->terminating = true;
+            break;
+#endif
+
+          /* We have a new buffer to send.  We will catch this case at
+           * the top of the loop.
+           */
+
+          case AUDIO_MSG_ENQUEUE:
+            audinfo("AUDIO_MSG_ENQUEUE\n");
+            break;
+
+          /* We will wake up from the I2S callback with this message */
+
+          case AUDIO_MSG_COMPLETE:
+            audinfo("AUDIO_MSG_COMPLETE\n");
+            cs4344_returnbuffers(priv);
+            break;
+
+          default:
+            auderr("ERROR: Ignoring message ID %d\n", msg.msg_id);
+            break;
+        }
+    }
+
+  /* Reset the CS4344 hardware */
+
+  cs4344_reset(priv);
+
+  /* Return any pending buffers in our pending queue */
+
+  cs4344_forcetake(&priv->pendsem);
+  while ((apb = (FAR struct ap_buffer_s *)dq_remfirst(&priv->pendq)) != NULL)
+    {
+      /* Release our reference to the buffer */
+
+      apb_free(apb);
+
+      /* Send the buffer back up to the previous level. */
+
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+      priv->dev.upper(priv->dev.priv, AUDIO_CALLBACK_DEQUEUE, apb, OK, NULL);
+#else
+      priv->dev.upper(priv->dev.priv, AUDIO_CALLBACK_DEQUEUE, apb, OK);
+#endif
+    }
+
+  cs4344_givesem(&priv->pendsem);
+
+  /* Return any pending buffers in our done queue */
+
+  cs4344_returnbuffers(priv);
+
+  /* Close the message queue */
+
+  mq_close(priv->mq);
+  mq_unlink(priv->mqname);
+  priv->mq = NULL;
+
+  /* Send an AUDIO_MSG_COMPLETE message to the client */
+
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+  priv->dev.upper(priv->dev.priv, AUDIO_CALLBACK_COMPLETE, NULL, OK, NULL);
+#else
+  priv->dev.upper(priv->dev.priv, AUDIO_CALLBACK_COMPLETE, NULL, OK);
+#endif
+
+  audinfo("Exit\n");
+  return NULL;
+}
+
+/****************************************************************************
+ * Name: cs4344_reset
+ *
+ * Description:
+ *   Reset and re-initialize the CS4344
+ *
+ * Input Parameters:
+ *   priv - A reference to the driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void cs4344_reset(FAR struct cs4344_dev_s *priv)
+{
+  /* Put audio output back to its initial configuration */
+
+  priv->samprate   = CS4344_DEFAULT_SAMPRATE;
+  priv->nchannels  = CS4344_DEFAULT_NCHANNELS;
+  priv->bpsamp     = CS4344_DEFAULT_BPSAMP;
+
+  /* Configure the FLL and the LRCLK */
+
+  cs4344_setbitrate(priv);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cs4344_initialize
+ *
+ * Description:
+ *   Initialize the CS4344 device.
+ *
+ * Input Parameters:
+ *   i2s     - An I2S driver instance
+ *
+ * Returned Value:
+ *   A new lower half audio interface for the CS4344 device is returned on
+ *   success; NULL is returned on failure.
+ *
+ ****************************************************************************/
+
+FAR struct audio_lowerhalf_s *cs4344_initialize(FAR struct i2s_dev_s *i2s)
+{
+  FAR struct cs4344_dev_s *priv;
+
+  /* Sanity check */
+
+  DEBUGASSERT(i2s);
+
+  /* Allocate a CS4344 device structure */
+
+  priv = (FAR struct cs4344_dev_s *) kmm_zalloc(sizeof(struct cs4344_dev_s));
+  if (priv)
+    {
+      /* Initialize the CS4344 device structure.  Since we used kmm_zalloc,
+       * only the non-zero elements of the structure need to be initialized.
+       */
+
+      priv->dev.ops    = &g_audioops;
+      priv->i2s        = i2s;
+
+      nxsem_init(&priv->pendsem, 0, 1);
+      dq_init(&priv->pendq);
+      dq_init(&priv->doneq);
+
+      /* Reset and reconfigure the CS4344 hardware */
+
+      cs4344_reset(priv);
+      return &priv->dev;
+    }
+
+  nxsem_destroy(&priv->pendsem);
+  kmm_free(priv);
+  return NULL;
+}
diff --git a/drivers/audio/cs4344.h b/drivers/audio/cs4344.h
new file mode 100644
index 0000000..44d914e
--- /dev/null
+++ b/drivers/audio/cs4344.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+ * drivers/audio/cs4344.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __DRIVERS_AUDIO_CS4344_H
+#define __DRIVERS_AUDIO_CS4344_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/compiler.h>
+
+#include <pthread.h>
+#include <mqueue.h>
+
+#include <nuttx/wqueue.h>
+#include <nuttx/fs/ioctl.h>
+
+#ifdef CONFIG_AUDIO
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+#define CS4344_DEFAULT_SAMPRATE      11025     /* Initial sample rate */
+#define CS4344_DEFAULT_NCHANNELS     1         /* Initial number of channels */
+#define CS4344_DEFAULT_BPSAMP        16        /* Initial bits per sample */
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct cs4344_dev_s
+{
+  /* We are an audio lower half driver (We are also the upper "half" of
+   * the CS4344 driver with respect to the board lower half driver).
+   *
+   * Terminology:
+   * Our "lower" half audio instances will be called dev for the publicly
+   * visible version and "priv" for the version that only this driver
+   * knows.  From the point of view of this driver, it is the board lower
+   * "half" that is referred to as "lower".
+   */
+
+  struct audio_lowerhalf_s dev;             /* CS4344 audio lower half (this device) */
+
+  /* Our specific driver data goes here */
+
+  FAR struct i2s_dev_s   *i2s;              /* I2S driver to use */
+  struct dq_queue_s       pendq;            /* Queue of pending buffers to be sent */
+  struct dq_queue_s       doneq;            /* Queue of sent buffers to be returned */
+  mqd_t                   mq;               /* Message queue for receiving messages */
+  char                    mqname[16];       /* Our message queue name */
+  pthread_t               threadid;         /* ID of our thread */
+  uint32_t                bitrate;          /* Actual programmed bit rate */
+  sem_t                   pendsem;          /* Protect pendq */
+  uint16_t                samprate;         /* Configured samprate (samples/sec) */
+  uint8_t                 nchannels;        /* Number of channels (1 or 2) */
+  uint8_t                 bpsamp;           /* Bits per sample (8 or 16) */
+  volatile uint8_t        inflight;         /* Number of audio buffers in-flight */
+  bool                    running;          /* True: Worker thread is running */
+  bool                    paused;           /* True: Playing is paused */
+  bool                    mute;             /* True: Output is muted */
+#ifndef CONFIG_AUDIO_EXCLUDE_STOP
+  bool                    terminating;      /* True: Stop requested */
+#endif
+  bool                    reserved;         /* True: Device is reserved */
+  volatile int            result;           /* The result of the last transfer */
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#endif /* CONFIG_AUDIO */
+#endif /* __DRIVERS_AUDIO_CS4344_H */
diff --git a/include/nuttx/audio/cs4344.h b/include/nuttx/audio/cs4344.h
new file mode 100644
index 0000000..38b5fc9
--- /dev/null
+++ b/include/nuttx/audio/cs4344.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+ * include/nuttx/audio/cs4344.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_AUDIO_CS4344_H
+#define __INCLUDE_NUTTX_AUDIO_CS4344_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <nuttx/irq.h>
+
+#ifdef CONFIG_AUDIO_CS4344
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************
+ *
+ * CONFIG_AUDIO_CS4344 - Enables CS4344 support
+ * CONFIG_CS4344_INFLIGHT - Maximum number of buffers that the CS4344
+ *   driver will send to the I2S driver before any have completed.
+ * CONFIG_CS4344_MSG_PRIO - Priority of messages sent to the CS4344
+ *   worker thread.
+ * CONFIG_CS4344_BUFFER_SIZE - Preferred buffer size
+ * CONFIG_CS4344_NUM_BUFFERS - Preferred number of buffers
+ * CONFIG_CS4344_WORKER_STACKSIZE - Stack size to use when creating the the
+ *   CS4344 worker thread.
+ * CONFIG_CS4344_REGDUMP - Enable logic to dump all CS4344 registers to
+ *   the SYSLOG device.
+ */
+
+/* Pre-requisites */
+
+#ifndef CONFIG_AUDIO
+#  error CONFIG_AUDIO is required for audio subsystem support
+#endif
+
+#ifndef CONFIG_I2S
+#  error CONFIG_I2S is required by the CS4344 driver
+#endif
+
+#ifndef CONFIG_SCHED_WORKQUEUE
+#  error CONFIG_SCHED_WORKQUEUE is required by the CS4344 driver
+#endif
+
+/* Default configuration values */
+
+#ifndef CONFIG_CS4344_INFLIGHT
+#  define CONFIG_CS4344_INFLIGHT          2
+#endif
+
+#if CONFIG_CS4344_INFLIGHT > 255
+#  error CONFIG_CS4344_INFLIGHT must fit in a uint8_t
+#endif
+
+#ifndef CONFIG_CS4344_MSG_PRIO
+#  define CONFIG_CS4344_MSG_PRIO          1
+#endif
+
+#ifndef CONFIG_CS4344_BUFFER_SIZE
+#  define CONFIG_CS4344_BUFFER_SIZE       8192
+#endif
+
+#ifndef CONFIG_CS4344_NUM_BUFFERS
+#  define CONFIG_CS4344_NUM_BUFFERS       4
+#endif
+
+#ifndef CONFIG_CS4344_WORKER_STACKSIZE
+#  define CONFIG_CS4344_WORKER_STACKSIZE  768
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cs4344_initialize
+ *
+ * Description:
+ *   Initialize the CS4344 device.
+ *
+ * Input Parameters:
+ *   i2s     - An I2S driver instance
+ *   lower   - Persistent board configuration data
+ *
+ * Returned Value:
+ *   A new lower half audio interface for the CS4344 device is returned on
+ *   success; NULL is returned on failure.
+ *
+ ****************************************************************************/
+
+struct i2s_dev_s;         /* Forward reference. Defined in include/nuttx/audio/i2s.h */
+struct audio_lowerhalf_s; /* Forward reference. Defined in nuttx/audio/audio.h */
+
+FAR struct audio_lowerhalf_s * cs4344_initialize(FAR struct i2s_dev_s *i2s);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_AUDIO_CS4344 */
+#endif /* __INCLUDE_NUTTX_AUDIO_CS4344_H */


[incubator-nuttx] 02/03: boards/arm/stm32/olimex-stm32-p407: Add support for the CS4344 audio driver.

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit d001c82bc6376f411b34e0dbaacd24004d260a40
Author: Ouss4 <ab...@gmail.com>
AuthorDate: Wed Jun 3 15:45:41 2020 +0100

    boards/arm/stm32/olimex-stm32-p407: Add support for the CS4344 audio
    driver.
---
 .../olimex-stm32-p407/configs/audio/defconfig      |  78 ++++++++++
 boards/arm/stm32/olimex-stm32-p407/include/board.h |  18 +++
 boards/arm/stm32/olimex-stm32-p407/src/Make.defs   |   4 +
 .../olimex-stm32-p407/src/olimex-stm32-p407.h      |  34 +++++
 .../stm32/olimex-stm32-p407/src/stm32_bringup.c    |  10 ++
 .../arm/stm32/olimex-stm32-p407/src/stm32_cs4344.c | 169 +++++++++++++++++++++
 6 files changed, 313 insertions(+)

diff --git a/boards/arm/stm32/olimex-stm32-p407/configs/audio/defconfig b/boards/arm/stm32/olimex-stm32-p407/configs/audio/defconfig
new file mode 100644
index 0000000..8dbdbd0
--- /dev/null
+++ b/boards/arm/stm32/olimex-stm32-p407/configs/audio/defconfig
@@ -0,0 +1,78 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="olimex-stm32-p407"
+CONFIG_ARCH_BOARD_OLIMEX_STM32P407=y
+CONFIG_ARCH_BUTTONS=y
+CONFIG_ARCH_CHIP="stm32"
+CONFIG_ARCH_CHIP_STM32=y
+CONFIG_ARCH_CHIP_STM32F407ZG=y
+CONFIG_ARCH_IRQBUTTONS=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_AUDIO=y
+CONFIG_AUDIO_CS4344=y
+CONFIG_AUDIO_EXCLUDE_TONE=y
+CONFIG_AUDIO_EXCLUDE_VOLUME=y
+CONFIG_AUDIO_I2S=y
+CONFIG_BOARD_LATE_INITIALIZE=y
+CONFIG_BOARD_LOOPSPERMSEC=16717
+CONFIG_BUILTIN=y
+CONFIG_DRIVERS_AUDIO=y
+CONFIG_FAT_LCNAMES=y
+CONFIG_FAT_LFN=y
+CONFIG_FS_FAT=y
+CONFIG_FS_PROCFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_INTELHEX_BINARY=y
+CONFIG_MAX_TASKS=16
+CONFIG_MAX_WDOGPARMS=2
+CONFIG_NFILE_DESCRIPTORS=8
+CONFIG_NFILE_STREAMS=8
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_DISABLE_GET=y
+CONFIG_NSH_DISABLE_IFUPDOWN=y
+CONFIG_NSH_DISABLE_PUT=y
+CONFIG_NSH_DISABLE_WGET=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_LINELEN=64
+CONFIG_NSH_READLINE=y
+CONFIG_NXPLAYER_DEFAULT_MEDIADIR="/mnt/music"
+CONFIG_PREALLOC_MQ_MSGS=4
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_PREALLOC_WDOGS=8
+CONFIG_RAM_SIZE=131072
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_HPWORK=y
+CONFIG_SCHED_HPWORKPRIORITY=192
+CONFIG_SCHED_WAITPID=y
+CONFIG_SDCLONE_DISABLE=y
+CONFIG_START_YEAR=2013
+CONFIG_STM32_DISABLE_IDLE_SLEEP_DURING_DEBUG=y
+CONFIG_STM32_DMA1=y
+CONFIG_STM32_I2S3=y
+CONFIG_STM32_I2S3_TX=y
+CONFIG_STM32_I2S_MCK=y
+CONFIG_STM32_JTAG_SW_ENABLE=y
+CONFIG_STM32_OTGFS=y
+CONFIG_STM32_PWR=y
+CONFIG_STM32_SPI3=y
+CONFIG_STM32_SPI3_DMA=y
+CONFIG_STM32_SPI_DMA=y
+CONFIG_STM32_USART3=y
+CONFIG_STM32_USBHOST=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_SYSTEM_NSH_CXXINITIALIZE=y
+CONFIG_SYSTEM_NXPLAYER=y
+CONFIG_TASK_NAME_SIZE=32
+CONFIG_USART3_SERIAL_CONSOLE=y
+CONFIG_USBHOST_MSC=y
+CONFIG_USER_ENTRYPOINT="nsh_main"
+CONFIG_WDOG_INTRESERVE=1
diff --git a/boards/arm/stm32/olimex-stm32-p407/include/board.h b/boards/arm/stm32/olimex-stm32-p407/include/board.h
index e906dd5..e5f5992 100644
--- a/boards/arm/stm32/olimex-stm32-p407/include/board.h
+++ b/boards/arm/stm32/olimex-stm32-p407/include/board.h
@@ -341,4 +341,22 @@
 #define BOARD_DHTXX_GPIO_OUTPUT  GPIO_DHTXX_PIN_OUTPUT
 #define BOARD_DHTXX_FRTIMER      1  /* Free-run timer 1 */
 
+/* SPI3 DMA -- As used for I2S DMA transfer with the audio configuration */
+
+#define GPIO_SPI3_MISO    GPIO_SPI3_MISO_1
+#define GPIO_SPI3_MOSI    GPIO_SPI3_MOSI_1
+#define GPIO_SPI3_SCK     GPIO_SPI3_SCK_1
+
+#define DMACHAN_SPI3_RX   DMAMAP_SPI3_RX_1
+#define DMACHAN_SPI3_TX   DMAMAP_SPI3_TX_1
+
+/* I2S3 - CS4344 configuration uses I2S3 */
+
+#define GPIO_I2S3_SD      GPIO_I2S3_SD_1
+#define GPIO_I2S3_CK      GPIO_I2S3_CK_1
+#define GPIO_I2S3_WS      GPIO_I2S3_WS_2
+
+#define DMACHAN_I2S3_RX   DMAMAP_SPI3_RX_2
+#define DMACHAN_I2S3_TX   DMAMAP_SPI3_TX_2
+
 #endif /* __BOARDS_ARM_STM32_OLIMEX_STM32_P407_INCLUDE_BOARD_H */
diff --git a/boards/arm/stm32/olimex-stm32-p407/src/Make.defs b/boards/arm/stm32/olimex-stm32-p407/src/Make.defs
index 7272d4b..7274cc9 100644
--- a/boards/arm/stm32/olimex-stm32-p407/src/Make.defs
+++ b/boards/arm/stm32/olimex-stm32-p407/src/Make.defs
@@ -67,6 +67,10 @@ ifeq ($(CONFIG_CAN),y)
   CSRCS += stm32_can.c
 endif
 
+ifeq ($(CONFIG_AUDIO_CS4344),y)
+  CSRCS += stm32_cs4344.c
+endif
+
 DEPPATH += --dep-path board
 VPATH += :board
 CFLAGS += $(shell $(INCDIR) "$(CC)" $(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)board)
diff --git a/boards/arm/stm32/olimex-stm32-p407/src/olimex-stm32-p407.h b/boards/arm/stm32/olimex-stm32-p407/src/olimex-stm32-p407.h
index f3abd4a..c5e380a 100644
--- a/boards/arm/stm32/olimex-stm32-p407/src/olimex-stm32-p407.h
+++ b/boards/arm/stm32/olimex-stm32-p407/src/olimex-stm32-p407.h
@@ -48,6 +48,7 @@
 #include <nuttx/config.h>
 #include <nuttx/compiler.h>
 #include <stdint.h>
+#include <arch/stm32/chip.h>
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -187,6 +188,18 @@
 #  define GPIO_OTGFS_OVER (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN10)
 #endif
 
+/* The CS4344 depends on the CS4344 driver and I2S3 support */
+
+#if defined(CONFIG_AUDIO_CS4344) && defined(CONFIG_STM32_I2S3)
+#  define HAVE_CS4344
+#endif
+
+#ifdef HAVE_CS4344
+  /* The CS4344 transfers data on I2S3 */
+
+#  define CS4344_I2S_BUS      3
+#endif
+
 #ifndef __ASSEMBLY__
 
 /****************************************************************************
@@ -290,5 +303,26 @@ int stm32_adc_setup(void);
 int stm32_can_setup(void);
 #endif
 
+/****************************************************************************
+ * Name: stm32_cs4344_initialize
+ *
+ * Description:
+ *   This function is called by platform-specific, setup logic to configure
+ *   and register the CS4344 device.  This function will register the driver
+ *   as /dev/audio/pcm[x] where x is determined by the minor device number.
+ *
+ * Input Parameters:
+ *   minor - The input device minor number
+ *
+ * Returned Value:
+ *   Zero is returned on success.  Otherwise, a negated errno value is
+ *   returned to indicate the nature of the failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_AUDIO_CS4344
+int stm32_cs4344_initialize(int minor);
+#endif
+
 #endif /* __ASSEMBLY__ */
 #endif /* __BOARDS_ARM_STM32_OLIMEX_STM32_P407_SRC_H */
diff --git a/boards/arm/stm32/olimex-stm32-p407/src/stm32_bringup.c b/boards/arm/stm32/olimex-stm32-p407/src/stm32_bringup.c
index 8ba3ae8..7431d87 100644
--- a/boards/arm/stm32/olimex-stm32-p407/src/stm32_bringup.c
+++ b/boards/arm/stm32/olimex-stm32-p407/src/stm32_bringup.c
@@ -213,6 +213,16 @@ int stm32_bringup(void)
     }
 #endif
 
+#ifdef HAVE_CS4344
+  /* Configure CS4344 audio */
+
+  ret = stm32_cs4344_initialize(1);
+  if (ret != OK)
+    {
+      serr("Failed to initialize CS43L22 audio: %d\n", ret);
+    }
+#endif
+
   UNUSED(ret);
   return OK;
 }
diff --git a/boards/arm/stm32/olimex-stm32-p407/src/stm32_cs4344.c b/boards/arm/stm32/olimex-stm32-p407/src/stm32_cs4344.c
new file mode 100644
index 0000000..9ddac44
--- /dev/null
+++ b/boards/arm/stm32/olimex-stm32-p407/src/stm32_cs4344.c
@@ -0,0 +1,169 @@
+/****************************************************************************
+ * boards/arm/stm32/stm32f4discovery/src/stm32_cs4344.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <debug.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/audio/i2s.h>
+#include <nuttx/audio/pcm.h>
+#include <nuttx/audio/cs4344.h>
+
+#include <arch/board/board.h>
+
+#include "stm32.h"
+#include "olimex-stm32-p407.h"
+
+#ifdef HAVE_CS4344
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_cs4344_initialize
+ *
+ * Description:
+ *   This function is called by platform-specific, setup logic to configure
+ *   and register the CS4344 device.  This function will register the driver
+ *   as /dev/audio/pcm[x] where x is determined by the minor device number.
+ *
+ * Input Parameters:
+ *   minor - The input device minor number
+ *
+ * Returned Value:
+ *   Zero is returned on success.  Otherwise, a negated errno value is
+ *   returned to indicate the nature of the failure.
+ *
+ ****************************************************************************/
+
+int stm32_cs4344_initialize(int minor)
+{
+  FAR struct audio_lowerhalf_s *cs4344;
+  FAR struct audio_lowerhalf_s *pcm;
+  FAR struct i2s_dev_s *i2s;
+  static bool initialized = false;
+  char devname[12];
+  int ret;
+
+  audinfo("minor %d\n", minor);
+  DEBUGASSERT(minor >= 0 && minor <= 25);
+
+  /* Have we already initialized?  Since we never uninitialize we must prevent
+   * multiple initializations.  This is necessary, for example, when the
+   * touchscreen example is used as a built-in application in NSH and can be
+   * called numerous time.  It will attempt to initialize each time.
+   */
+
+  if (!initialized)
+    {
+      /* Get an instance of the I2S interface for the CS4344 data channel */
+
+      i2s = stm32_i2sbus_initialize(CS4344_I2S_BUS);
+      if (!i2s)
+        {
+          auderr("ERROR: Failed to initialize I2S%d\n", CS4344_I2S_BUS);
+          ret = -ENODEV;
+          goto errout;
+        }
+
+      /* Now we can use this I2S interface to initialize the CS4344 which
+       * will return an audio interface.
+       */
+
+      cs4344 = cs4344_initialize(i2s);
+      if (!cs4344)
+        {
+          auderr("ERROR: Failed to initialize the CS4344\n");
+          ret = -ENODEV;
+          goto errout;
+        }
+
+      /* No we can embed the CS4344/I2S conglomerate into a PCM decoder
+       * instance so that we will have a PCM front end for the the CS4344
+       * driver.
+       */
+
+      pcm = pcm_decode_initialize(cs4344);
+      if (!pcm)
+        {
+          auderr("ERROR: Failed create the PCM decoder\n");
+          ret = -ENODEV;
+          goto errout;
+        }
+
+      /* Create a device name */
+
+      snprintf(devname, 12, "pcm%d",  minor);
+
+      /* Finally, we can register the PCM/CS4344/I2S audio device.
+       *
+       * Is anyone young enough to remember Rube Goldberg?
+       */
+
+      ret = audio_register(devname, pcm);
+      if (ret < 0)
+        {
+          auderr("ERROR: Failed to register /dev/%s device: %d\n",
+                 devname, ret);
+          goto errout;
+        }
+
+      /* Now we are initialized */
+
+      initialized = true;
+    }
+
+  return OK;
+
+errout:
+  return ret;
+}
+
+#endif /* HAVE_CS4344 */


[incubator-nuttx] 03/03: Fix PR1201 nxstyle issues.

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 36f54e280fa0041d2b353d8f4bf4dfb82ebc8fec
Author: Ouss4 <ab...@gmail.com>
AuthorDate: Fri Jun 5 18:41:58 2020 +0100

    Fix PR1201 nxstyle issues.
---
 boards/arm/stm32/olimex-stm32-p407/src/stm32_cs4344.c | 9 +++++----
 drivers/audio/cs4344.c                                | 8 ++++----
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/boards/arm/stm32/olimex-stm32-p407/src/stm32_cs4344.c b/boards/arm/stm32/olimex-stm32-p407/src/stm32_cs4344.c
index 9ddac44..51ea0d1 100644
--- a/boards/arm/stm32/olimex-stm32-p407/src/stm32_cs4344.c
+++ b/boards/arm/stm32/olimex-stm32-p407/src/stm32_cs4344.c
@@ -95,10 +95,11 @@ int stm32_cs4344_initialize(int minor)
   audinfo("minor %d\n", minor);
   DEBUGASSERT(minor >= 0 && minor <= 25);
 
-  /* Have we already initialized?  Since we never uninitialize we must prevent
-   * multiple initializations.  This is necessary, for example, when the
-   * touchscreen example is used as a built-in application in NSH and can be
-   * called numerous time.  It will attempt to initialize each time.
+  /* Have we already initialized?  Since we never uninitialize we must
+   * prevent multiple initializations.  This is necessary, for example,
+   * when the touchscreen example is used as a built-in application in
+   * NSH and can be called numerous time.  It will attempt to initialize
+   * each time.
    */
 
   if (!initialized)
diff --git a/drivers/audio/cs4344.c b/drivers/audio/cs4344.c
index 0c2619b..907ef4c 100644
--- a/drivers/audio/cs4344.c
+++ b/drivers/audio/cs4344.c
@@ -146,13 +146,13 @@ static const struct audio_ops_s g_audioops =
   cs4344_pause,         /* pause */
   cs4344_resume,        /* resume */
 #endif
-  NULL,                  /* allocbuffer */
-  NULL,                  /* freebuffer */
+  NULL,                 /* allocbuffer */
+  NULL,                 /* freebuffer */
   cs4344_enqueuebuffer, /* enqueue_buffer */
   cs4344_cancelbuffer,  /* cancel_buffer */
   cs4344_ioctl,         /* ioctl */
-  NULL,                  /* read */
-  NULL,                  /* write */
+  NULL,                 /* read */
+  NULL,                 /* write */
   cs4344_reserve,       /* reserve */
   cs4344_release        /* release */
 };