aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-11-08 05:43:18 -0500
committerMark Brown <broonie@linaro.org>2013-11-08 05:43:18 -0500
commit5196e6ffc253937a8f22121d28ac7192e7260793 (patch)
tree338644a50b42a361093e3e5b1235b1df186baf84 /sound/soc
parent53659907765e8b91481d9ff8a4fc78c4897043f0 (diff)
parenta894bd7fb539d671149fea9420c94c0fbe6baf7a (diff)
Merge remote-tracking branch 'asoc/fix/dma' into asoc-linus
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/cirrus/ep93xx-pcm.c13
-rw-r--r--sound/soc/fsl/imx-pcm-dma.c4
-rw-r--r--sound/soc/samsung/i2s.c9
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c105
-rw-r--r--sound/soc/tegra/tegra_pcm.c1
5 files changed, 103 insertions, 29 deletions
diff --git a/sound/soc/cirrus/ep93xx-pcm.c b/sound/soc/cirrus/ep93xx-pcm.c
index 0e9f56e0d4b2..cfe517e68009 100644
--- a/sound/soc/cirrus/ep93xx-pcm.c
+++ b/sound/soc/cirrus/ep93xx-pcm.c
@@ -57,9 +57,22 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
57 return false; 57 return false;
58} 58}
59 59
60static struct dma_chan *ep93xx_compat_request_channel(
61 struct snd_soc_pcm_runtime *rtd,
62 struct snd_pcm_substream *substream)
63{
64 struct snd_dmaengine_dai_dma_data *dma_data;
65
66 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
67
68 return snd_dmaengine_pcm_request_channel(ep93xx_pcm_dma_filter,
69 dma_data);
70}
71
60static const struct snd_dmaengine_pcm_config ep93xx_dmaengine_pcm_config = { 72static const struct snd_dmaengine_pcm_config ep93xx_dmaengine_pcm_config = {
61 .pcm_hardware = &ep93xx_pcm_hardware, 73 .pcm_hardware = &ep93xx_pcm_hardware,
62 .compat_filter_fn = ep93xx_pcm_dma_filter, 74 .compat_filter_fn = ep93xx_pcm_dma_filter,
75 .compat_request_channel = ep93xx_compat_request_channel,
63 .prealloc_buffer_size = 131072, 76 .prealloc_buffer_size = 131072,
64}; 77};
65 78
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
index 4dc1296688e9..aee23077080a 100644
--- a/sound/soc/fsl/imx-pcm-dma.c
+++ b/sound/soc/fsl/imx-pcm-dma.c
@@ -25,12 +25,10 @@
25 25
26static bool filter(struct dma_chan *chan, void *param) 26static bool filter(struct dma_chan *chan, void *param)
27{ 27{
28 struct snd_dmaengine_dai_dma_data *dma_data = param;
29
30 if (!imx_dma_is_general_purpose(chan)) 28 if (!imx_dma_is_general_purpose(chan))
31 return false; 29 return false;
32 30
33 chan->private = dma_data->filter_data; 31 chan->private = param;
34 32
35 return true; 33 return true;
36} 34}
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index b302f3b7a587..3e08b6c0f7ba 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -702,13 +702,6 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
702 } 702 }
703 writel(mod, i2s->addr + I2SMOD); 703 writel(mod, i2s->addr + I2SMOD);
704 704
705 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
706 snd_soc_dai_set_dma_data(dai, substream,
707 (void *)&i2s->dma_playback);
708 else
709 snd_soc_dai_set_dma_data(dai, substream,
710 (void *)&i2s->dma_capture);
711
712 i2s->frmclk = params_rate(params); 705 i2s->frmclk = params_rate(params);
713 706
714 return 0; 707 return 0;
@@ -970,6 +963,8 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
970 } 963 }
971 clk_prepare_enable(i2s->clk); 964 clk_prepare_enable(i2s->clk);
972 965
966 snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
967
973 if (other) { 968 if (other) {
974 other->addr = i2s->addr; 969 other->addr = i2s->addr;
975 other->clk = i2s->clk; 970 other->clk = i2s->clk;
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c
index e29ec3cd84b1..6ad4c7a47f5d 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -25,7 +25,7 @@
25#include <sound/dmaengine_pcm.h> 25#include <sound/dmaengine_pcm.h>
26 26
27struct dmaengine_pcm { 27struct dmaengine_pcm {
28 struct dma_chan *chan[SNDRV_PCM_STREAM_CAPTURE + 1]; 28 struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1];
29 const struct snd_dmaengine_pcm_config *config; 29 const struct snd_dmaengine_pcm_config *config;
30 struct snd_soc_platform platform; 30 struct snd_soc_platform platform;
31 unsigned int flags; 31 unsigned int flags;
@@ -36,6 +36,15 @@ static struct dmaengine_pcm *soc_platform_to_pcm(struct snd_soc_platform *p)
36 return container_of(p, struct dmaengine_pcm, platform); 36 return container_of(p, struct dmaengine_pcm, platform);
37} 37}
38 38
39static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm,
40 struct snd_pcm_substream *substream)
41{
42 if (!pcm->chan[substream->stream])
43 return NULL;
44
45 return pcm->chan[substream->stream]->device->dev;
46}
47
39/** 48/**
40 * snd_dmaengine_pcm_prepare_slave_config() - Generic prepare_slave_config callback 49 * snd_dmaengine_pcm_prepare_slave_config() - Generic prepare_slave_config callback
41 * @substream: PCM substream 50 * @substream: PCM substream
@@ -75,12 +84,21 @@ static int dmaengine_pcm_hw_params(struct snd_pcm_substream *substream,
75 struct snd_soc_pcm_runtime *rtd = substream->private_data; 84 struct snd_soc_pcm_runtime *rtd = substream->private_data;
76 struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); 85 struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
77 struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); 86 struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
87 int (*prepare_slave_config)(struct snd_pcm_substream *substream,
88 struct snd_pcm_hw_params *params,
89 struct dma_slave_config *slave_config);
78 struct dma_slave_config slave_config; 90 struct dma_slave_config slave_config;
79 int ret; 91 int ret;
80 92
81 if (pcm->config->prepare_slave_config) { 93 memset(&slave_config, 0, sizeof(slave_config));
82 ret = pcm->config->prepare_slave_config(substream, params, 94
83 &slave_config); 95 if (!pcm->config)
96 prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config;
97 else
98 prepare_slave_config = pcm->config->prepare_slave_config;
99
100 if (prepare_slave_config) {
101 ret = prepare_slave_config(substream, params, &slave_config);
84 if (ret) 102 if (ret)
85 return ret; 103 return ret;
86 104
@@ -92,28 +110,54 @@ static int dmaengine_pcm_hw_params(struct snd_pcm_substream *substream,
92 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); 110 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
93} 111}
94 112
95static int dmaengine_pcm_open(struct snd_pcm_substream *substream) 113static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substream)
96{ 114{
97 struct snd_soc_pcm_runtime *rtd = substream->private_data; 115 struct snd_soc_pcm_runtime *rtd = substream->private_data;
98 struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); 116 struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
117 struct device *dma_dev = dmaengine_dma_dev(pcm, substream);
99 struct dma_chan *chan = pcm->chan[substream->stream]; 118 struct dma_chan *chan = pcm->chan[substream->stream];
119 struct snd_dmaengine_dai_dma_data *dma_data;
120 struct dma_slave_caps dma_caps;
121 struct snd_pcm_hardware hw;
100 int ret; 122 int ret;
101 123
102 ret = snd_soc_set_runtime_hwparams(substream, 124 if (pcm->config && pcm->config->pcm_hardware)
125 return snd_soc_set_runtime_hwparams(substream,
103 pcm->config->pcm_hardware); 126 pcm->config->pcm_hardware);
104 if (ret)
105 return ret;
106 127
107 return snd_dmaengine_pcm_open(substream, chan); 128 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
129
130 memset(&hw, 0, sizeof(hw));
131 hw.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
132 SNDRV_PCM_INFO_INTERLEAVED;
133 hw.periods_min = 2;
134 hw.periods_max = UINT_MAX;
135 hw.period_bytes_min = 256;
136 hw.period_bytes_max = dma_get_max_seg_size(dma_dev);
137 hw.buffer_bytes_max = SIZE_MAX;
138 hw.fifo_size = dma_data->fifo_size;
139
140 ret = dma_get_slave_caps(chan, &dma_caps);
141 if (ret == 0) {
142 if (dma_caps.cmd_pause)
143 hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME;
144 }
145
146 return snd_soc_set_runtime_hwparams(substream, &hw);
108} 147}
109 148
110static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm, 149static int dmaengine_pcm_open(struct snd_pcm_substream *substream)
111 struct snd_pcm_substream *substream)
112{ 150{
113 if (!pcm->chan[substream->stream]) 151 struct snd_soc_pcm_runtime *rtd = substream->private_data;
114 return NULL; 152 struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
153 struct dma_chan *chan = pcm->chan[substream->stream];
154 int ret;
115 155
116 return pcm->chan[substream->stream]->device->dev; 156 ret = dmaengine_pcm_set_runtime_hwparams(substream);
157 if (ret)
158 return ret;
159
160 return snd_dmaengine_pcm_open(substream, chan);
117} 161}
118 162
119static void dmaengine_pcm_free(struct snd_pcm *pcm) 163static void dmaengine_pcm_free(struct snd_pcm *pcm)
@@ -126,6 +170,9 @@ static struct dma_chan *dmaengine_pcm_compat_request_channel(
126 struct snd_pcm_substream *substream) 170 struct snd_pcm_substream *substream)
127{ 171{
128 struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); 172 struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
173 struct snd_dmaengine_dai_dma_data *dma_data;
174
175 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
129 176
130 if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) && pcm->chan[0]) 177 if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) && pcm->chan[0])
131 return pcm->chan[0]; 178 return pcm->chan[0];
@@ -134,22 +181,42 @@ static struct dma_chan *dmaengine_pcm_compat_request_channel(
134 return pcm->config->compat_request_channel(rtd, substream); 181 return pcm->config->compat_request_channel(rtd, substream);
135 182
136 return snd_dmaengine_pcm_request_channel(pcm->config->compat_filter_fn, 183 return snd_dmaengine_pcm_request_channel(pcm->config->compat_filter_fn,
137 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream)); 184 dma_data->filter_data);
138} 185}
139 186
140static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) 187static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd)
141{ 188{
142 struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); 189 struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
143 const struct snd_dmaengine_pcm_config *config = pcm->config; 190 const struct snd_dmaengine_pcm_config *config = pcm->config;
191 struct device *dev = rtd->platform->dev;
192 struct snd_dmaengine_dai_dma_data *dma_data;
144 struct snd_pcm_substream *substream; 193 struct snd_pcm_substream *substream;
194 size_t prealloc_buffer_size;
195 size_t max_buffer_size;
145 unsigned int i; 196 unsigned int i;
146 int ret; 197 int ret;
147 198
199 if (config && config->prealloc_buffer_size) {
200 prealloc_buffer_size = config->prealloc_buffer_size;
201 max_buffer_size = config->pcm_hardware->buffer_bytes_max;
202 } else {
203 prealloc_buffer_size = 512 * 1024;
204 max_buffer_size = SIZE_MAX;
205 }
206
207
148 for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) { 208 for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
149 substream = rtd->pcm->streams[i].substream; 209 substream = rtd->pcm->streams[i].substream;
150 if (!substream) 210 if (!substream)
151 continue; 211 continue;
152 212
213 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
214
215 if (!pcm->chan[i] &&
216 (pcm->flags & SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME))
217 pcm->chan[i] = dma_request_slave_channel(dev,
218 dma_data->chan_name);
219
153 if (!pcm->chan[i] && (pcm->flags & SND_DMAENGINE_PCM_FLAG_COMPAT)) { 220 if (!pcm->chan[i] && (pcm->flags & SND_DMAENGINE_PCM_FLAG_COMPAT)) {
154 pcm->chan[i] = dmaengine_pcm_compat_request_channel(rtd, 221 pcm->chan[i] = dmaengine_pcm_compat_request_channel(rtd,
155 substream); 222 substream);
@@ -165,8 +232,8 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd)
165 ret = snd_pcm_lib_preallocate_pages(substream, 232 ret = snd_pcm_lib_preallocate_pages(substream,
166 SNDRV_DMA_TYPE_DEV, 233 SNDRV_DMA_TYPE_DEV,
167 dmaengine_dma_dev(pcm, substream), 234 dmaengine_dma_dev(pcm, substream),
168 config->prealloc_buffer_size, 235 prealloc_buffer_size,
169 config->pcm_hardware->buffer_bytes_max); 236 max_buffer_size);
170 if (ret) 237 if (ret)
171 goto err_free; 238 goto err_free;
172 } 239 }
@@ -222,7 +289,9 @@ static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
222{ 289{
223 unsigned int i; 290 unsigned int i;
224 291
225 if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_DT) || !dev->of_node) 292 if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT |
293 SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) ||
294 !dev->of_node)
226 return; 295 return;
227 296
228 if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) { 297 if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) {
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index f056f632557c..7b2d23ba69b3 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -56,7 +56,6 @@ static const struct snd_pcm_hardware tegra_pcm_hardware = {
56static const struct snd_dmaengine_pcm_config tegra_dmaengine_pcm_config = { 56static const struct snd_dmaengine_pcm_config tegra_dmaengine_pcm_config = {
57 .pcm_hardware = &tegra_pcm_hardware, 57 .pcm_hardware = &tegra_pcm_hardware,
58 .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, 58 .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
59 .compat_filter_fn = NULL,
60 .prealloc_buffer_size = PAGE_SIZE * 8, 59 .prealloc_buffer_size = PAGE_SIZE * 8,
61}; 60};
62 61