diff options
author | Eric Laurent <elaurent@google.com> | 2011-10-14 11:12:24 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2011-10-14 11:35:43 -0700 |
commit | 73b9c679a656c7b0f5e265dae5a76664c7d03031 (patch) | |
tree | c4778fe02eff8c7f8512f7426fbd17648e4934e6 | |
parent | e9942c8b1fab1cea4836b5af2dd59a1bf0ad411d (diff) | |
download | tinyalsa-ics-mr0.tar.gz |
Add dynamic change of avail_min for mmap modeandroid-sdk-adt_r16.0.1android-cts-4.0_r1android-4.0.2_r1android-4.0.1_r1.2android-4.0.1_r1.1android-4.0.1_r1ics-mr0-releaseics-mr0ics-factoryrom-2-release
Added support for setting avail_min when opening a stream as well
as dynamically changing its value whitout stopping playback when the
stream is opened in mmap and no irq mode.
Allow writing less than avail_min frames to pcm_mmap_write() without
systematically waiting for avail_min frames to be available.
Also fixed wait timeout for no irq mode in pcm_mmap_write().
Change-Id: Ief8e05dde8d538185174da9ef14e27a0a470057c
-rw-r--r-- | include/tinyalsa/asoundlib.h | 5 | ||||
-rw-r--r-- | pcm.c | 80 |
2 files changed, 63 insertions, 22 deletions
diff --git a/include/tinyalsa/asoundlib.h b/include/tinyalsa/asoundlib.h index 3c86c84..741c466 100644 --- a/include/tinyalsa/asoundlib.h +++ b/include/tinyalsa/asoundlib.h @@ -84,6 +84,7 @@ struct pcm_config { unsigned int start_threshold; unsigned int stop_threshold; unsigned int silence_threshold; + int avail_min; }; /* Mixer control types */ @@ -150,6 +151,10 @@ int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames); int pcm_start(struct pcm *pcm); int pcm_stop(struct pcm *pcm); +/* Change avail_min after the stream has been opened with no need to stop the stream. + * Only accepted if opened with PCM_MMAP and PCM_NOIRQ flags + */ +int pcm_set_avail_min(struct pcm *pcm, int avail_min); /* * MIXER API @@ -156,6 +156,7 @@ struct pcm { struct snd_pcm_sync_ptr *sync_ptr; void *mmap_buffer; unsigned int noirq_frames_per_msec; + int wait_for_avail_min; }; unsigned int pcm_get_buffer_size(struct pcm *pcm) @@ -249,7 +250,10 @@ static int pcm_hw_mmap_status(struct pcm *pcm) { pcm->mmap_status = NULL; goto mmap_error; } - pcm->mmap_control->avail_min = 1; + if (pcm->flags & PCM_MMAP) + pcm->mmap_control->avail_min = pcm->config.avail_min; + else + pcm->mmap_control->avail_min = 1; return 0; @@ -260,7 +264,11 @@ mmap_error: return -ENOMEM; pcm->mmap_status = &pcm->sync_ptr->s.status; pcm->mmap_control = &pcm->sync_ptr->c.control; - pcm->mmap_control->avail_min = 1; + if (pcm->flags & PCM_MMAP) + pcm->mmap_control->avail_min = pcm->config.avail_min; + else + pcm->mmap_control->avail_min = 1; + pcm_sync_ptr(pcm, 0); return 0; @@ -344,7 +352,9 @@ int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail, frames = hw_ptr + pcm->buffer_size - pcm->mmap_control->appl_ptr; if (frames < 0) - return -1; + frames += pcm->boundary; + else if (frames > (int)pcm->boundary) + frames -= pcm->boundary; *avail = (unsigned int)frames; @@ -529,7 +539,6 @@ struct pcm *pcm_open(unsigned int card, unsigned int device, memset(&sparams, 0, sizeof(sparams)); sparams.tstamp_mode = SNDRV_PCM_TSTAMP_ENABLE; sparams.period_step = 1; - sparams.avail_min = 1; if (!config->start_threshold) pcm->config.start_threshold = sparams.start_threshold = @@ -544,6 +553,14 @@ struct pcm *pcm_open(unsigned int card, unsigned int device, else sparams.stop_threshold = config->stop_threshold; + if (!pcm->config.avail_min) { + if (pcm->flags & PCM_MMAP) + pcm->config.avail_min = sparams.avail_min = pcm->config.period_size; + else + pcm->config.avail_min = sparams.avail_min = 1; + } else + sparams.avail_min = config->avail_min; + sparams.xfer_align = config->period_size / 2; /* needed for old kernels */ sparams.silence_size = 0; sparams.silence_threshold = config->silence_threshold; @@ -697,6 +714,15 @@ int pcm_state(struct pcm *pcm) return pcm->mmap_status->state; } +int pcm_set_avail_min(struct pcm *pcm, int avail_min) +{ + if ((~pcm->flags) & (PCM_MMAP | PCM_NOIRQ)) + return -ENOSYS; + + pcm->config.avail_min = avail_min; + return 0; +} + int pcm_wait(struct pcm *pcm, int timeout) { struct pollfd pfd; @@ -768,28 +794,38 @@ int pcm_mmap_write(struct pcm *pcm, void *buffer, unsigned int bytes) avail); return -errno; } + pcm->wait_for_avail_min = 0; } /* sleep until we have space to write new frames */ - if (pcm->running && - (unsigned int)avail < pcm->mmap_control->avail_min) { - int time = -1; - - if (pcm->flags & PCM_NOIRQ) - time = (pcm->buffer_size - avail - pcm->mmap_control->avail_min) - / pcm->noirq_frames_per_msec; - - err = pcm_wait(pcm, time); - if (err < 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, - (unsigned int)pcm->mmap_control->appl_ptr, - avail); - pcm->mmap_control->appl_ptr = 0; - return err; + if (pcm->running) { + /* enable waiting for avail_min threshold when less frames than we have to write + * are available. */ + if (!pcm->wait_for_avail_min && (count > (unsigned int)avail)) + pcm->wait_for_avail_min = 1; + + if (pcm->wait_for_avail_min && (avail < pcm->config.avail_min)) { + int time = -1; + + /* disable waiting for avail_min threshold to allow small amounts of data to be + * written without waiting as long as there is enough room in buffer. */ + pcm->wait_for_avail_min = 0; + + if (pcm->flags & PCM_NOIRQ) + time = (pcm->config.avail_min - avail) / pcm->noirq_frames_per_msec; + + err = pcm_wait(pcm, time); + if (err < 0) { + pcm->running = 0; + oops(pcm, err, "wait error: hw 0x%x app 0x%x avail 0x%x\n", + (unsigned int)pcm->mmap_status->hw_ptr, + (unsigned int)pcm->mmap_control->appl_ptr, + avail); + pcm->mmap_control->appl_ptr = 0; + return err; + } + continue; } - continue; } frames = count; |