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/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 7eeba71366 audio: add audio_dma device driver.
7eeba71366 is described below

commit 7eeba713666dbc4a6c31fa3d730073b97a753fdd
Author: ZhongAn <[email protected]>
AuthorDate: Mon Jun 25 20:22:32 2018 +0800

    audio: add audio_dma device driver.
    
    Signed-off-by: ZhongAn <[email protected]>
---
 drivers/audio/Kconfig           |   6 +
 drivers/audio/Make.defs         |   4 +
 drivers/audio/audio_dma.c       | 613 ++++++++++++++++++++++++++++++++++++++++
 include/nuttx/audio/audio_dma.h |  41 +++
 4 files changed, 664 insertions(+)

diff --git a/drivers/audio/Kconfig b/drivers/audio/Kconfig
index dd6c628a64..6437d7e317 100644
--- a/drivers/audio/Kconfig
+++ b/drivers/audio/Kconfig
@@ -492,4 +492,10 @@ config AUDIO_I2S
        depends on AUDIO
        depends on I2S
 
+config AUDIO_DMA
+        bool "Audio DMA"
+        select AUDIO_DRIVER_SPECIFIC_BUFFERS
+        depends on AUDIO
+        depends on DMA
+
 endif # DRIVERS_AUDIO
diff --git a/drivers/audio/Make.defs b/drivers/audio/Make.defs
index 33109cba24..31de28713c 100644
--- a/drivers/audio/Make.defs
+++ b/drivers/audio/Make.defs
@@ -93,6 +93,10 @@ ifeq ($(CONFIG_AUDIO_I2S),y)
 CSRCS += audio_i2s.c
 endif
 
+ifeq ($(CONFIG_AUDIO_DMA),y)
+CSRCS += audio_dma.c
+endif
+
 # Include Audio driver support
 
 DEPPATH += --dep-path audio
diff --git a/drivers/audio/audio_dma.c b/drivers/audio/audio_dma.c
new file mode 100644
index 0000000000..700a393a8c
--- /dev/null
+++ b/drivers/audio/audio_dma.c
@@ -0,0 +1,613 @@
+/****************************************************************************
+ * drivers/audio/audio_dma.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 <nuttx/audio/audio_dma.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/queue.h>
+
+#include <debug.h>
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct audio_dma_s
+{
+  struct audio_lowerhalf_s dev;
+  struct dma_chan_s *chan;
+  uintptr_t src_addr;
+  uintptr_t dst_addr;
+  uint8_t *alloc_addr;
+  uint8_t alloc_index;
+  uint8_t fifo_width;
+  bool playback;
+  bool xrun;
+  struct dq_queue_s pendq;
+  apb_samp_t buffer_size;
+  apb_samp_t buffer_num;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int audio_dma_getcaps(struct audio_lowerhalf_s *dev, int type,
+                             struct audio_caps_s *caps);
+static int audio_dma_shutdown(struct audio_lowerhalf_s *dev);
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int audio_dma_configure(struct audio_lowerhalf_s *dev,
+                               void *session,
+                               const struct audio_caps_s *caps);
+static int audio_dma_start(struct audio_lowerhalf_s *dev,
+                           void *session);
+#ifndef CONFIG_AUDIO_EXCLUDE_STOP
+static int audio_dma_stop(struct audio_lowerhalf_s *dev, void *session);
+#endif
+#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
+static int audio_dma_pause(struct audio_lowerhalf_s *dev,
+                           void *session);
+static int audio_dma_resume(struct audio_lowerhalf_s *dev,
+                            void *session);
+#endif
+static int audio_dma_reserve(struct audio_lowerhalf_s *dev,
+                             void **session);
+static int audio_dma_release(struct audio_lowerhalf_s *dev,
+                             void *session);
+#else
+static int audio_dma_configure(struct audio_lowerhalf_s *dev,
+                               const struct audio_caps_s *caps);
+static int audio_dma_start(struct audio_lowerhalf_s *dev);
+#ifndef CONFIG_AUDIO_EXCLUDE_STOP
+static int audio_dma_stop(struct audio_lowerhalf_s *dev);
+#endif
+#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
+static int audio_dma_pause(struct audio_lowerhalf_s *dev);
+static int audio_dma_resume(struct audio_lowerhalf_s *dev);
+#endif
+static int audio_dma_reserve(struct audio_lowerhalf_s *dev);
+static int audio_dma_release(struct audio_lowerhalf_s *dev);
+#endif
+static int audio_dma_allocbuffer(struct audio_lowerhalf_s *dev,
+                                 struct audio_buf_desc_s *bufdesc);
+static int audio_dma_freebuffer(struct audio_lowerhalf_s *dev,
+                                struct audio_buf_desc_s *bufdesc);
+static int audio_dma_enqueuebuffer(struct audio_lowerhalf_s *dev,
+                                   struct ap_buffer_s *apb);
+static int audio_dma_ioctl(struct audio_lowerhalf_s *dev, int cmd,
+                           unsigned long arg);
+static void audio_dma_callback(struct dma_chan_s *chan, void *arg,
+                               ssize_t len);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct audio_ops_s g_audio_dma_ops =
+{
+  .getcaps = audio_dma_getcaps,
+  .configure = audio_dma_configure,
+  .shutdown = audio_dma_shutdown,
+  .start = audio_dma_start,
+#ifndef CONFIG_AUDIO_EXCLUDE_STOP
+  .stop = audio_dma_stop,
+#endif
+#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
+  .pause = audio_dma_pause,
+  .resume = audio_dma_resume,
+#endif
+  .allocbuffer = audio_dma_allocbuffer,
+  .freebuffer = audio_dma_freebuffer,
+  .enqueuebuffer = audio_dma_enqueuebuffer,
+  .ioctl = audio_dma_ioctl,
+  .reserve = audio_dma_reserve,
+  .release = audio_dma_release,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int audio_dma_getcaps(struct audio_lowerhalf_s *dev, int type,
+                             struct audio_caps_s *caps)
+{
+  struct audio_dma_s *audio_dma = (struct audio_dma_s *)dev;
+
+  /* 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 */
+
+              if (audio_dma->playback)
+                caps->ac_controls.b[0] = AUDIO_TYPE_OUTPUT;
+              else
+                caps->ac_controls.b[0] = AUDIO_TYPE_INPUT;
+              caps->ac_format.hw = 1 << (AUDIO_FMT_PCM - 1);
+              break;
+
+            default:
+              caps->ac_controls.b[0] = AUDIO_SUBFMT_END;
+              break;
+          }
+
+        break;
+
+        /* Provide capabilities of our OUTPUT unit */
+
+      case AUDIO_TYPE_OUTPUT:
+      case AUDIO_TYPE_INPUT:
+
+        caps->ac_channels = 2;
+
+        switch (caps->ac_subtype)
+          {
+            case AUDIO_TYPE_QUERY:
+
+            /* Report the Sample rates we support */
+
+              caps->ac_controls.hw[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 |
+                                        AUDIO_SAMP_RATE_96K |
+                                        AUDIO_SAMP_RATE_128K |
+                                        AUDIO_SAMP_RATE_160K |
+                                        AUDIO_SAMP_RATE_172K |
+                                        AUDIO_SAMP_RATE_192K;
+              break;
+          }
+
+        break;
+   }
+
+  /* Return the length of the audio_caps_s struct for validation of
+   * proper Audio device type.
+   */
+
+  return caps->ac_len;
+}
+
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int audio_dma_configure(struct audio_lowerhalf_s *dev,
+                               void *session,
+                               const struct audio_caps_s *caps)
+#else
+static int audio_dma_configure(struct audio_lowerhalf_s *dev,
+                               const struct audio_caps_s *caps)
+#endif
+{
+  struct audio_dma_s *audio_dma = (struct audio_dma_s *)dev;
+  struct dma_config_s cfg;
+  int ret = -EINVAL;
+
+  DEBUGASSERT(audio_dma && caps);
+  audinfo("ac_type: %d\n", caps->ac_type);
+
+  /* Process the configure operation */
+
+  switch (caps->ac_type)
+    {
+      case AUDIO_TYPE_OUTPUT:
+        if (audio_dma->playback)
+          {
+            memset(&cfg, 0, sizeof(struct dma_config_s));
+            cfg.direction = DMA_MEM_TO_DEV;
+            if (audio_dma->fifo_width)
+              cfg.dst_width = audio_dma->fifo_width;
+            else
+              cfg.dst_width = caps->ac_controls.b[2] / 8;
+            ret = DMA_CONFIG(audio_dma->chan, &cfg);
+          }
+        break;
+      case AUDIO_TYPE_INPUT:
+        if (!audio_dma->playback)
+          {
+            memset(&cfg, 0, sizeof(struct dma_config_s));
+            cfg.direction = DMA_DEV_TO_MEM;
+            if (audio_dma->fifo_width)
+              cfg.src_width = audio_dma->fifo_width;
+            else
+              cfg.src_width = caps->ac_controls.b[2] / 8;
+            ret = DMA_CONFIG(audio_dma->chan, &cfg);
+          }
+        break;
+      default:
+        ret = -ENOTTY;
+        break;
+    }
+
+  return ret;
+}
+
+static int audio_dma_shutdown(struct audio_lowerhalf_s *dev)
+{
+  /* apps enqueued buffers, but doesn't start. stop here to
+   * clear audio_dma->pendq.
+   */
+
+#ifndef CONFIG_AUDIO_EXCLUDE_STOP
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+  audio_dma_stop(dev, NULL);
+#else
+  audio_dma_stop(dev);
+#endif
+#endif
+
+  return OK;
+}
+
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int audio_dma_start(struct audio_lowerhalf_s *dev, void *session)
+#else
+static int audio_dma_start(struct audio_lowerhalf_s *dev)
+#endif
+{
+  struct audio_dma_s *audio_dma = (struct audio_dma_s *)dev;
+
+  return DMA_START_CYCLIC(audio_dma->chan, audio_dma_callback, audio_dma,
+                          audio_dma->dst_addr, audio_dma->src_addr,
+                          audio_dma->buffer_num * audio_dma->buffer_size,
+                          audio_dma->buffer_size);
+}
+
+#ifndef CONFIG_AUDIO_EXCLUDE_STOP
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int audio_dma_stop(struct audio_lowerhalf_s *dev, void *session)
+#else
+static int audio_dma_stop(struct audio_lowerhalf_s *dev)
+#endif
+{
+  struct audio_dma_s *audio_dma = (struct audio_dma_s *)dev;
+  struct ap_buffer_s *apb;
+
+  DMA_STOP(audio_dma->chan);
+
+  while (!dq_empty(&audio_dma->pendq))
+    {
+      apb = (struct ap_buffer_s *)dq_remfirst(&audio_dma->pendq);
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+      audio_dma->dev.upper(audio_dma->dev.priv, AUDIO_CALLBACK_DEQUEUE,
+                           apb, OK, NULL);
+#else
+      audio_dma->dev.upper(audio_dma->dev.priv, AUDIO_CALLBACK_DEQUEUE,
+                           apb, OK);
+#endif
+    }
+
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+  audio_dma->dev.upper(audio_dma->dev.priv, AUDIO_CALLBACK_COMPLETE,
+                       NULL, OK, NULL);
+#else
+  audio_dma->dev.upper(audio_dma->dev.priv, AUDIO_CALLBACK_COMPLETE,
+                       NULL, OK);
+#endif
+  audio_dma->xrun = false;
+  return OK;
+}
+#endif
+
+#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int audio_dma_pause(struct audio_lowerhalf_s *dev, void *session)
+#else
+static int audio_dma_pause(struct audio_lowerhalf_s *dev)
+#endif
+{
+  struct audio_dma_s *audio_dma = (struct audio_dma_s *)dev;
+
+  return DMA_PAUSE(audio_dma->chan);
+}
+
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int audio_dma_resume(struct audio_lowerhalf_s *dev, void *session)
+#else
+static int audio_dma_resume(struct audio_lowerhalf_s *dev)
+#endif
+{
+  struct audio_dma_s *audio_dma = (struct audio_dma_s *)dev;
+
+  if (dq_empty(&audio_dma->pendq))
+    {
+      return -EINVAL;
+    }
+
+  return DMA_RESUME(audio_dma->chan);
+}
+#endif
+
+static int audio_dma_allocbuffer(struct audio_lowerhalf_s *dev,
+                                 struct audio_buf_desc_s *bufdesc)
+{
+  struct audio_dma_s *audio_dma = (struct audio_dma_s *)dev;
+  struct ap_buffer_s *apb;
+
+  if (bufdesc->numbytes != audio_dma->buffer_size)
+    {
+      return -EINVAL;
+    }
+
+  if (audio_dma->alloc_index == audio_dma->buffer_num)
+    {
+      return -ENOMEM;
+    }
+
+  if (!audio_dma->alloc_addr)
+    {
+      audio_dma->alloc_addr = kumm_memalign(32,
+                                            audio_dma->buffer_num *
+                                            audio_dma->buffer_size);
+      if (!audio_dma->alloc_addr)
+        {
+          return -ENOMEM;
+        }
+
+      if (audio_dma->playback)
+        audio_dma->src_addr = up_addrenv_va_to_pa(audio_dma->alloc_addr);
+      else
+        audio_dma->dst_addr = up_addrenv_va_to_pa(audio_dma->alloc_addr);
+    }
+
+  apb = kumm_zalloc(sizeof(struct ap_buffer_s));
+  *bufdesc->u.pbuffer = apb;
+
+  /* Test if the allocation was successful or not */
+
+  if (*bufdesc->u.pbuffer == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  /* Populate the buffer contents */
+
+  apb->i.channels = 2;
+  apb->crefs      = 1;
+  apb->nmaxbytes  = audio_dma->buffer_size;
+  apb->samp = audio_dma->alloc_addr +
+              audio_dma->alloc_index *
+              audio_dma->buffer_size;
+  audio_dma->alloc_index++;
+  nxmutex_init(&apb->lock);
+
+  return sizeof(struct audio_buf_desc_s);
+}
+
+static int audio_dma_freebuffer(struct audio_lowerhalf_s *dev,
+                                struct audio_buf_desc_s *bufdesc)
+{
+  struct audio_dma_s *audio_dma = (struct audio_dma_s *)dev;
+  struct ap_buffer_s *apb;
+
+  apb = bufdesc->u.buffer;
+  audio_dma->alloc_index--;
+  nxmutex_destroy(&apb->lock);
+  kumm_free(apb);
+
+  if (audio_dma->alloc_index == 0)
+    {
+      kumm_free(audio_dma->alloc_addr);
+      audio_dma->alloc_addr = NULL;
+    }
+
+  return sizeof(struct audio_buf_desc_s);
+}
+
+static int audio_dma_enqueuebuffer(struct audio_lowerhalf_s *dev,
+                                   struct ap_buffer_s *apb)
+{
+  struct audio_dma_s *audio_dma = (struct audio_dma_s *)dev;
+  irqstate_t flags;
+
+  if (audio_dma->playback)
+    up_clean_dcache((uintptr_t)apb->samp,
+                    (uintptr_t)apb->samp + apb->nbytes);
+
+  apb->flags |= AUDIO_APB_OUTPUT_ENQUEUED;
+
+  flags = enter_critical_section();
+  dq_addlast(&apb->dq_entry, &audio_dma->pendq);
+  leave_critical_section(flags);
+
+  if (audio_dma->xrun)
+    {
+      audio_dma->xrun = false;
+      return audio_dma_resume(dev);
+    }
+
+  return OK;
+}
+
+static int audio_dma_ioctl(struct audio_lowerhalf_s *dev, int cmd,
+                           unsigned long arg)
+{
+  struct audio_dma_s *audio_dma = (struct audio_dma_s *)dev;
+  struct ap_buffer_info_s *bufinfo;
+
+  switch (cmd)
+    {
+      /* Report our preferred buffer size and quantity */
+
+      case AUDIOIOC_GETBUFFERINFO:
+        audinfo("AUDIOIOC_GETBUFFERINFO:\n");
+        bufinfo              = (struct ap_buffer_info_s *)arg;
+        bufinfo->buffer_size = audio_dma->buffer_size;
+        bufinfo->nbuffers    = audio_dma->buffer_num;
+
+        return OK;
+
+      case AUDIOIOC_SETBUFFERINFO:
+        audinfo("AUDIOIOC_GETBUFFERINFO:\n");
+        bufinfo                = (struct ap_buffer_info_s *)arg;
+        audio_dma->buffer_size = bufinfo->buffer_size;
+        audio_dma->buffer_num  = bufinfo->nbuffers;
+        kumm_free(audio_dma->alloc_addr);
+        audio_dma->alloc_addr = NULL;
+        audio_dma->alloc_index = 0;
+
+        return OK;
+    }
+
+  return -ENOTTY;
+}
+
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int audio_dma_reserve(struct audio_lowerhalf_s *dev, void **session)
+#else
+static int audio_dma_reserve(struct audio_lowerhalf_s *dev)
+#endif
+{
+  return OK;
+}
+
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+static int audio_dma_release(struct audio_lowerhalf_s *dev, void *session)
+#else
+static int audio_dma_release(struct audio_lowerhalf_s *dev)
+#endif
+{
+  return OK;
+}
+
+static void audio_dma_callback(struct dma_chan_s *chan,
+                               void *arg, ssize_t len)
+{
+  struct audio_dma_s *audio_dma = (struct audio_dma_s *)arg;
+  struct ap_buffer_s *apb;
+  bool final = false;
+
+  apb = (struct ap_buffer_s *)dq_remfirst(&audio_dma->pendq);
+  if (!apb)
+    {
+      /* xrun */
+
+      DMA_PAUSE(audio_dma->chan);
+      audio_dma->xrun = true;
+      return;
+    }
+
+  if (!audio_dma->playback)
+    up_invalidate_dcache((uintptr_t)apb->samp,
+                         (uintptr_t)apb->samp + apb->nbytes);
+
+  if ((apb->flags & AUDIO_APB_FINAL) != 0)
+    final = true;
+
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+    audio_dma->dev.upper(audio_dma->dev.priv, AUDIO_CALLBACK_DEQUEUE,
+                         apb, OK, NULL);
+#else
+    audio_dma->dev.upper(audio_dma->dev.priv, AUDIO_CALLBACK_DEQUEUE,
+                         apb, OK);
+#endif
+  if (final)
+    {
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+      audio_dma_stop(&audio_dma->dev, NULL);
+#else
+      audio_dma_stop(&audio_dma->dev);
+#endif
+    }
+  else if (dq_empty(&audio_dma->pendq))
+    {
+      /* xrun */
+
+      DMA_PAUSE(audio_dma->chan);
+      audio_dma->xrun = true;
+    }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+struct audio_lowerhalf_s *audio_dma_initialize(struct dma_dev_s *dma_dev,
+                                               uint8_t chan_num,
+                                               bool playback,
+                                               uint8_t fifo_width,
+                                               uintptr_t fifo_addr)
+{
+  struct audio_dma_s *audio_dma;
+
+  if (!dma_dev)
+    {
+      return NULL;
+    }
+
+  audio_dma = kmm_zalloc(sizeof(struct audio_dma_s));
+  if (!audio_dma)
+    {
+      return NULL;
+    }
+
+  audio_dma->chan = DMA_GET_CHAN(dma_dev, chan_num);
+  if (!audio_dma->chan)
+    {
+      kmm_free(audio_dma);
+      return NULL;
+    }
+
+  audio_dma->playback = playback;
+  audio_dma->fifo_width = fifo_width;
+
+  if (audio_dma->playback)
+    audio_dma->dst_addr = up_addrenv_va_to_pa((void *)fifo_addr);
+  else
+    audio_dma->src_addr = up_addrenv_va_to_pa((void *)fifo_addr);
+
+  audio_dma->buffer_size = CONFIG_AUDIO_BUFFER_NUMBYTES;
+  audio_dma->buffer_num  = CONFIG_AUDIO_NUM_BUFFERS;
+  dq_init(&audio_dma->pendq);
+
+  audio_dma->dev.ops = &g_audio_dma_ops;
+  return &audio_dma->dev;
+}
diff --git a/include/nuttx/audio/audio_dma.h b/include/nuttx/audio/audio_dma.h
new file mode 100644
index 0000000000..4ad79431ab
--- /dev/null
+++ b/include/nuttx/audio/audio_dma.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+ * include/nuttx/audio/audio_dma.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_AUDIO_DMA_H
+#define __INCLUDE_NUTTX_AUDIO_AUDIO_DMA_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/audio/audio.h>
+#include <nuttx/dma/dma.h>
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+struct audio_lowerhalf_s *audio_dma_initialize(struct dma_dev_s *dma_dev,
+                                               uint8_t chan_num,
+                                               bool playback,
+                                               uint8_t fifo_width,
+                                               uintptr_t fifo_addr);
+#endif

Reply via email to