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.c60
1 files changed, 51 insertions, 9 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 86d0caf91b35..3420bd3da5d7 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -23,6 +23,7 @@
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/time.h> 24#include <linux/time.h>
25#include <linux/math64.h> 25#include <linux/math64.h>
26#include <linux/export.h>
26#include <sound/core.h> 27#include <sound/core.h>
27#include <sound/control.h> 28#include <sound/control.h>
28#include <sound/info.h> 29#include <sound/info.h>
@@ -1399,6 +1400,32 @@ int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime,
1399 1400
1400EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2); 1401EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2);
1401 1402
1403static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params,
1404 struct snd_pcm_hw_rule *rule)
1405{
1406 unsigned int base_rate = (unsigned int)(uintptr_t)rule->private;
1407 struct snd_interval *rate;
1408
1409 rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
1410 return snd_interval_list(rate, 1, &base_rate, 0);
1411}
1412
1413/**
1414 * snd_pcm_hw_rule_noresample - add a rule to allow disabling hw resampling
1415 * @runtime: PCM runtime instance
1416 * @base_rate: the rate at which the hardware does not resample
1417 */
1418int snd_pcm_hw_rule_noresample(struct snd_pcm_runtime *runtime,
1419 unsigned int base_rate)
1420{
1421 return snd_pcm_hw_rule_add(runtime, SNDRV_PCM_HW_PARAMS_NORESAMPLE,
1422 SNDRV_PCM_HW_PARAM_RATE,
1423 snd_pcm_hw_rule_noresample_func,
1424 (void *)(uintptr_t)base_rate,
1425 SNDRV_PCM_HW_PARAM_RATE, -1);
1426}
1427EXPORT_SYMBOL(snd_pcm_hw_rule_noresample);
1428
1402static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params, 1429static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params,
1403 snd_pcm_hw_param_t var) 1430 snd_pcm_hw_param_t var)
1404{ 1431{
@@ -1761,6 +1788,10 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
1761 snd_pcm_uframes_t avail = 0; 1788 snd_pcm_uframes_t avail = 0;
1762 long wait_time, tout; 1789 long wait_time, tout;
1763 1790
1791 init_waitqueue_entry(&wait, current);
1792 set_current_state(TASK_INTERRUPTIBLE);
1793 add_wait_queue(&runtime->tsleep, &wait);
1794
1764 if (runtime->no_period_wakeup) 1795 if (runtime->no_period_wakeup)
1765 wait_time = MAX_SCHEDULE_TIMEOUT; 1796 wait_time = MAX_SCHEDULE_TIMEOUT;
1766 else { 1797 else {
@@ -1771,16 +1802,32 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
1771 } 1802 }
1772 wait_time = msecs_to_jiffies(wait_time * 1000); 1803 wait_time = msecs_to_jiffies(wait_time * 1000);
1773 } 1804 }
1774 init_waitqueue_entry(&wait, current); 1805
1775 add_wait_queue(&runtime->tsleep, &wait);
1776 for (;;) { 1806 for (;;) {
1777 if (signal_pending(current)) { 1807 if (signal_pending(current)) {
1778 err = -ERESTARTSYS; 1808 err = -ERESTARTSYS;
1779 break; 1809 break;
1780 } 1810 }
1811
1812 /*
1813 * We need to check if space became available already
1814 * (and thus the wakeup happened already) first to close
1815 * the race of space already having become available.
1816 * This check must happen after been added to the waitqueue
1817 * and having current state be INTERRUPTIBLE.
1818 */
1819 if (is_playback)
1820 avail = snd_pcm_playback_avail(runtime);
1821 else
1822 avail = snd_pcm_capture_avail(runtime);
1823 if (avail >= runtime->twake)
1824 break;
1781 snd_pcm_stream_unlock_irq(substream); 1825 snd_pcm_stream_unlock_irq(substream);
1782 tout = schedule_timeout_interruptible(wait_time); 1826
1827 tout = schedule_timeout(wait_time);
1828
1783 snd_pcm_stream_lock_irq(substream); 1829 snd_pcm_stream_lock_irq(substream);
1830 set_current_state(TASK_INTERRUPTIBLE);
1784 switch (runtime->status->state) { 1831 switch (runtime->status->state) {
1785 case SNDRV_PCM_STATE_SUSPENDED: 1832 case SNDRV_PCM_STATE_SUSPENDED:
1786 err = -ESTRPIPE; 1833 err = -ESTRPIPE;
@@ -1806,14 +1853,9 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
1806 err = -EIO; 1853 err = -EIO;
1807 break; 1854 break;
1808 } 1855 }
1809 if (is_playback)
1810 avail = snd_pcm_playback_avail(runtime);
1811 else
1812 avail = snd_pcm_capture_avail(runtime);
1813 if (avail >= runtime->twake)
1814 break;
1815 } 1856 }
1816 _endloop: 1857 _endloop:
1858 set_current_state(TASK_RUNNING);
1817 remove_wait_queue(&runtime->tsleep, &wait); 1859 remove_wait_queue(&runtime->tsleep, &wait);
1818 *availp = avail; 1860 *availp = avail;
1819 return err; 1861 return err;