aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/pcm_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/pcm_lib.c')
-rw-r--r--sound/core/pcm_lib.c113
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
1452EXPORT_SYMBOL(snd_pcm_lib_ioctl); 1452EXPORT_SYMBOL(snd_pcm_lib_ioctl);
1453 1453
1454/*
1455 * Conditions
1456 */
1457
1458static 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 */
1472void snd_pcm_tick_set(struct snd_pcm_substream *substream, unsigned long ticks)
1473{
1474 snd_pcm_system_tick_set(substream, ticks);
1475}
1476
1477void 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
1534void 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);