From: Jaroslav Kysela Date: Tue, 16 Aug 2005 12:19:15 +0000 (+0000) Subject: direct plugins (dmix) - suspend/resume fixes X-Git-Tag: android-x86-9.0-r1~1695 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=bac9a7de83f0136e2a06cc5686857898c8df7a85;p=android-x86%2Fexternal-alsa-lib.git direct plugins (dmix) - suspend/resume fixes - this patch adds support for suspend & result for dmix and other direct plugins - the timer detection / initialization (TREAD support) was redesigned and the check for proper driver version was moved to the timer_hw.c --- diff --git a/include/sound/asound.h b/include/sound/asound.h index 39d6f0a9..32582ef6 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h @@ -693,7 +693,7 @@ enum sndrv_timer_event { SNDRV_TIMER_EVENT_PAUSE, /* val = 0 */ SNDRV_TIMER_EVENT_EARLY, /* val = 0, early event */ SNDRV_TIMER_EVENT_SUSPEND, /* val = 0 */ - SNDRV_TIMER_EVENT_RESUME, /* val = 0 */ + SNDRV_TIMER_EVENT_RESUME, /* val = resolution in ns */ /* master timer events for slave timer instances */ SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10, SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10, diff --git a/include/timer.h b/include/timer.h index 10d7264a..a3671499 100644 --- a/include/timer.h +++ b/include/timer.h @@ -85,11 +85,15 @@ typedef enum _snd_timer_event { SND_TIMER_EVENT_CONTINUE, /* val = resolution in ns */ SND_TIMER_EVENT_PAUSE, /* val = 0 */ SND_TIMER_EVENT_EARLY, /* val = 0 */ + SND_TIMER_EVENT_SUSPEND, /* val = 0 */ + SND_TIMER_EVENT_RESUME, /* val = resolution in ns */ /* master timer events for slave timer instances */ SND_TIMER_EVENT_MSTART = SND_TIMER_EVENT_START + 10, SND_TIMER_EVENT_MSTOP = SND_TIMER_EVENT_STOP + 10, SND_TIMER_EVENT_MCONTINUE = SND_TIMER_EVENT_CONTINUE + 10, SND_TIMER_EVENT_MPAUSE = SND_TIMER_EVENT_PAUSE + 10, + SND_TIMER_EVENT_MSUSPEND = SND_TIMER_EVENT_SUSPEND + 10, + SND_TIMER_EVENT_MRESUME = SND_TIMER_EVENT_RESUME + 10 } snd_timer_event_t; /** timer read structure */ diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c index 3d3f1d4a..e5780100 100644 --- a/src/pcm/pcm_direct.c +++ b/src/pcm/pcm_direct.c @@ -431,6 +431,13 @@ int snd_pcm_direct_async(snd_pcm_t *pcm, int sig, pid_t pid) return snd_timer_async(dmix->timer, sig, pid); } +static inline void process_timer_event(snd_pcm_direct_t *dmix, snd_timer_tread_t *te) +{ +#if 0 + printf("te->event = %i\n", te->event); +#endif +} + /* empty the timer read queue */ void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix) { @@ -440,6 +447,7 @@ void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix) if (dmix->tread) { snd_timer_tread_t rbuf; snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf)); + process_timer_event(dmix, &rbuf); } else { snd_timer_read_t rbuf; snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf)); @@ -449,7 +457,7 @@ void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix) if (dmix->tread) { snd_timer_tread_t rbuf; while (snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf)) > 0) - ; + process_timer_event(dmix, &rbuf); } else { snd_timer_read_t rbuf; while (snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf)) > 0) @@ -666,6 +674,23 @@ int snd_pcm_direct_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) return 0; } +int snd_pcm_direct_resume(snd_pcm_t *pcm) +{ + snd_pcm_direct_t *dmix = pcm->private_data; + int err; + + snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT); + err = snd_pcm_resume(dmix->spcm); + if (err == -ENOSYS) { + /* FIXME: error handling? */ + snd_pcm_prepare(dmix->spcm); + snd_pcm_start(dmix->spcm); + err = 0; + } + snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); + return err; +} + /* * this function initializes hardware and starts playback operation with * no stop threshold (it operates all time without xrun checking) @@ -909,8 +934,8 @@ int snd_pcm_direct_initialize_poll_fd(snd_pcm_direct_t *dmix) snd_pcm_info_t *info; char name[128]; int capture = dmix->type == SND_PCM_TYPE_DSNOOP ? 1 : 0; - - dmix->tread = 0; + + dmix->tread = 1; dmix->timer_need_poll = 0; snd_pcm_info_alloca(&info); ret = snd_pcm_info(dmix->spcm, info); @@ -923,11 +948,14 @@ int snd_pcm_direct_initialize_poll_fd(snd_pcm_direct_t *dmix) snd_pcm_info_get_card(info), snd_pcm_info_get_device(info), snd_pcm_info_get_subdevice(info) * 2 + capture); - ret = snd_timer_open(&dmix->timer, name, SND_TIMER_OPEN_NONBLOCK - /*| SND_TIMER_OPEN_TREAD*/); /* XXX: TREAD is set later */ + ret = snd_timer_open(&dmix->timer, name, SND_TIMER_OPEN_NONBLOCK | SND_TIMER_OPEN_TREAD); if (ret < 0) { - SNDERR("unable to open timer '%s'", name); - return ret; + dmix->tread = 1; + ret = snd_timer_open(&dmix->timer, name, SND_TIMER_OPEN_NONBLOCK); + if (ret < 0) { + SNDERR("unable to open timer '%s'", name); + return ret; + } } if (snd_timer_poll_descriptors_count(dmix->timer) != 1) { @@ -937,27 +965,30 @@ int snd_pcm_direct_initialize_poll_fd(snd_pcm_direct_t *dmix) snd_timer_poll_descriptors(dmix->timer, &dmix->timer_fd, 1); dmix->poll_fd = dmix->timer_fd.fd; + dmix->timer_event_suspend = 1<timer_event_resume = 1<poll_fd, SNDRV_TIMER_IOCTL_PVERSION, &ver); - if (ver >= SNDRV_PROTOCOL_VERSION(2, 0, 3)) { - dmix->tread = 1; - if (ioctl(dmix->poll_fd, SNDRV_TIMER_IOCTL_TREAD, &dmix->tread) < 0) - dmix->tread = 0; - } /* In older versions, check via poll before read() is needed * because of the confliction between TIMER_START and * FIONBIO ioctls. */ if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 4)) dmix->timer_need_poll = 1; + /* + * In older versions, timer uses pause events instead + * suspend/resume events. + */ + if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 5)) { + dmix->timer_event_suspend = 1<timer_event_resume = 1<type != SND_PCM_TYPE_DSNOOP) snd_timer_params_set_early_event(params, 1); snd_timer_params_set_ticks(params, 1); - if (dmix->tread) - snd_timer_params_set_filter(params, (1<tread) { + filter = (1<timer_event_suspend | + dmix->timer_event_resume; + snd_timer_params_set_filter(params, filter); + } ret = snd_timer_params(dmix->timer, params); if (ret < 0) { SNDERR("unable to set timer parameters"); diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h index da300b78..ed49e03d 100644 --- a/src/pcm/pcm_direct.h +++ b/src/pcm/pcm_direct.h @@ -105,6 +105,8 @@ struct snd_pcm_direct { int poll_fd; int tread; int timer_need_poll; + unsigned int timer_event_suspend; + unsigned int timer_event_resume; int server_fd; pid_t server_pid; snd_timer_t *timer; /* timer used as poll_fd */ @@ -153,6 +155,7 @@ int snd_pcm_direct_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params); int snd_pcm_direct_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info); int snd_pcm_direct_mmap(snd_pcm_t *pcm); int snd_pcm_direct_munmap(snd_pcm_t *pcm); +int snd_pcm_direct_resume(snd_pcm_t *pcm); int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix); void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix); int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix); diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c index 36a7a5c9..c9cfdcc0 100644 --- a/src/pcm/pcm_dmix.c +++ b/src/pcm/pcm_dmix.c @@ -580,13 +580,6 @@ static snd_pcm_sframes_t snd_pcm_dmix_forward(snd_pcm_t *pcm, snd_pcm_uframes_t return frames; } -static int snd_pcm_dmix_resume(snd_pcm_t *pcm) -{ - snd_pcm_direct_t *dmix = pcm->private_data; - snd_pcm_resume(dmix->spcm); - return 0; -} - static snd_pcm_sframes_t snd_pcm_dmix_readi(snd_pcm_t *pcm ATTRIBUTE_UNUSED, void *buffer ATTRIBUTE_UNUSED, snd_pcm_uframes_t size ATTRIBUTE_UNUSED) { return -ENODEV; @@ -715,7 +708,7 @@ static snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = { .pause = snd_pcm_dmix_pause, .rewind = snd_pcm_dmix_rewind, .forward = snd_pcm_dmix_forward, - .resume = snd_pcm_dmix_resume, + .resume = snd_pcm_direct_resume, .link_fd = NULL, .link = NULL, .unlink = NULL, diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c index a90cd636..30a57bc7 100644 --- a/src/pcm/pcm_dshare.c +++ b/src/pcm/pcm_dshare.c @@ -434,13 +434,6 @@ static snd_pcm_sframes_t snd_pcm_dshare_forward(snd_pcm_t *pcm, snd_pcm_uframes_ return frames; } -static int snd_pcm_dshare_resume(snd_pcm_t *pcm) -{ - snd_pcm_direct_t *dshare = pcm->private_data; - snd_pcm_resume(dshare->spcm); - return 0; -} - static snd_pcm_sframes_t snd_pcm_dshare_readi(snd_pcm_t *pcm ATTRIBUTE_UNUSED, void *buffer ATTRIBUTE_UNUSED, snd_pcm_uframes_t size ATTRIBUTE_UNUSED) { return -ENODEV; @@ -561,7 +554,7 @@ static snd_pcm_fast_ops_t snd_pcm_dshare_fast_ops = { .pause = snd_pcm_dshare_pause, .rewind = snd_pcm_dshare_rewind, .forward = snd_pcm_dshare_forward, - .resume = snd_pcm_dshare_resume, + .resume = snd_pcm_direct_resume, .link_fd = NULL, .link = NULL, .unlink = NULL, diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c index d0f43576..e2da4b71 100644 --- a/src/pcm/pcm_dsnoop.c +++ b/src/pcm/pcm_dsnoop.c @@ -457,7 +457,7 @@ static snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = { .pause = snd_pcm_dsnoop_pause, .rewind = snd_pcm_dsnoop_rewind, .forward = snd_pcm_dsnoop_forward, - .resume = snd_pcm_dsnoop_resume, + .resume = snd_pcm_direct_resume, .link_fd = NULL, .link = NULL, .unlink = NULL, diff --git a/src/timer/timer_hw.c b/src/timer/timer_hw.c index 4b5cff70..2fc576c5 100644 --- a/src/timer/timer_hw.c +++ b/src/timer/timer_hw.c @@ -258,9 +258,14 @@ int snd_timer_hw_open(snd_timer_t **handle, const char *name, int dev_class, int } if (mode & SND_TIMER_OPEN_TREAD) { int arg = 1; + if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 3)) { + ret = -ENOTTY; + goto __no_tread; + } if (ioctl(fd, SNDRV_TIMER_IOCTL_TREAD, &arg) < 0) { ret = -errno; close(fd); + __no_tread: SNDERR("extended read is not supported (SNDRV_TIMER_IOCTL_TREAD)"); return ret; }