diff options
Diffstat (limited to 'sound/core/pcm_lib.c')
-rw-r--r-- | sound/core/pcm_lib.c | 113 |
1 files changed, 3 insertions, 110 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index b406630d8fd..f00758c2bde 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -1451,112 +1451,13 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, | |||
1451 | 1451 | ||
1452 | EXPORT_SYMBOL(snd_pcm_lib_ioctl); | 1452 | EXPORT_SYMBOL(snd_pcm_lib_ioctl); |
1453 | 1453 | ||
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 to_avail_min = | ||
1501 | runtime->control->avail_min - avail; | ||
1502 | if (to_avail_min > 0 && | ||
1503 | frames > (snd_pcm_uframes_t)to_avail_min) | ||
1504 | frames = to_avail_min; | ||
1505 | } | ||
1506 | if (avail < runtime->buffer_size) { | ||
1507 | snd_pcm_sframes_t to_buffer_size = | ||
1508 | runtime->buffer_size - avail; | ||
1509 | if (to_buffer_size > 0 && | ||
1510 | frames > (snd_pcm_uframes_t)to_buffer_size) | ||
1511 | frames = to_buffer_size; | ||
1512 | } | ||
1513 | if (frames == ULONG_MAX) { | ||
1514 | snd_pcm_tick_set(substream, 0); | ||
1515 | return; | ||
1516 | } | ||
1517 | dist = runtime->status->hw_ptr - runtime->hw_ptr_base; | ||
1518 | /* Distance to next interrupt */ | ||
1519 | dist = runtime->period_size - dist % runtime->period_size; | ||
1520 | if (dist <= frames) { | ||
1521 | snd_pcm_tick_set(substream, 0); | ||
1522 | return; | ||
1523 | } | ||
1524 | /* the base time is us */ | ||
1525 | n = frames; | ||
1526 | n *= 1000000; | ||
1527 | div64_32(&n, runtime->tick_time * runtime->rate, &r); | ||
1528 | ticks = n + (r > 0 ? 1 : 0); | ||
1529 | if (ticks < runtime->sleep_min) | ||
1530 | ticks = runtime->sleep_min; | ||
1531 | snd_pcm_tick_set(substream, (unsigned long) ticks); | ||
1532 | } | ||
1533 | |||
1534 | void snd_pcm_tick_elapsed(struct snd_pcm_substream *substream) | ||
1535 | { | ||
1536 | struct snd_pcm_runtime *runtime; | ||
1537 | unsigned long flags; | ||
1538 | |||
1539 | snd_assert(substream != NULL, return); | ||
1540 | runtime = substream->runtime; | ||
1541 | snd_assert(runtime != NULL, return); | ||
1542 | |||
1543 | snd_pcm_stream_lock_irqsave(substream, flags); | ||
1544 | if (!snd_pcm_running(substream) || | ||
1545 | snd_pcm_update_hw_ptr(substream) < 0) | ||
1546 | goto _end; | ||
1547 | if (runtime->sleep_min) | ||
1548 | snd_pcm_tick_prepare(substream); | ||
1549 | _end: | ||
1550 | snd_pcm_stream_unlock_irqrestore(substream, flags); | ||
1551 | } | ||
1552 | |||
1553 | /** | 1454 | /** |
1554 | * snd_pcm_period_elapsed - update the pcm status for the next period | 1455 | * snd_pcm_period_elapsed - update the pcm status for the next period |
1555 | * @substream: the pcm substream instance | 1456 | * @substream: the pcm substream instance |
1556 | * | 1457 | * |
1557 | * This function is called from the interrupt handler when the | 1458 | * This function is called from the interrupt handler when the |
1558 | * PCM has processed the period size. It will update the current | 1459 | * PCM has processed the period size. It will update the current |
1559 | * pointer, set up the tick, wake up sleepers, etc. | 1460 | * pointer, wake up sleepers, etc. |
1560 | * | 1461 | * |
1561 | * Even if more than one periods have elapsed since the last call, you | 1462 | * Even if more than one periods have elapsed since the last call, you |
1562 | * have to call this only once. | 1463 | * have to call this only once. |
@@ -1580,8 +1481,6 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) | |||
1580 | 1481 | ||
1581 | if (substream->timer_running) | 1482 | if (substream->timer_running) |
1582 | snd_timer_interrupt(substream->timer, 1); | 1483 | snd_timer_interrupt(substream->timer, 1); |
1583 | if (runtime->sleep_min) | ||
1584 | snd_pcm_tick_prepare(substream); | ||
1585 | _end: | 1484 | _end: |
1586 | snd_pcm_stream_unlock_irqrestore(substream, flags); | 1485 | snd_pcm_stream_unlock_irqrestore(substream, flags); |
1587 | if (runtime->transfer_ack_end) | 1486 | if (runtime->transfer_ack_end) |
@@ -1715,7 +1614,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, | |||
1715 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; | 1614 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; |
1716 | snd_pcm_uframes_t avail; | 1615 | snd_pcm_uframes_t avail; |
1717 | snd_pcm_uframes_t cont; | 1616 | snd_pcm_uframes_t cont; |
1718 | if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING) | 1617 | if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) |
1719 | snd_pcm_update_hw_ptr(substream); | 1618 | snd_pcm_update_hw_ptr(substream); |
1720 | avail = snd_pcm_playback_avail(runtime); | 1619 | avail = snd_pcm_playback_avail(runtime); |
1721 | if (!avail) { | 1620 | if (!avail) { |
@@ -1764,9 +1663,6 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, | |||
1764 | if (err < 0) | 1663 | if (err < 0) |
1765 | goto _end_unlock; | 1664 | goto _end_unlock; |
1766 | } | 1665 | } |
1767 | if (runtime->sleep_min && | ||
1768 | runtime->status->state == SNDRV_PCM_STATE_RUNNING) | ||
1769 | snd_pcm_tick_prepare(substream); | ||
1770 | } | 1666 | } |
1771 | _end_unlock: | 1667 | _end_unlock: |
1772 | snd_pcm_stream_unlock_irq(substream); | 1668 | snd_pcm_stream_unlock_irq(substream); |
@@ -1923,7 +1819,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, | |||
1923 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; | 1819 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; |
1924 | snd_pcm_uframes_t avail; | 1820 | snd_pcm_uframes_t avail; |
1925 | snd_pcm_uframes_t cont; | 1821 | snd_pcm_uframes_t cont; |
1926 | if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING) | 1822 | if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) |
1927 | snd_pcm_update_hw_ptr(substream); | 1823 | snd_pcm_update_hw_ptr(substream); |
1928 | avail = snd_pcm_capture_avail(runtime); | 1824 | avail = snd_pcm_capture_avail(runtime); |
1929 | if (!avail) { | 1825 | if (!avail) { |
@@ -1973,9 +1869,6 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, | |||
1973 | offset += frames; | 1869 | offset += frames; |
1974 | size -= frames; | 1870 | size -= frames; |
1975 | xfer += frames; | 1871 | xfer += frames; |
1976 | if (runtime->sleep_min && | ||
1977 | runtime->status->state == SNDRV_PCM_STATE_RUNNING) | ||
1978 | snd_pcm_tick_prepare(substream); | ||
1979 | } | 1872 | } |
1980 | _end_unlock: | 1873 | _end_unlock: |
1981 | snd_pcm_stream_unlock_irq(substream); | 1874 | snd_pcm_stream_unlock_irq(substream); |