aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-01-08 12:08:14 -0500
committerJaroslav Kysela <perex@perex.cz>2008-01-31 11:29:47 -0500
commit130755108ba03461f69da990e54e02a254accd23 (patch)
tree57d71dc89dc83b87d3e33541bcfe47d045ff82fe /sound/core
parentd948035a928400ae127c873fbf771389bee18949 (diff)
[ALSA] PCM - clean up snd_pcm_lib_read/write
Introduce a common helper function for snd_pcm_lib_read and snd_pcm_lib_write for cleaning up the code. Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/pcm_lib.c216
1 files changed, 76 insertions, 140 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index c1c1556105c0..b406630d8fdf 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1591,6 +1591,71 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
1591 1591
1592EXPORT_SYMBOL(snd_pcm_period_elapsed); 1592EXPORT_SYMBOL(snd_pcm_period_elapsed);
1593 1593
1594/*
1595 * Wait until avail_min data becomes available
1596 * Returns a negative error code if any error occurs during operation.
1597 * The available space is stored on availp. When err = 0 and avail = 0
1598 * on the capture stream, it indicates the stream is in DRAINING state.
1599 */
1600static int wait_for_avail_min(struct snd_pcm_substream *substream,
1601 snd_pcm_uframes_t *availp)
1602{
1603 struct snd_pcm_runtime *runtime = substream->runtime;
1604 int is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
1605 wait_queue_t wait;
1606 int err = 0;
1607 snd_pcm_uframes_t avail = 0;
1608 long tout;
1609
1610 init_waitqueue_entry(&wait, current);
1611 add_wait_queue(&runtime->sleep, &wait);
1612 for (;;) {
1613 if (signal_pending(current)) {
1614 err = -ERESTARTSYS;
1615 break;
1616 }
1617 set_current_state(TASK_INTERRUPTIBLE);
1618 snd_pcm_stream_unlock_irq(substream);
1619 tout = schedule_timeout(msecs_to_jiffies(10000));
1620 snd_pcm_stream_lock_irq(substream);
1621 switch (runtime->status->state) {
1622 case SNDRV_PCM_STATE_SUSPENDED:
1623 err = -ESTRPIPE;
1624 goto _endloop;
1625 case SNDRV_PCM_STATE_XRUN:
1626 err = -EPIPE;
1627 goto _endloop;
1628 case SNDRV_PCM_STATE_DRAINING:
1629 if (is_playback)
1630 err = -EPIPE;
1631 else
1632 avail = 0; /* indicate draining */
1633 goto _endloop;
1634 case SNDRV_PCM_STATE_OPEN:
1635 case SNDRV_PCM_STATE_SETUP:
1636 case SNDRV_PCM_STATE_DISCONNECTED:
1637 err = -EBADFD;
1638 goto _endloop;
1639 }
1640 if (!tout) {
1641 snd_printd("%s write error (DMA or IRQ trouble?)\n",
1642 is_playback ? "playback" : "capture");
1643 err = -EIO;
1644 break;
1645 }
1646 if (is_playback)
1647 avail = snd_pcm_playback_avail(runtime);
1648 else
1649 avail = snd_pcm_capture_avail(runtime);
1650 if (avail >= runtime->control->avail_min)
1651 break;
1652 }
1653 _endloop:
1654 remove_wait_queue(&runtime->sleep, &wait);
1655 *availp = avail;
1656 return err;
1657}
1658
1594static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream, 1659static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
1595 unsigned int hwoff, 1660 unsigned int hwoff,
1596 unsigned long data, unsigned int off, 1661 unsigned long data, unsigned int off,
@@ -1653,79 +1718,14 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
1653 if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING) 1718 if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
1654 snd_pcm_update_hw_ptr(substream); 1719 snd_pcm_update_hw_ptr(substream);
1655 avail = snd_pcm_playback_avail(runtime); 1720 avail = snd_pcm_playback_avail(runtime);
1656 if (!avail || 1721 if (!avail) {
1657 (snd_pcm_running(substream) &&
1658 (avail < runtime->control->avail_min && size > avail))) {
1659 wait_queue_t wait;
1660 enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED, DROPPED } state;
1661 long tout;
1662
1663 if (nonblock) { 1722 if (nonblock) {
1664 err = -EAGAIN; 1723 err = -EAGAIN;
1665 goto _end_unlock; 1724 goto _end_unlock;
1666 } 1725 }
1667 1726 err = wait_for_avail_min(substream, &avail);
1668 init_waitqueue_entry(&wait, current); 1727 if (err < 0)
1669 add_wait_queue(&runtime->sleep, &wait);
1670 while (1) {
1671 if (signal_pending(current)) {
1672 state = SIGNALED;
1673 break;
1674 }
1675 set_current_state(TASK_INTERRUPTIBLE);
1676 snd_pcm_stream_unlock_irq(substream);
1677 tout = schedule_timeout(10 * HZ);
1678 snd_pcm_stream_lock_irq(substream);
1679 if (tout == 0) {
1680 if (runtime->status->state != SNDRV_PCM_STATE_PREPARED &&
1681 runtime->status->state != SNDRV_PCM_STATE_PAUSED) {
1682 state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
1683 break;
1684 }
1685 }
1686 switch (runtime->status->state) {
1687 case SNDRV_PCM_STATE_XRUN:
1688 case SNDRV_PCM_STATE_DRAINING:
1689 state = ERROR;
1690 goto _end_loop;
1691 case SNDRV_PCM_STATE_SUSPENDED:
1692 state = SUSPENDED;
1693 goto _end_loop;
1694 case SNDRV_PCM_STATE_SETUP:
1695 state = DROPPED;
1696 goto _end_loop;
1697 default:
1698 break;
1699 }
1700 avail = snd_pcm_playback_avail(runtime);
1701 if (avail >= runtime->control->avail_min) {
1702 state = READY;
1703 break;
1704 }
1705 }
1706 _end_loop:
1707 remove_wait_queue(&runtime->sleep, &wait);
1708
1709 switch (state) {
1710 case ERROR:
1711 err = -EPIPE;
1712 goto _end_unlock;
1713 case SUSPENDED:
1714 err = -ESTRPIPE;
1715 goto _end_unlock;
1716 case SIGNALED:
1717 err = -ERESTARTSYS;
1718 goto _end_unlock;
1719 case EXPIRED:
1720 snd_printd("playback write error (DMA or IRQ trouble?)\n");
1721 err = -EIO;
1722 goto _end_unlock;
1723 case DROPPED:
1724 err = -EBADFD;
1725 goto _end_unlock; 1728 goto _end_unlock;
1726 default:
1727 break;
1728 }
1729 } 1729 }
1730 frames = size > avail ? avail : size; 1730 frames = size > avail ? avail : size;
1731 cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; 1731 cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
@@ -1925,86 +1925,22 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
1925 snd_pcm_uframes_t cont; 1925 snd_pcm_uframes_t cont;
1926 if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING) 1926 if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
1927 snd_pcm_update_hw_ptr(substream); 1927 snd_pcm_update_hw_ptr(substream);
1928 __draining:
1929 avail = snd_pcm_capture_avail(runtime); 1928 avail = snd_pcm_capture_avail(runtime);
1930 if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { 1929 if (!avail) {
1931 if (!avail) { 1930 if (runtime->status->state ==
1932 err = -EPIPE; 1931 SNDRV_PCM_STATE_DRAINING) {
1932 snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
1933 goto _end_unlock; 1933 goto _end_unlock;
1934 } 1934 }
1935 } else if (avail < runtime->control->avail_min &&
1936 size > avail) {
1937 wait_queue_t wait;
1938 enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED, DROPPED } state;
1939 long tout;
1940
1941 if (nonblock) { 1935 if (nonblock) {
1942 err = -EAGAIN; 1936 err = -EAGAIN;
1943 goto _end_unlock; 1937 goto _end_unlock;
1944 } 1938 }
1945 1939 err = wait_for_avail_min(substream, &avail);
1946 init_waitqueue_entry(&wait, current); 1940 if (err < 0)
1947 add_wait_queue(&runtime->sleep, &wait);
1948 while (1) {
1949 if (signal_pending(current)) {
1950 state = SIGNALED;
1951 break;
1952 }
1953 set_current_state(TASK_INTERRUPTIBLE);
1954 snd_pcm_stream_unlock_irq(substream);
1955 tout = schedule_timeout(10 * HZ);
1956 snd_pcm_stream_lock_irq(substream);
1957 if (tout == 0) {
1958 if (runtime->status->state != SNDRV_PCM_STATE_PREPARED &&
1959 runtime->status->state != SNDRV_PCM_STATE_PAUSED) {
1960 state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
1961 break;
1962 }
1963 }
1964 switch (runtime->status->state) {
1965 case SNDRV_PCM_STATE_XRUN:
1966 state = ERROR;
1967 goto _end_loop;
1968 case SNDRV_PCM_STATE_SUSPENDED:
1969 state = SUSPENDED;
1970 goto _end_loop;
1971 case SNDRV_PCM_STATE_DRAINING:
1972 goto __draining;
1973 case SNDRV_PCM_STATE_SETUP:
1974 state = DROPPED;
1975 goto _end_loop;
1976 default:
1977 break;
1978 }
1979 avail = snd_pcm_capture_avail(runtime);
1980 if (avail >= runtime->control->avail_min) {
1981 state = READY;
1982 break;
1983 }
1984 }
1985 _end_loop:
1986 remove_wait_queue(&runtime->sleep, &wait);
1987
1988 switch (state) {
1989 case ERROR:
1990 err = -EPIPE;
1991 goto _end_unlock;
1992 case SUSPENDED:
1993 err = -ESTRPIPE;
1994 goto _end_unlock;
1995 case SIGNALED:
1996 err = -ERESTARTSYS;
1997 goto _end_unlock;
1998 case EXPIRED:
1999 snd_printd("capture read error (DMA or IRQ trouble?)\n");
2000 err = -EIO;
2001 goto _end_unlock;
2002 case DROPPED:
2003 err = -EBADFD;
2004 goto _end_unlock; 1941 goto _end_unlock;
2005 default: 1942 if (!avail)
2006 break; 1943 continue; /* draining */
2007 }
2008 } 1944 }
2009 frames = size > avail ? avail : size; 1945 frames = size > avail ? avail : size;
2010 cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; 1946 cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;