| 
					
				 | 
			
			
				@@ -372,3 +372,104 @@ static int s3c2410_dma_start(struct s3c2410_dma_chan *chan) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	dbg_showchan(chan); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	/* if we've only loaded one buffer onto the channel, then chec 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * to see if we have another, and if so, try and load it so when 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * the first buffer is finished, the new one will be loaded onto 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * the channel */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (chan->next != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (chan->load_state == S3C2410_DMALOAD_1LOADED) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				pr_debug("%s: buff not yet loaded, no more todo\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					 __func__); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				chan->load_state = S3C2410_DMALOAD_1RUNNING; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				s3c2410_dma_loadbuffer(chan, chan->next); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			s3c2410_dma_loadbuffer(chan, chan->next); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	local_irq_restore(flags); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* s3c2410_dma_canload 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * work out if we can queue another buffer into the DMA engine 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+s3c2410_dma_canload(struct s3c2410_dma_chan *chan) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (chan->load_state == S3C2410_DMALOAD_NONE || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	    chan->load_state == S3C2410_DMALOAD_1RUNNING) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* s3c2410_dma_enqueue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * queue an given buffer for dma transfer. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * id         the device driver's id information for this buffer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * data       the physical address of the buffer data 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * size       the size of the buffer in bytes 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * is checked, and if set, the channel is started. If this flag isn't set, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * then an error will be returned. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * It is possible to queue more than one DMA buffer onto a channel at 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * once, and the code will deal with the re-loading of the next buffer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * when necessary. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+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 s3c2410_dma_buf *buf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long flags; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (chan == NULL) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return -EINVAL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pr_debug("%s: id=%p, data=%08x, size=%d\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 __func__, id, (unsigned int)data, size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (buf == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		pr_debug("%s: out of memory (%ld alloc)\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 __func__, (long)sizeof(*buf)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return -ENOMEM; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	//pr_debug("%s: new buffer %p\n", __func__, buf); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	//dbg_showchan(chan); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	buf->next  = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	buf->data  = buf->ptr = data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	buf->size  = size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	buf->id    = id; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	buf->magic = BUF_MAGIC; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	local_irq_save(flags); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (chan->curr == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/* we've got nothing loaded... */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		pr_debug("%s: buffer %p queued onto empty channel\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 __func__, buf); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		chan->curr = buf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		chan->end  = buf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		chan->next = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 chan->number, __func__, buf); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 |