diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-31 18:16:28 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-31 18:16:28 -0500 |
commit | e1a9c9872dd004617555dff079b357a6ffd945e9 (patch) | |
tree | c34779e59712ff345f8e4ee97e74086a85b34974 /sound/core/pcm_lib.c | |
parent | fcc3ff4f9d695a80dc6e6058e0d631a3026ed4c3 (diff) | |
parent | 2ecba4ffbbc6c85fce8c3878514be415edace413 (diff) |
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/perex/alsa
* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/perex/alsa: (299 commits)
[ALSA] version 1.0.16rc2
[ALSA] hda: fix Mic in as output
[ALSA] emu10k1 - Another EMU0404 Board ID
[ALSA] emu10k1 - Fix kthread handling at resume
[ALSA] emu10k1: General cleanup, add new locks, fix alsa bug#3501, kernel bug#9304.
[ALSA] emu10k1 - Use enum for emu_model types
[ALSA] emu10k1 - Don't create emu1010 controls for non-emu boards
[ALSA] emu10k1 - 1616(M) cardbus improvements
[ALSA] snd:emu10k1: E-Mu updates. Fixes to firmware loading and support for 0404.
[ALSA] emu10k1: Add comments regarding E-Mu ins and outs.
[ALSA] oxygen: revert SPI clock frequency change for AK4396/WM8785
[ALSA] es1938 - improve capture hw pointer reads
[ALSA] HDA-Intel - Add support for Intel SCH
[ALSA] hda: Add GPIO mute support to STAC9205
[ALSA] hda-codec - Add Dell T3400 support
[ALSA] hda-codec - Add model for HP DV9553EG laptop
[ALSA] hda-codec - Control SPDIF as slave
[ALSA] hda_intel: ALSA HD Audio patch for Intel ICH10 DeviceID's
[ALSA] Fix Oops with PCM OSS sync
[ALSA] hda-codec - Add speaker automute to ALC262 HP models
...
Diffstat (limited to 'sound/core/pcm_lib.c')
-rw-r--r-- | sound/core/pcm_lib.c | 339 |
1 files changed, 82 insertions, 257 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 806f1fba5446..1533f0379e9d 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -20,7 +20,6 @@ | |||
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <sound/driver.h> | ||
24 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
25 | #include <linux/time.h> | 24 | #include <linux/time.h> |
26 | #include <sound/core.h> | 25 | #include <sound/core.h> |
@@ -145,11 +144,11 @@ static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substre | |||
145 | { | 144 | { |
146 | snd_pcm_uframes_t pos; | 145 | snd_pcm_uframes_t pos; |
147 | 146 | ||
147 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) | ||
148 | snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp); | ||
148 | pos = substream->ops->pointer(substream); | 149 | pos = substream->ops->pointer(substream); |
149 | if (pos == SNDRV_PCM_POS_XRUN) | 150 | if (pos == SNDRV_PCM_POS_XRUN) |
150 | return pos; /* XRUN */ | 151 | return pos; /* XRUN */ |
151 | if (runtime->tstamp_mode & SNDRV_PCM_TSTAMP_MMAP) | ||
152 | getnstimeofday((struct timespec *)&runtime->status->tstamp); | ||
153 | #ifdef CONFIG_SND_DEBUG | 152 | #ifdef CONFIG_SND_DEBUG |
154 | if (pos >= runtime->buffer_size) { | 153 | if (pos >= runtime->buffer_size) { |
155 | snd_printk(KERN_ERR "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size); | 154 | snd_printk(KERN_ERR "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size); |
@@ -1139,7 +1138,7 @@ EXPORT_SYMBOL(snd_pcm_hw_constraint_step); | |||
1139 | 1138 | ||
1140 | static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) | 1139 | static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) |
1141 | { | 1140 | { |
1142 | static int pow2_sizes[] = { | 1141 | static unsigned int pow2_sizes[] = { |
1143 | 1<<0, 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7, | 1142 | 1<<0, 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7, |
1144 | 1<<8, 1<<9, 1<<10, 1<<11, 1<<12, 1<<13, 1<<14, 1<<15, | 1143 | 1<<8, 1<<9, 1<<10, 1<<11, 1<<12, 1<<13, 1<<14, 1<<15, |
1145 | 1<<16, 1<<17, 1<<18, 1<<19, 1<<20, 1<<21, 1<<22, 1<<23, | 1144 | 1<<16, 1<<17, 1<<18, 1<<19, 1<<20, 1<<21, 1<<22, 1<<23, |
@@ -1451,108 +1450,13 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, | |||
1451 | 1450 | ||
1452 | EXPORT_SYMBOL(snd_pcm_lib_ioctl); | 1451 | EXPORT_SYMBOL(snd_pcm_lib_ioctl); |
1453 | 1452 | ||
1454 | /* | ||
1455 | * Conditions | ||
1456 | */ | ||
1457 | |||
1458 | static void snd_pcm_system_tick_set(struct snd_pcm_substream *substream, | ||
1459 | unsigned long ticks) | ||
1460 | { | ||
1461 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1462 | if (ticks == 0) | ||
1463 | del_timer(&runtime->tick_timer); | ||
1464 | else { | ||
1465 | ticks += (1000000 / HZ) - 1; | ||
1466 | ticks /= (1000000 / HZ); | ||
1467 | mod_timer(&runtime->tick_timer, jiffies + ticks); | ||
1468 | } | ||
1469 | } | ||
1470 | |||
1471 | /* Temporary alias */ | ||
1472 | void snd_pcm_tick_set(struct snd_pcm_substream *substream, unsigned long ticks) | ||
1473 | { | ||
1474 | snd_pcm_system_tick_set(substream, ticks); | ||
1475 | } | ||
1476 | |||
1477 | void snd_pcm_tick_prepare(struct snd_pcm_substream *substream) | ||
1478 | { | ||
1479 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1480 | snd_pcm_uframes_t frames = ULONG_MAX; | ||
1481 | snd_pcm_uframes_t avail, dist; | ||
1482 | unsigned int ticks; | ||
1483 | u_int64_t n; | ||
1484 | u_int32_t r; | ||
1485 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
1486 | if (runtime->silence_size >= runtime->boundary) { | ||
1487 | frames = 1; | ||
1488 | } else if (runtime->silence_size > 0 && | ||
1489 | runtime->silence_filled < runtime->buffer_size) { | ||
1490 | snd_pcm_sframes_t noise_dist; | ||
1491 | noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silence_filled; | ||
1492 | if (noise_dist > (snd_pcm_sframes_t)runtime->silence_threshold) | ||
1493 | frames = noise_dist - runtime->silence_threshold; | ||
1494 | } | ||
1495 | avail = snd_pcm_playback_avail(runtime); | ||
1496 | } else { | ||
1497 | avail = snd_pcm_capture_avail(runtime); | ||
1498 | } | ||
1499 | if (avail < runtime->control->avail_min) { | ||
1500 | snd_pcm_sframes_t n = runtime->control->avail_min - avail; | ||
1501 | if (n > 0 && frames > (snd_pcm_uframes_t)n) | ||
1502 | frames = n; | ||
1503 | } | ||
1504 | if (avail < runtime->buffer_size) { | ||
1505 | snd_pcm_sframes_t n = runtime->buffer_size - avail; | ||
1506 | if (n > 0 && frames > (snd_pcm_uframes_t)n) | ||
1507 | frames = n; | ||
1508 | } | ||
1509 | if (frames == ULONG_MAX) { | ||
1510 | snd_pcm_tick_set(substream, 0); | ||
1511 | return; | ||
1512 | } | ||
1513 | dist = runtime->status->hw_ptr - runtime->hw_ptr_base; | ||
1514 | /* Distance to next interrupt */ | ||
1515 | dist = runtime->period_size - dist % runtime->period_size; | ||
1516 | if (dist <= frames) { | ||
1517 | snd_pcm_tick_set(substream, 0); | ||
1518 | return; | ||
1519 | } | ||
1520 | /* the base time is us */ | ||
1521 | n = frames; | ||
1522 | n *= 1000000; | ||
1523 | div64_32(&n, runtime->tick_time * runtime->rate, &r); | ||
1524 | ticks = n + (r > 0 ? 1 : 0); | ||
1525 | if (ticks < runtime->sleep_min) | ||
1526 | ticks = runtime->sleep_min; | ||
1527 | snd_pcm_tick_set(substream, (unsigned long) ticks); | ||
1528 | } | ||
1529 | |||
1530 | void snd_pcm_tick_elapsed(struct snd_pcm_substream *substream) | ||
1531 | { | ||
1532 | struct snd_pcm_runtime *runtime; | ||
1533 | unsigned long flags; | ||
1534 | |||
1535 | snd_assert(substream != NULL, return); | ||
1536 | runtime = substream->runtime; | ||
1537 | snd_assert(runtime != NULL, return); | ||
1538 | |||
1539 | snd_pcm_stream_lock_irqsave(substream, flags); | ||
1540 | if (!snd_pcm_running(substream) || | ||
1541 | snd_pcm_update_hw_ptr(substream) < 0) | ||
1542 | goto _end; | ||
1543 | if (runtime->sleep_min) | ||
1544 | snd_pcm_tick_prepare(substream); | ||
1545 | _end: | ||
1546 | snd_pcm_stream_unlock_irqrestore(substream, flags); | ||
1547 | } | ||
1548 | |||
1549 | /** | 1453 | /** |
1550 | * snd_pcm_period_elapsed - update the pcm status for the next period | 1454 | * snd_pcm_period_elapsed - update the pcm status for the next period |
1551 | * @substream: the pcm substream instance | 1455 | * @substream: the pcm substream instance |
1552 | * | 1456 | * |
1553 | * This function is called from the interrupt handler when the | 1457 | * This function is called from the interrupt handler when the |
1554 | * PCM has processed the period size. It will update the current | 1458 | * PCM has processed the period size. It will update the current |
1555 | * pointer, set up the tick, wake up sleepers, etc. | 1459 | * pointer, wake up sleepers, etc. |
1556 | * | 1460 | * |
1557 | * Even if more than one periods have elapsed since the last call, you | 1461 | * Even if more than one periods have elapsed since the last call, you |
1558 | * have to call this only once. | 1462 | * have to call this only once. |
@@ -1576,8 +1480,6 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) | |||
1576 | 1480 | ||
1577 | if (substream->timer_running) | 1481 | if (substream->timer_running) |
1578 | snd_timer_interrupt(substream->timer, 1); | 1482 | snd_timer_interrupt(substream->timer, 1); |
1579 | if (runtime->sleep_min) | ||
1580 | snd_pcm_tick_prepare(substream); | ||
1581 | _end: | 1483 | _end: |
1582 | snd_pcm_stream_unlock_irqrestore(substream, flags); | 1484 | snd_pcm_stream_unlock_irqrestore(substream, flags); |
1583 | if (runtime->transfer_ack_end) | 1485 | if (runtime->transfer_ack_end) |
@@ -1587,6 +1489,71 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) | |||
1587 | 1489 | ||
1588 | EXPORT_SYMBOL(snd_pcm_period_elapsed); | 1490 | EXPORT_SYMBOL(snd_pcm_period_elapsed); |
1589 | 1491 | ||
1492 | /* | ||
1493 | * Wait until avail_min data becomes available | ||
1494 | * Returns a negative error code if any error occurs during operation. | ||
1495 | * The available space is stored on availp. When err = 0 and avail = 0 | ||
1496 | * on the capture stream, it indicates the stream is in DRAINING state. | ||
1497 | */ | ||
1498 | static int wait_for_avail_min(struct snd_pcm_substream *substream, | ||
1499 | snd_pcm_uframes_t *availp) | ||
1500 | { | ||
1501 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1502 | int is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
1503 | wait_queue_t wait; | ||
1504 | int err = 0; | ||
1505 | snd_pcm_uframes_t avail = 0; | ||
1506 | long tout; | ||
1507 | |||
1508 | init_waitqueue_entry(&wait, current); | ||
1509 | add_wait_queue(&runtime->sleep, &wait); | ||
1510 | for (;;) { | ||
1511 | if (signal_pending(current)) { | ||
1512 | err = -ERESTARTSYS; | ||
1513 | break; | ||
1514 | } | ||
1515 | set_current_state(TASK_INTERRUPTIBLE); | ||
1516 | snd_pcm_stream_unlock_irq(substream); | ||
1517 | tout = schedule_timeout(msecs_to_jiffies(10000)); | ||
1518 | snd_pcm_stream_lock_irq(substream); | ||
1519 | switch (runtime->status->state) { | ||
1520 | case SNDRV_PCM_STATE_SUSPENDED: | ||
1521 | err = -ESTRPIPE; | ||
1522 | goto _endloop; | ||
1523 | case SNDRV_PCM_STATE_XRUN: | ||
1524 | err = -EPIPE; | ||
1525 | goto _endloop; | ||
1526 | case SNDRV_PCM_STATE_DRAINING: | ||
1527 | if (is_playback) | ||
1528 | err = -EPIPE; | ||
1529 | else | ||
1530 | avail = 0; /* indicate draining */ | ||
1531 | goto _endloop; | ||
1532 | case SNDRV_PCM_STATE_OPEN: | ||
1533 | case SNDRV_PCM_STATE_SETUP: | ||
1534 | case SNDRV_PCM_STATE_DISCONNECTED: | ||
1535 | err = -EBADFD; | ||
1536 | goto _endloop; | ||
1537 | } | ||
1538 | if (!tout) { | ||
1539 | snd_printd("%s write error (DMA or IRQ trouble?)\n", | ||
1540 | is_playback ? "playback" : "capture"); | ||
1541 | err = -EIO; | ||
1542 | break; | ||
1543 | } | ||
1544 | if (is_playback) | ||
1545 | avail = snd_pcm_playback_avail(runtime); | ||
1546 | else | ||
1547 | avail = snd_pcm_capture_avail(runtime); | ||
1548 | if (avail >= runtime->control->avail_min) | ||
1549 | break; | ||
1550 | } | ||
1551 | _endloop: | ||
1552 | remove_wait_queue(&runtime->sleep, &wait); | ||
1553 | *availp = avail; | ||
1554 | return err; | ||
1555 | } | ||
1556 | |||
1590 | static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream, | 1557 | static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream, |
1591 | unsigned int hwoff, | 1558 | unsigned int hwoff, |
1592 | unsigned long data, unsigned int off, | 1559 | unsigned long data, unsigned int off, |
@@ -1624,8 +1591,6 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, | |||
1624 | 1591 | ||
1625 | if (size == 0) | 1592 | if (size == 0) |
1626 | return 0; | 1593 | return 0; |
1627 | if (size > runtime->xfer_align) | ||
1628 | size -= size % runtime->xfer_align; | ||
1629 | 1594 | ||
1630 | snd_pcm_stream_lock_irq(substream); | 1595 | snd_pcm_stream_lock_irq(substream); |
1631 | switch (runtime->status->state) { | 1596 | switch (runtime->status->state) { |
@@ -1648,84 +1613,18 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, | |||
1648 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; | 1613 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; |
1649 | snd_pcm_uframes_t avail; | 1614 | snd_pcm_uframes_t avail; |
1650 | snd_pcm_uframes_t cont; | 1615 | snd_pcm_uframes_t cont; |
1651 | if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING) | 1616 | if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) |
1652 | snd_pcm_update_hw_ptr(substream); | 1617 | snd_pcm_update_hw_ptr(substream); |
1653 | avail = snd_pcm_playback_avail(runtime); | 1618 | avail = snd_pcm_playback_avail(runtime); |
1654 | if (((avail < runtime->control->avail_min && size > avail) || | 1619 | if (!avail) { |
1655 | (size >= runtime->xfer_align && avail < runtime->xfer_align))) { | ||
1656 | wait_queue_t wait; | ||
1657 | enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED, DROPPED } state; | ||
1658 | long tout; | ||
1659 | |||
1660 | if (nonblock) { | 1620 | if (nonblock) { |
1661 | err = -EAGAIN; | 1621 | err = -EAGAIN; |
1662 | goto _end_unlock; | 1622 | goto _end_unlock; |
1663 | } | 1623 | } |
1664 | 1624 | err = wait_for_avail_min(substream, &avail); | |
1665 | init_waitqueue_entry(&wait, current); | 1625 | if (err < 0) |
1666 | add_wait_queue(&runtime->sleep, &wait); | ||
1667 | while (1) { | ||
1668 | if (signal_pending(current)) { | ||
1669 | state = SIGNALED; | ||
1670 | break; | ||
1671 | } | ||
1672 | set_current_state(TASK_INTERRUPTIBLE); | ||
1673 | snd_pcm_stream_unlock_irq(substream); | ||
1674 | tout = schedule_timeout(10 * HZ); | ||
1675 | snd_pcm_stream_lock_irq(substream); | ||
1676 | if (tout == 0) { | ||
1677 | if (runtime->status->state != SNDRV_PCM_STATE_PREPARED && | ||
1678 | runtime->status->state != SNDRV_PCM_STATE_PAUSED) { | ||
1679 | state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED; | ||
1680 | break; | ||
1681 | } | ||
1682 | } | ||
1683 | switch (runtime->status->state) { | ||
1684 | case SNDRV_PCM_STATE_XRUN: | ||
1685 | case SNDRV_PCM_STATE_DRAINING: | ||
1686 | state = ERROR; | ||
1687 | goto _end_loop; | ||
1688 | case SNDRV_PCM_STATE_SUSPENDED: | ||
1689 | state = SUSPENDED; | ||
1690 | goto _end_loop; | ||
1691 | case SNDRV_PCM_STATE_SETUP: | ||
1692 | state = DROPPED; | ||
1693 | goto _end_loop; | ||
1694 | default: | ||
1695 | break; | ||
1696 | } | ||
1697 | avail = snd_pcm_playback_avail(runtime); | ||
1698 | if (avail >= runtime->control->avail_min) { | ||
1699 | state = READY; | ||
1700 | break; | ||
1701 | } | ||
1702 | } | ||
1703 | _end_loop: | ||
1704 | remove_wait_queue(&runtime->sleep, &wait); | ||
1705 | |||
1706 | switch (state) { | ||
1707 | case ERROR: | ||
1708 | err = -EPIPE; | ||
1709 | goto _end_unlock; | ||
1710 | case SUSPENDED: | ||
1711 | err = -ESTRPIPE; | ||
1712 | goto _end_unlock; | ||
1713 | case SIGNALED: | ||
1714 | err = -ERESTARTSYS; | ||
1715 | goto _end_unlock; | ||
1716 | case EXPIRED: | ||
1717 | snd_printd("playback write error (DMA or IRQ trouble?)\n"); | ||
1718 | err = -EIO; | ||
1719 | goto _end_unlock; | ||
1720 | case DROPPED: | ||
1721 | err = -EBADFD; | ||
1722 | goto _end_unlock; | 1626 | goto _end_unlock; |
1723 | default: | ||
1724 | break; | ||
1725 | } | ||
1726 | } | 1627 | } |
1727 | if (avail > runtime->xfer_align) | ||
1728 | avail -= avail % runtime->xfer_align; | ||
1729 | frames = size > avail ? avail : size; | 1628 | frames = size > avail ? avail : size; |
1730 | cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; | 1629 | cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; |
1731 | if (frames > cont) | 1630 | if (frames > cont) |
@@ -1763,9 +1662,6 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, | |||
1763 | if (err < 0) | 1662 | if (err < 0) |
1764 | goto _end_unlock; | 1663 | goto _end_unlock; |
1765 | } | 1664 | } |
1766 | if (runtime->sleep_min && | ||
1767 | runtime->status->state == SNDRV_PCM_STATE_RUNNING) | ||
1768 | snd_pcm_tick_prepare(substream); | ||
1769 | } | 1665 | } |
1770 | _end_unlock: | 1666 | _end_unlock: |
1771 | snd_pcm_stream_unlock_irq(substream); | 1667 | snd_pcm_stream_unlock_irq(substream); |
@@ -1893,8 +1789,6 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, | |||
1893 | 1789 | ||
1894 | if (size == 0) | 1790 | if (size == 0) |
1895 | return 0; | 1791 | return 0; |
1896 | if (size > runtime->xfer_align) | ||
1897 | size -= size % runtime->xfer_align; | ||
1898 | 1792 | ||
1899 | snd_pcm_stream_lock_irq(substream); | 1793 | snd_pcm_stream_lock_irq(substream); |
1900 | switch (runtime->status->state) { | 1794 | switch (runtime->status->state) { |
@@ -1924,91 +1818,25 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, | |||
1924 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; | 1818 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; |
1925 | snd_pcm_uframes_t avail; | 1819 | snd_pcm_uframes_t avail; |
1926 | snd_pcm_uframes_t cont; | 1820 | snd_pcm_uframes_t cont; |
1927 | if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING) | 1821 | if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) |
1928 | snd_pcm_update_hw_ptr(substream); | 1822 | snd_pcm_update_hw_ptr(substream); |
1929 | __draining: | ||
1930 | avail = snd_pcm_capture_avail(runtime); | 1823 | avail = snd_pcm_capture_avail(runtime); |
1931 | if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { | 1824 | if (!avail) { |
1932 | if (avail < runtime->xfer_align) { | 1825 | if (runtime->status->state == |
1933 | err = -EPIPE; | 1826 | SNDRV_PCM_STATE_DRAINING) { |
1827 | snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); | ||
1934 | goto _end_unlock; | 1828 | goto _end_unlock; |
1935 | } | 1829 | } |
1936 | } else if ((avail < runtime->control->avail_min && size > avail) || | ||
1937 | (size >= runtime->xfer_align && avail < runtime->xfer_align)) { | ||
1938 | wait_queue_t wait; | ||
1939 | enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED, DROPPED } state; | ||
1940 | long tout; | ||
1941 | |||
1942 | if (nonblock) { | 1830 | if (nonblock) { |
1943 | err = -EAGAIN; | 1831 | err = -EAGAIN; |
1944 | goto _end_unlock; | 1832 | goto _end_unlock; |
1945 | } | 1833 | } |
1946 | 1834 | err = wait_for_avail_min(substream, &avail); | |
1947 | init_waitqueue_entry(&wait, current); | 1835 | if (err < 0) |
1948 | add_wait_queue(&runtime->sleep, &wait); | ||
1949 | while (1) { | ||
1950 | if (signal_pending(current)) { | ||
1951 | state = SIGNALED; | ||
1952 | break; | ||
1953 | } | ||
1954 | set_current_state(TASK_INTERRUPTIBLE); | ||
1955 | snd_pcm_stream_unlock_irq(substream); | ||
1956 | tout = schedule_timeout(10 * HZ); | ||
1957 | snd_pcm_stream_lock_irq(substream); | ||
1958 | if (tout == 0) { | ||
1959 | if (runtime->status->state != SNDRV_PCM_STATE_PREPARED && | ||
1960 | runtime->status->state != SNDRV_PCM_STATE_PAUSED) { | ||
1961 | state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED; | ||
1962 | break; | ||
1963 | } | ||
1964 | } | ||
1965 | switch (runtime->status->state) { | ||
1966 | case SNDRV_PCM_STATE_XRUN: | ||
1967 | state = ERROR; | ||
1968 | goto _end_loop; | ||
1969 | case SNDRV_PCM_STATE_SUSPENDED: | ||
1970 | state = SUSPENDED; | ||
1971 | goto _end_loop; | ||
1972 | case SNDRV_PCM_STATE_DRAINING: | ||
1973 | goto __draining; | ||
1974 | case SNDRV_PCM_STATE_SETUP: | ||
1975 | state = DROPPED; | ||
1976 | goto _end_loop; | ||
1977 | default: | ||
1978 | break; | ||
1979 | } | ||
1980 | avail = snd_pcm_capture_avail(runtime); | ||
1981 | if (avail >= runtime->control->avail_min) { | ||
1982 | state = READY; | ||
1983 | break; | ||
1984 | } | ||
1985 | } | ||
1986 | _end_loop: | ||
1987 | remove_wait_queue(&runtime->sleep, &wait); | ||
1988 | |||
1989 | switch (state) { | ||
1990 | case ERROR: | ||
1991 | err = -EPIPE; | ||
1992 | goto _end_unlock; | ||
1993 | case SUSPENDED: | ||
1994 | err = -ESTRPIPE; | ||
1995 | goto _end_unlock; | ||
1996 | case SIGNALED: | ||
1997 | err = -ERESTARTSYS; | ||
1998 | goto _end_unlock; | ||
1999 | case EXPIRED: | ||
2000 | snd_printd("capture read error (DMA or IRQ trouble?)\n"); | ||
2001 | err = -EIO; | ||
2002 | goto _end_unlock; | ||
2003 | case DROPPED: | ||
2004 | err = -EBADFD; | ||
2005 | goto _end_unlock; | 1836 | goto _end_unlock; |
2006 | default: | 1837 | if (!avail) |
2007 | break; | 1838 | continue; /* draining */ |
2008 | } | ||
2009 | } | 1839 | } |
2010 | if (avail > runtime->xfer_align) | ||
2011 | avail -= avail % runtime->xfer_align; | ||
2012 | frames = size > avail ? avail : size; | 1840 | frames = size > avail ? avail : size; |
2013 | cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; | 1841 | cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; |
2014 | if (frames > cont) | 1842 | if (frames > cont) |
@@ -2040,9 +1868,6 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, | |||
2040 | offset += frames; | 1868 | offset += frames; |
2041 | size -= frames; | 1869 | size -= frames; |
2042 | xfer += frames; | 1870 | xfer += frames; |
2043 | if (runtime->sleep_min && | ||
2044 | runtime->status->state == SNDRV_PCM_STATE_RUNNING) | ||
2045 | snd_pcm_tick_prepare(substream); | ||
2046 | } | 1871 | } |
2047 | _end_unlock: | 1872 | _end_unlock: |
2048 | snd_pcm_stream_unlock_irq(substream); | 1873 | snd_pcm_stream_unlock_irq(substream); |