From c9032a07de3321063cbd0c1136cb2b065d2478a5 Mon Sep 17 00:00:00 2001 From: Omair Mohammed Abdullah Date: Thu, 31 Jan 2013 16:35:39 +0530 Subject: tinyalsa: add separate call for pcm prepare Tinyalsa combines PREPARE and START calls to the driver in the pcm_start() function. Typically, this is needed for making a driver allocating hardware resources that are not related to a PCM stream. Change-Id: Ic83fad784936bbebab28e8e425debd449182db88 Signed-off-by: Omair Mohammed Abdullah Signed-off-by: David Wagner Signed-off-by: Bruce Beare Signed-off-by: Jack Ren Author-Tracking-BZ: 73509 --- include/tinyalsa/asoundlib.h | 2 ++ pcm.c | 26 +++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/tinyalsa/asoundlib.h b/include/tinyalsa/asoundlib.h index 3d20b94..8ba5aca 100644 --- a/include/tinyalsa/asoundlib.h +++ b/include/tinyalsa/asoundlib.h @@ -189,6 +189,8 @@ int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset, unsigned int *frames); int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames); +/* Prepare the PCM substream to be triggerable */ +int pcm_prepare(struct pcm *pcm); /* Start and stop a PCM channel that doesn't transfer data */ int pcm_start(struct pcm *pcm); int pcm_stop(struct pcm *pcm); diff --git a/pcm.c b/pcm.c index ca3eb3e..b081e87 100644 --- a/pcm.c +++ b/pcm.c @@ -159,6 +159,7 @@ struct pcm { int fd; unsigned int flags; int running:1; + int prepared:1; int underruns; unsigned int buffer_size; unsigned int boundary; @@ -386,14 +387,16 @@ int pcm_write(struct pcm *pcm, const void *data, unsigned int count) for (;;) { if (!pcm->running) { - if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE)) - return oops(pcm, errno, "cannot prepare channel"); + int prepare_error = pcm_prepare(pcm); + if (prepare_error) + return prepare_error; if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) return oops(pcm, errno, "cannot write initial data"); pcm->running = 1; return 0; } if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) { + pcm->prepared = 0; pcm->running = 0; if (errno == EPIPE) { /* we failed to make our window -- try to restart if we are @@ -429,6 +432,7 @@ int pcm_read(struct pcm *pcm, void *data, unsigned int count) } } if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) { + pcm->prepared = 0; pcm->running = 0; if (errno == EPIPE) { /* we failed to make our window -- try to restart */ @@ -582,6 +586,7 @@ int pcm_close(struct pcm *pcm) if (pcm->fd >= 0) close(pcm->fd); + pcm->prepared = 0; pcm->running = 0; pcm->buffer_size = 0; pcm->fd = -1; @@ -736,11 +741,24 @@ int pcm_is_ready(struct pcm *pcm) return pcm->fd >= 0; } -int pcm_start(struct pcm *pcm) +int pcm_prepare(struct pcm *pcm) { + if (pcm->prepared) + return 0; + if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE) < 0) return oops(pcm, errno, "cannot prepare channel"); + pcm->prepared = 1; + return 0; +} + +int pcm_start(struct pcm *pcm) +{ + int prepare_error = pcm_prepare(pcm); + if (prepare_error) + return prepare_error; + if (pcm->flags & PCM_MMAP) pcm_sync_ptr(pcm, 0); @@ -756,6 +774,7 @@ int pcm_stop(struct pcm *pcm) if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_DROP) < 0) return oops(pcm, errno, "cannot stop channel"); + pcm->prepared = 0; pcm->running = 0; return 0; } @@ -936,6 +955,7 @@ int pcm_mmap_write(struct pcm *pcm, const void *buffer, unsigned int bytes) err = pcm_wait(pcm, time); if (err < 0) { + pcm->prepared = 0; pcm->running = 0; fprintf(stderr, "wait error: hw 0x%x app 0x%x avail 0x%x\n", (unsigned int)pcm->mmap_status->hw_ptr, -- cgit v1.2.3