X-Git-Url: http://git.samba.org/samba.git/?p=sfrench%2Fcifs-2.6.git;a=blobdiff_plain;f=arch%2Farm%2Fmach-s3c2410%2Fdma.c;h=717322a0916bd4f9a9f5831a11db6d6cb3fecc83;hp=25855452fe8ce7029cbc4b726a77868e18bb4b23;hb=8df8bb4adf7e4abb48d29dc16c29eda40a64afed;hpb=b01e86fee6c821e4e003fd4e9f65453ac478a58e diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c index 25855452fe8c..717322a0916b 100644 --- a/arch/arm/mach-s3c2410/dma.c +++ b/arch/arm/mach-s3c2410/dma.c @@ -1,35 +1,16 @@ -/* linux/arch/arm/mach-bast/dma.c +/* linux/arch/arm/mach-s3c2410/dma.c * - * (c) 2003-2005 Simtec Electronics + * Copyright (c) 2003-2005,2006 Simtec Electronics * Ben Dooks * * S3C2410 DMA core * - * http://www.simtec.co.uk/products/EB2410ITX/ + * http://armlinux.simtec.co.uk/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * - * Changelog: - * 27-Feb-2005 BJD Added kmem cache for dma descriptors - * 18-Nov-2004 BJD Removed error for loading onto stopped channel - * 10-Nov-2004 BJD Ensure all external symbols exported for modules - * 10-Nov-2004 BJD Use sys_device and sysdev_class for power management - * 08-Aug-2004 BJD Apply rmk's suggestions - * 21-Jul-2004 BJD Ported to linux 2.6 - * 12-Jul-2004 BJD Finished re-write and change of API - * 06-Jul-2004 BJD Rewrote dma code to try and cope with various problems - * 23-May-2003 BJD Created file - * 19-Aug-2003 BJD Cleanup, header fix, added URL - * - * This file is based on the Sangwook Lee/Samsung patches, re-written due - * to various ommisions from the code (such as flexible dma configuration) - * for use with the BAST system board. - * - * The re-write is pretty much complete, and should be good enough for any - * possible DMA function - */ +*/ #ifdef CONFIG_S3C2410_DMA_DEBUG @@ -55,12 +36,16 @@ #include #include +#include "dma.h" + /* io map for dma */ static void __iomem *dma_base; -static kmem_cache_t *dma_kmem; +static struct kmem_cache *dma_kmem; + +struct s3c24xx_dma_selection dma_sel; /* dma channel state information */ -s3c2410_dma_chan_t s3c2410_chans[S3C2410_DMA_CHANNELS]; +struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS]; /* debugging functions */ @@ -74,12 +59,11 @@ s3c2410_dma_chan_t s3c2410_chans[S3C2410_DMA_CHANNELS]; #define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg)) #else static inline void -dma_wrreg(s3c2410_dma_chan_t *chan, int reg, unsigned long val) +dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val) { pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg); writel(val, dma_regaddr(chan, reg)); } - #endif #define dma_rdreg(chan, reg) readl((chan)->regs + (reg)) @@ -102,7 +86,7 @@ struct s3c2410_dma_regstate { */ static void -dmadbg_capture(s3c2410_dma_chan_t *chan, struct s3c2410_dma_regstate *regs) +dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs) { regs->dcsrc = dma_rdreg(chan, S3C2410_DMA_DCSRC); regs->disrc = dma_rdreg(chan, S3C2410_DMA_DISRC); @@ -112,7 +96,7 @@ dmadbg_capture(s3c2410_dma_chan_t *chan, struct s3c2410_dma_regstate *regs) } static void -dmadbg_dumpregs(const char *fname, int line, s3c2410_dma_chan_t *chan, +dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs) { printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n", @@ -122,7 +106,7 @@ dmadbg_dumpregs(const char *fname, int line, s3c2410_dma_chan_t *chan, } static void -dmadbg_showchan(const char *fname, int line, s3c2410_dma_chan_t *chan) +dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan) { struct s3c2410_dma_regstate state; @@ -136,7 +120,7 @@ dmadbg_showchan(const char *fname, int line, s3c2410_dma_chan_t *chan) } static void -dmadbg_showregs(const char *fname, int line, s3c2410_dma_chan_t *chan) +dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan) { struct s3c2410_dma_regstate state; @@ -151,12 +135,20 @@ dmadbg_showregs(const char *fname, int line, s3c2410_dma_chan_t *chan) #define dbg_showchan(chan) do { } while(0) #endif /* CONFIG_S3C2410_DMA_DEBUG */ -#define check_channel(chan) \ - do { if ((chan) >= S3C2410_DMA_CHANNELS) { \ - printk(KERN_ERR "%s: invalid channel %d\n", __FUNCTION__, (chan)); \ - return -EINVAL; \ - } } while(0) +static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX]; +/* lookup_dma_channel + * + * change the dma channel number given into a real dma channel id +*/ + +static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel) +{ + if (channel & DMACH_LOW_LEVEL) + return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL]; + else + return dma_chan_map[channel]; +} /* s3c2410_dma_stats_timeout * @@ -164,7 +156,7 @@ dmadbg_showregs(const char *fname, int line, s3c2410_dma_chan_t *chan) */ static void -s3c2410_dma_stats_timeout(s3c2410_dma_stats_t *stats, int val) +s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val) { if (stats == NULL) return; @@ -183,7 +175,7 @@ s3c2410_dma_stats_timeout(s3c2410_dma_stats_t *stats, int val) */ static int -s3c2410_dma_waitforload(s3c2410_dma_chan_t *chan, int line) +s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line) { int timeout = chan->load_timeout; int took; @@ -230,8 +222,8 @@ s3c2410_dma_waitforload(s3c2410_dma_chan_t *chan, int line) */ static inline int -s3c2410_dma_loadbuffer(s3c2410_dma_chan_t *chan, - s3c2410_dma_buf_t *buf) +s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan, + struct s3c2410_dma_buf *buf) { unsigned long reload; @@ -304,7 +296,7 @@ s3c2410_dma_loadbuffer(s3c2410_dma_chan_t *chan, */ static void -s3c2410_dma_call_op(s3c2410_dma_chan_t *chan, s3c2410_chan_op_t op) +s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op) { if (chan->op_fn != NULL) { (chan->op_fn)(chan, op); @@ -318,11 +310,13 @@ s3c2410_dma_call_op(s3c2410_dma_chan_t *chan, s3c2410_chan_op_t op) */ static inline void -s3c2410_dma_buffdone(s3c2410_dma_chan_t *chan, s3c2410_dma_buf_t *buf, - s3c2410_dma_buffresult_t result) +s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf, + enum s3c2410_dma_buffresult result) { +#if 0 pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n", chan->callback_fn, buf, buf->id, buf->size, result); +#endif if (chan->callback_fn != NULL) { (chan->callback_fn)(chan, buf->id, buf->size, result); @@ -334,7 +328,7 @@ s3c2410_dma_buffdone(s3c2410_dma_chan_t *chan, s3c2410_dma_buf_t *buf, * start a dma channel going */ -static int s3c2410_dma_start(s3c2410_dma_chan_t *chan) +static int s3c2410_dma_start(struct s3c2410_dma_chan *chan) { unsigned long tmp; unsigned long flags; @@ -430,7 +424,7 @@ static int s3c2410_dma_start(s3c2410_dma_chan_t *chan) */ static int -s3c2410_dma_canload(s3c2410_dma_chan_t *chan) +s3c2410_dma_canload(struct s3c2410_dma_chan *chan) { if (chan->load_state == S3C2410_DMALOAD_NONE || chan->load_state == S3C2410_DMALOAD_1RUNNING) @@ -439,7 +433,6 @@ s3c2410_dma_canload(s3c2410_dma_chan_t *chan) return 0; } - /* s3c2410_dma_enqueue * * queue an given buffer for dma transfer. @@ -460,11 +453,12 @@ s3c2410_dma_canload(s3c2410_dma_chan_t *chan) int s3c2410_dma_enqueue(unsigned int channel, void *id, dma_addr_t data, int size) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; - s3c2410_dma_buf_t *buf; + struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); + struct s3c2410_dma_buf *buf; unsigned long flags; - check_channel(channel); + if (chan == NULL) + return -EINVAL; pr_debug("%s: id=%p, data=%08x, size=%d\n", __FUNCTION__, id, (unsigned int)data, size); @@ -540,7 +534,7 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id, EXPORT_SYMBOL(s3c2410_dma_enqueue); static inline void -s3c2410_dma_freebuf(s3c2410_dma_buf_t *buf) +s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf) { int magicok = (buf->magic == BUF_MAGIC); @@ -560,10 +554,12 @@ s3c2410_dma_freebuf(s3c2410_dma_buf_t *buf) */ static inline void -s3c2410_dma_lastxfer(s3c2410_dma_chan_t *chan) +s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan) { +#if 0 pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n", chan->number, chan->load_state); +#endif switch (chan->load_state) { case S3C2410_DMALOAD_NONE: @@ -599,10 +595,10 @@ s3c2410_dma_lastxfer(s3c2410_dma_chan_t *chan) #define dmadbg2(x...) static irqreturn_t -s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs) +s3c2410_dma_irq(int irq, void *devpw) { - s3c2410_dma_chan_t *chan = (s3c2410_dma_chan_t *)devpw; - s3c2410_dma_buf_t *buf; + struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw; + struct s3c2410_dma_buf *buf; buf = chan->curr; @@ -718,7 +714,8 @@ s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs) if (chan->load_state == S3C2410_DMALOAD_NONE) { pr_debug("dma%d: end of transfer, stopping channel (%ld)\n", chan->number, jiffies); - s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP); + s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL, + S3C2410_DMAOP_STOP); } } @@ -726,37 +723,34 @@ s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs) return IRQ_HANDLED; } +static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel); + /* s3c2410_request_dma * * get control of an dma channel */ -int s3c2410_dma_request(unsigned int channel, s3c2410_dma_client_t *client, +int s3c2410_dma_request(unsigned int channel, + struct s3c2410_dma_client *client, void *dev) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan; unsigned long flags; int err; pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n", channel, client->name, dev); - check_channel(channel); - local_irq_save(flags); - dbg_showchan(chan); - - if (chan->in_use) { - if (client != chan->client) { - printk(KERN_ERR "dma%d: already in use\n", channel); - local_irq_restore(flags); - return -EBUSY; - } else { - printk(KERN_ERR "dma%d: client already has channel\n", channel); - } + chan = s3c2410_dma_map_channel(channel); + if (chan == NULL) { + local_irq_restore(flags); + return -EBUSY; } + dbg_showchan(chan); + chan->client = client; chan->in_use = 1; @@ -807,16 +801,16 @@ EXPORT_SYMBOL(s3c2410_dma_request); * allowed to go through. */ -int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *client) +int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); unsigned long flags; - check_channel(channel); + if (chan == NULL) + return -EINVAL; local_irq_save(flags); - if (chan->client != client) { printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n", channel, chan->client, client); @@ -837,8 +831,12 @@ int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *client) if (chan->irq_claimed) free_irq(chan->irq, (void *)chan); + chan->irq_claimed = 0; + if (!(channel & DMACH_LOW_LEVEL)) + dma_chan_map[channel] = NULL; + local_irq_restore(flags); return 0; @@ -846,10 +844,10 @@ int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *client) EXPORT_SYMBOL(s3c2410_dma_free); -static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan) +static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan) { - unsigned long tmp; unsigned long flags; + unsigned long tmp; pr_debug("%s:\n", __FUNCTION__); @@ -880,7 +878,7 @@ static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan) return 0; } -void s3c2410_dma_waitforstop(s3c2410_dma_chan_t *chan) +void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan) { unsigned long tmp; unsigned int timeout = 0x10000; @@ -901,9 +899,9 @@ void s3c2410_dma_waitforstop(s3c2410_dma_chan_t *chan) * stop the channel, and remove all current and pending transfers */ -static int s3c2410_dma_flush(s3c2410_dma_chan_t *chan) +static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan) { - s3c2410_dma_buf_t *buf, *next; + struct s3c2410_dma_buf *buf, *next; unsigned long flags; pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number); @@ -958,7 +956,7 @@ static int s3c2410_dma_flush(s3c2410_dma_chan_t *chan) } int -s3c2410_dma_started(s3c2410_dma_chan_t *chan) +s3c2410_dma_started(struct s3c2410_dma_chan *chan) { unsigned long flags; @@ -995,11 +993,12 @@ s3c2410_dma_started(s3c2410_dma_chan_t *chan) } int -s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op) +s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - check_channel(channel); + if (chan == NULL) + return -EINVAL; switch (op) { case S3C2410_DMAOP_START: @@ -1046,12 +1045,19 @@ int s3c2410_dma_config(dmach_t channel, int xferunit, int dcon) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n", __FUNCTION__, channel, xferunit, dcon); - check_channel(channel); + if (chan == NULL) + return -EINVAL; + + printk("Initial dcon is %08x\n", dcon); + + dcon |= chan->dcon & dma_sel.dcon_mask; + + printk("New dcon is %08x\n", dcon); switch (xferunit) { case 1: @@ -1086,9 +1092,10 @@ EXPORT_SYMBOL(s3c2410_dma_config); int s3c2410_dma_setflags(dmach_t channel, unsigned int flags) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - check_channel(channel); + if (chan == NULL) + return -EINVAL; pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags); @@ -1106,9 +1113,10 @@ EXPORT_SYMBOL(s3c2410_dma_setflags); int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - check_channel(channel); + if (chan == NULL) + return -EINVAL; pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn); @@ -1121,9 +1129,10 @@ EXPORT_SYMBOL(s3c2410_dma_set_opfn); int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - check_channel(channel); + if (chan == NULL) + return -EINVAL; pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn); @@ -1149,13 +1158,14 @@ EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn); */ int s3c2410_dma_devconfig(int channel, - s3c2410_dmasrc_t source, + enum s3c2410_dmasrc source, int hwcfg, unsigned long devaddr) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - check_channel(channel); + if (chan == NULL) + return -EINVAL; pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n", __FUNCTION__, (int)source, hwcfg, devaddr); @@ -1200,9 +1210,10 @@ EXPORT_SYMBOL(s3c2410_dma_devconfig); int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst) { - s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); - check_channel(channel); + if (chan == NULL) + return -EINVAL; if (src != NULL) *src = dma_rdreg(chan, S3C2410_DMA_DCSRC); @@ -1222,7 +1233,7 @@ EXPORT_SYMBOL(s3c2410_dma_getposition); static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state) { - s3c2410_dma_chan_t *cp = container_of(dev, s3c2410_dma_chan_t, dev); + struct s3c2410_dma_chan *cp = container_of(dev, struct s3c2410_dma_chan, dev); printk(KERN_DEBUG "suspending dma channel %d\n", cp->number); @@ -1252,7 +1263,7 @@ static int s3c2410_dma_resume(struct sys_device *dev) #define s3c2410_dma_resume NULL #endif /* CONFIG_PM */ -static struct sysdev_class dma_sysclass = { +struct sysdev_class dma_sysclass = { set_kset_name("s3c24xx-dma"), .suspend = s3c2410_dma_suspend, .resume = s3c2410_dma_resume, @@ -1260,21 +1271,20 @@ static struct sysdev_class dma_sysclass = { /* kmem cache implementation */ -static void s3c2410_dma_cache_ctor(void *p, kmem_cache_t *c, unsigned long f) +static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long f) { - memset(p, 0, sizeof(s3c2410_dma_buf_t)); + memset(p, 0, sizeof(struct s3c2410_dma_buf)); } - /* initialisation code */ static int __init s3c2410_init_dma(void) { - s3c2410_dma_chan_t *cp; + struct s3c2410_dma_chan *cp; int channel; int ret; - printk("S3C2410 DMA Driver, (c) 2003-2004 Simtec Electronics\n"); + printk("S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics\n"); dma_base = ioremap(S3C24XX_PA_DMA, 0x200); if (dma_base == NULL) { @@ -1282,13 +1292,15 @@ static int __init s3c2410_init_dma(void) return -ENOMEM; } + printk("Registering sysclass\n"); + ret = sysdev_class_register(&dma_sysclass); if (ret != 0) { printk(KERN_ERR "dma sysclass registration failed\n"); goto err; } - dma_kmem = kmem_cache_create("dma_desc", sizeof(s3c2410_dma_buf_t), 0, + dma_kmem = kmem_cache_create("dma_desc", sizeof(struct s3c2410_dma_buf), 0, SLAB_HWCACHE_ALIGN, s3c2410_dma_cache_ctor, NULL); @@ -1301,7 +1313,7 @@ static int __init s3c2410_init_dma(void) for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) { cp = &s3c2410_chans[channel]; - memset(cp, 0, sizeof(s3c2410_dma_chan_t)); + memset(cp, 0, sizeof(struct s3c2410_dma_chan)); /* dma channel irqs are in order.. */ cp->number = channel; @@ -1335,4 +1347,95 @@ static int __init s3c2410_init_dma(void) return ret; } -__initcall(s3c2410_init_dma); +core_initcall(s3c2410_init_dma); + +static inline int is_channel_valid(unsigned int channel) +{ + return (channel & DMA_CH_VALID); +} + +/* s3c2410_dma_map_channel() + * + * turn the virtual channel number into a real, and un-used hardware + * channel. + * + * currently this code uses first-free channel from the specified harware + * map, not taking into account anything that the board setup code may + * have to say about the likely peripheral set to be in use. +*/ + +struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel) +{ + struct s3c24xx_dma_map *ch_map; + struct s3c2410_dma_chan *dmach; + int ch; + + if (dma_sel.map == NULL || channel > dma_sel.map_size) + return NULL; + + ch_map = dma_sel.map + channel; + + for (ch = 0; ch < S3C2410_DMA_CHANNELS; ch++) { + if (!is_channel_valid(ch_map->channels[ch])) + continue; + + if (s3c2410_chans[ch].in_use == 0) { + printk("mapped channel %d to %d\n", channel, ch); + break; + } + } + + if (ch >= S3C2410_DMA_CHANNELS) + return NULL; + + /* update our channel mapping */ + + dmach = &s3c2410_chans[ch]; + dma_chan_map[channel] = dmach; + + /* select the channel */ + + (dma_sel.select)(dmach, ch_map); + + return dmach; +} + +static void s3c24xx_dma_show_ch(struct s3c24xx_dma_map *map, int ch) +{ + /* show the channel configuration */ + + printk("%2d: %20s, channels %c%c%c%c\n", ch, map->name, + (is_channel_valid(map->channels[0]) ? '0' : '-'), + (is_channel_valid(map->channels[1]) ? '1' : '-'), + (is_channel_valid(map->channels[2]) ? '2' : '-'), + (is_channel_valid(map->channels[3]) ? '3' : '-')); +} + +static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch) +{ + if (1) + s3c24xx_dma_show_ch(map, ch); + + return 0; +} + +int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel) +{ + struct s3c24xx_dma_map *nmap; + size_t map_sz = sizeof(*nmap) * sel->map_size; + int ptr; + + nmap = kmalloc(map_sz, GFP_KERNEL); + if (nmap == NULL) + return -ENOMEM; + + memcpy(nmap, sel->map, map_sz); + memcpy(&dma_sel, sel, sizeof(*sel)); + + dma_sel.map = nmap; + + for (ptr = 0; ptr < sel->map_size; ptr++) + s3c24xx_dma_check_entry(nmap+ptr, ptr); + + return 0; +}