aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2014-01-14 16:28:35 -0500
committerMark Brown <broonie@linaro.org>2014-01-14 16:28:35 -0500
commit8e6714ac6081dc400828c01a8cc78bbd3b2b687a (patch)
tree8803fb274c1036e6734d3ace3e53c652c4c8ff4e
parent67c2fe2f5d6c5448874479d0181909536b495d78 (diff)
parent328089a47112a4fc06071e2003ecd75cc6d31029 (diff)
Merge branch 'topic/samsung' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-dma
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/mach-s3c64xx/Kconfig7
-rw-r--r--arch/arm/mach-s3c64xx/Makefile2
-rw-r--r--arch/arm/mach-s3c64xx/common.h5
-rw-r--r--arch/arm/mach-s3c64xx/dma.c762
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/dma.h144
-rw-r--r--arch/arm/mach-s3c64xx/pl080.c244
-rw-r--r--arch/arm/plat-samsung/devs.c10
-rw-r--r--arch/arm/plat-samsung/dma-ops.c8
-rw-r--r--drivers/clk/samsung/clk-s3c64xx.c4
-rw-r--r--drivers/spi/Kconfig2
-rw-r--r--sound/soc/samsung/Kconfig13
-rw-r--r--sound/soc/samsung/Makefile6
-rw-r--r--sound/soc/samsung/ac97.c51
-rw-r--r--sound/soc/samsung/dma.c14
-rw-r--r--sound/soc/samsung/dma.h6
-rw-r--r--sound/soc/samsung/dmaengine.c84
-rw-r--r--sound/soc/samsung/i2s.c9
-rw-r--r--sound/soc/samsung/idma.c8
-rw-r--r--sound/soc/samsung/pcm.c18
-rw-r--r--sound/soc/samsung/regs-ac97.h9
-rw-r--r--sound/soc/samsung/regs-iis.h9
22 files changed, 469 insertions, 947 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c1f1a7eee953..ba0e23234ecf 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -723,6 +723,7 @@ config ARCH_S3C64XX
723 bool "Samsung S3C64XX" 723 bool "Samsung S3C64XX"
724 select ARCH_HAS_CPUFREQ 724 select ARCH_HAS_CPUFREQ
725 select ARCH_REQUIRE_GPIOLIB 725 select ARCH_REQUIRE_GPIOLIB
726 select ARM_AMBA
726 select ARM_VIC 727 select ARM_VIC
727 select CLKDEV_LOOKUP 728 select CLKDEV_LOOKUP
728 select CLKSRC_SAMSUNG_PWM 729 select CLKSRC_SAMSUNG_PWM
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
index 2cb8dc55b50e..7094bccbae91 100644
--- a/arch/arm/mach-s3c64xx/Kconfig
+++ b/arch/arm/mach-s3c64xx/Kconfig
@@ -17,9 +17,10 @@ config CPU_S3C6410
17 help 17 help
18 Enable S3C6410 CPU support 18 Enable S3C6410 CPU support
19 19
20config S3C64XX_DMA 20config S3C64XX_PL080
21 bool "S3C64XX DMA" 21 bool "S3C64XX DMA using generic PL08x driver"
22 select S3C_DMA 22 select AMBA_PL08X
23 select SAMSUNG_DMADEV
23 24
24config S3C64XX_SETUP_SDHCI 25config S3C64XX_SETUP_SDHCI
25 bool 26 bool
diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile
index 6faedcffce04..58069a702a43 100644
--- a/arch/arm/mach-s3c64xx/Makefile
+++ b/arch/arm/mach-s3c64xx/Makefile
@@ -26,7 +26,7 @@ obj-$(CONFIG_CPU_IDLE) += cpuidle.o
26 26
27# DMA support 27# DMA support
28 28
29obj-$(CONFIG_S3C64XX_DMA) += dma.o 29obj-$(CONFIG_S3C64XX_PL080) += pl080.o
30 30
31# Device support 31# Device support
32 32
diff --git a/arch/arm/mach-s3c64xx/common.h b/arch/arm/mach-s3c64xx/common.h
index bd3bd562011e..7043e7a3a67e 100644
--- a/arch/arm/mach-s3c64xx/common.h
+++ b/arch/arm/mach-s3c64xx/common.h
@@ -58,4 +58,9 @@ int __init s3c64xx_pm_late_initcall(void);
58static inline int s3c64xx_pm_late_initcall(void) { return 0; } 58static inline int s3c64xx_pm_late_initcall(void) { return 0; }
59#endif 59#endif
60 60
61#ifdef CONFIG_S3C64XX_PL080
62extern struct pl08x_platform_data s3c64xx_dma0_plat_data;
63extern struct pl08x_platform_data s3c64xx_dma1_plat_data;
64#endif
65
61#endif /* __ARCH_ARM_MACH_S3C64XX_COMMON_H */ 66#endif /* __ARCH_ARM_MACH_S3C64XX_COMMON_H */
diff --git a/arch/arm/mach-s3c64xx/dma.c b/arch/arm/mach-s3c64xx/dma.c
deleted file mode 100644
index 7e22c2113816..000000000000
--- a/arch/arm/mach-s3c64xx/dma.c
+++ /dev/null
@@ -1,762 +0,0 @@
1/* linux/arch/arm/plat-s3c64xx/dma.c
2 *
3 * Copyright 2009 Openmoko, Inc.
4 * Copyright 2009 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
7 *
8 * S3C64XX DMA core
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15/*
16 * NOTE: Code in this file is not used when booting with Device Tree support.
17 */
18
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/interrupt.h>
22#include <linux/dmapool.h>
23#include <linux/device.h>
24#include <linux/errno.h>
25#include <linux/slab.h>
26#include <linux/delay.h>
27#include <linux/clk.h>
28#include <linux/err.h>
29#include <linux/io.h>
30#include <linux/amba/pl080.h>
31#include <linux/of.h>
32
33#include <mach/dma.h>
34#include <mach/map.h>
35#include <mach/irqs.h>
36
37#include "regs-sys.h"
38
39/* dma channel state information */
40
41struct s3c64xx_dmac {
42 struct device dev;
43 struct clk *clk;
44 void __iomem *regs;
45 struct s3c2410_dma_chan *channels;
46 enum dma_ch chanbase;
47};
48
49/* pool to provide LLI buffers */
50static struct dma_pool *dma_pool;
51
52/* Debug configuration and code */
53
54static unsigned char debug_show_buffs = 0;
55
56static void dbg_showchan(struct s3c2410_dma_chan *chan)
57{
58 pr_debug("DMA%d: %08x->%08x L %08x C %08x,%08x S %08x\n",
59 chan->number,
60 readl(chan->regs + PL080_CH_SRC_ADDR),
61 readl(chan->regs + PL080_CH_DST_ADDR),
62 readl(chan->regs + PL080_CH_LLI),
63 readl(chan->regs + PL080_CH_CONTROL),
64 readl(chan->regs + PL080S_CH_CONTROL2),
65 readl(chan->regs + PL080S_CH_CONFIG));
66}
67
68static void show_lli(struct pl080s_lli *lli)
69{
70 pr_debug("LLI[%p] %08x->%08x, NL %08x C %08x,%08x\n",
71 lli, lli->src_addr, lli->dst_addr, lli->next_lli,
72 lli->control0, lli->control1);
73}
74
75static void dbg_showbuffs(struct s3c2410_dma_chan *chan)
76{
77 struct s3c64xx_dma_buff *ptr;
78 struct s3c64xx_dma_buff *end;
79
80 pr_debug("DMA%d: buffs next %p, curr %p, end %p\n",
81 chan->number, chan->next, chan->curr, chan->end);
82
83 ptr = chan->next;
84 end = chan->end;
85
86 if (debug_show_buffs) {
87 for (; ptr != NULL; ptr = ptr->next) {
88 pr_debug("DMA%d: %08x ",
89 chan->number, ptr->lli_dma);
90 show_lli(ptr->lli);
91 }
92 }
93}
94
95/* End of Debug */
96
97static struct s3c2410_dma_chan *s3c64xx_dma_map_channel(unsigned int channel)
98{
99 struct s3c2410_dma_chan *chan;
100 unsigned int start, offs;
101
102 start = 0;
103
104 if (channel >= DMACH_PCM1_TX)
105 start = 8;
106
107 for (offs = 0; offs < 8; offs++) {
108 chan = &s3c2410_chans[start + offs];
109 if (!chan->in_use)
110 goto found;
111 }
112
113 return NULL;
114
115found:
116 s3c_dma_chan_map[channel] = chan;
117 return chan;
118}
119
120int s3c2410_dma_config(enum dma_ch channel, int xferunit)
121{
122 struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
123
124 if (chan == NULL)
125 return -EINVAL;
126
127 switch (xferunit) {
128 case 1:
129 chan->hw_width = 0;
130 break;
131 case 2:
132 chan->hw_width = 1;
133 break;
134 case 4:
135 chan->hw_width = 2;
136 break;
137 default:
138 printk(KERN_ERR "%s: illegal width %d\n", __func__, xferunit);
139 return -EINVAL;
140 }
141
142 return 0;
143}
144EXPORT_SYMBOL(s3c2410_dma_config);
145
146static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
147 struct pl080s_lli *lli,
148 dma_addr_t data, int size)
149{
150 dma_addr_t src, dst;
151 u32 control0, control1;
152
153 switch (chan->source) {
154 case DMA_FROM_DEVICE:
155 src = chan->dev_addr;
156 dst = data;
157 control0 = PL080_CONTROL_SRC_AHB2;
158 control0 |= PL080_CONTROL_DST_INCR;
159 break;
160
161 case DMA_TO_DEVICE:
162 src = data;
163 dst = chan->dev_addr;
164 control0 = PL080_CONTROL_DST_AHB2;
165 control0 |= PL080_CONTROL_SRC_INCR;
166 break;
167 default:
168 BUG();
169 }
170
171 /* note, we do not currently setup any of the burst controls */
172
173 control1 = size >> chan->hw_width; /* size in no of xfers */
174 control0 |= PL080_CONTROL_PROT_SYS; /* always in priv. mode */
175 control0 |= PL080_CONTROL_TC_IRQ_EN; /* always fire IRQ */
176 control0 |= (u32)chan->hw_width << PL080_CONTROL_DWIDTH_SHIFT;
177 control0 |= (u32)chan->hw_width << PL080_CONTROL_SWIDTH_SHIFT;
178
179 lli->src_addr = src;
180 lli->dst_addr = dst;
181 lli->next_lli = 0;
182 lli->control0 = control0;
183 lli->control1 = control1;
184}
185
186static void s3c64xx_lli_to_regs(struct s3c2410_dma_chan *chan,
187 struct pl080s_lli *lli)
188{
189 void __iomem *regs = chan->regs;
190
191 pr_debug("%s: LLI %p => regs\n", __func__, lli);
192 show_lli(lli);
193
194 writel(lli->src_addr, regs + PL080_CH_SRC_ADDR);
195 writel(lli->dst_addr, regs + PL080_CH_DST_ADDR);
196 writel(lli->next_lli, regs + PL080_CH_LLI);
197 writel(lli->control0, regs + PL080_CH_CONTROL);
198 writel(lli->control1, regs + PL080S_CH_CONTROL2);
199}
200
201static int s3c64xx_dma_start(struct s3c2410_dma_chan *chan)
202{
203 struct s3c64xx_dmac *dmac = chan->dmac;
204 u32 config;
205 u32 bit = chan->bit;
206
207 dbg_showchan(chan);
208
209 pr_debug("%s: clearing interrupts\n", __func__);
210
211 /* clear interrupts */
212 writel(bit, dmac->regs + PL080_TC_CLEAR);
213 writel(bit, dmac->regs + PL080_ERR_CLEAR);
214
215 pr_debug("%s: starting channel\n", __func__);
216
217 config = readl(chan->regs + PL080S_CH_CONFIG);
218 config |= PL080_CONFIG_ENABLE;
219 config &= ~PL080_CONFIG_HALT;
220
221 pr_debug("%s: writing config %08x\n", __func__, config);
222 writel(config, chan->regs + PL080S_CH_CONFIG);
223
224 return 0;
225}
226
227static int s3c64xx_dma_stop(struct s3c2410_dma_chan *chan)
228{
229 u32 config;
230 int timeout;
231
232 pr_debug("%s: stopping channel\n", __func__);
233
234 dbg_showchan(chan);
235
236 config = readl(chan->regs + PL080S_CH_CONFIG);
237 config |= PL080_CONFIG_HALT;
238 writel(config, chan->regs + PL080S_CH_CONFIG);
239
240 timeout = 1000;
241 do {
242 config = readl(chan->regs + PL080S_CH_CONFIG);
243 pr_debug("%s: %d - config %08x\n", __func__, timeout, config);
244 if (config & PL080_CONFIG_ACTIVE)
245 udelay(10);
246 else
247 break;
248 } while (--timeout > 0);
249
250 if (config & PL080_CONFIG_ACTIVE) {
251 printk(KERN_ERR "%s: channel still active\n", __func__);
252 return -EFAULT;
253 }
254
255 config = readl(chan->regs + PL080S_CH_CONFIG);
256 config &= ~PL080_CONFIG_ENABLE;
257 writel(config, chan->regs + PL080S_CH_CONFIG);
258
259 return 0;
260}
261
262static inline void s3c64xx_dma_bufffdone(struct s3c2410_dma_chan *chan,
263 struct s3c64xx_dma_buff *buf,
264 enum s3c2410_dma_buffresult result)
265{
266 if (chan->callback_fn != NULL)
267 (chan->callback_fn)(chan, buf->pw, 0, result);
268}
269
270static void s3c64xx_dma_freebuff(struct s3c64xx_dma_buff *buff)
271{
272 dma_pool_free(dma_pool, buff->lli, buff->lli_dma);
273 kfree(buff);
274}
275
276static int s3c64xx_dma_flush(struct s3c2410_dma_chan *chan)
277{
278 struct s3c64xx_dma_buff *buff, *next;
279 u32 config;
280
281 dbg_showchan(chan);
282
283 pr_debug("%s: flushing channel\n", __func__);
284
285 config = readl(chan->regs + PL080S_CH_CONFIG);
286 config &= ~PL080_CONFIG_ENABLE;
287 writel(config, chan->regs + PL080S_CH_CONFIG);
288
289 /* dump all the buffers associated with this channel */
290
291 for (buff = chan->curr; buff != NULL; buff = next) {
292 next = buff->next;
293 pr_debug("%s: buff %p (next %p)\n", __func__, buff, buff->next);
294
295 s3c64xx_dma_bufffdone(chan, buff, S3C2410_RES_ABORT);
296 s3c64xx_dma_freebuff(buff);
297 }
298
299 chan->curr = chan->next = chan->end = NULL;
300
301 return 0;
302}
303
304int s3c2410_dma_ctrl(enum dma_ch channel, enum s3c2410_chan_op op)
305{
306 struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
307
308 WARN_ON(!chan);
309 if (!chan)
310 return -EINVAL;
311
312 switch (op) {
313 case S3C2410_DMAOP_START:
314 return s3c64xx_dma_start(chan);
315
316 case S3C2410_DMAOP_STOP:
317 return s3c64xx_dma_stop(chan);
318
319 case S3C2410_DMAOP_FLUSH:
320 return s3c64xx_dma_flush(chan);
321
322 /* believe PAUSE/RESUME are no-ops */
323 case S3C2410_DMAOP_PAUSE:
324 case S3C2410_DMAOP_RESUME:
325 case S3C2410_DMAOP_STARTED:
326 case S3C2410_DMAOP_TIMEOUT:
327 return 0;
328 }
329
330 return -ENOENT;
331}
332EXPORT_SYMBOL(s3c2410_dma_ctrl);
333
334/* s3c2410_dma_enque
335 *
336 */
337
338int s3c2410_dma_enqueue(enum dma_ch channel, void *id,
339 dma_addr_t data, int size)
340{
341 struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
342 struct s3c64xx_dma_buff *next;
343 struct s3c64xx_dma_buff *buff;
344 struct pl080s_lli *lli;
345 unsigned long flags;
346 int ret;
347
348 WARN_ON(!chan);
349 if (!chan)
350 return -EINVAL;
351
352 buff = kzalloc(sizeof(struct s3c64xx_dma_buff), GFP_ATOMIC);
353 if (!buff) {
354 printk(KERN_ERR "%s: no memory for buffer\n", __func__);
355 return -ENOMEM;
356 }
357
358 lli = dma_pool_alloc(dma_pool, GFP_ATOMIC, &buff->lli_dma);
359 if (!lli) {
360 printk(KERN_ERR "%s: no memory for lli\n", __func__);
361 ret = -ENOMEM;
362 goto err_buff;
363 }
364
365 pr_debug("%s: buff %p, dp %08x lli (%p, %08x) %d\n",
366 __func__, buff, data, lli, (u32)buff->lli_dma, size);
367
368 buff->lli = lli;
369 buff->pw = id;
370
371 s3c64xx_dma_fill_lli(chan, lli, data, size);
372
373 local_irq_save(flags);
374
375 if ((next = chan->next) != NULL) {
376 struct s3c64xx_dma_buff *end = chan->end;
377 struct pl080s_lli *endlli = end->lli;
378
379 pr_debug("enquing onto channel\n");
380
381 end->next = buff;
382 endlli->next_lli = buff->lli_dma;
383
384 if (chan->flags & S3C2410_DMAF_CIRCULAR) {
385 struct s3c64xx_dma_buff *curr = chan->curr;
386 lli->next_lli = curr->lli_dma;
387 }
388
389 if (next == chan->curr) {
390 writel(buff->lli_dma, chan->regs + PL080_CH_LLI);
391 chan->next = buff;
392 }
393
394 show_lli(endlli);
395 chan->end = buff;
396 } else {
397 pr_debug("enquing onto empty channel\n");
398
399 chan->curr = buff;
400 chan->next = buff;
401 chan->end = buff;
402
403 s3c64xx_lli_to_regs(chan, lli);
404 }
405
406 local_irq_restore(flags);
407
408 show_lli(lli);
409
410 dbg_showchan(chan);
411 dbg_showbuffs(chan);
412 return 0;
413
414err_buff:
415 kfree(buff);
416 return ret;
417}
418
419EXPORT_SYMBOL(s3c2410_dma_enqueue);
420
421
422int s3c2410_dma_devconfig(enum dma_ch channel,
423 enum dma_data_direction source,
424 unsigned long devaddr)
425{
426 struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
427 u32 peripheral;
428 u32 config = 0;
429
430 pr_debug("%s: channel %d, source %d, dev %08lx, chan %p\n",
431 __func__, channel, source, devaddr, chan);
432
433 WARN_ON(!chan);
434 if (!chan)
435 return -EINVAL;
436
437 peripheral = (chan->peripheral & 0xf);
438 chan->source = source;
439 chan->dev_addr = devaddr;
440
441 pr_debug("%s: peripheral %d\n", __func__, peripheral);
442
443 switch (source) {
444 case DMA_FROM_DEVICE:
445 config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
446 config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT;
447 break;
448 case DMA_TO_DEVICE:
449 config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
450 config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT;
451 break;
452 default:
453 printk(KERN_ERR "%s: bad source\n", __func__);
454 return -EINVAL;
455 }
456
457 /* allow TC and ERR interrupts */
458 config |= PL080_CONFIG_TC_IRQ_MASK;
459 config |= PL080_CONFIG_ERR_IRQ_MASK;
460
461 pr_debug("%s: config %08x\n", __func__, config);
462
463 writel(config, chan->regs + PL080S_CH_CONFIG);
464
465 return 0;
466}
467EXPORT_SYMBOL(s3c2410_dma_devconfig);
468
469
470int s3c2410_dma_getposition(enum dma_ch channel,
471 dma_addr_t *src, dma_addr_t *dst)
472{
473 struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
474
475 WARN_ON(!chan);
476 if (!chan)
477 return -EINVAL;
478
479 if (src != NULL)
480 *src = readl(chan->regs + PL080_CH_SRC_ADDR);
481
482 if (dst != NULL)
483 *dst = readl(chan->regs + PL080_CH_DST_ADDR);
484
485 return 0;
486}
487EXPORT_SYMBOL(s3c2410_dma_getposition);
488
489/* s3c2410_request_dma
490 *
491 * get control of an dma channel
492*/
493
494int s3c2410_dma_request(enum dma_ch channel,
495 struct s3c2410_dma_client *client,
496 void *dev)
497{
498 struct s3c2410_dma_chan *chan;
499 unsigned long flags;
500
501 pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
502 channel, client->name, dev);
503
504 local_irq_save(flags);
505
506 chan = s3c64xx_dma_map_channel(channel);
507 if (chan == NULL) {
508 local_irq_restore(flags);
509 return -EBUSY;
510 }
511
512 dbg_showchan(chan);
513
514 chan->client = client;
515 chan->in_use = 1;
516 chan->peripheral = channel;
517 chan->flags = 0;
518
519 local_irq_restore(flags);
520
521 /* need to setup */
522
523 pr_debug("%s: channel initialised, %p\n", __func__, chan);
524
525 return chan->number | DMACH_LOW_LEVEL;
526}
527
528EXPORT_SYMBOL(s3c2410_dma_request);
529
530/* s3c2410_dma_free
531 *
532 * release the given channel back to the system, will stop and flush
533 * any outstanding transfers, and ensure the channel is ready for the
534 * next claimant.
535 *
536 * Note, although a warning is currently printed if the freeing client
537 * info is not the same as the registrant's client info, the free is still
538 * allowed to go through.
539*/
540
541int s3c2410_dma_free(enum dma_ch channel, struct s3c2410_dma_client *client)
542{
543 struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
544 unsigned long flags;
545
546 if (chan == NULL)
547 return -EINVAL;
548
549 local_irq_save(flags);
550
551 if (chan->client != client) {
552 printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
553 channel, chan->client, client);
554 }
555
556 /* sort out stopping and freeing the channel */
557
558
559 chan->client = NULL;
560 chan->in_use = 0;
561
562 if (!(channel & DMACH_LOW_LEVEL))
563 s3c_dma_chan_map[channel] = NULL;
564
565 local_irq_restore(flags);
566
567 return 0;
568}
569
570EXPORT_SYMBOL(s3c2410_dma_free);
571
572static irqreturn_t s3c64xx_dma_irq(int irq, void *pw)
573{
574 struct s3c64xx_dmac *dmac = pw;
575 struct s3c2410_dma_chan *chan;
576 enum s3c2410_dma_buffresult res;
577 u32 tcstat, errstat;
578 u32 bit;
579 int offs;
580
581 tcstat = readl(dmac->regs + PL080_TC_STATUS);
582 errstat = readl(dmac->regs + PL080_ERR_STATUS);
583
584 for (offs = 0, bit = 1; offs < 8; offs++, bit <<= 1) {
585 struct s3c64xx_dma_buff *buff;
586
587 if (!(errstat & bit) && !(tcstat & bit))
588 continue;
589
590 chan = dmac->channels + offs;
591 res = S3C2410_RES_ERR;
592
593 if (tcstat & bit) {
594 writel(bit, dmac->regs + PL080_TC_CLEAR);
595 res = S3C2410_RES_OK;
596 }
597
598 if (errstat & bit)
599 writel(bit, dmac->regs + PL080_ERR_CLEAR);
600
601 /* 'next' points to the buffer that is next to the
602 * currently active buffer.
603 * For CIRCULAR queues, 'next' will be same as 'curr'
604 * when 'end' is the active buffer.
605 */
606 buff = chan->curr;
607 while (buff && buff != chan->next
608 && buff->next != chan->next)
609 buff = buff->next;
610
611 if (!buff)
612 BUG();
613
614 if (buff == chan->next)
615 buff = chan->end;
616
617 s3c64xx_dma_bufffdone(chan, buff, res);
618
619 /* Free the node and update curr, if non-circular queue */
620 if (!(chan->flags & S3C2410_DMAF_CIRCULAR)) {
621 chan->curr = buff->next;
622 s3c64xx_dma_freebuff(buff);
623 }
624
625 /* Update 'next' */
626 buff = chan->next;
627 if (chan->next == chan->end) {
628 chan->next = chan->curr;
629 if (!(chan->flags & S3C2410_DMAF_CIRCULAR))
630 chan->end = NULL;
631 } else {
632 chan->next = buff->next;
633 }
634 }
635
636 return IRQ_HANDLED;
637}
638
639static struct bus_type dma_subsys = {
640 .name = "s3c64xx-dma",
641 .dev_name = "s3c64xx-dma",
642};
643
644static int s3c64xx_dma_init1(int chno, enum dma_ch chbase,
645 int irq, unsigned int base)
646{
647 struct s3c2410_dma_chan *chptr = &s3c2410_chans[chno];
648 struct s3c64xx_dmac *dmac;
649 char clkname[16];
650 void __iomem *regs;
651 void __iomem *regptr;
652 int err, ch;
653
654 dmac = kzalloc(sizeof(struct s3c64xx_dmac), GFP_KERNEL);
655 if (!dmac) {
656 printk(KERN_ERR "%s: failed to alloc mem\n", __func__);
657 return -ENOMEM;
658 }
659
660 dmac->dev.id = chno / 8;
661 dmac->dev.bus = &dma_subsys;
662
663 err = device_register(&dmac->dev);
664 if (err) {
665 printk(KERN_ERR "%s: failed to register device\n", __func__);
666 goto err_alloc;
667 }
668
669 regs = ioremap(base, 0x200);
670 if (!regs) {
671 printk(KERN_ERR "%s: failed to ioremap()\n", __func__);
672 err = -ENXIO;
673 goto err_dev;
674 }
675
676 snprintf(clkname, sizeof(clkname), "dma%d", dmac->dev.id);
677
678 dmac->clk = clk_get(NULL, clkname);
679 if (IS_ERR(dmac->clk)) {
680 printk(KERN_ERR "%s: failed to get clock %s\n", __func__, clkname);
681 err = PTR_ERR(dmac->clk);
682 goto err_map;
683 }
684
685 clk_prepare_enable(dmac->clk);
686
687 dmac->regs = regs;
688 dmac->chanbase = chbase;
689 dmac->channels = chptr;
690
691 err = request_irq(irq, s3c64xx_dma_irq, 0, "DMA", dmac);
692 if (err < 0) {
693 printk(KERN_ERR "%s: failed to get irq\n", __func__);
694 goto err_clk;
695 }
696
697 regptr = regs + PL080_Cx_BASE(0);
698
699 for (ch = 0; ch < 8; ch++, chptr++) {
700 pr_debug("%s: registering DMA %d (%p)\n",
701 __func__, chno + ch, regptr);
702
703 chptr->bit = 1 << ch;
704 chptr->number = chno + ch;
705 chptr->dmac = dmac;
706 chptr->regs = regptr;
707 regptr += PL080_Cx_STRIDE;
708 }
709
710 /* for the moment, permanently enable the controller */
711 writel(PL080_CONFIG_ENABLE, regs + PL080_CONFIG);
712
713 printk(KERN_INFO "PL080: IRQ %d, at %p, channels %d..%d\n",
714 irq, regs, chno, chno+8);
715
716 return 0;
717
718err_clk:
719 clk_disable_unprepare(dmac->clk);
720 clk_put(dmac->clk);
721err_map:
722 iounmap(regs);
723err_dev:
724 device_unregister(&dmac->dev);
725err_alloc:
726 kfree(dmac);
727 return err;
728}
729
730static int __init s3c64xx_dma_init(void)
731{
732 int ret;
733
734 /* This driver is not supported when booting with device tree. */
735 if (of_have_populated_dt())
736 return -ENODEV;
737
738 printk(KERN_INFO "%s: Registering DMA channels\n", __func__);
739
740 dma_pool = dma_pool_create("DMA-LLI", NULL, sizeof(struct pl080s_lli), 16, 0);
741 if (!dma_pool) {
742 printk(KERN_ERR "%s: failed to create pool\n", __func__);
743 return -ENOMEM;
744 }
745
746 ret = subsys_system_register(&dma_subsys, NULL);
747 if (ret) {
748 printk(KERN_ERR "%s: failed to create subsys\n", __func__);
749 return -ENOMEM;
750 }
751
752 /* Set all DMA configuration to be DMA, not SDMA */
753 writel(0xffffff, S3C64XX_SDMA_SEL);
754
755 /* Register standard DMA controllers */
756 s3c64xx_dma_init1(0, DMACH_UART0, IRQ_DMA0, 0x75000000);
757 s3c64xx_dma_init1(8, DMACH_PCM1_TX, IRQ_DMA1, 0x75100000);
758
759 return 0;
760}
761
762arch_initcall(s3c64xx_dma_init);
diff --git a/arch/arm/mach-s3c64xx/include/mach/dma.h b/arch/arm/mach-s3c64xx/include/mach/dma.h
index fe1a98cf0e4c..059b1fc85037 100644
--- a/arch/arm/mach-s3c64xx/include/mach/dma.h
+++ b/arch/arm/mach-s3c64xx/include/mach/dma.h
@@ -11,51 +11,48 @@
11#ifndef __ASM_ARCH_DMA_H 11#ifndef __ASM_ARCH_DMA_H
12#define __ASM_ARCH_DMA_H __FILE__ 12#define __ASM_ARCH_DMA_H __FILE__
13 13
14#define S3C_DMA_CHANNELS (16) 14#define S3C64XX_DMA_CHAN(name) ((unsigned long)(name))
15
16/* DMA0/SDMA0 */
17#define DMACH_UART0 S3C64XX_DMA_CHAN("uart0_tx")
18#define DMACH_UART0_SRC2 S3C64XX_DMA_CHAN("uart0_rx")
19#define DMACH_UART1 S3C64XX_DMA_CHAN("uart1_tx")
20#define DMACH_UART1_SRC2 S3C64XX_DMA_CHAN("uart1_rx")
21#define DMACH_UART2 S3C64XX_DMA_CHAN("uart2_tx")
22#define DMACH_UART2_SRC2 S3C64XX_DMA_CHAN("uart2_rx")
23#define DMACH_UART3 S3C64XX_DMA_CHAN("uart3_tx")
24#define DMACH_UART3_SRC2 S3C64XX_DMA_CHAN("uart3_rx")
25#define DMACH_PCM0_TX S3C64XX_DMA_CHAN("pcm0_tx")
26#define DMACH_PCM0_RX S3C64XX_DMA_CHAN("pcm0_rx")
27#define DMACH_I2S0_OUT S3C64XX_DMA_CHAN("i2s0_tx")
28#define DMACH_I2S0_IN S3C64XX_DMA_CHAN("i2s0_rx")
29#define DMACH_SPI0_TX S3C64XX_DMA_CHAN("spi0_tx")
30#define DMACH_SPI0_RX S3C64XX_DMA_CHAN("spi0_rx")
31#define DMACH_HSI_I2SV40_TX S3C64XX_DMA_CHAN("i2s2_tx")
32#define DMACH_HSI_I2SV40_RX S3C64XX_DMA_CHAN("i2s2_rx")
33
34/* DMA1/SDMA1 */
35#define DMACH_PCM1_TX S3C64XX_DMA_CHAN("pcm1_tx")
36#define DMACH_PCM1_RX S3C64XX_DMA_CHAN("pcm1_rx")
37#define DMACH_I2S1_OUT S3C64XX_DMA_CHAN("i2s1_tx")
38#define DMACH_I2S1_IN S3C64XX_DMA_CHAN("i2s1_rx")
39#define DMACH_SPI1_TX S3C64XX_DMA_CHAN("spi1_tx")
40#define DMACH_SPI1_RX S3C64XX_DMA_CHAN("spi1_rx")
41#define DMACH_AC97_PCMOUT S3C64XX_DMA_CHAN("ac97_out")
42#define DMACH_AC97_PCMIN S3C64XX_DMA_CHAN("ac97_in")
43#define DMACH_AC97_MICIN S3C64XX_DMA_CHAN("ac97_mic")
44#define DMACH_PWM S3C64XX_DMA_CHAN("pwm")
45#define DMACH_IRDA S3C64XX_DMA_CHAN("irda")
46#define DMACH_EXTERNAL S3C64XX_DMA_CHAN("external")
47#define DMACH_SECURITY_RX S3C64XX_DMA_CHAN("sec_rx")
48#define DMACH_SECURITY_TX S3C64XX_DMA_CHAN("sec_tx")
15 49
16/* see mach-s3c2410/dma.h for notes on dma channel numbers */
17
18/* Note, for the S3C64XX architecture we keep the DMACH_
19 * defines in the order they are allocated to [S]DMA0/[S]DMA1
20 * so that is easy to do DHACH_ -> DMA controller conversion
21 */
22enum dma_ch { 50enum dma_ch {
23 /* DMA0/SDMA0 */ 51 DMACH_MAX = 32
24 DMACH_UART0 = 0, 52};
25 DMACH_UART0_SRC2,
26 DMACH_UART1,
27 DMACH_UART1_SRC2,
28 DMACH_UART2,
29 DMACH_UART2_SRC2,
30 DMACH_UART3,
31 DMACH_UART3_SRC2,
32 DMACH_PCM0_TX,
33 DMACH_PCM0_RX,
34 DMACH_I2S0_OUT,
35 DMACH_I2S0_IN,
36 DMACH_SPI0_TX,
37 DMACH_SPI0_RX,
38 DMACH_HSI_I2SV40_TX,
39 DMACH_HSI_I2SV40_RX,
40 53
41 /* DMA1/SDMA1 */ 54struct s3c2410_dma_client {
42 DMACH_PCM1_TX = 16, 55 char *name;
43 DMACH_PCM1_RX,
44 DMACH_I2S1_OUT,
45 DMACH_I2S1_IN,
46 DMACH_SPI1_TX,
47 DMACH_SPI1_RX,
48 DMACH_AC97_PCMOUT,
49 DMACH_AC97_PCMIN,
50 DMACH_AC97_MICIN,
51 DMACH_PWM,
52 DMACH_IRDA,
53 DMACH_EXTERNAL,
54 DMACH_RES1,
55 DMACH_RES2,
56 DMACH_SECURITY_RX, /* SDMA1 only */
57 DMACH_SECURITY_TX, /* SDMA1 only */
58 DMACH_MAX /* the end */
59}; 56};
60 57
61static inline bool samsung_dma_has_circular(void) 58static inline bool samsung_dma_has_circular(void)
@@ -65,67 +62,10 @@ static inline bool samsung_dma_has_circular(void)
65 62
66static inline bool samsung_dma_is_dmadev(void) 63static inline bool samsung_dma_is_dmadev(void)
67{ 64{
68 return false; 65 return true;
69} 66}
70#define S3C2410_DMAF_CIRCULAR (1 << 0)
71
72#include <plat/dma.h>
73
74#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */
75
76struct s3c64xx_dma_buff;
77
78/** s3c64xx_dma_buff - S3C64XX DMA buffer descriptor
79 * @next: Pointer to next buffer in queue or ring.
80 * @pw: Client provided identifier
81 * @lli: Pointer to hardware descriptor this buffer is associated with.
82 * @lli_dma: Hardare address of the descriptor.
83 */
84struct s3c64xx_dma_buff {
85 struct s3c64xx_dma_buff *next;
86
87 void *pw;
88 struct pl080s_lli *lli;
89 dma_addr_t lli_dma;
90};
91
92struct s3c64xx_dmac;
93
94struct s3c2410_dma_chan {
95 unsigned char number; /* number of this dma channel */
96 unsigned char in_use; /* channel allocated */
97 unsigned char bit; /* bit for enable/disable/etc */
98 unsigned char hw_width;
99 unsigned char peripheral;
100
101 unsigned int flags;
102 enum dma_data_direction source;
103
104
105 dma_addr_t dev_addr;
106
107 struct s3c2410_dma_client *client;
108 struct s3c64xx_dmac *dmac; /* pointer to controller */
109
110 void __iomem *regs;
111
112 /* cdriver callbacks */
113 s3c2410_dma_cbfn_t callback_fn; /* buffer done callback */
114 s3c2410_dma_opfn_t op_fn; /* channel op callback */
115
116 /* buffer list and information */
117 struct s3c64xx_dma_buff *curr; /* current dma buffer */
118 struct s3c64xx_dma_buff *next; /* next buffer to load */
119 struct s3c64xx_dma_buff *end; /* end of queue */
120
121 /* note, when channel is running in circular mode, curr is the
122 * first buffer enqueued, end is the last and curr is where the
123 * last buffer-done event is set-at. The buffers are not freed
124 * and the last buffer hardware descriptor points back to the
125 * first.
126 */
127};
128 67
129#include <plat/dma-core.h> 68#include <linux/amba/pl08x.h>
69#include <plat/dma-ops.h>
130 70
131#endif /* __ASM_ARCH_IRQ_H */ 71#endif /* __ASM_ARCH_IRQ_H */
diff --git a/arch/arm/mach-s3c64xx/pl080.c b/arch/arm/mach-s3c64xx/pl080.c
new file mode 100644
index 000000000000..901a984bddc2
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/pl080.c
@@ -0,0 +1,244 @@
1/*
2 * Samsung's S3C64XX generic DMA support using amba-pl08x driver.
3 *
4 * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/kernel.h>
12#include <linux/amba/bus.h>
13#include <linux/amba/pl080.h>
14#include <linux/amba/pl08x.h>
15#include <linux/of.h>
16
17#include <mach/irqs.h>
18#include <mach/map.h>
19
20#include "regs-sys.h"
21
22static int pl08x_get_xfer_signal(const struct pl08x_channel_data *cd)
23{
24 return cd->min_signal;
25}
26
27static void pl08x_put_xfer_signal(const struct pl08x_channel_data *cd, int ch)
28{
29}
30
31/*
32 * DMA0
33 */
34
35static struct pl08x_channel_data s3c64xx_dma0_info[] = {
36 {
37 .bus_id = "uart0_tx",
38 .min_signal = 0,
39 .max_signal = 0,
40 .periph_buses = PL08X_AHB2,
41 }, {
42 .bus_id = "uart0_rx",
43 .min_signal = 1,
44 .max_signal = 1,
45 .periph_buses = PL08X_AHB2,
46 }, {
47 .bus_id = "uart1_tx",
48 .min_signal = 2,
49 .max_signal = 2,
50 .periph_buses = PL08X_AHB2,
51 }, {
52 .bus_id = "uart1_rx",
53 .min_signal = 3,
54 .max_signal = 3,
55 .periph_buses = PL08X_AHB2,
56 }, {
57 .bus_id = "uart2_tx",
58 .min_signal = 4,
59 .max_signal = 4,
60 .periph_buses = PL08X_AHB2,
61 }, {
62 .bus_id = "uart2_rx",
63 .min_signal = 5,
64 .max_signal = 5,
65 .periph_buses = PL08X_AHB2,
66 }, {
67 .bus_id = "uart3_tx",
68 .min_signal = 6,
69 .max_signal = 6,
70 .periph_buses = PL08X_AHB2,
71 }, {
72 .bus_id = "uart3_rx",
73 .min_signal = 7,
74 .max_signal = 7,
75 .periph_buses = PL08X_AHB2,
76 }, {
77 .bus_id = "pcm0_tx",
78 .min_signal = 8,
79 .max_signal = 8,
80 .periph_buses = PL08X_AHB2,
81 }, {
82 .bus_id = "pcm0_rx",
83 .min_signal = 9,
84 .max_signal = 9,
85 .periph_buses = PL08X_AHB2,
86 }, {
87 .bus_id = "i2s0_tx",
88 .min_signal = 10,
89 .max_signal = 10,
90 .periph_buses = PL08X_AHB2,
91 }, {
92 .bus_id = "i2s0_rx",
93 .min_signal = 11,
94 .max_signal = 11,
95 .periph_buses = PL08X_AHB2,
96 }, {
97 .bus_id = "spi0_tx",
98 .min_signal = 12,
99 .max_signal = 12,
100 .periph_buses = PL08X_AHB2,
101 }, {
102 .bus_id = "spi0_rx",
103 .min_signal = 13,
104 .max_signal = 13,
105 .periph_buses = PL08X_AHB2,
106 }, {
107 .bus_id = "i2s2_tx",
108 .min_signal = 14,
109 .max_signal = 14,
110 .periph_buses = PL08X_AHB2,
111 }, {
112 .bus_id = "i2s2_rx",
113 .min_signal = 15,
114 .max_signal = 15,
115 .periph_buses = PL08X_AHB2,
116 }
117};
118
119struct pl08x_platform_data s3c64xx_dma0_plat_data = {
120 .memcpy_channel = {
121 .bus_id = "memcpy",
122 .cctl_memcpy =
123 (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
124 PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
125 PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
126 PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
127 PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
128 PL080_CONTROL_PROT_SYS),
129 },
130 .lli_buses = PL08X_AHB1,
131 .mem_buses = PL08X_AHB1,
132 .get_xfer_signal = pl08x_get_xfer_signal,
133 .put_xfer_signal = pl08x_put_xfer_signal,
134 .slave_channels = s3c64xx_dma0_info,
135 .num_slave_channels = ARRAY_SIZE(s3c64xx_dma0_info),
136};
137
138static AMBA_AHB_DEVICE(s3c64xx_dma0, "dma-pl080s.0", 0,
139 0x75000000, {IRQ_DMA0}, &s3c64xx_dma0_plat_data);
140
141/*
142 * DMA1
143 */
144
145static struct pl08x_channel_data s3c64xx_dma1_info[] = {
146 {
147 .bus_id = "pcm1_tx",
148 .min_signal = 0,
149 .max_signal = 0,
150 .periph_buses = PL08X_AHB2,
151 }, {
152 .bus_id = "pcm1_rx",
153 .min_signal = 1,
154 .max_signal = 1,
155 .periph_buses = PL08X_AHB2,
156 }, {
157 .bus_id = "i2s1_tx",
158 .min_signal = 2,
159 .max_signal = 2,
160 .periph_buses = PL08X_AHB2,
161 }, {
162 .bus_id = "i2s1_rx",
163 .min_signal = 3,
164 .max_signal = 3,
165 .periph_buses = PL08X_AHB2,
166 }, {
167 .bus_id = "spi1_tx",
168 .min_signal = 4,
169 .max_signal = 4,
170 .periph_buses = PL08X_AHB2,
171 }, {
172 .bus_id = "spi1_rx",
173 .min_signal = 5,
174 .max_signal = 5,
175 .periph_buses = PL08X_AHB2,
176 }, {
177 .bus_id = "ac97_out",
178 .min_signal = 6,
179 .max_signal = 6,
180 .periph_buses = PL08X_AHB2,
181 }, {
182 .bus_id = "ac97_in",
183 .min_signal = 7,
184 .max_signal = 7,
185 .periph_buses = PL08X_AHB2,
186 }, {
187 .bus_id = "ac97_mic",
188 .min_signal = 8,
189 .max_signal = 8,
190 .periph_buses = PL08X_AHB2,
191 }, {
192 .bus_id = "pwm",
193 .min_signal = 9,
194 .max_signal = 9,
195 .periph_buses = PL08X_AHB2,
196 }, {
197 .bus_id = "irda",
198 .min_signal = 10,
199 .max_signal = 10,
200 .periph_buses = PL08X_AHB2,
201 }, {
202 .bus_id = "external",
203 .min_signal = 11,
204 .max_signal = 11,
205 .periph_buses = PL08X_AHB2,
206 },
207};
208
209struct pl08x_platform_data s3c64xx_dma1_plat_data = {
210 .memcpy_channel = {
211 .bus_id = "memcpy",
212 .cctl_memcpy =
213 (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
214 PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
215 PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
216 PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
217 PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
218 PL080_CONTROL_PROT_SYS),
219 },
220 .lli_buses = PL08X_AHB1,
221 .mem_buses = PL08X_AHB1,
222 .get_xfer_signal = pl08x_get_xfer_signal,
223 .put_xfer_signal = pl08x_put_xfer_signal,
224 .slave_channels = s3c64xx_dma1_info,
225 .num_slave_channels = ARRAY_SIZE(s3c64xx_dma1_info),
226};
227
228static AMBA_AHB_DEVICE(s3c64xx_dma1, "dma-pl080s.1", 0,
229 0x75100000, {IRQ_DMA1}, &s3c64xx_dma1_plat_data);
230
231static int __init s3c64xx_pl080_init(void)
232{
233 /* Set all DMA configuration to be DMA, not SDMA */
234 writel(0xffffff, S3C64XX_SDMA_SEL);
235
236 if (of_have_populated_dt())
237 return 0;
238
239 amba_device_register(&s3c64xx_dma0_device, &iomem_resource);
240 amba_device_register(&s3c64xx_dma1_device, &iomem_resource);
241
242 return 0;
243}
244arch_initcall(s3c64xx_pl080_init);
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index 99a3590f0349..ac07e871f6a7 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -1468,6 +1468,8 @@ void __init s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
1468 pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi0_cfg_gpio; 1468 pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi0_cfg_gpio;
1469#if defined(CONFIG_PL330_DMA) 1469#if defined(CONFIG_PL330_DMA)
1470 pd.filter = pl330_filter; 1470 pd.filter = pl330_filter;
1471#elif defined(CONFIG_S3C64XX_PL080)
1472 pd.filter = pl08x_filter_id;
1471#elif defined(CONFIG_S3C24XX_DMAC) 1473#elif defined(CONFIG_S3C24XX_DMAC)
1472 pd.filter = s3c24xx_dma_filter; 1474 pd.filter = s3c24xx_dma_filter;
1473#endif 1475#endif
@@ -1509,8 +1511,10 @@ void __init s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
1509 pd.num_cs = num_cs; 1511 pd.num_cs = num_cs;
1510 pd.src_clk_nr = src_clk_nr; 1512 pd.src_clk_nr = src_clk_nr;
1511 pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi1_cfg_gpio; 1513 pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi1_cfg_gpio;
1512#ifdef CONFIG_PL330_DMA 1514#if defined(CONFIG_PL330_DMA)
1513 pd.filter = pl330_filter; 1515 pd.filter = pl330_filter;
1516#elif defined(CONFIG_S3C64XX_PL080)
1517 pd.filter = pl08x_filter_id;
1514#endif 1518#endif
1515 1519
1516 s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi1); 1520 s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi1);
@@ -1550,8 +1554,10 @@ void __init s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
1550 pd.num_cs = num_cs; 1554 pd.num_cs = num_cs;
1551 pd.src_clk_nr = src_clk_nr; 1555 pd.src_clk_nr = src_clk_nr;
1552 pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi2_cfg_gpio; 1556 pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi2_cfg_gpio;
1553#ifdef CONFIG_PL330_DMA 1557#if defined(CONFIG_PL330_DMA)
1554 pd.filter = pl330_filter; 1558 pd.filter = pl330_filter;
1559#elif defined(CONFIG_S3C64XX_PL080)
1560 pd.filter = pl08x_filter_id;
1555#endif 1561#endif
1556 1562
1557 s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi2); 1563 s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi2);
diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c
index ec0d731b0e7b..886326ee6f6c 100644
--- a/arch/arm/plat-samsung/dma-ops.c
+++ b/arch/arm/plat-samsung/dma-ops.c
@@ -18,6 +18,12 @@
18 18
19#include <mach/dma.h> 19#include <mach/dma.h>
20 20
21#if defined(CONFIG_PL330_DMA)
22#define dma_filter pl330_filter
23#elif defined(CONFIG_S3C64XX_PL080)
24#define dma_filter pl08x_filter_id
25#endif
26
21static unsigned samsung_dmadev_request(enum dma_ch dma_ch, 27static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
22 struct samsung_dma_req *param, 28 struct samsung_dma_req *param,
23 struct device *dev, char *ch_name) 29 struct device *dev, char *ch_name)
@@ -30,7 +36,7 @@ static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
30 if (dev->of_node) 36 if (dev->of_node)
31 return (unsigned)dma_request_slave_channel(dev, ch_name); 37 return (unsigned)dma_request_slave_channel(dev, ch_name);
32 else 38 else
33 return (unsigned)dma_request_channel(mask, pl330_filter, 39 return (unsigned)dma_request_channel(mask, dma_filter,
34 (void *)dma_ch); 40 (void *)dma_ch);
35} 41}
36 42
diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c
index 7d2c84265947..8e27aee6887e 100644
--- a/drivers/clk/samsung/clk-s3c64xx.c
+++ b/drivers/clk/samsung/clk-s3c64xx.c
@@ -331,8 +331,8 @@ static struct samsung_clock_alias s3c64xx_clock_aliases[] = {
331 ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"), 331 ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
332 ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"), 332 ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
333 ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"), 333 ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
334 ALIAS(HCLK_DMA1, NULL, "dma1"), 334 ALIAS(HCLK_DMA1, "dma-pl080s.1", "apb_pclk"),
335 ALIAS(HCLK_DMA0, NULL, "dma0"), 335 ALIAS(HCLK_DMA0, "dma-pl080s.0", "apb_pclk"),
336 ALIAS(HCLK_CAMIF, "s3c-camif", "camif"), 336 ALIAS(HCLK_CAMIF, "s3c-camif", "camif"),
337 ALIAS(HCLK_LCD, "s3c-fb", "lcd"), 337 ALIAS(HCLK_LCD, "s3c-fb", "lcd"),
338 ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi"), 338 ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi"),
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index eb1f1ef5fa2e..e2dd2fbec5ee 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -395,7 +395,7 @@ config SPI_S3C24XX_FIQ
395config SPI_S3C64XX 395config SPI_S3C64XX
396 tristate "Samsung S3C64XX series type SPI" 396 tristate "Samsung S3C64XX series type SPI"
397 depends on PLAT_SAMSUNG 397 depends on PLAT_SAMSUNG
398 select S3C64XX_DMA if ARCH_S3C64XX 398 select S3C64XX_PL080 if ARCH_S3C64XX
399 help 399 help
400 SPI driver for Samsung S3C64XX and newer SoCs. 400 SPI driver for Samsung S3C64XX and newer SoCs.
401 401
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index 37459dfd168d..27930fc432dc 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -1,13 +1,22 @@
1config SND_SOC_SAMSUNG 1config SND_SOC_SAMSUNG
2 tristate "ASoC support for Samsung" 2 tristate "ASoC support for Samsung"
3 depends on PLAT_SAMSUNG 3 depends on PLAT_SAMSUNG
4 select S3C64XX_DMA if ARCH_S3C64XX 4 select S3C2410_DMA if ARCH_S3C24XX
5 select S3C24XX_DMA if ARCH_S3C24XX 5 select S3C64XX_PL080 if ARCH_S3C64XX
6 select SND_S3C_DMA if !ARCH_S3C24XX
7 select SND_S3C_DMA_LEGACY if ARCH_S3C24XX
8 select SND_SOC_GENERIC_DMAENGINE_PCM if !ARCH_S3C24XX
6 help 9 help
7 Say Y or M if you want to add support for codecs attached to 10 Say Y or M if you want to add support for codecs attached to
8 the Samsung SoCs' Audio interfaces. You will also need to 11 the Samsung SoCs' Audio interfaces. You will also need to
9 select the audio interfaces to support below. 12 select the audio interfaces to support below.
10 13
14config SND_S3C_DMA
15 tristate
16
17config SND_S3C_DMA_LEGACY
18 tristate
19
11config SND_S3C24XX_I2S 20config SND_S3C24XX_I2S
12 tristate 21 tristate
13 select S3C2410_DMA 22 select S3C2410_DMA
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile
index 709f6059ad67..86715d8efee6 100644
--- a/sound/soc/samsung/Makefile
+++ b/sound/soc/samsung/Makefile
@@ -1,5 +1,6 @@
1# S3c24XX Platform Support 1# S3c24XX Platform Support
2snd-soc-s3c24xx-objs := dma.o 2snd-soc-s3c-dma-objs := dmaengine.o
3snd-soc-s3c-dma-legacy-objs := dma.o
3snd-soc-idma-objs := idma.o 4snd-soc-idma-objs := idma.o
4snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o 5snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o
5snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o 6snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o
@@ -9,7 +10,8 @@ snd-soc-samsung-spdif-objs := spdif.o
9snd-soc-pcm-objs := pcm.o 10snd-soc-pcm-objs := pcm.o
10snd-soc-i2s-objs := i2s.o 11snd-soc-i2s-objs := i2s.o
11 12
12obj-$(CONFIG_SND_SOC_SAMSUNG) += snd-soc-s3c24xx.o 13obj-$(CONFIG_SND_S3C_DMA) += snd-soc-s3c-dma.o
14obj-$(CONFIG_SND_S3C_DMA_LEGACY) += snd-soc-s3c-dma-legacy.o
13obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o 15obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o
14obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o 16obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o
15obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o 17obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index 350ba23a9893..4a88e36c82ec 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -221,24 +221,6 @@ static struct snd_ac97_bus_ops s3c_ac97_ops = {
221 .reset = s3c_ac97_cold_reset, 221 .reset = s3c_ac97_cold_reset,
222}; 222};
223 223
224static int s3c_ac97_hw_params(struct snd_pcm_substream *substream,
225 struct snd_pcm_hw_params *params,
226 struct snd_soc_dai *dai)
227{
228 struct snd_soc_pcm_runtime *rtd = substream->private_data;
229 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
230 struct s3c_dma_params *dma_data;
231
232 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
233 dma_data = &s3c_ac97_pcm_out;
234 else
235 dma_data = &s3c_ac97_pcm_in;
236
237 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
238
239 return 0;
240}
241
242static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd, 224static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
243 struct snd_soc_dai *dai) 225 struct snd_soc_dai *dai)
244{ 226{
@@ -279,21 +261,6 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
279 return 0; 261 return 0;
280} 262}
281 263
282static int s3c_ac97_hw_mic_params(struct snd_pcm_substream *substream,
283 struct snd_pcm_hw_params *params,
284 struct snd_soc_dai *dai)
285{
286 struct snd_soc_pcm_runtime *rtd = substream->private_data;
287 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
288
289 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
290 return -ENODEV;
291 else
292 snd_soc_dai_set_dma_data(cpu_dai, substream, &s3c_ac97_mic_in);
293
294 return 0;
295}
296
297static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream, 264static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
298 int cmd, struct snd_soc_dai *dai) 265 int cmd, struct snd_soc_dai *dai)
299{ 266{
@@ -329,15 +296,27 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
329} 296}
330 297
331static const struct snd_soc_dai_ops s3c_ac97_dai_ops = { 298static const struct snd_soc_dai_ops s3c_ac97_dai_ops = {
332 .hw_params = s3c_ac97_hw_params,
333 .trigger = s3c_ac97_trigger, 299 .trigger = s3c_ac97_trigger,
334}; 300};
335 301
336static const struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = { 302static const struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = {
337 .hw_params = s3c_ac97_hw_mic_params,
338 .trigger = s3c_ac97_mic_trigger, 303 .trigger = s3c_ac97_mic_trigger,
339}; 304};
340 305
306static int s3c_ac97_dai_probe(struct snd_soc_dai *dai)
307{
308 samsung_asoc_init_dma_data(dai, &s3c_ac97_pcm_out, &s3c_ac97_pcm_in);
309
310 return 0;
311}
312
313static int s3c_ac97_mic_dai_probe(struct snd_soc_dai *dai)
314{
315 samsung_asoc_init_dma_data(dai, NULL, &s3c_ac97_mic_in);
316
317 return 0;
318}
319
341static struct snd_soc_dai_driver s3c_ac97_dai[] = { 320static struct snd_soc_dai_driver s3c_ac97_dai[] = {
342 [S3C_AC97_DAI_PCM] = { 321 [S3C_AC97_DAI_PCM] = {
343 .name = "samsung-ac97", 322 .name = "samsung-ac97",
@@ -354,6 +333,7 @@ static struct snd_soc_dai_driver s3c_ac97_dai[] = {
354 .channels_max = 2, 333 .channels_max = 2,
355 .rates = SNDRV_PCM_RATE_8000_48000, 334 .rates = SNDRV_PCM_RATE_8000_48000,
356 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 335 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
336 .probe = s3c_ac97_dai_probe,
357 .ops = &s3c_ac97_dai_ops, 337 .ops = &s3c_ac97_dai_ops,
358 }, 338 },
359 [S3C_AC97_DAI_MIC] = { 339 [S3C_AC97_DAI_MIC] = {
@@ -365,6 +345,7 @@ static struct snd_soc_dai_driver s3c_ac97_dai[] = {
365 .channels_max = 1, 345 .channels_max = 1,
366 .rates = SNDRV_PCM_RATE_8000_48000, 346 .rates = SNDRV_PCM_RATE_8000_48000,
367 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 347 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
348 .probe = s3c_ac97_mic_dai_probe,
368 .ops = &s3c_ac97_mic_dai_ops, 349 .ops = &s3c_ac97_mic_dai_ops,
369 }, 350 },
370}; 351};
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index fe2748b494d4..dc09b71b7d9f 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -35,12 +35,6 @@ static const struct snd_pcm_hardware dma_hardware = {
35 SNDRV_PCM_INFO_BLOCK_TRANSFER | 35 SNDRV_PCM_INFO_BLOCK_TRANSFER |
36 SNDRV_PCM_INFO_MMAP | 36 SNDRV_PCM_INFO_MMAP |
37 SNDRV_PCM_INFO_MMAP_VALID, 37 SNDRV_PCM_INFO_MMAP_VALID,
38 .formats = SNDRV_PCM_FMTBIT_S16_LE |
39 SNDRV_PCM_FMTBIT_U16_LE |
40 SNDRV_PCM_FMTBIT_U8 |
41 SNDRV_PCM_FMTBIT_S8,
42 .channels_min = 2,
43 .channels_max = 2,
44 .buffer_bytes_max = 128*1024, 38 .buffer_bytes_max = 128*1024,
45 .period_bytes_min = PAGE_SIZE, 39 .period_bytes_min = PAGE_SIZE,
46 .period_bytes_max = PAGE_SIZE*2, 40 .period_bytes_max = PAGE_SIZE*2,
@@ -441,6 +435,14 @@ static struct snd_soc_platform_driver samsung_asoc_platform = {
441 .pcm_free = dma_free_dma_buffers, 435 .pcm_free = dma_free_dma_buffers,
442}; 436};
443 437
438void samsung_asoc_init_dma_data(struct snd_soc_dai *dai,
439 struct s3c_dma_params *playback,
440 struct s3c_dma_params *capture)
441{
442 snd_soc_dai_init_dma_data(dai, playback, capture);
443}
444EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data);
445
444int samsung_asoc_dma_platform_register(struct device *dev) 446int samsung_asoc_dma_platform_register(struct device *dev)
445{ 447{
446 return snd_soc_register_platform(dev, &samsung_asoc_platform); 448 return snd_soc_register_platform(dev, &samsung_asoc_platform);
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
index 0e86315a3eaf..225e5378014e 100644
--- a/sound/soc/samsung/dma.h
+++ b/sound/soc/samsung/dma.h
@@ -12,6 +12,8 @@
12#ifndef _S3C_AUDIO_H 12#ifndef _S3C_AUDIO_H
13#define _S3C_AUDIO_H 13#define _S3C_AUDIO_H
14 14
15#include <sound/dmaengine_pcm.h>
16
15struct s3c_dma_params { 17struct s3c_dma_params {
16 struct s3c2410_dma_client *client; /* stream identifier */ 18 struct s3c2410_dma_client *client; /* stream identifier */
17 int channel; /* Channel ID */ 19 int channel; /* Channel ID */
@@ -20,8 +22,12 @@ struct s3c_dma_params {
20 unsigned ch; 22 unsigned ch;
21 struct samsung_dma_ops *ops; 23 struct samsung_dma_ops *ops;
22 char *ch_name; 24 char *ch_name;
25 struct snd_dmaengine_dai_dma_data dma_data;
23}; 26};
24 27
28void samsung_asoc_init_dma_data(struct snd_soc_dai *dai,
29 struct s3c_dma_params *playback,
30 struct s3c_dma_params *capture);
25int samsung_asoc_dma_platform_register(struct device *dev); 31int samsung_asoc_dma_platform_register(struct device *dev);
26void samsung_asoc_dma_platform_unregister(struct device *dev); 32void samsung_asoc_dma_platform_unregister(struct device *dev);
27 33
diff --git a/sound/soc/samsung/dmaengine.c b/sound/soc/samsung/dmaengine.c
new file mode 100644
index 000000000000..3be479d51b9b
--- /dev/null
+++ b/sound/soc/samsung/dmaengine.c
@@ -0,0 +1,84 @@
1/*
2 * dmaengine.c - Samsung dmaengine wrapper
3 *
4 * Author: Mark Brown <broonie@linaro.org>
5 * Copyright 2013 Linaro
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/amba/pl08x.h>
20
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/pcm_params.h>
24#include <sound/dmaengine_pcm.h>
25#include <sound/soc.h>
26#include <sound/soc-dai.h>
27
28#include "dma.h"
29
30#ifdef CONFIG_ARCH_S3C64XX
31#define filter_fn pl08x_filter_id
32#else
33#define filter_fn NULL
34#endif
35
36static const struct snd_dmaengine_pcm_config samsung_dmaengine_pcm_config = {
37 .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
38 .compat_filter_fn = filter_fn,
39};
40
41void samsung_asoc_init_dma_data(struct snd_soc_dai *dai,
42 struct s3c_dma_params *playback,
43 struct s3c_dma_params *capture)
44{
45 struct snd_dmaengine_dai_dma_data *playback_data = NULL;
46 struct snd_dmaengine_dai_dma_data *capture_data = NULL;
47
48 if (playback) {
49 playback_data = &playback->dma_data;
50 playback_data->filter_data = (void *)playback->channel;
51 playback_data->chan_name = playback->ch_name;
52 playback_data->addr = playback->dma_addr;
53 playback_data->addr_width = playback->dma_size;
54 }
55 if (capture) {
56 capture_data = &capture->dma_data;
57 capture_data->filter_data = (void *)capture->channel;
58 capture_data->chan_name = capture->ch_name;
59 capture_data->addr = capture->dma_addr;
60 capture_data->addr_width = capture->dma_size;
61 }
62
63 snd_soc_dai_init_dma_data(dai, playback_data, capture_data);
64}
65EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data);
66
67int samsung_asoc_dma_platform_register(struct device *dev)
68{
69 return snd_dmaengine_pcm_register(dev, &samsung_dmaengine_pcm_config,
70 SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME |
71 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
72 SND_DMAENGINE_PCM_FLAG_COMPAT);
73}
74EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register);
75
76void samsung_asoc_dma_platform_unregister(struct device *dev)
77{
78 return snd_dmaengine_pcm_unregister(dev);
79}
80EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_unregister);
81
82MODULE_AUTHOR("Mark Brown <broonie@linaro.org>");
83MODULE_DESCRIPTION("Samsung dmaengine ASoC driver");
84MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index a5cbdb4f1655..92f64363427d 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -702,6 +702,8 @@ 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 samsung_asoc_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
706
705 i2s->frmclk = params_rate(params); 707 i2s->frmclk = params_rate(params);
706 708
707 return 0; 709 return 0;
@@ -946,8 +948,11 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
946 struct i2s_dai *i2s = to_info(dai); 948 struct i2s_dai *i2s = to_info(dai);
947 struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai; 949 struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai;
948 950
949 if (other && other->clk) /* If this is probe on secondary */ 951 if (other && other->clk) { /* If this is probe on secondary */
952 samsung_asoc_init_dma_data(dai, &other->sec_dai->dma_playback,
953 NULL);
950 goto probe_exit; 954 goto probe_exit;
955 }
951 956
952 i2s->addr = ioremap(i2s->base, 0x100); 957 i2s->addr = ioremap(i2s->base, 0x100);
953 if (i2s->addr == NULL) { 958 if (i2s->addr == NULL) {
@@ -963,7 +968,7 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
963 } 968 }
964 clk_prepare_enable(i2s->clk); 969 clk_prepare_enable(i2s->clk);
965 970
966 snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture); 971 samsung_asoc_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
967 972
968 if (other) { 973 if (other) {
969 other->addr = i2s->addr; 974 other->addr = i2s->addr;
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c
index e4f318fc2f82..3d5cf1530b6f 100644
--- a/sound/soc/samsung/idma.c
+++ b/sound/soc/samsung/idma.c
@@ -35,14 +35,6 @@ static const struct snd_pcm_hardware idma_hardware = {
35 SNDRV_PCM_INFO_MMAP_VALID | 35 SNDRV_PCM_INFO_MMAP_VALID |
36 SNDRV_PCM_INFO_PAUSE | 36 SNDRV_PCM_INFO_PAUSE |
37 SNDRV_PCM_INFO_RESUME, 37 SNDRV_PCM_INFO_RESUME,
38 .formats = SNDRV_PCM_FMTBIT_S16_LE |
39 SNDRV_PCM_FMTBIT_U16_LE |
40 SNDRV_PCM_FMTBIT_S24_LE |
41 SNDRV_PCM_FMTBIT_U24_LE |
42 SNDRV_PCM_FMTBIT_U8 |
43 SNDRV_PCM_FMTBIT_S8,
44 .channels_min = 2,
45 .channels_max = 2,
46 .buffer_bytes_max = MAX_IDMA_BUFFER, 38 .buffer_bytes_max = MAX_IDMA_BUFFER,
47 .period_bytes_min = 128, 39 .period_bytes_min = 128,
48 .period_bytes_max = MAX_IDMA_PERIOD, 40 .period_bytes_max = MAX_IDMA_PERIOD,
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index e54256fc4b2c..6a5e4bf6ac96 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -275,7 +275,6 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
275{ 275{
276 struct snd_soc_pcm_runtime *rtd = substream->private_data; 276 struct snd_soc_pcm_runtime *rtd = substream->private_data;
277 struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai); 277 struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai);
278 struct s3c_dma_params *dma_data;
279 void __iomem *regs = pcm->regs; 278 void __iomem *regs = pcm->regs;
280 struct clk *clk; 279 struct clk *clk;
281 int sclk_div, sync_div; 280 int sclk_div, sync_div;
@@ -284,13 +283,6 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
284 283
285 dev_dbg(pcm->dev, "Entered %s\n", __func__); 284 dev_dbg(pcm->dev, "Entered %s\n", __func__);
286 285
287 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
288 dma_data = pcm->dma_playback;
289 else
290 dma_data = pcm->dma_capture;
291
292 snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);
293
294 /* Strictly check for sample size */ 286 /* Strictly check for sample size */
295 switch (params_format(params)) { 287 switch (params_format(params)) {
296 case SNDRV_PCM_FORMAT_S16_LE: 288 case SNDRV_PCM_FORMAT_S16_LE:
@@ -461,10 +453,20 @@ static const struct snd_soc_dai_ops s3c_pcm_dai_ops = {
461 .set_fmt = s3c_pcm_set_fmt, 453 .set_fmt = s3c_pcm_set_fmt,
462}; 454};
463 455
456static int s3c_pcm_dai_probe(struct snd_soc_dai *dai)
457{
458 struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(dai);
459
460 snd_soc_dai_init_dma_data(dai, pcm->dma_playback, pcm->dma_capture);
461
462 return 0;
463}
464
464#define S3C_PCM_RATES SNDRV_PCM_RATE_8000_96000 465#define S3C_PCM_RATES SNDRV_PCM_RATE_8000_96000
465 466
466#define S3C_PCM_DAI_DECLARE \ 467#define S3C_PCM_DAI_DECLARE \
467 .symmetric_rates = 1, \ 468 .symmetric_rates = 1, \
469 .probe = s3c_pcm_dai_probe, \
468 .ops = &s3c_pcm_dai_ops, \ 470 .ops = &s3c_pcm_dai_ops, \
469 .playback = { \ 471 .playback = { \
470 .channels_min = 2, \ 472 .channels_min = 2, \
diff --git a/sound/soc/samsung/regs-ac97.h b/sound/soc/samsung/regs-ac97.h
index c3878f7acb83..a71be45bbffc 100644
--- a/sound/soc/samsung/regs-ac97.h
+++ b/sound/soc/samsung/regs-ac97.h
@@ -1,5 +1,4 @@
1/* arch/arm/mach-s3c2410/include/mach/regs-ac97.h 1/*
2 *
3 * Copyright (c) 2006 Simtec Electronics <linux@simtec.co.uk> 2 * Copyright (c) 2006 Simtec Electronics <linux@simtec.co.uk>
4 * http://www.simtec.co.uk/products/SWLINUX/ 3 * http://www.simtec.co.uk/products/SWLINUX/
5 * 4 *
@@ -10,8 +9,8 @@
10 * S3C2440 AC97 Controller 9 * S3C2440 AC97 Controller
11*/ 10*/
12 11
13#ifndef __ASM_ARCH_REGS_AC97_H 12#ifndef __SAMSUNG_REGS_AC97_H__
14#define __ASM_ARCH_REGS_AC97_H __FILE__ 13#define __SAMSUNG_REGS_AC97_H__
15 14
16#define S3C_AC97_GLBCTRL (0x00) 15#define S3C_AC97_GLBCTRL (0x00)
17 16
@@ -64,4 +63,4 @@
64#define S3C_AC97_PCM_DATA (0x18) 63#define S3C_AC97_PCM_DATA (0x18)
65#define S3C_AC97_MIC_DATA (0x1C) 64#define S3C_AC97_MIC_DATA (0x1C)
66 65
67#endif /* __ASM_ARCH_REGS_AC97_H */ 66#endif /* __SAMSUNG_REGS_AC97_H__ */
diff --git a/sound/soc/samsung/regs-iis.h b/sound/soc/samsung/regs-iis.h
index a18d35e7a735..dc6cbbe9c4f0 100644
--- a/sound/soc/samsung/regs-iis.h
+++ b/sound/soc/samsung/regs-iis.h
@@ -1,5 +1,4 @@
1/* arch/arm/plat-samsung/include/plat/regs-iis.h 1/*
2 *
3 * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk> 2 * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
4 * http://www.simtec.co.uk/products/SWLINUX/ 3 * http://www.simtec.co.uk/products/SWLINUX/
5 * 4 *
@@ -10,8 +9,8 @@
10 * S3C2410 IIS register definition 9 * S3C2410 IIS register definition
11*/ 10*/
12 11
13#ifndef __ASM_ARCH_REGS_IIS_H 12#ifndef __SAMSUNG_REGS_IIS_H__
14#define __ASM_ARCH_REGS_IIS_H 13#define __SAMSUNG_REGS_IIS_H__
15 14
16#define S3C2410_IISCON (0x00) 15#define S3C2410_IISCON (0x00)
17 16
@@ -67,4 +66,4 @@
67 66
68#define S3C2410_IISFIFO (0x10) 67#define S3C2410_IISFIFO (0x10)
69 68
70#endif /* __ASM_ARCH_REGS_IIS_H */ 69#endif /* __SAMSUNG_REGS_IIS_H__ */