diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-07-23 10:12:32 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-07-23 10:12:32 -0600 |
commit | a21d23eca9cb5321a98b0d0e2c21e0c71a029bcf (patch) | |
tree | d312bfae6da7ee6cd38681361a0f388e0104fc2f /nuttx/drivers/audio | |
parent | 4d28fb87602303f98eb520f63a058b690c722a7b (diff) | |
download | nuttx-a21d23eca9cb5321a98b0d0e2c21e0c71a029bcf.tar.gz nuttx-a21d23eca9cb5321a98b0d0e2c21e0c71a029bcf.tar.bz2 nuttx-a21d23eca9cb5321a98b0d0e2c21e0c71a029bcf.zip |
Audio: Add a NULL audio device that can be used to simply unit-level testing of audio decoders
Diffstat (limited to 'nuttx/drivers/audio')
-rw-r--r-- | nuttx/drivers/audio/Kconfig | 52 | ||||
-rw-r--r-- | nuttx/drivers/audio/Make.defs | 4 | ||||
-rw-r--r-- | nuttx/drivers/audio/audio_null.c | 764 | ||||
-rw-r--r-- | nuttx/drivers/audio/wm8904.c | 13 |
4 files changed, 824 insertions, 9 deletions
diff --git a/nuttx/drivers/audio/Kconfig b/nuttx/drivers/audio/Kconfig index c6649750f..039b8a0dd 100644 --- a/nuttx/drivers/audio/Kconfig +++ b/nuttx/drivers/audio/Kconfig @@ -106,5 +106,57 @@ config AUDIO_WM8904 that dependency is not explicit here. if AUDIO_WM8904 + +config WM8904_INITVOLUME + int "WM8904 initial volume setting" + default 250 + +config WM8904_INFLIGHT + int "WM8904 maximum in-flight audio buffers" + default 2 + +config WM8904_MSG_PRIO + int "WM8904 message priority" + default 1 + +config WM8904_BUFFER_SIZE + int "WM8904 preferred buffer size" + default 8192 + +config WM8904_NUM_BUFFERS + int "WM8904 preferred number of buffers" + default 4 + +config WM8904_WORKER_STACKSIZE + int "WM8904 worker thread stack size" + default 768 + endif # AUDIO_WM8904 +config AUDIO_NULL + bool "NULL audio device" + default n + depends on AUDIO + ---help--- + A do-nothinig audio device driver to simplify testing of audio + decoders. + +if AUDIO_NULL + +config AUDIO_NULL_MSG_PRIO + int "Null audio device message priority" + default 1 + +config UDIO_NULL_BUFFER_SIZE + int "Null audio device preferred buffer size" + default 8192 + +config AUDIO_NULL_NUM_BUFFERS + int "Null audio device preferred number of buffers" + default 4 + +config AUDIO_NULL_WORKER_STACKSIZE + int "Null audio device worker thread stack size" + default 768 + +endif # AUDIO_NULL diff --git a/nuttx/drivers/audio/Make.defs b/nuttx/drivers/audio/Make.defs index 72bb16b1a..2b8e97818 100644 --- a/nuttx/drivers/audio/Make.defs +++ b/nuttx/drivers/audio/Make.defs @@ -47,6 +47,10 @@ ifeq ($(CONFIG_AUDIO_WM8904),y) CSRCS += wm8904.c endif +ifeq ($(CONFIG_AUDIO_NULL),y) +CSRCS += audio_null.c +endif + ifeq ($(CONFIG_AUDIO_I2SCHAR),y) CSRCS += i2schar.c endif diff --git a/nuttx/drivers/audio/audio_null.c b/nuttx/drivers/audio/audio_null.c new file mode 100644 index 000000000..ea59921de --- /dev/null +++ b/nuttx/drivers/audio/audio_null.c @@ -0,0 +1,764 @@ +/**************************************************************************** + * drivers/audio/audio_null.c + * + * A do-nothinig audio device driver to simplify testing of audio decoders. + * + * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * 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 <queue.h> +#include <debug.h> + +#include <nuttx/kmalloc.h> +#include <nuttx/fs/fs.h> +#include <nuttx/fs/ioctl.h> +#include <nuttx/audio/audio.h> +#include <nuttx/audio/audio_null.h> + +/**************************************************************************** + * Private Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct null_dev_s +{ + struct audio_lowerhalf_s dev; /* Audio lower half (this device) */ + mqd_t mq; /* Message queue for receiving messages */ + char mqname[16]; /* Our message queue name */ + pthread_t threadid; /* ID of our thread */ +#ifndef CONFIG_AUDIO_EXCLUDE_STOP + volatile bool terminate; /* True: request to terminate */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int null_getcaps(FAR struct audio_lowerhalf_s *dev, int type, + FAR struct audio_caps_s *caps); +#ifdef CONFIG_AUDIO_MULTI_SESSION +static int null_configure(FAR struct audio_lowerhalf_s *dev, + FAR void *session, FAR const struct audio_caps_s *caps); +#else +static int null_configure(FAR struct audio_lowerhalf_s *dev, + FAR const struct audio_caps_s *caps); +#endif +static int null_shutdown(FAR struct audio_lowerhalf_s *dev); +static void *null_workerthread(pthread_addr_t pvarg); +#ifdef CONFIG_AUDIO_MULTI_SESSION +static int null_start(FAR struct audio_lowerhalf_s *dev, + FAR void *session); +#else +static int null_start(FAR struct audio_lowerhalf_s *dev); +#endif +#ifndef CONFIG_AUDIO_EXCLUDE_STOP +#ifdef CONFIG_AUDIO_MULTI_SESSION +static int null_stop(FAR struct audio_lowerhalf_s *dev, + FAR void* session); +#else +static int null_stop(FAR struct audio_lowerhalf_s *dev); +#endif +#endif +#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME +#ifdef CONFIG_AUDIO_MULTI_SESSION +static int null_pause(FAR struct audio_lowerhalf_s *dev, + FAR void* session); +static int null_resume(FAR struct audio_lowerhalf_s *dev, + FAR void* session); +#else +static int null_pause(FAR struct audio_lowerhalf_s *dev); +static int null_resume(FAR struct audio_lowerhalf_s *dev); +#endif +#endif +static int null_enqueuebuffer(FAR struct audio_lowerhalf_s *dev, + FAR struct ap_buffer_s *apb); +static int null_cancelbuffer(FAR struct audio_lowerhalf_s *dev, + FAR struct ap_buffer_s *apb); +static int null_ioctl(FAR struct audio_lowerhalf_s *dev, int cmd, + unsigned long arg); +#ifdef CONFIG_AUDIO_MULTI_SESSION +static int null_reserve(FAR struct audio_lowerhalf_s *dev, + FAR void **session); +#else +static int null_reserve(FAR struct audio_lowerhalf_s *dev); +#endif +#ifdef CONFIG_AUDIO_MULTI_SESSION +static int null_release(FAR struct audio_lowerhalf_s *dev, + FAR void *session); +#else +static int null_release(FAR struct audio_lowerhalf_s *dev); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct audio_ops_s g_audioops = +{ + null_getcaps, /* getcaps */ + null_configure, /* configure */ + null_shutdown, /* shutdown */ + null_start, /* start */ +#ifndef CONFIG_AUDIO_EXCLUDE_STOP + null_stop, /* stop */ +#endif +#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME + null_pause, /* pause */ + null_resume, /* resume */ +#endif + NULL, /* allocbuffer */ + NULL, /* freebuffer */ + null_enqueuebuffer, /* enqueue_buffer */ + null_cancelbuffer, /* cancel_buffer */ + null_ioctl, /* ioctl */ + NULL, /* read */ + NULL, /* write */ + null_reserve, /* reserve */ + null_release /* release */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: null_getcaps + * + * Description: Get the audio device capabilities + * + ****************************************************************************/ + +static int null_getcaps(FAR struct audio_lowerhalf_s *dev, int type, + FAR struct audio_caps_s *caps) +{ + audvdbg("Entry\n"); + + /* Validate the structure */ + + DEBUGASSERT(caps->ac_len >= sizeof(struct audio_caps_s)); + + /* Fill in the caller's structure based on requested info */ + + caps->ac_format[0] = 0; + caps->ac_format[1] = 0; + caps->ac_controls[0] = 0; + caps->ac_controls[1] = 0; + caps->ac_controls[2] = 0; + caps->ac_controls[3] = 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[0] = AUDIO_TYPE_OUTPUT | AUDIO_TYPE_FEATURE | + AUDIO_TYPE_PROCESSING; + + break; + + case AUDIO_FMT_MIDI: + /* We only support Format 0 */ + + caps->ac_controls[0] = AUDIO_SUBFMT_END; + break; + + default: + caps->ac_controls[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[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[0] = AUDIO_FU_VOLUME | AUDIO_FU_BASS | AUDIO_FU_TREBLE; + caps->ac_controls[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[0] = AUDIO_PU_STEREO_EXTENDER; + break; + + case AUDIO_PU_STEREO_EXTENDER: + + /* Provide capabilities of our Stereo Extender */ + + caps->ac_controls[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. + */ + + audvdbg("Return %d\n", caps->ac_len); + return caps->ac_len; +} + +/**************************************************************************** + * Name: null_configure + * + * Description: + * Configure the audio device for the specified mode of operation. + * + ****************************************************************************/ + +#ifdef CONFIG_AUDIO_MULTI_SESSION +static int null_configure(FAR struct audio_lowerhalf_s *dev, + FAR void *session, + FAR const struct audio_caps_s *caps) +#else +static int null_configure(FAR struct audio_lowerhalf_s *dev, + FAR const struct audio_caps_s *caps) +#endif +{ + audvdbg("Return OK\n"); + return OK; +} + +/**************************************************************************** + * Name: null_shutdown + * + * Description: + * Shutdown the driver and put it in the lowest power state possible. + * + ****************************************************************************/ + +static int null_shutdown(FAR struct audio_lowerhalf_s *dev) +{ + audvdbg("Return OK\n"); + return OK; +} + +/**************************************************************************** + * Name: null_workerthread + * + * This is the thread that feeds data to the chip and keeps the audio + * stream going. + * + ****************************************************************************/ + +static void *null_workerthread(pthread_addr_t pvarg) +{ + FAR struct null_dev_s *priv = (struct null_dev_s *) pvarg; + struct audio_msg_s msg; + int msglen; + int prio; + + audvdbg("Entry\n"); + + /* Loop as long as we are supposed to be running */ + +#ifndef CONFIG_AUDIO_EXCLUDE_STOP + while (!priv->terminate) +#else + for (;;) +#endif + { + /* Wait for messages from our message queue */ + + msglen = mq_receive(priv->mq, &msg, sizeof(msg), &prio); + + /* Handle the case when we return with no message */ + + if (msglen < sizeof(struct audio_msg_s)) + { + auddbg("ERROR: Message too small: %d\n", msglen); + continue; + } + + /* Process the message */ + + switch (msg.msgId) + { + case AUDIO_MSG_DATA_REQUEST: + break; + +#ifndef CONFIG_AUDIO_EXCLUDE_STOP + case AUDIO_MSG_STOP: + priv->terminate = true; + break; +#endif + + case AUDIO_MSG_ENQUEUE: + break; + + case AUDIO_MSG_COMPLETE: + break; + + default: + auddbg("ERROR: Ignoring message ID %d\n", msg.msgId); + break; + } + } + + /* 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 + + audvdbg("Exit\n"); + return NULL; +} + +/**************************************************************************** + * Name: null_start + * + * Description: + * Start the configured operation (audio streaming, volume enabled, etc.). + * + ****************************************************************************/ + +#ifdef CONFIG_AUDIO_MULTI_SESSION +static int null_start(FAR struct audio_lowerhalf_s *dev, FAR void *session) +#else +static int null_start(FAR struct audio_lowerhalf_s *dev) +#endif +{ + FAR struct null_dev_s *priv = (FAR struct null_dev_s *)dev; + struct sched_param sparam; + struct mq_attr attr; + pthread_attr_t tattr; + FAR void *value; + int ret; + + audvdbg("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! */ + + auddbg("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) + { + audvdbg("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; + (void)pthread_attr_setschedparam(&tattr, &sparam); + (void)pthread_attr_setstacksize(&tattr, CONFIG_AUDIO_NULL_WORKER_STACKSIZE); + + audvdbg("Starting worker thread\n"); + ret = pthread_create(&priv->threadid, &tattr, null_workerthread, + (pthread_addr_t)priv); + if (ret != OK) + { + auddbg("ERROR: pthread_create failed: %d\n", ret); + } + else + { + pthread_setname_np(priv->threadid, "null audio"); + audvdbg("Created worker thread\n"); + } + + audvdbg("Return %d\n", ret); + return ret; +} + +/**************************************************************************** + * Name: null_stop + * + * Description: Stop the configured operation (audio streaming, volume + * disabled, etc.). + * + ****************************************************************************/ + +#ifndef CONFIG_AUDIO_EXCLUDE_STOP +#ifdef CONFIG_AUDIO_MULTI_SESSION +static int null_stop(FAR struct audio_lowerhalf_s *dev, FAR void* session) +#else +static int null_stop(FAR struct audio_lowerhalf_s *dev) +#endif +{ + FAR struct null_dev_s *priv = (FAR struct null_dev_s *)dev; + struct audio_msg_s term_msg; + FAR void *value; + + /* Send a message to stop all audio streaming */ + + term_msg.msgId = AUDIO_MSG_STOP; + term_msg.u.data = 0; + mq_send(priv->mq, &term_msg, sizeof(term_msg), CONFIG_AUDIO_NULL_MSG_PRIO); + + /* Join the worker thread */ + + pthread_join(priv->threadid, &value); + priv->threadid = 0; + + audvdbg("Return OK\n"); + return OK; +} +#endif + +/**************************************************************************** + * Name: null_pause + * + * Description: Pauses the playback. + * + ****************************************************************************/ + +#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME +#ifdef CONFIG_AUDIO_MULTI_SESSION +static int null_pause(FAR struct audio_lowerhalf_s *dev, FAR void* session) +#else +static int null_pause(FAR struct audio_lowerhalf_s *dev) +#endif +{ + audvdbg("Return OK\n"); + return OK; +} +#endif /* CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME */ + +/**************************************************************************** + * Name: null_resume + * + * Description: Resumes the playback. + * + ****************************************************************************/ + +#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME +#ifdef CONFIG_AUDIO_MULTI_SESSION +static int null_resume(FAR struct audio_lowerhalf_s *dev, FAR void* session) +#else +static int null_resume(FAR struct audio_lowerhalf_s *dev) +#endif +{ + audvdbg("Return OK\n"); + return OK; +} +#endif /* CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME */ + +/**************************************************************************** + * Name: null_enqueuebuffer + * + * Description: Enqueue an Audio Pipeline Buffer for playback/ processing. + * + ****************************************************************************/ + +static int null_enqueuebuffer(FAR struct audio_lowerhalf_s *dev, + FAR struct ap_buffer_s *apb) +{ + /* Take a reference */ + + apb_reference(apb); + + /* say that we consumed all of the data */ + + apb->curbyte = apb->nbytes; + + /* Release the reference and return success */ + + apb_free(apb); + + audvdbg("Return OK\n"); + return OK; +} + +/**************************************************************************** + * Name: null_cancelbuffer + * + * Description: Called when an enqueued buffer is being cancelled. + * + ****************************************************************************/ + +static int null_cancelbuffer(FAR struct audio_lowerhalf_s *dev, + FAR struct ap_buffer_s *apb) +{ + audvdbg("Return OK\n"); + return OK; +} + +/**************************************************************************** + * Name: null_ioctl + * + * Description: Perform a device ioctl + * + ****************************************************************************/ + +static int null_ioctl(FAR struct audio_lowerhalf_s *dev, int cmd, + unsigned long arg) +{ +#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: + break; + + /* Report our preferred buffer size and quantity */ + +#ifdef CONFIG_AUDIO_DRIVER_SPECIFIC_BUFFERS + case AUDIOIOC_GETBUFFERINFO: + bufinfo = (FAR struct ap_buffer_info_s *) arg; + bufinfo->buffer_size = CONFIG_AUDIO_NULL_BUFFER_SIZE; + bufinfo->nbuffers = CONFIG_AUDIO_NULL_NUM_BUFFERS; + break; +#endif + + default: + break; + } + + audvdbg("Return OK\n"); + return OK; +} + +/**************************************************************************** + * Name: null_reserve + * + * Description: Reserves a session (the only one we have). + * + ****************************************************************************/ + +#ifdef CONFIG_AUDIO_MULTI_SESSION +static int null_reserve(FAR struct audio_lowerhalf_s *dev, + FAR void **session) +#else +static int null_reserve(FAR struct audio_lowerhalf_s *dev) +#endif +{ + audvdbg("Return OK\n"); + return OK; +} + +/**************************************************************************** + * Name: null_release + * + * Description: Releases the session (the only one we have). + * + ****************************************************************************/ + +#ifdef CONFIG_AUDIO_MULTI_SESSION +static int null_release(FAR struct audio_lowerhalf_s *dev, + FAR void *session) +#else +static int null_release(FAR struct audio_lowerhalf_s *dev) +#endif +{ + FAR struct null_dev_s *priv = (FAR struct null_dev_s *)dev; + void *value; + + /* 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; + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: audio_null_initialize + * + * Description: + * Initialize the null audio device. + * + * Input Parameters: + * i2c - An I2C driver instance + * i2s - An I2S driver instance + * lower - Persistent board configuration data + * + * Returned Value: + * A new lower half audio interface for the NULL audio device is returned + * on success; NULL is returned on failure. + * + ****************************************************************************/ + +FAR struct audio_lowerhalf_s *audio_null_initialize(void) +{ + FAR struct null_dev_s *priv; + + /* Allocate the null audio device structure */ + + priv = (FAR struct null_dev_s *)kzalloc(sizeof(struct null_dev_s)); + if (priv) + { + /* Initialize the null audio device structure. Since we used kzalloc, + * only the non-zero elements of the structure need to be initialized. + */ + + priv->dev.ops = &g_audioops; + return &priv->dev; + } + + return NULL; +} diff --git a/nuttx/drivers/audio/wm8904.c b/nuttx/drivers/audio/wm8904.c index d37ef116c..2a85505d8 100644 --- a/nuttx/drivers/audio/wm8904.c +++ b/nuttx/drivers/audio/wm8904.c @@ -95,7 +95,7 @@ struct wm8904_dev_s * "half" that is referred to as "lower". */ - struct audio_lowerhalf_s dev; /* WM8904 audio lower half (this drive) */ + struct audio_lowerhalf_s dev; /* WM8904 audio lower half (this device) */ /* Our specific driver data goes here */ @@ -181,15 +181,10 @@ static int wm8904_stop(FAR struct audio_lowerhalf_s *dev); #ifdef CONFIG_AUDIO_MULTI_SESSION static int wm8904_pause(FAR struct audio_lowerhalf_s *dev, FAR void* session); -#else -static int wm8904_pause(FAR struct audio_lowerhalf_s *dev); -#endif -#endif -#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME -#ifdef CONFIG_AUDIO_MULTI_SESSION static int wm8904_resume(FAR struct audio_lowerhalf_s *dev, FAR void* session); #else +static int wm8904_pause(FAR struct audio_lowerhalf_s *dev); static int wm8904_resume(FAR struct audio_lowerhalf_s *dev); #endif #endif @@ -1755,8 +1750,8 @@ static void wm8904_audio_input(FAR struct wm8904_dev_s *priv) * lower - Persistent board configuration data * * Returned Value: - * A new lower half audio interface is returned for the WM8904 device is - * returned on success; NULL is returned on failure. + * A new lower half audio interface for the WM8904 device is returned on + * success; NULL is returned on failure. * ****************************************************************************/ |