aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-06-17 12:20:28 -0400
committerMark Brown <broonie@linaro.org>2013-06-17 12:20:28 -0400
commit5f5eb4efe575734e54f26c34ffffc4b48cdca3aa (patch)
treea5cb60c08f3f7100606886a438f2c981a56d3240
parentd238ffabc5e97c3e330995cf5e04d47279a8ff94 (diff)
parentfc09cfbe3e3535897456c12f37fa83024bdab92d (diff)
Merge remote-tracking branch 'asoc/topic/spear' into asoc-next
-rw-r--r--sound/soc/Kconfig1
-rw-r--r--sound/soc/Makefile1
-rw-r--r--sound/soc/spear/Kconfig9
-rw-r--r--sound/soc/spear/Makefile8
-rw-r--r--sound/soc/spear/spdif_in.c31
-rw-r--r--sound/soc/spear/spdif_out.c43
-rw-r--r--sound/soc/spear/spear_pcm.c152
7 files changed, 52 insertions, 193 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 9e675c76436c..45eeaa9f7fec 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -51,6 +51,7 @@ source "sound/soc/pxa/Kconfig"
51source "sound/soc/samsung/Kconfig" 51source "sound/soc/samsung/Kconfig"
52source "sound/soc/s6000/Kconfig" 52source "sound/soc/s6000/Kconfig"
53source "sound/soc/sh/Kconfig" 53source "sound/soc/sh/Kconfig"
54source "sound/soc/spear/Kconfig"
54source "sound/soc/tegra/Kconfig" 55source "sound/soc/tegra/Kconfig"
55source "sound/soc/txx9/Kconfig" 56source "sound/soc/txx9/Kconfig"
56source "sound/soc/ux500/Kconfig" 57source "sound/soc/ux500/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 197b6ae54c8d..bc0261476d7a 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_SND_SOC) += pxa/
29obj-$(CONFIG_SND_SOC) += samsung/ 29obj-$(CONFIG_SND_SOC) += samsung/
30obj-$(CONFIG_SND_SOC) += s6000/ 30obj-$(CONFIG_SND_SOC) += s6000/
31obj-$(CONFIG_SND_SOC) += sh/ 31obj-$(CONFIG_SND_SOC) += sh/
32obj-$(CONFIG_SND_SOC) += spear/
32obj-$(CONFIG_SND_SOC) += tegra/ 33obj-$(CONFIG_SND_SOC) += tegra/
33obj-$(CONFIG_SND_SOC) += txx9/ 34obj-$(CONFIG_SND_SOC) += txx9/
34obj-$(CONFIG_SND_SOC) += ux500/ 35obj-$(CONFIG_SND_SOC) += ux500/
diff --git a/sound/soc/spear/Kconfig b/sound/soc/spear/Kconfig
new file mode 100644
index 000000000000..3567d73b218e
--- /dev/null
+++ b/sound/soc/spear/Kconfig
@@ -0,0 +1,9 @@
1config SND_SPEAR_SOC
2 tristate
3 select SND_SOC_DMAENGINE_PCM
4
5config SND_SPEAR_SPDIF_OUT
6 tristate
7
8config SND_SPEAR_SPDIF_IN
9 tristate
diff --git a/sound/soc/spear/Makefile b/sound/soc/spear/Makefile
new file mode 100644
index 000000000000..c4ea7161056c
--- /dev/null
+++ b/sound/soc/spear/Makefile
@@ -0,0 +1,8 @@
1# SPEAR Platform Support
2snd-soc-spear-pcm-objs := spear_pcm.o
3snd-soc-spear-spdif-in-objs := spdif_in.o
4snd-soc-spear-spdif-out-objs := spdif_out.o
5
6obj-$(CONFIG_SND_SPEAR_SOC) += snd-soc-spear-pcm.o
7obj-$(CONFIG_SND_SPEAR_SPDIF_IN) += snd-soc-spear-spdif-in.o
8obj-$(CONFIG_SND_SPEAR_SPDIF_OUT) += snd-soc-spear-spdif-out.o
diff --git a/sound/soc/spear/spdif_in.c b/sound/soc/spear/spdif_in.c
index 14d57e89bcba..63acfeb4b69d 100644
--- a/sound/soc/spear/spdif_in.c
+++ b/sound/soc/spear/spdif_in.c
@@ -49,15 +49,12 @@ static void spdif_in_configure(struct spdif_in_dev *host)
49 writel(0xF, host->io_base + SPDIF_IN_IRQ_MASK); 49 writel(0xF, host->io_base + SPDIF_IN_IRQ_MASK);
50} 50}
51 51
52static int spdif_in_startup(struct snd_pcm_substream *substream, 52static int spdif_in_dai_probe(struct snd_soc_dai *dai)
53 struct snd_soc_dai *cpu_dai)
54{ 53{
55 struct spdif_in_dev *host = snd_soc_dai_get_drvdata(cpu_dai); 54 struct spdif_in_dev *host = snd_soc_dai_get_drvdata(dai);
56 55
57 if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) 56 dai->capture_dma_data = &host->dma_params;
58 return -EINVAL;
59 57
60 snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)&host->dma_params);
61 return 0; 58 return 0;
62} 59}
63 60
@@ -70,7 +67,6 @@ static void spdif_in_shutdown(struct snd_pcm_substream *substream,
70 return; 67 return;
71 68
72 writel(0x0, host->io_base + SPDIF_IN_IRQ_MASK); 69 writel(0x0, host->io_base + SPDIF_IN_IRQ_MASK);
73 snd_soc_dai_set_dma_data(dai, substream, NULL);
74} 70}
75 71
76static void spdif_in_format(struct spdif_in_dev *host, u32 format) 72static void spdif_in_format(struct spdif_in_dev *host, u32 format)
@@ -151,13 +147,13 @@ static int spdif_in_trigger(struct snd_pcm_substream *substream, int cmd,
151} 147}
152 148
153static struct snd_soc_dai_ops spdif_in_dai_ops = { 149static struct snd_soc_dai_ops spdif_in_dai_ops = {
154 .startup = spdif_in_startup,
155 .shutdown = spdif_in_shutdown, 150 .shutdown = spdif_in_shutdown,
156 .trigger = spdif_in_trigger, 151 .trigger = spdif_in_trigger,
157 .hw_params = spdif_in_hw_params, 152 .hw_params = spdif_in_hw_params,
158}; 153};
159 154
160struct snd_soc_dai_driver spdif_in_dai = { 155static struct snd_soc_dai_driver spdif_in_dai = {
156 .probe = spdif_in_dai_probe,
161 .capture = { 157 .capture = {
162 .channels_min = 2, 158 .channels_min = 2,
163 .channels_max = 2, 159 .channels_max = 2,
@@ -235,7 +231,7 @@ static int spdif_in_probe(struct platform_device *pdev)
235 if (host->irq < 0) 231 if (host->irq < 0)
236 return -EINVAL; 232 return -EINVAL;
237 233
238 host->clk = clk_get(&pdev->dev, NULL); 234 host->clk = devm_clk_get(&pdev->dev, NULL);
239 if (IS_ERR(host->clk)) 235 if (IS_ERR(host->clk))
240 return PTR_ERR(host->clk); 236 return PTR_ERR(host->clk);
241 237
@@ -257,34 +253,21 @@ static int spdif_in_probe(struct platform_device *pdev)
257 ret = devm_request_irq(&pdev->dev, host->irq, spdif_in_irq, 0, 253 ret = devm_request_irq(&pdev->dev, host->irq, spdif_in_irq, 0,
258 "spdif-in", host); 254 "spdif-in", host);
259 if (ret) { 255 if (ret) {
260 clk_put(host->clk);
261 dev_warn(&pdev->dev, "request_irq failed\n"); 256 dev_warn(&pdev->dev, "request_irq failed\n");
262 return ret; 257 return ret;
263 } 258 }
264 259
265 ret = snd_soc_register_component(&pdev->dev, &spdif_in_component, 260 return snd_soc_register_component(&pdev->dev, &spdif_in_component,
266 &spdif_in_dai, 1); 261 &spdif_in_dai, 1);
267 if (ret != 0) {
268 clk_put(host->clk);
269 return ret;
270 }
271
272 return 0;
273} 262}
274 263
275static int spdif_in_remove(struct platform_device *pdev) 264static int spdif_in_remove(struct platform_device *pdev)
276{ 265{
277 struct spdif_in_dev *host = dev_get_drvdata(&pdev->dev);
278
279 snd_soc_unregister_component(&pdev->dev); 266 snd_soc_unregister_component(&pdev->dev);
280 dev_set_drvdata(&pdev->dev, NULL);
281
282 clk_put(host->clk);
283 267
284 return 0; 268 return 0;
285} 269}
286 270
287
288static struct platform_driver spdif_in_driver = { 271static struct platform_driver spdif_in_driver = {
289 .probe = spdif_in_probe, 272 .probe = spdif_in_probe,
290 .remove = spdif_in_remove, 273 .remove = spdif_in_remove,
diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c
index 1e3c3dda3598..2fdf68c98d22 100644
--- a/sound/soc/spear/spdif_out.c
+++ b/sound/soc/spear/spdif_out.c
@@ -62,8 +62,6 @@ static int spdif_out_startup(struct snd_pcm_substream *substream,
62 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) 62 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
63 return -EINVAL; 63 return -EINVAL;
64 64
65 snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)&host->dma_params);
66
67 ret = clk_enable(host->clk); 65 ret = clk_enable(host->clk);
68 if (ret) 66 if (ret)
69 return ret; 67 return ret;
@@ -84,7 +82,6 @@ static void spdif_out_shutdown(struct snd_pcm_substream *substream,
84 82
85 clk_disable(host->clk); 83 clk_disable(host->clk);
86 host->running = false; 84 host->running = false;
87 snd_soc_dai_set_dma_data(dai, substream, NULL);
88} 85}
89 86
90static void spdif_out_clock(struct spdif_out_dev *host, u32 core_freq, 87static void spdif_out_clock(struct spdif_out_dev *host, u32 core_freq,
@@ -243,8 +240,12 @@ static const struct snd_kcontrol_new spdif_out_controls[] = {
243 spdif_mute_get, spdif_mute_put), 240 spdif_mute_get, spdif_mute_put),
244}; 241};
245 242
246int spdif_soc_dai_probe(struct snd_soc_dai *dai) 243static int spdif_soc_dai_probe(struct snd_soc_dai *dai)
247{ 244{
245 struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai);
246
247 dai->playback_dma_data = &host->dma_params;
248
248 return snd_soc_add_dai_controls(dai, spdif_out_controls, 249 return snd_soc_add_dai_controls(dai, spdif_out_controls,
249 ARRAY_SIZE(spdif_out_controls)); 250 ARRAY_SIZE(spdif_out_controls));
250} 251}
@@ -281,30 +282,18 @@ static int spdif_out_probe(struct platform_device *pdev)
281 struct resource *res; 282 struct resource *res;
282 int ret; 283 int ret;
283 284
284 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
285 if (!res)
286 return -EINVAL;
287
288 if (!devm_request_mem_region(&pdev->dev, res->start,
289 resource_size(res), pdev->name)) {
290 dev_warn(&pdev->dev, "Failed to get memory resourse\n");
291 return -ENOENT;
292 }
293
294 host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); 285 host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
295 if (!host) { 286 if (!host) {
296 dev_warn(&pdev->dev, "kzalloc fail\n"); 287 dev_warn(&pdev->dev, "kzalloc fail\n");
297 return -ENOMEM; 288 return -ENOMEM;
298 } 289 }
299 290
300 host->io_base = devm_ioremap(&pdev->dev, res->start, 291 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
301 resource_size(res)); 292 host->io_base = devm_ioremap_resource(&pdev->dev, res);
302 if (!host->io_base) { 293 if (IS_ERR(host->io_base))
303 dev_warn(&pdev->dev, "ioremap failed\n"); 294 return PTR_ERR(host->io_base);
304 return -ENOMEM;
305 }
306 295
307 host->clk = clk_get(&pdev->dev, NULL); 296 host->clk = devm_clk_get(&pdev->dev, NULL);
308 if (IS_ERR(host->clk)) 297 if (IS_ERR(host->clk))
309 return PTR_ERR(host->clk); 298 return PTR_ERR(host->clk);
310 299
@@ -320,22 +309,12 @@ static int spdif_out_probe(struct platform_device *pdev)
320 309
321 ret = snd_soc_register_component(&pdev->dev, &spdif_out_component, 310 ret = snd_soc_register_component(&pdev->dev, &spdif_out_component,
322 &spdif_out_dai, 1); 311 &spdif_out_dai, 1);
323 if (ret != 0) { 312 return ret;
324 clk_put(host->clk);
325 return ret;
326 }
327
328 return 0;
329} 313}
330 314
331static int spdif_out_remove(struct platform_device *pdev) 315static int spdif_out_remove(struct platform_device *pdev)
332{ 316{
333 struct spdif_out_dev *host = dev_get_drvdata(&pdev->dev);
334
335 snd_soc_unregister_component(&pdev->dev); 317 snd_soc_unregister_component(&pdev->dev);
336 dev_set_drvdata(&pdev->dev, NULL);
337
338 clk_put(host->clk);
339 318
340 return 0; 319 return 0;
341} 320}
diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c
index 2fbd4899d8ef..4707f2b862c3 100644
--- a/sound/soc/spear/spear_pcm.c
+++ b/sound/soc/spear/spear_pcm.c
@@ -13,19 +13,13 @@
13 13
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/dmaengine.h> 15#include <linux/dmaengine.h>
16#include <linux/dma-mapping.h>
17#include <linux/init.h>
18#include <linux/platform_device.h> 16#include <linux/platform_device.h>
19#include <linux/scatterlist.h>
20#include <linux/slab.h>
21#include <sound/core.h>
22#include <sound/dmaengine_pcm.h> 17#include <sound/dmaengine_pcm.h>
23#include <sound/pcm.h> 18#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h> 19#include <sound/soc.h>
26#include <sound/spear_dma.h> 20#include <sound/spear_dma.h>
27 21
28static struct snd_pcm_hardware spear_pcm_hardware = { 22static const struct snd_pcm_hardware spear_pcm_hardware = {
29 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | 23 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
30 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 24 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
31 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), 25 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
@@ -37,149 +31,33 @@ static struct snd_pcm_hardware spear_pcm_hardware = {
37 .fifo_size = 0, /* fifo size in bytes */ 31 .fifo_size = 0, /* fifo size in bytes */
38}; 32};
39 33
40static int spear_pcm_hw_params(struct snd_pcm_substream *substream, 34static struct dma_chan *spear_pcm_request_chan(struct snd_soc_pcm_runtime *rtd,
41 struct snd_pcm_hw_params *params) 35 struct snd_pcm_substream *substream)
42{ 36{
43 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 37 struct spear_dma_data *dma_data;
44 38
45 return 0; 39 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
46}
47
48static int spear_pcm_hw_free(struct snd_pcm_substream *substream)
49{
50 snd_pcm_set_runtime_buffer(substream, NULL);
51
52 return 0;
53}
54
55static int spear_pcm_open(struct snd_pcm_substream *substream)
56{
57 struct snd_soc_pcm_runtime *rtd = substream->private_data;
58
59 struct spear_dma_data *dma_data = (struct spear_dma_data *)
60 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
61 int ret;
62
63 ret = snd_soc_set_runtime_hwparams(substream, &spear_pcm_hardware);
64 if (ret)
65 return ret;
66 40
67 return snd_dmaengine_pcm_open_request_chan(substream, dma_data->filter, 41 return snd_dmaengine_pcm_request_channel(dma_data->filter, dma_data);
68 dma_data);
69} 42}
70 43
71static int spear_pcm_mmap(struct snd_pcm_substream *substream, 44static const struct snd_dmaengine_pcm_config spear_dmaengine_pcm_config = {
72 struct vm_area_struct *vma) 45 .pcm_hardware = &spear_pcm_hardware,
73{ 46 .compat_request_channel = spear_pcm_request_chan,
74 struct snd_pcm_runtime *runtime = substream->runtime; 47 .prealloc_buffer_size = 16 * 1024,
75
76 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
77 runtime->dma_area, runtime->dma_addr,
78 runtime->dma_bytes);
79}
80
81static struct snd_pcm_ops spear_pcm_ops = {
82 .open = spear_pcm_open,
83 .close = snd_dmaengine_pcm_close_release_chan,
84 .ioctl = snd_pcm_lib_ioctl,
85 .hw_params = spear_pcm_hw_params,
86 .hw_free = spear_pcm_hw_free,
87 .trigger = snd_dmaengine_pcm_trigger,
88 .pointer = snd_dmaengine_pcm_pointer,
89 .mmap = spear_pcm_mmap,
90};
91
92static int
93spear_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream,
94 size_t size)
95{
96 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
97 struct snd_dma_buffer *buf = &substream->dma_buffer;
98
99 buf->dev.type = SNDRV_DMA_TYPE_DEV;
100 buf->dev.dev = pcm->card->dev;
101 buf->private_data = NULL;
102
103 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
104 &buf->addr, GFP_KERNEL);
105 if (!buf->area)
106 return -ENOMEM;
107
108 dev_info(buf->dev.dev,
109 " preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
110 (void *)buf->area, (void *)buf->addr, size);
111
112 buf->bytes = size;
113 return 0;
114}
115
116static void spear_pcm_free(struct snd_pcm *pcm)
117{
118 struct snd_pcm_substream *substream;
119 struct snd_dma_buffer *buf;
120 int stream;
121
122 for (stream = 0; stream < 2; stream++) {
123 substream = pcm->streams[stream].substream;
124 if (!substream)
125 continue;
126
127 buf = &substream->dma_buffer;
128 if (!buf || !buf->area)
129 continue;
130
131 dma_free_writecombine(pcm->card->dev, buf->bytes,
132 buf->area, buf->addr);
133 buf->area = NULL;
134 }
135}
136
137static u64 spear_pcm_dmamask = DMA_BIT_MASK(32);
138
139static int spear_pcm_new(struct snd_soc_pcm_runtime *rtd)
140{
141 struct snd_card *card = rtd->card->snd_card;
142 int ret;
143
144 if (!card->dev->dma_mask)
145 card->dev->dma_mask = &spear_pcm_dmamask;
146 if (!card->dev->coherent_dma_mask)
147 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
148
149 if (rtd->cpu_dai->driver->playback.channels_min) {
150 ret = spear_pcm_preallocate_dma_buffer(rtd->pcm,
151 SNDRV_PCM_STREAM_PLAYBACK,
152 spear_pcm_hardware.buffer_bytes_max);
153 if (ret)
154 return ret;
155 }
156
157 if (rtd->cpu_dai->driver->capture.channels_min) {
158 ret = spear_pcm_preallocate_dma_buffer(rtd->pcm,
159 SNDRV_PCM_STREAM_CAPTURE,
160 spear_pcm_hardware.buffer_bytes_max);
161 if (ret)
162 return ret;
163 }
164
165 return 0;
166}
167
168static struct snd_soc_platform_driver spear_soc_platform = {
169 .ops = &spear_pcm_ops,
170 .pcm_new = spear_pcm_new,
171 .pcm_free = spear_pcm_free,
172}; 48};
173 49
174static int spear_soc_platform_probe(struct platform_device *pdev) 50static int spear_soc_platform_probe(struct platform_device *pdev)
175{ 51{
176 return snd_soc_register_platform(&pdev->dev, &spear_soc_platform); 52 return snd_dmaengine_pcm_register(&pdev->dev,
53 &spear_dmaengine_pcm_config,
54 SND_DMAENGINE_PCM_FLAG_NO_DT |
55 SND_DMAENGINE_PCM_FLAG_COMPAT);
177} 56}
178 57
179static int spear_soc_platform_remove(struct platform_device *pdev) 58static int spear_soc_platform_remove(struct platform_device *pdev)
180{ 59{
181 snd_soc_unregister_platform(&pdev->dev); 60 snd_dmaengine_pcm_unregister(&pdev->dev);
182
183 return 0; 61 return 0;
184} 62}
185 63