| 
					
				 | 
			
			
				@@ -302,3 +302,125 @@ int s3c2410_dma_ctrl(enum dma_ch channel, enum s3c2410_chan_op op) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	WARN_ON(!chan); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (!chan) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return -EINVAL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	switch (op) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case S3C2410_DMAOP_START: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return s3c64xx_dma_start(chan); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case S3C2410_DMAOP_STOP: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return s3c64xx_dma_stop(chan); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case S3C2410_DMAOP_FLUSH: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return s3c64xx_dma_flush(chan); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* believe PAUSE/RESUME are no-ops */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case S3C2410_DMAOP_PAUSE: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case S3C2410_DMAOP_RESUME: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case S3C2410_DMAOP_STARTED: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case S3C2410_DMAOP_TIMEOUT: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return -ENOENT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+EXPORT_SYMBOL(s3c2410_dma_ctrl); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* s3c2410_dma_enque 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int s3c2410_dma_enqueue(enum dma_ch channel, void *id, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			dma_addr_t data, int size) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	struct s3c64xx_dma_buff *next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	struct s3c64xx_dma_buff *buff; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	struct pl080s_lli *lli; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long flags; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int ret; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	WARN_ON(!chan); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (!chan) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return -EINVAL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	buff = kzalloc(sizeof(struct s3c64xx_dma_buff), GFP_ATOMIC); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (!buff) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		printk(KERN_ERR "%s: no memory for buffer\n", __func__); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return -ENOMEM; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	lli = dma_pool_alloc(dma_pool, GFP_ATOMIC, &buff->lli_dma); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (!lli) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		printk(KERN_ERR "%s: no memory for lli\n", __func__); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		ret = -ENOMEM; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		goto err_buff; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pr_debug("%s: buff %p, dp %08x lli (%p, %08x) %d\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 __func__, buff, data, lli, (u32)buff->lli_dma, size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	buff->lli = lli; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	buff->pw = id; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	s3c64xx_dma_fill_lli(chan, lli, data, size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	local_irq_save(flags); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ((next = chan->next) != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		struct s3c64xx_dma_buff *end = chan->end; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		struct pl080s_lli *endlli = end->lli; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		pr_debug("enquing onto channel\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		end->next = buff; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		endlli->next_lli = buff->lli_dma; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (chan->flags & S3C2410_DMAF_CIRCULAR) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			struct s3c64xx_dma_buff *curr = chan->curr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			lli->next_lli = curr->lli_dma; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (next == chan->curr) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			writel(buff->lli_dma, chan->regs + PL080_CH_LLI); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			chan->next = buff; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		show_lli(endlli); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		chan->end = buff; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		pr_debug("enquing onto empty channel\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		chan->curr = buff; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		chan->next = buff; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		chan->end = buff; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		s3c64xx_lli_to_regs(chan, lli); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	local_irq_restore(flags); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	show_lli(lli); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	dbg_showchan(chan); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	dbg_showbuffs(chan); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+err_buff: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	kfree(buff); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return ret; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+EXPORT_SYMBOL(s3c2410_dma_enqueue); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int s3c2410_dma_devconfig(enum dma_ch channel, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			  enum dma_data_direction source, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			  unsigned long devaddr) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 peripheral; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 config = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pr_debug("%s: channel %d, source %d, dev %08lx, chan %p\n", 
			 |