Skip to content

Commit

Permalink
audio: Add setup method and add reference counter on shutdown
Browse files Browse the repository at this point in the history
Add an 'setup' method on the 'struct audio_ops_s' to notify to the
driver that the related device file has been opened and is ready
for use.
And also add refcount argument on shutdown method to know how many
device file is still opened.
  • Loading branch information
SPRESENSE committed Feb 28, 2024
1 parent 9b1c451 commit 0f7edd8
Show file tree
Hide file tree
Showing 19 changed files with 193 additions and 38 deletions.
5 changes: 3 additions & 2 deletions arch/arm/src/cxd56xx/cxd56_nxaudio.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ static int cxd56_release(struct audio_lowerhalf_s *lower);

static int cxd56_getcaps(struct audio_lowerhalf_s *lower, int type,
struct audio_caps_s *caps);
static int cxd56_shutdown(struct audio_lowerhalf_s *lower);
static int cxd56_shutdown(struct audio_lowerhalf_s *lower, int opencnt);
static int cxd56_enqueuebuffer(struct audio_lowerhalf_s *lower,
struct ap_buffer_s *apb);
static int cxd56_cancelbuffer(struct audio_lowerhalf_s *lower,
Expand Down Expand Up @@ -438,6 +438,7 @@ static uint16_t g_codec_start_count = 0;

static const struct audio_ops_s g_audioops =
{
NULL, /* setup */
cxd56_getcaps, /* getcaps */
cxd56_configure, /* configure */
cxd56_shutdown, /* shutdown */
Expand Down Expand Up @@ -2698,7 +2699,7 @@ static int cxd56_getcaps(struct audio_lowerhalf_s *lower, int type,
*
****************************************************************************/

static int cxd56_shutdown(struct audio_lowerhalf_s *lower)
static int cxd56_shutdown(struct audio_lowerhalf_s *lower, int opencnt)
{
int ret;
struct cxd56_dev_s *priv = (struct cxd56_dev_s *)lower;
Expand Down
3 changes: 2 additions & 1 deletion arch/arm/src/sama5/sam_classd.c
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ static struct sam_classd_config_s sam_classd_const =

static const struct audio_ops_s g_audioops =
{
NULL, /* setup */
classd_getcaps, /* getcaps */
classd_configure, /* configure */
classd_shutdown, /* shutdown */
Expand Down Expand Up @@ -1747,7 +1748,7 @@ static int classd_configure(struct audio_lowerhalf_s *dev,
*
****************************************************************************/

static int classd_shutdown(struct audio_lowerhalf_s *dev)
static int classd_shutdown(struct audio_lowerhalf_s *dev, int cnt)
{
struct classd_dev_s *priv = (struct classd_dev_s *)dev;

Expand Down
5 changes: 3 additions & 2 deletions arch/sim/src/sim/posix/sim_alsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ static int sim_audio_resume(struct audio_lowerhalf_s *dev);
static int sim_audio_reserve(struct audio_lowerhalf_s *dev);
static int sim_audio_release(struct audio_lowerhalf_s *dev);
#endif
static int sim_audio_shutdown(struct audio_lowerhalf_s *dev);
static int sim_audio_shutdown(struct audio_lowerhalf_s *dev, int cnt);
static int sim_audio_enqueuebuffer(struct audio_lowerhalf_s *dev,
struct ap_buffer_s *apb);
static int sim_audio_ioctl(struct audio_lowerhalf_s *dev, int cmd,
Expand All @@ -115,6 +115,7 @@ static int sim_audio_ioctl(struct audio_lowerhalf_s *dev, int cmd,

static const struct audio_ops_s g_sim_audio_ops =
{
.setup = NULL,
.getcaps = sim_audio_getcaps,
.configure = sim_audio_configure,
.shutdown = sim_audio_shutdown,
Expand Down Expand Up @@ -484,7 +485,7 @@ static int sim_audio_configure(struct audio_lowerhalf_s *dev,
return ret;
}

static int sim_audio_shutdown(struct audio_lowerhalf_s *dev)
static int sim_audio_shutdown(struct audio_lowerhalf_s *dev, int cnt)
{
return 0;
}
Expand Down
63 changes: 61 additions & 2 deletions audio/audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ static int audio_open(FAR struct file *filep)
{
FAR struct inode *inode = filep->f_inode;
FAR struct audio_upperhalf_s *upper = inode->i_private;
FAR struct audio_lowerhalf_s *lower = upper->dev;
uint8_t tmp;
int ret;

Expand Down Expand Up @@ -166,6 +167,17 @@ static int audio_open(FAR struct file *filep)
goto errout_with_lock;
}

/* Call open method of lowerhalf if exist */

if (lower && lower->ops && lower->ops->setup)
{
ret = lower->ops->setup(lower, tmp);
if (ret < 0)
{
goto errout_with_lock;
}
}

/* Save the new open count on success */

upper->crefs = tmp;
Expand Down Expand Up @@ -223,7 +235,7 @@ static int audio_close(FAR struct file *filep)
DEBUGASSERT(lower->ops->shutdown != NULL);
audinfo("calling shutdown\n");

lower->ops->shutdown(lower);
lower->ops->shutdown(lower, upper->crefs);
upper->usermq = NULL;
}

Expand Down Expand Up @@ -415,7 +427,8 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg)

/* Call the lower-half driver initialize handler */

ret = lower->ops->shutdown(lower);
ret = lower->ops->shutdown(lower, upper->crefs);
upper->started = false;
}
break;

Expand Down Expand Up @@ -479,6 +492,7 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
audinfo("AUDIOIOC_PAUSE\n");
DEBUGASSERT(lower->ops->pause != NULL);

ret = -EAGAIN;
if (upper->started)
{
#ifdef CONFIG_AUDIO_MULTI_SESSION
Expand All @@ -501,6 +515,7 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
audinfo("AUDIOIOC_RESUME\n");
DEBUGASSERT(lower->ops->resume != NULL);

ret = -EAGAIN;
if (upper->started)
{
#ifdef CONFIG_AUDIO_MULTI_SESSION
Expand Down Expand Up @@ -723,6 +738,45 @@ static inline void audio_dequeuebuffer(FAR struct audio_upperhalf_s *upper,
}
}

/****************************************************************************
* Name: audio_ioerror
*
* Description:
* Send an AUDIO_MSG_IOERROR message to the client to indicate that a
* something error was happend in lower-half driver. The lower-half
* driver initiates this call via its callback pointer to our upper-half
* driver.
*
****************************************************************************/

#ifdef CONFIG_AUDIO_MULTI_SESSION
static inline void audio_ioerror(FAR struct audio_upperhalf_s *upper,
FAR struct ap_buffer_s *apb, uint16_t status,
FAR void *session)
#else
static inline void audio_ioerror(FAR struct audio_upperhalf_s *upper,
FAR struct ap_buffer_s *apb, uint16_t status)
#endif
{
struct audio_msg_s msg;

audinfo("Entry\n");

/* Send a dequeue message to the user if a message queue is registered */

upper->started = false;
if (upper->usermq != NULL)
{
msg.msg_id = AUDIO_MSG_IOERROR;
msg.u.data = (uint32_t)status;
#ifdef CONFIG_AUDIO_MULTI_SESSION
msg.session = session;
#endif
file_mq_send(upper->usermq, (FAR const char *)&msg, sizeof(msg),
CONFIG_AUDIO_BUFFER_DEQUEUE_PRIO);
}
}

/****************************************************************************
* Name: audio_complete
*
Expand Down Expand Up @@ -849,6 +903,11 @@ static void audio_callback(FAR void *handle, uint16_t reason,

case AUDIO_CALLBACK_IOERR:
{
#ifdef CONFIG_AUDIO_MULTI_SESSION
audio_ioerror(upper, apb, status, session);
#else
audio_ioerror(upper, apb, status);
#endif
}
break;

Expand Down
52 changes: 49 additions & 3 deletions audio/audio_comp.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ struct audio_comp_priv_s
* Private Function Prototypes
****************************************************************************/

static int audio_comp_setup(FAR struct audio_lowerhalf_s *dev, int opencnt);
static int audio_comp_getcaps(FAR struct audio_lowerhalf_s *dev, int type,
FAR struct audio_caps_s *caps);
#ifdef CONFIG_AUDIO_MULTI_SESSION
Expand All @@ -67,7 +68,7 @@ static int audio_comp_configure(FAR struct audio_lowerhalf_s *dev,
static int audio_comp_configure(FAR struct audio_lowerhalf_s *dev,
FAR const struct audio_caps_s *caps);
#endif
static int audio_comp_shutdown(FAR struct audio_lowerhalf_s *dev);
static int audio_comp_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt);
#ifdef CONFIG_AUDIO_MULTI_SESSION
static int audio_comp_start(FAR struct audio_lowerhalf_s *dev,
FAR void *session);
Expand Down Expand Up @@ -137,6 +138,7 @@ static void audio_comp_callback(FAR void *arg, uint16_t reason,

static const struct audio_ops_s g_audio_comp_ops =
{
audio_comp_setup, /* setup */
audio_comp_getcaps, /* getcaps */
audio_comp_configure, /* configure */
audio_comp_shutdown, /* shutdown */
Expand All @@ -163,6 +165,50 @@ static const struct audio_ops_s g_audio_comp_ops =
* Private Functions
****************************************************************************/

/****************************************************************************
* Name: audio_comp_setup
*
* Description: Call lower device driver's setup
*
****************************************************************************/

static int audio_comp_setup(FAR struct audio_lowerhalf_s *dev, int cnt)
{
FAR struct audio_comp_priv_s *priv = (FAR struct audio_comp_priv_s *)dev;
FAR struct audio_lowerhalf_s **lower = priv->lower;
int i;
int ret;

for (i = 0; i < priv->count; i++)
{
if (lower[i]->ops->setup)
{
ret = lower[i]->ops->setup(lower[i], cnt);
if (ret < 0)
{
break;
}
}
}

/* If an error is occured on a lower device,
* shutdown of lower device which is already opened is called.
*/

if (i != priv->count)
{
for (; i >= 0; i--)
{
if (lower[i]->ops->open && lower[i]->ops->shutdown)
{
lower[i]->ops->shutdown(lower[i], cnt - 1);
}
}
}

return ret;
}

/****************************************************************************
* Name: audio_comp_getcaps
*
Expand Down Expand Up @@ -280,7 +326,7 @@ static int audio_comp_configure(FAR struct audio_lowerhalf_s *dev,
*
****************************************************************************/

static int audio_comp_shutdown(FAR struct audio_lowerhalf_s *dev)
static int audio_comp_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt)
{
FAR struct audio_comp_priv_s *priv = (FAR struct audio_comp_priv_s *)dev;
FAR struct audio_lowerhalf_s **lower = priv->lower;
Expand All @@ -291,7 +337,7 @@ static int audio_comp_shutdown(FAR struct audio_lowerhalf_s *dev)
{
if (lower[i]->ops->shutdown)
{
int tmp = lower[i]->ops->shutdown(lower[i]);
int tmp = lower[i]->ops->shutdown(lower[i], cnt);
if (tmp == -ENOTTY)
{
continue;
Expand Down
37 changes: 34 additions & 3 deletions audio/pcm_decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ static void pcm_subsample(FAR struct pcm_decode_s *priv,

/* struct audio_lowerhalf_s methods *****************************************/

static int pcm_setup(FAR struct audio_lowerhalf_s *dev, int opencnt);

static int pcm_getcaps(FAR struct audio_lowerhalf_s *dev, int type,
FAR struct audio_caps_s *caps);

Expand All @@ -133,7 +135,7 @@ static int pcm_configure(FAR struct audio_lowerhalf_s *dev,
FAR const struct audio_caps_s *caps);
#endif

static int pcm_shutdown(FAR struct audio_lowerhalf_s *dev);
static int pcm_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt);

#ifdef CONFIG_AUDIO_MULTI_SESSION
static int pcm_start(FAR struct audio_lowerhalf_s *dev, FAR void *session);
Expand Down Expand Up @@ -665,6 +667,34 @@ static void pcm_subsample(FAR struct pcm_decode_s *priv,
}
#endif

/****************************************************************************
* Name: pcm_setup
*
* Description:
* This method is called when the related device file is opened.
* And then next lower's setup is called in this method.
*
****************************************************************************/

static int pcm_setup(FAR struct audio_lowerhalf_s *dev, int opencnt)
{
FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev;
FAR struct audio_lowerhalf_s *lower;

DEBUGASSERT(priv);

lower = priv->lower;

DEBUGASSERT(lower);

if (lower->ops && lower->ops->setup)
{
return lower->ops->setup(lower, opencnt);
}

return OK;
}

/****************************************************************************
* Name: pcm_getcaps
*
Expand Down Expand Up @@ -788,7 +818,7 @@ static int pcm_configure(FAR struct audio_lowerhalf_s *dev,
*
****************************************************************************/

static int pcm_shutdown(FAR struct audio_lowerhalf_s *dev)
static int pcm_shutdown(FAR struct audio_lowerhalf_s *dev, int cnt)
{
FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev;
FAR struct audio_lowerhalf_s *lower;
Expand All @@ -805,7 +835,7 @@ static int pcm_shutdown(FAR struct audio_lowerhalf_s *dev)
DEBUGASSERT(lower && lower->ops->start);

audinfo("Defer to lower shutdown\n");
return lower->ops->shutdown(lower);
return lower->ops->shutdown(lower, cnt);
}

/****************************************************************************
Expand Down Expand Up @@ -1403,6 +1433,7 @@ FAR struct audio_lowerhalf_s *
/* Setup our operations */

ops = &priv->ops;
ops->setup = pcm_setup;
ops->getcaps = pcm_getcaps;
ops->configure = pcm_configure;
ops->shutdown = pcm_shutdown;
Expand Down
5 changes: 3 additions & 2 deletions drivers/audio/audio_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ struct audio_dma_s

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);
static int audio_dma_shutdown(struct audio_lowerhalf_s *dev, int cnt);
#ifdef CONFIG_AUDIO_MULTI_SESSION
static int audio_dma_configure(struct audio_lowerhalf_s *dev,
void *session,
Expand Down Expand Up @@ -106,6 +106,7 @@ static void audio_dma_callback(struct dma_chan_s *chan, void *arg,

static const struct audio_ops_s g_audio_dma_ops =
{
.setup = NULL,
.getcaps = audio_dma_getcaps,
.configure = audio_dma_configure,
.shutdown = audio_dma_shutdown,
Expand Down Expand Up @@ -255,7 +256,7 @@ static int audio_dma_configure(struct audio_lowerhalf_s *dev,
return ret;
}

static int audio_dma_shutdown(struct audio_lowerhalf_s *dev)
static int audio_dma_shutdown(struct audio_lowerhalf_s *dev, int cnt)
{
/* apps enqueued buffers, but doesn't start. stop here to
* clear audio_dma->pendq.
Expand Down
Loading

0 comments on commit 0f7edd8

Please sign in to comment.