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.c668
1 files changed, 253 insertions, 415 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 877176067072..a93a4235a332 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -33,6 +33,8 @@
33#include <sound/pcm_params.h> 33#include <sound/pcm_params.h>
34#include <sound/timer.h> 34#include <sound/timer.h>
35 35
36#include "pcm_local.h"
37
36#ifdef CONFIG_SND_PCM_XRUN_DEBUG 38#ifdef CONFIG_SND_PCM_XRUN_DEBUG
37#define CREATE_TRACE_POINTS 39#define CREATE_TRACE_POINTS
38#include "pcm_trace.h" 40#include "pcm_trace.h"
@@ -40,8 +42,12 @@
40#define trace_hwptr(substream, pos, in_interrupt) 42#define trace_hwptr(substream, pos, in_interrupt)
41#define trace_xrun(substream) 43#define trace_xrun(substream)
42#define trace_hw_ptr_error(substream, reason) 44#define trace_hw_ptr_error(substream, reason)
45#define trace_applptr(substream, prev, curr)
43#endif 46#endif
44 47
48static int fill_silence_frames(struct snd_pcm_substream *substream,
49 snd_pcm_uframes_t off, snd_pcm_uframes_t frames);
50
45/* 51/*
46 * fill ring buffer with silence 52 * fill ring buffer with silence
47 * runtime->silence_start: starting pointer to silence area 53 * runtime->silence_start: starting pointer to silence area
@@ -55,18 +61,20 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
55{ 61{
56 struct snd_pcm_runtime *runtime = substream->runtime; 62 struct snd_pcm_runtime *runtime = substream->runtime;
57 snd_pcm_uframes_t frames, ofs, transfer; 63 snd_pcm_uframes_t frames, ofs, transfer;
64 int err;
58 65
59 if (runtime->silence_size < runtime->boundary) { 66 if (runtime->silence_size < runtime->boundary) {
60 snd_pcm_sframes_t noise_dist, n; 67 snd_pcm_sframes_t noise_dist, n;
61 if (runtime->silence_start != runtime->control->appl_ptr) { 68 snd_pcm_uframes_t appl_ptr = READ_ONCE(runtime->control->appl_ptr);
62 n = runtime->control->appl_ptr - runtime->silence_start; 69 if (runtime->silence_start != appl_ptr) {
70 n = appl_ptr - runtime->silence_start;
63 if (n < 0) 71 if (n < 0)
64 n += runtime->boundary; 72 n += runtime->boundary;
65 if ((snd_pcm_uframes_t)n < runtime->silence_filled) 73 if ((snd_pcm_uframes_t)n < runtime->silence_filled)
66 runtime->silence_filled -= n; 74 runtime->silence_filled -= n;
67 else 75 else
68 runtime->silence_filled = 0; 76 runtime->silence_filled = 0;
69 runtime->silence_start = runtime->control->appl_ptr; 77 runtime->silence_start = appl_ptr;
70 } 78 }
71 if (runtime->silence_filled >= runtime->buffer_size) 79 if (runtime->silence_filled >= runtime->buffer_size)
72 return; 80 return;
@@ -107,33 +115,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
107 ofs = runtime->silence_start % runtime->buffer_size; 115 ofs = runtime->silence_start % runtime->buffer_size;
108 while (frames > 0) { 116 while (frames > 0) {
109 transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames; 117 transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames;
110 if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || 118 err = fill_silence_frames(substream, ofs, transfer);
111 runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) { 119 snd_BUG_ON(err < 0);
112 if (substream->ops->silence) {
113 int err;
114 err = substream->ops->silence(substream, -1, ofs, transfer);
115 snd_BUG_ON(err < 0);
116 } else {
117 char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs);
118 snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels);
119 }
120 } else {
121 unsigned int c;
122 unsigned int channels = runtime->channels;
123 if (substream->ops->silence) {
124 for (c = 0; c < channels; ++c) {
125 int err;
126 err = substream->ops->silence(substream, c, ofs, transfer);
127 snd_BUG_ON(err < 0);
128 }
129 } else {
130 size_t dma_csize = runtime->dma_bytes / channels;
131 for (c = 0; c < channels; ++c) {
132 char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, ofs);
133 snd_pcm_format_set_silence(runtime->format, hwbuf, transfer);
134 }
135 }
136 }
137 runtime->silence_filled += transfer; 120 runtime->silence_filled += transfer;
138 frames -= transfer; 121 frames -= transfer;
139 ofs = 0; 122 ofs = 0;
@@ -508,7 +491,6 @@ void snd_pcm_set_ops(struct snd_pcm *pcm, int direction,
508 for (substream = stream->substream; substream != NULL; substream = substream->next) 491 for (substream = stream->substream; substream != NULL; substream = substream->next)
509 substream->ops = ops; 492 substream->ops = ops;
510} 493}
511
512EXPORT_SYMBOL(snd_pcm_set_ops); 494EXPORT_SYMBOL(snd_pcm_set_ops);
513 495
514/** 496/**
@@ -526,7 +508,6 @@ void snd_pcm_set_sync(struct snd_pcm_substream *substream)
526 runtime->sync.id32[2] = -1; 508 runtime->sync.id32[2] = -1;
527 runtime->sync.id32[3] = -1; 509 runtime->sync.id32[3] = -1;
528} 510}
529
530EXPORT_SYMBOL(snd_pcm_set_sync); 511EXPORT_SYMBOL(snd_pcm_set_sync);
531 512
532/* 513/*
@@ -643,7 +624,6 @@ int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v)
643 } 624 }
644 return changed; 625 return changed;
645} 626}
646
647EXPORT_SYMBOL(snd_interval_refine); 627EXPORT_SYMBOL(snd_interval_refine);
648 628
649static int snd_interval_refine_first(struct snd_interval *i) 629static int snd_interval_refine_first(struct snd_interval *i)
@@ -906,7 +886,6 @@ int snd_interval_ratnum(struct snd_interval *i,
906 } 886 }
907 return err; 887 return err;
908} 888}
909
910EXPORT_SYMBOL(snd_interval_ratnum); 889EXPORT_SYMBOL(snd_interval_ratnum);
911 890
912/** 891/**
@@ -1044,7 +1023,6 @@ int snd_interval_list(struct snd_interval *i, unsigned int count,
1044 } 1023 }
1045 return snd_interval_refine(i, &list_range); 1024 return snd_interval_refine(i, &list_range);
1046} 1025}
1047
1048EXPORT_SYMBOL(snd_interval_list); 1026EXPORT_SYMBOL(snd_interval_list);
1049 1027
1050/** 1028/**
@@ -1183,7 +1161,6 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,
1183 va_end(args); 1161 va_end(args);
1184 return 0; 1162 return 0;
1185} 1163}
1186
1187EXPORT_SYMBOL(snd_pcm_hw_rule_add); 1164EXPORT_SYMBOL(snd_pcm_hw_rule_add);
1188 1165
1189/** 1166/**
@@ -1247,7 +1224,6 @@ int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_pa
1247 struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints; 1224 struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
1248 return snd_interval_setinteger(constrs_interval(constrs, var)); 1225 return snd_interval_setinteger(constrs_interval(constrs, var));
1249} 1226}
1250
1251EXPORT_SYMBOL(snd_pcm_hw_constraint_integer); 1227EXPORT_SYMBOL(snd_pcm_hw_constraint_integer);
1252 1228
1253/** 1229/**
@@ -1273,7 +1249,6 @@ int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_par
1273 t.integer = 0; 1249 t.integer = 0;
1274 return snd_interval_refine(constrs_interval(constrs, var), &t); 1250 return snd_interval_refine(constrs_interval(constrs, var), &t);
1275} 1251}
1276
1277EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax); 1252EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax);
1278 1253
1279static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params, 1254static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params,
@@ -1304,7 +1279,6 @@ int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime,
1304 snd_pcm_hw_rule_list, (void *)l, 1279 snd_pcm_hw_rule_list, (void *)l,
1305 var, -1); 1280 var, -1);
1306} 1281}
1307
1308EXPORT_SYMBOL(snd_pcm_hw_constraint_list); 1282EXPORT_SYMBOL(snd_pcm_hw_constraint_list);
1309 1283
1310static int snd_pcm_hw_rule_ranges(struct snd_pcm_hw_params *params, 1284static int snd_pcm_hw_rule_ranges(struct snd_pcm_hw_params *params,
@@ -1371,7 +1345,6 @@ int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime,
1371 snd_pcm_hw_rule_ratnums, (void *)r, 1345 snd_pcm_hw_rule_ratnums, (void *)r,
1372 var, -1); 1346 var, -1);
1373} 1347}
1374
1375EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums); 1348EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums);
1376 1349
1377static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params, 1350static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params,
@@ -1406,7 +1379,6 @@ int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime,
1406 snd_pcm_hw_rule_ratdens, (void *)r, 1379 snd_pcm_hw_rule_ratdens, (void *)r,
1407 var, -1); 1380 var, -1);
1408} 1381}
1409
1410EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens); 1382EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens);
1411 1383
1412static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params, 1384static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params,
@@ -1415,7 +1387,8 @@ static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params,
1415 unsigned int l = (unsigned long) rule->private; 1387 unsigned int l = (unsigned long) rule->private;
1416 int width = l & 0xffff; 1388 int width = l & 0xffff;
1417 unsigned int msbits = l >> 16; 1389 unsigned int msbits = l >> 16;
1418 struct snd_interval *i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); 1390 const struct snd_interval *i =
1391 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
1419 1392
1420 if (!snd_interval_single(i)) 1393 if (!snd_interval_single(i))
1421 return 0; 1394 return 0;
@@ -1452,7 +1425,6 @@ int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime,
1452 (void*) l, 1425 (void*) l,
1453 SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); 1426 SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
1454} 1427}
1455
1456EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits); 1428EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits);
1457 1429
1458static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params, 1430static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params,
@@ -1480,7 +1452,6 @@ int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime,
1480 snd_pcm_hw_rule_step, (void *) step, 1452 snd_pcm_hw_rule_step, (void *) step,
1481 var, -1); 1453 var, -1);
1482} 1454}
1483
1484EXPORT_SYMBOL(snd_pcm_hw_constraint_step); 1455EXPORT_SYMBOL(snd_pcm_hw_constraint_step);
1485 1456
1486static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) 1457static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
@@ -1511,7 +1482,6 @@ int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime,
1511 snd_pcm_hw_rule_pow2, NULL, 1482 snd_pcm_hw_rule_pow2, NULL,
1512 var, -1); 1483 var, -1);
1513} 1484}
1514
1515EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2); 1485EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2);
1516 1486
1517static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params, 1487static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params,
@@ -1570,7 +1540,6 @@ void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params)
1570 _snd_pcm_hw_param_any(params, k); 1540 _snd_pcm_hw_param_any(params, k);
1571 params->info = ~0U; 1541 params->info = ~0U;
1572} 1542}
1573
1574EXPORT_SYMBOL(_snd_pcm_hw_params_any); 1543EXPORT_SYMBOL(_snd_pcm_hw_params_any);
1575 1544
1576/** 1545/**
@@ -1603,7 +1572,6 @@ int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
1603 } 1572 }
1604 return -EINVAL; 1573 return -EINVAL;
1605} 1574}
1606
1607EXPORT_SYMBOL(snd_pcm_hw_param_value); 1575EXPORT_SYMBOL(snd_pcm_hw_param_value);
1608 1576
1609void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, 1577void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params,
@@ -1621,7 +1589,6 @@ void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params,
1621 snd_BUG(); 1589 snd_BUG();
1622 } 1590 }
1623} 1591}
1624
1625EXPORT_SYMBOL(_snd_pcm_hw_param_setempty); 1592EXPORT_SYMBOL(_snd_pcm_hw_param_setempty);
1626 1593
1627static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params, 1594static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params,
@@ -1668,7 +1635,6 @@ int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm,
1668 } 1635 }
1669 return snd_pcm_hw_param_value(params, var, dir); 1636 return snd_pcm_hw_param_value(params, var, dir);
1670} 1637}
1671
1672EXPORT_SYMBOL(snd_pcm_hw_param_first); 1638EXPORT_SYMBOL(snd_pcm_hw_param_first);
1673 1639
1674static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params, 1640static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params,
@@ -1715,48 +1681,8 @@ int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm,
1715 } 1681 }
1716 return snd_pcm_hw_param_value(params, var, dir); 1682 return snd_pcm_hw_param_value(params, var, dir);
1717} 1683}
1718
1719EXPORT_SYMBOL(snd_pcm_hw_param_last); 1684EXPORT_SYMBOL(snd_pcm_hw_param_last);
1720 1685
1721/**
1722 * snd_pcm_hw_param_choose - choose a configuration defined by @params
1723 * @pcm: PCM instance
1724 * @params: the hw_params instance
1725 *
1726 * Choose one configuration from configuration space defined by @params.
1727 * The configuration chosen is that obtained fixing in this order:
1728 * first access, first format, first subformat, min channels,
1729 * min rate, min period time, max buffer size, min tick time
1730 *
1731 * Return: Zero if successful, or a negative error code on failure.
1732 */
1733int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
1734 struct snd_pcm_hw_params *params)
1735{
1736 static int vars[] = {
1737 SNDRV_PCM_HW_PARAM_ACCESS,
1738 SNDRV_PCM_HW_PARAM_FORMAT,
1739 SNDRV_PCM_HW_PARAM_SUBFORMAT,
1740 SNDRV_PCM_HW_PARAM_CHANNELS,
1741 SNDRV_PCM_HW_PARAM_RATE,
1742 SNDRV_PCM_HW_PARAM_PERIOD_TIME,
1743 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
1744 SNDRV_PCM_HW_PARAM_TICK_TIME,
1745 -1
1746 };
1747 int err, *v;
1748
1749 for (v = vars; *v != -1; v++) {
1750 if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE)
1751 err = snd_pcm_hw_param_first(pcm, params, *v, NULL);
1752 else
1753 err = snd_pcm_hw_param_last(pcm, params, *v, NULL);
1754 if (snd_BUG_ON(err < 0))
1755 return err;
1756 }
1757 return 0;
1758}
1759
1760static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream, 1686static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
1761 void *arg) 1687 void *arg)
1762{ 1688{
@@ -1843,8 +1769,6 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
1843 unsigned int cmd, void *arg) 1769 unsigned int cmd, void *arg)
1844{ 1770{
1845 switch (cmd) { 1771 switch (cmd) {
1846 case SNDRV_PCM_IOCTL1_INFO:
1847 return 0;
1848 case SNDRV_PCM_IOCTL1_RESET: 1772 case SNDRV_PCM_IOCTL1_RESET:
1849 return snd_pcm_lib_ioctl_reset(substream, arg); 1773 return snd_pcm_lib_ioctl_reset(substream, arg);
1850 case SNDRV_PCM_IOCTL1_CHANNEL_INFO: 1774 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
@@ -1854,7 +1778,6 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
1854 } 1778 }
1855 return -ENXIO; 1779 return -ENXIO;
1856} 1780}
1857
1858EXPORT_SYMBOL(snd_pcm_lib_ioctl); 1781EXPORT_SYMBOL(snd_pcm_lib_ioctl);
1859 1782
1860/** 1783/**
@@ -1890,7 +1813,6 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
1890 kill_fasync(&runtime->fasync, SIGIO, POLL_IN); 1813 kill_fasync(&runtime->fasync, SIGIO, POLL_IN);
1891 snd_pcm_stream_unlock_irqrestore(substream, flags); 1814 snd_pcm_stream_unlock_irqrestore(substream, flags);
1892} 1815}
1893
1894EXPORT_SYMBOL(snd_pcm_period_elapsed); 1816EXPORT_SYMBOL(snd_pcm_period_elapsed);
1895 1817
1896/* 1818/*
@@ -1985,129 +1907,147 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
1985 return err; 1907 return err;
1986} 1908}
1987 1909
1988static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream, 1910typedef int (*pcm_transfer_f)(struct snd_pcm_substream *substream,
1989 unsigned int hwoff, 1911 int channel, unsigned long hwoff,
1990 unsigned long data, unsigned int off, 1912 void *buf, unsigned long bytes);
1991 snd_pcm_uframes_t frames) 1913
1914typedef int (*pcm_copy_f)(struct snd_pcm_substream *, snd_pcm_uframes_t, void *,
1915 snd_pcm_uframes_t, snd_pcm_uframes_t, pcm_transfer_f);
1916
1917/* calculate the target DMA-buffer position to be written/read */
1918static void *get_dma_ptr(struct snd_pcm_runtime *runtime,
1919 int channel, unsigned long hwoff)
1992{ 1920{
1993 struct snd_pcm_runtime *runtime = substream->runtime; 1921 return runtime->dma_area + hwoff +
1994 int err; 1922 channel * (runtime->dma_bytes / runtime->channels);
1995 char __user *buf = (char __user *) data + frames_to_bytes(runtime, off); 1923}
1996 if (substream->ops->copy) { 1924
1997 if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0) 1925/* default copy_user ops for write; used for both interleaved and non- modes */
1998 return err; 1926static int default_write_copy(struct snd_pcm_substream *substream,
1999 } else { 1927 int channel, unsigned long hwoff,
2000 char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff); 1928 void *buf, unsigned long bytes)
2001 if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames))) 1929{
2002 return -EFAULT; 1930 if (copy_from_user(get_dma_ptr(substream->runtime, channel, hwoff),
2003 } 1931 (void __user *)buf, bytes))
1932 return -EFAULT;
2004 return 0; 1933 return 0;
2005} 1934}
2006
2007typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int hwoff,
2008 unsigned long data, unsigned int off,
2009 snd_pcm_uframes_t size);
2010 1935
2011static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, 1936/* default copy_kernel ops for write */
2012 unsigned long data, 1937static int default_write_copy_kernel(struct snd_pcm_substream *substream,
2013 snd_pcm_uframes_t size, 1938 int channel, unsigned long hwoff,
2014 int nonblock, 1939 void *buf, unsigned long bytes)
2015 transfer_f transfer) 1940{
1941 memcpy(get_dma_ptr(substream->runtime, channel, hwoff), buf, bytes);
1942 return 0;
1943}
1944
1945/* fill silence instead of copy data; called as a transfer helper
1946 * from __snd_pcm_lib_write() or directly from noninterleaved_copy() when
1947 * a NULL buffer is passed
1948 */
1949static int fill_silence(struct snd_pcm_substream *substream, int channel,
1950 unsigned long hwoff, void *buf, unsigned long bytes)
2016{ 1951{
2017 struct snd_pcm_runtime *runtime = substream->runtime; 1952 struct snd_pcm_runtime *runtime = substream->runtime;
2018 snd_pcm_uframes_t xfer = 0;
2019 snd_pcm_uframes_t offset = 0;
2020 snd_pcm_uframes_t avail;
2021 int err = 0;
2022 1953
2023 if (size == 0) 1954 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
2024 return 0; 1955 return 0;
1956 if (substream->ops->fill_silence)
1957 return substream->ops->fill_silence(substream, channel,
1958 hwoff, bytes);
2025 1959
2026 snd_pcm_stream_lock_irq(substream); 1960 snd_pcm_format_set_silence(runtime->format,
2027 switch (runtime->status->state) { 1961 get_dma_ptr(runtime, channel, hwoff),
2028 case SNDRV_PCM_STATE_PREPARED: 1962 bytes_to_samples(runtime, bytes));
2029 case SNDRV_PCM_STATE_RUNNING: 1963 return 0;
2030 case SNDRV_PCM_STATE_PAUSED: 1964}
2031 break;
2032 case SNDRV_PCM_STATE_XRUN:
2033 err = -EPIPE;
2034 goto _end_unlock;
2035 case SNDRV_PCM_STATE_SUSPENDED:
2036 err = -ESTRPIPE;
2037 goto _end_unlock;
2038 default:
2039 err = -EBADFD;
2040 goto _end_unlock;
2041 }
2042 1965
2043 runtime->twake = runtime->control->avail_min ? : 1; 1966/* default copy_user ops for read; used for both interleaved and non- modes */
2044 if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) 1967static int default_read_copy(struct snd_pcm_substream *substream,
2045 snd_pcm_update_hw_ptr(substream); 1968 int channel, unsigned long hwoff,
2046 avail = snd_pcm_playback_avail(runtime); 1969 void *buf, unsigned long bytes)
2047 while (size > 0) { 1970{
2048 snd_pcm_uframes_t frames, appl_ptr, appl_ofs; 1971 if (copy_to_user((void __user *)buf,
2049 snd_pcm_uframes_t cont; 1972 get_dma_ptr(substream->runtime, channel, hwoff),
2050 if (!avail) { 1973 bytes))
2051 if (nonblock) { 1974 return -EFAULT;
2052 err = -EAGAIN; 1975 return 0;
2053 goto _end_unlock; 1976}
2054 }
2055 runtime->twake = min_t(snd_pcm_uframes_t, size,
2056 runtime->control->avail_min ? : 1);
2057 err = wait_for_avail(substream, &avail);
2058 if (err < 0)
2059 goto _end_unlock;
2060 }
2061 frames = size > avail ? avail : size;
2062 cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
2063 if (frames > cont)
2064 frames = cont;
2065 if (snd_BUG_ON(!frames)) {
2066 runtime->twake = 0;
2067 snd_pcm_stream_unlock_irq(substream);
2068 return -EINVAL;
2069 }
2070 appl_ptr = runtime->control->appl_ptr;
2071 appl_ofs = appl_ptr % runtime->buffer_size;
2072 snd_pcm_stream_unlock_irq(substream);
2073 err = transfer(substream, appl_ofs, data, offset, frames);
2074 snd_pcm_stream_lock_irq(substream);
2075 if (err < 0)
2076 goto _end_unlock;
2077 switch (runtime->status->state) {
2078 case SNDRV_PCM_STATE_XRUN:
2079 err = -EPIPE;
2080 goto _end_unlock;
2081 case SNDRV_PCM_STATE_SUSPENDED:
2082 err = -ESTRPIPE;
2083 goto _end_unlock;
2084 default:
2085 break;
2086 }
2087 appl_ptr += frames;
2088 if (appl_ptr >= runtime->boundary)
2089 appl_ptr -= runtime->boundary;
2090 runtime->control->appl_ptr = appl_ptr;
2091 if (substream->ops->ack)
2092 substream->ops->ack(substream);
2093 1977
2094 offset += frames; 1978/* default copy_kernel ops for read */
2095 size -= frames; 1979static int default_read_copy_kernel(struct snd_pcm_substream *substream,
2096 xfer += frames; 1980 int channel, unsigned long hwoff,
2097 avail -= frames; 1981 void *buf, unsigned long bytes)
2098 if (runtime->status->state == SNDRV_PCM_STATE_PREPARED && 1982{
2099 snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) { 1983 memcpy(buf, get_dma_ptr(substream->runtime, channel, hwoff), bytes);
2100 err = snd_pcm_start(substream); 1984 return 0;
2101 if (err < 0) 1985}
2102 goto _end_unlock; 1986
2103 } 1987/* call transfer function with the converted pointers and sizes;
1988 * for interleaved mode, it's one shot for all samples
1989 */
1990static int interleaved_copy(struct snd_pcm_substream *substream,
1991 snd_pcm_uframes_t hwoff, void *data,
1992 snd_pcm_uframes_t off,
1993 snd_pcm_uframes_t frames,
1994 pcm_transfer_f transfer)
1995{
1996 struct snd_pcm_runtime *runtime = substream->runtime;
1997
1998 /* convert to bytes */
1999 hwoff = frames_to_bytes(runtime, hwoff);
2000 off = frames_to_bytes(runtime, off);
2001 frames = frames_to_bytes(runtime, frames);
2002 return transfer(substream, 0, hwoff, data + off, frames);
2003}
2004
2005/* call transfer function with the converted pointers and sizes for each
2006 * non-interleaved channel; when buffer is NULL, silencing instead of copying
2007 */
2008static int noninterleaved_copy(struct snd_pcm_substream *substream,
2009 snd_pcm_uframes_t hwoff, void *data,
2010 snd_pcm_uframes_t off,
2011 snd_pcm_uframes_t frames,
2012 pcm_transfer_f transfer)
2013{
2014 struct snd_pcm_runtime *runtime = substream->runtime;
2015 int channels = runtime->channels;
2016 void **bufs = data;
2017 int c, err;
2018
2019 /* convert to bytes; note that it's not frames_to_bytes() here.
2020 * in non-interleaved mode, we copy for each channel, thus
2021 * each copy is n_samples bytes x channels = whole frames.
2022 */
2023 off = samples_to_bytes(runtime, off);
2024 frames = samples_to_bytes(runtime, frames);
2025 hwoff = samples_to_bytes(runtime, hwoff);
2026 for (c = 0; c < channels; ++c, ++bufs) {
2027 if (!data || !*bufs)
2028 err = fill_silence(substream, c, hwoff, NULL, frames);
2029 else
2030 err = transfer(substream, c, hwoff, *bufs + off,
2031 frames);
2032 if (err < 0)
2033 return err;
2104 } 2034 }
2105 _end_unlock: 2035 return 0;
2106 runtime->twake = 0; 2036}
2107 if (xfer > 0 && err >= 0) 2037
2108 snd_pcm_update_state(substream, runtime); 2038/* fill silence on the given buffer position;
2109 snd_pcm_stream_unlock_irq(substream); 2039 * called from snd_pcm_playback_silence()
2110 return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; 2040 */
2041static int fill_silence_frames(struct snd_pcm_substream *substream,
2042 snd_pcm_uframes_t off, snd_pcm_uframes_t frames)
2043{
2044 if (substream->runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
2045 substream->runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED)
2046 return interleaved_copy(substream, off, NULL, 0, frames,
2047 fill_silence);
2048 else
2049 return noninterleaved_copy(substream, off, NULL, 0, frames,
2050 fill_silence);
2111} 2051}
2112 2052
2113/* sanity-check for read/write methods */ 2053/* sanity-check for read/write methods */
@@ -2117,164 +2057,137 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream)
2117 if (PCM_RUNTIME_CHECK(substream)) 2057 if (PCM_RUNTIME_CHECK(substream))
2118 return -ENXIO; 2058 return -ENXIO;
2119 runtime = substream->runtime; 2059 runtime = substream->runtime;
2120 if (snd_BUG_ON(!substream->ops->copy && !runtime->dma_area)) 2060 if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area))
2121 return -EINVAL; 2061 return -EINVAL;
2122 if (runtime->status->state == SNDRV_PCM_STATE_OPEN) 2062 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2123 return -EBADFD; 2063 return -EBADFD;
2124 return 0; 2064 return 0;
2125} 2065}
2126 2066
2127snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const void __user *buf, snd_pcm_uframes_t size) 2067static int pcm_accessible_state(struct snd_pcm_runtime *runtime)
2128{ 2068{
2129 struct snd_pcm_runtime *runtime; 2069 switch (runtime->status->state) {
2130 int nonblock; 2070 case SNDRV_PCM_STATE_PREPARED:
2131 int err; 2071 case SNDRV_PCM_STATE_RUNNING:
2132 2072 case SNDRV_PCM_STATE_PAUSED:
2133 err = pcm_sanity_check(substream); 2073 return 0;
2134 if (err < 0) 2074 case SNDRV_PCM_STATE_XRUN:
2135 return err; 2075 return -EPIPE;
2136 runtime = substream->runtime; 2076 case SNDRV_PCM_STATE_SUSPENDED:
2137 nonblock = !!(substream->f_flags & O_NONBLOCK); 2077 return -ESTRPIPE;
2138 2078 default:
2139 if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && 2079 return -EBADFD;
2140 runtime->channels > 1) 2080 }
2141 return -EINVAL;
2142 return snd_pcm_lib_write1(substream, (unsigned long)buf, size, nonblock,
2143 snd_pcm_lib_write_transfer);
2144} 2081}
2145 2082
2146EXPORT_SYMBOL(snd_pcm_lib_write); 2083/* update to the given appl_ptr and call ack callback if needed;
2147 2084 * when an error is returned, take back to the original value
2148static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream, 2085 */
2149 unsigned int hwoff, 2086int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream,
2150 unsigned long data, unsigned int off, 2087 snd_pcm_uframes_t appl_ptr)
2151 snd_pcm_uframes_t frames)
2152{ 2088{
2153 struct snd_pcm_runtime *runtime = substream->runtime; 2089 struct snd_pcm_runtime *runtime = substream->runtime;
2154 int err; 2090 snd_pcm_uframes_t old_appl_ptr = runtime->control->appl_ptr;
2155 void __user **bufs = (void __user **)data; 2091 int ret;
2156 int channels = runtime->channels; 2092
2157 int c; 2093 if (old_appl_ptr == appl_ptr)
2158 if (substream->ops->copy) { 2094 return 0;
2159 if (snd_BUG_ON(!substream->ops->silence)) 2095
2160 return -EINVAL; 2096 runtime->control->appl_ptr = appl_ptr;
2161 for (c = 0; c < channels; ++c, ++bufs) { 2097 if (substream->ops->ack) {
2162 if (*bufs == NULL) { 2098 ret = substream->ops->ack(substream);
2163 if ((err = substream->ops->silence(substream, c, hwoff, frames)) < 0) 2099 if (ret < 0) {
2164 return err; 2100 runtime->control->appl_ptr = old_appl_ptr;
2165 } else { 2101 return ret;
2166 char __user *buf = *bufs + samples_to_bytes(runtime, off);
2167 if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0)
2168 return err;
2169 }
2170 }
2171 } else {
2172 /* default transfer behaviour */
2173 size_t dma_csize = runtime->dma_bytes / channels;
2174 for (c = 0; c < channels; ++c, ++bufs) {
2175 char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
2176 if (*bufs == NULL) {
2177 snd_pcm_format_set_silence(runtime->format, hwbuf, frames);
2178 } else {
2179 char __user *buf = *bufs + samples_to_bytes(runtime, off);
2180 if (copy_from_user(hwbuf, buf, samples_to_bytes(runtime, frames)))
2181 return -EFAULT;
2182 }
2183 } 2102 }
2184 } 2103 }
2104
2105 trace_applptr(substream, old_appl_ptr, appl_ptr);
2106
2185 return 0; 2107 return 0;
2186} 2108}
2187 2109
2188snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream, 2110/* the common loop for read/write data */
2189 void __user **bufs, 2111snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
2190 snd_pcm_uframes_t frames) 2112 void *data, bool interleaved,
2113 snd_pcm_uframes_t size, bool in_kernel)
2191{ 2114{
2192 struct snd_pcm_runtime *runtime; 2115 struct snd_pcm_runtime *runtime = substream->runtime;
2193 int nonblock; 2116 snd_pcm_uframes_t xfer = 0;
2117 snd_pcm_uframes_t offset = 0;
2118 snd_pcm_uframes_t avail;
2119 pcm_copy_f writer;
2120 pcm_transfer_f transfer;
2121 bool nonblock;
2122 bool is_playback;
2194 int err; 2123 int err;
2195 2124
2196 err = pcm_sanity_check(substream); 2125 err = pcm_sanity_check(substream);
2197 if (err < 0) 2126 if (err < 0)
2198 return err; 2127 return err;
2199 runtime = substream->runtime;
2200 nonblock = !!(substream->f_flags & O_NONBLOCK);
2201
2202 if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
2203 return -EINVAL;
2204 return snd_pcm_lib_write1(substream, (unsigned long)bufs, frames,
2205 nonblock, snd_pcm_lib_writev_transfer);
2206}
2207
2208EXPORT_SYMBOL(snd_pcm_lib_writev);
2209 2128
2210static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream, 2129 is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
2211 unsigned int hwoff, 2130 if (interleaved) {
2212 unsigned long data, unsigned int off, 2131 if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
2213 snd_pcm_uframes_t frames) 2132 runtime->channels > 1)
2214{ 2133 return -EINVAL;
2215 struct snd_pcm_runtime *runtime = substream->runtime; 2134 writer = interleaved_copy;
2216 int err;
2217 char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
2218 if (substream->ops->copy) {
2219 if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0)
2220 return err;
2221 } else { 2135 } else {
2222 char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff); 2136 if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
2223 if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames))) 2137 return -EINVAL;
2224 return -EFAULT; 2138 writer = noninterleaved_copy;
2225 } 2139 }
2226 return 0;
2227}
2228 2140
2229static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, 2141 if (!data) {
2230 unsigned long data, 2142 if (is_playback)
2231 snd_pcm_uframes_t size, 2143 transfer = fill_silence;
2232 int nonblock, 2144 else
2233 transfer_f transfer) 2145 return -EINVAL;
2234{ 2146 } else if (in_kernel) {
2235 struct snd_pcm_runtime *runtime = substream->runtime; 2147 if (substream->ops->copy_kernel)
2236 snd_pcm_uframes_t xfer = 0; 2148 transfer = substream->ops->copy_kernel;
2237 snd_pcm_uframes_t offset = 0; 2149 else
2238 snd_pcm_uframes_t avail; 2150 transfer = is_playback ?
2239 int err = 0; 2151 default_write_copy_kernel : default_read_copy_kernel;
2152 } else {
2153 if (substream->ops->copy_user)
2154 transfer = (pcm_transfer_f)substream->ops->copy_user;
2155 else
2156 transfer = is_playback ?
2157 default_write_copy : default_read_copy;
2158 }
2240 2159
2241 if (size == 0) 2160 if (size == 0)
2242 return 0; 2161 return 0;
2243 2162
2163 nonblock = !!(substream->f_flags & O_NONBLOCK);
2164
2244 snd_pcm_stream_lock_irq(substream); 2165 snd_pcm_stream_lock_irq(substream);
2245 switch (runtime->status->state) { 2166 err = pcm_accessible_state(runtime);
2246 case SNDRV_PCM_STATE_PREPARED: 2167 if (err < 0)
2247 if (size >= runtime->start_threshold) {
2248 err = snd_pcm_start(substream);
2249 if (err < 0)
2250 goto _end_unlock;
2251 }
2252 break;
2253 case SNDRV_PCM_STATE_DRAINING:
2254 case SNDRV_PCM_STATE_RUNNING:
2255 case SNDRV_PCM_STATE_PAUSED:
2256 break;
2257 case SNDRV_PCM_STATE_XRUN:
2258 err = -EPIPE;
2259 goto _end_unlock;
2260 case SNDRV_PCM_STATE_SUSPENDED:
2261 err = -ESTRPIPE;
2262 goto _end_unlock;
2263 default:
2264 err = -EBADFD;
2265 goto _end_unlock; 2168 goto _end_unlock;
2169
2170 if (!is_playback &&
2171 runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
2172 size >= runtime->start_threshold) {
2173 err = snd_pcm_start(substream);
2174 if (err < 0)
2175 goto _end_unlock;
2266 } 2176 }
2267 2177
2268 runtime->twake = runtime->control->avail_min ? : 1; 2178 runtime->twake = runtime->control->avail_min ? : 1;
2269 if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) 2179 if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
2270 snd_pcm_update_hw_ptr(substream); 2180 snd_pcm_update_hw_ptr(substream);
2271 avail = snd_pcm_capture_avail(runtime); 2181 if (is_playback)
2182 avail = snd_pcm_playback_avail(runtime);
2183 else
2184 avail = snd_pcm_capture_avail(runtime);
2272 while (size > 0) { 2185 while (size > 0) {
2273 snd_pcm_uframes_t frames, appl_ptr, appl_ofs; 2186 snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
2274 snd_pcm_uframes_t cont; 2187 snd_pcm_uframes_t cont;
2275 if (!avail) { 2188 if (!avail) {
2276 if (runtime->status->state == 2189 if (!is_playback &&
2277 SNDRV_PCM_STATE_DRAINING) { 2190 runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
2278 snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); 2191 snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
2279 goto _end_unlock; 2192 goto _end_unlock;
2280 } 2193 }
@@ -2291,7 +2204,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
2291 continue; /* draining */ 2204 continue; /* draining */
2292 } 2205 }
2293 frames = size > avail ? avail : size; 2206 frames = size > avail ? avail : size;
2294 cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; 2207 appl_ptr = READ_ONCE(runtime->control->appl_ptr);
2208 appl_ofs = appl_ptr % runtime->buffer_size;
2209 cont = runtime->buffer_size - appl_ofs;
2295 if (frames > cont) 2210 if (frames > cont)
2296 frames = cont; 2211 frames = cont;
2297 if (snd_BUG_ON(!frames)) { 2212 if (snd_BUG_ON(!frames)) {
@@ -2299,34 +2214,33 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
2299 snd_pcm_stream_unlock_irq(substream); 2214 snd_pcm_stream_unlock_irq(substream);
2300 return -EINVAL; 2215 return -EINVAL;
2301 } 2216 }
2302 appl_ptr = runtime->control->appl_ptr;
2303 appl_ofs = appl_ptr % runtime->buffer_size;
2304 snd_pcm_stream_unlock_irq(substream); 2217 snd_pcm_stream_unlock_irq(substream);
2305 err = transfer(substream, appl_ofs, data, offset, frames); 2218 err = writer(substream, appl_ofs, data, offset, frames,
2219 transfer);
2306 snd_pcm_stream_lock_irq(substream); 2220 snd_pcm_stream_lock_irq(substream);
2307 if (err < 0) 2221 if (err < 0)
2308 goto _end_unlock; 2222 goto _end_unlock;
2309 switch (runtime->status->state) { 2223 err = pcm_accessible_state(runtime);
2310 case SNDRV_PCM_STATE_XRUN: 2224 if (err < 0)
2311 err = -EPIPE;
2312 goto _end_unlock;
2313 case SNDRV_PCM_STATE_SUSPENDED:
2314 err = -ESTRPIPE;
2315 goto _end_unlock; 2225 goto _end_unlock;
2316 default:
2317 break;
2318 }
2319 appl_ptr += frames; 2226 appl_ptr += frames;
2320 if (appl_ptr >= runtime->boundary) 2227 if (appl_ptr >= runtime->boundary)
2321 appl_ptr -= runtime->boundary; 2228 appl_ptr -= runtime->boundary;
2322 runtime->control->appl_ptr = appl_ptr; 2229 err = pcm_lib_apply_appl_ptr(substream, appl_ptr);
2323 if (substream->ops->ack) 2230 if (err < 0)
2324 substream->ops->ack(substream); 2231 goto _end_unlock;
2325 2232
2326 offset += frames; 2233 offset += frames;
2327 size -= frames; 2234 size -= frames;
2328 xfer += frames; 2235 xfer += frames;
2329 avail -= frames; 2236 avail -= frames;
2237 if (is_playback &&
2238 runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
2239 snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) {
2240 err = snd_pcm_start(substream);
2241 if (err < 0)
2242 goto _end_unlock;
2243 }
2330 } 2244 }
2331 _end_unlock: 2245 _end_unlock:
2332 runtime->twake = 0; 2246 runtime->twake = 0;
@@ -2335,83 +2249,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
2335 snd_pcm_stream_unlock_irq(substream); 2249 snd_pcm_stream_unlock_irq(substream);
2336 return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; 2250 return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
2337} 2251}
2338 2252EXPORT_SYMBOL(__snd_pcm_lib_xfer);
2339snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __user *buf, snd_pcm_uframes_t size)
2340{
2341 struct snd_pcm_runtime *runtime;
2342 int nonblock;
2343 int err;
2344
2345 err = pcm_sanity_check(substream);
2346 if (err < 0)
2347 return err;
2348 runtime = substream->runtime;
2349 nonblock = !!(substream->f_flags & O_NONBLOCK);
2350 if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
2351 return -EINVAL;
2352 return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
2353}
2354
2355EXPORT_SYMBOL(snd_pcm_lib_read);
2356
2357static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
2358 unsigned int hwoff,
2359 unsigned long data, unsigned int off,
2360 snd_pcm_uframes_t frames)
2361{
2362 struct snd_pcm_runtime *runtime = substream->runtime;
2363 int err;
2364 void __user **bufs = (void __user **)data;
2365 int channels = runtime->channels;
2366 int c;
2367 if (substream->ops->copy) {
2368 for (c = 0; c < channels; ++c, ++bufs) {
2369 char __user *buf;
2370 if (*bufs == NULL)
2371 continue;
2372 buf = *bufs + samples_to_bytes(runtime, off);
2373 if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0)
2374 return err;
2375 }
2376 } else {
2377 snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels;
2378 for (c = 0; c < channels; ++c, ++bufs) {
2379 char *hwbuf;
2380 char __user *buf;
2381 if (*bufs == NULL)
2382 continue;
2383
2384 hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
2385 buf = *bufs + samples_to_bytes(runtime, off);
2386 if (copy_to_user(buf, hwbuf, samples_to_bytes(runtime, frames)))
2387 return -EFAULT;
2388 }
2389 }
2390 return 0;
2391}
2392
2393snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
2394 void __user **bufs,
2395 snd_pcm_uframes_t frames)
2396{
2397 struct snd_pcm_runtime *runtime;
2398 int nonblock;
2399 int err;
2400
2401 err = pcm_sanity_check(substream);
2402 if (err < 0)
2403 return err;
2404 runtime = substream->runtime;
2405 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
2406 return -EBADFD;
2407
2408 nonblock = !!(substream->f_flags & O_NONBLOCK);
2409 if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
2410 return -EINVAL;
2411 return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer);
2412}
2413
2414EXPORT_SYMBOL(snd_pcm_lib_readv);
2415 2253
2416/* 2254/*
2417 * standard channel mapping helpers 2255 * standard channel mapping helpers