diff options
Diffstat (limited to 'recipes-kernel/linux/linux-yocto-3.14/h1940/0014-dmaengine-s3c24xx-dma-Add-cyclic-transfer-support.patch')
-rw-r--r-- | recipes-kernel/linux/linux-yocto-3.14/h1940/0014-dmaengine-s3c24xx-dma-Add-cyclic-transfer-support.patch | 183 |
1 files changed, 0 insertions, 183 deletions
diff --git a/recipes-kernel/linux/linux-yocto-3.14/h1940/0014-dmaengine-s3c24xx-dma-Add-cyclic-transfer-support.patch b/recipes-kernel/linux/linux-yocto-3.14/h1940/0014-dmaengine-s3c24xx-dma-Add-cyclic-transfer-support.patch deleted file mode 100644 index b3c68ed..0000000 --- a/recipes-kernel/linux/linux-yocto-3.14/h1940/0014-dmaengine-s3c24xx-dma-Add-cyclic-transfer-support.patch +++ /dev/null @@ -1,183 +0,0 @@ -From a2b08b319caba9b3297efa7d1d48cba4f99281f2 Mon Sep 17 00:00:00 2001 -From: Vasily Khoruzhick <anarsoul@gmail.com> -Date: Sun, 18 May 2014 11:44:51 +0300 -Subject: [PATCH 14/17] dmaengine: s3c24xx-dma: Add cyclic transfer support - -Many audio interface drivers require support of cyclic transfers to work -correctly, for example Samsung ASoC DMA driver. This patch adds support -for cyclic transfers to the s3c24xx-dma driver - -Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com> ---- - drivers/dma/s3c24xx-dma.c | 112 +++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 111 insertions(+), 1 deletion(-) - -diff --git a/drivers/dma/s3c24xx-dma.c b/drivers/dma/s3c24xx-dma.c -index 2167608..141e220 100644 ---- a/drivers/dma/s3c24xx-dma.c -+++ b/drivers/dma/s3c24xx-dma.c -@@ -164,6 +164,7 @@ struct s3c24xx_sg { - * @disrcc: value for source control register - * @didstc: value for destination control register - * @dcon: base value for dcon register -+ * @cyclic: indicate cyclic transfer - */ - struct s3c24xx_txd { - struct virt_dma_desc vd; -@@ -173,6 +174,7 @@ struct s3c24xx_txd { - u32 disrcc; - u32 didstc; - u32 dcon; -+ bool cyclic; - }; - - struct s3c24xx_dma_chan; -@@ -669,8 +671,10 @@ static irqreturn_t s3c24xx_dma_irq(int irq, void *data) - /* when more sg's are in this txd, start the next one */ - if (!list_is_last(txd->at, &txd->dsg_list)) { - txd->at = txd->at->next; -+ if (txd->cyclic) -+ vchan_cyclic_callback(&txd->vd); - s3c24xx_dma_start_next_sg(s3cchan, txd); -- } else { -+ } else if (!txd->cyclic) { - s3cchan->at = NULL; - vchan_cookie_complete(&txd->vd); - -@@ -682,6 +686,12 @@ static irqreturn_t s3c24xx_dma_irq(int irq, void *data) - s3c24xx_dma_start_next_txd(s3cchan); - else - s3c24xx_dma_phy_free(s3cchan); -+ } else { -+ vchan_cyclic_callback(&txd->vd); -+ -+ /* Cyclic: reset at beginning */ -+ txd->at = txd->dsg_list.next; -+ s3c24xx_dma_start_next_sg(s3cchan, txd); - } - } - spin_unlock(&s3cchan->vc.lock); -@@ -877,6 +887,104 @@ static struct dma_async_tx_descriptor *s3c24xx_dma_prep_memcpy( - return vchan_tx_prep(&s3cchan->vc, &txd->vd, flags); - } - -+static struct dma_async_tx_descriptor *s3c24xx_dma_prep_dma_cyclic( -+ struct dma_chan *chan, dma_addr_t addr, size_t size, size_t period, -+ enum dma_transfer_direction direction, unsigned long flags, -+ void *context) -+{ -+ struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(chan); -+ struct s3c24xx_dma_engine *s3cdma = s3cchan->host; -+ const struct s3c24xx_dma_platdata *pdata = s3cdma->pdata; -+ struct s3c24xx_dma_channel *cdata = &pdata->channels[s3cchan->id]; -+ struct s3c24xx_txd *txd; -+ struct s3c24xx_sg *dsg; -+ unsigned sg_len; -+ dma_addr_t slave_addr; -+ u32 hwcfg = 0; -+ int i; -+ -+ dev_dbg(&s3cdma->pdev->dev, -+ "prepare cyclic transaction of %d bytes with period %d from %s\n", -+ size, period, s3cchan->name); -+ -+ if (!is_slave_direction(direction)) { -+ dev_err(&s3cdma->pdev->dev, -+ "direction %d unsupported\n", direction); -+ return NULL; -+ } -+ -+ txd = s3c24xx_dma_get_txd(); -+ if (!txd) -+ return NULL; -+ -+ txd->cyclic = 1; -+ -+ if (cdata->handshake) -+ txd->dcon |= S3C24XX_DCON_HANDSHAKE; -+ -+ switch (cdata->bus) { -+ case S3C24XX_DMA_APB: -+ txd->dcon |= S3C24XX_DCON_SYNC_PCLK; -+ hwcfg |= S3C24XX_DISRCC_LOC_APB; -+ break; -+ case S3C24XX_DMA_AHB: -+ txd->dcon |= S3C24XX_DCON_SYNC_HCLK; -+ hwcfg |= S3C24XX_DISRCC_LOC_AHB; -+ break; -+ } -+ -+ /* -+ * Always assume our peripheral desintation is a fixed -+ * address in memory. -+ */ -+ hwcfg |= S3C24XX_DISRCC_INC_FIXED; -+ -+ /* -+ * Individual dma operations are requested by the slave, -+ * so serve only single atomic operations (S3C24XX_DCON_SERV_SINGLE). -+ */ -+ txd->dcon |= S3C24XX_DCON_SERV_SINGLE; -+ -+ if (direction == DMA_MEM_TO_DEV) { -+ txd->disrcc = S3C24XX_DISRCC_LOC_AHB | -+ S3C24XX_DISRCC_INC_INCREMENT; -+ txd->didstc = hwcfg; -+ slave_addr = s3cchan->cfg.dst_addr; -+ txd->width = s3cchan->cfg.dst_addr_width; -+ } else { -+ txd->disrcc = hwcfg; -+ txd->didstc = S3C24XX_DIDSTC_LOC_AHB | -+ S3C24XX_DIDSTC_INC_INCREMENT; -+ slave_addr = s3cchan->cfg.src_addr; -+ txd->width = s3cchan->cfg.src_addr_width; -+ } -+ -+ sg_len = size / period; -+ -+ for (i = 0; i < sg_len; i++) { -+ dsg = kzalloc(sizeof(*dsg), GFP_NOWAIT); -+ if (!dsg) { -+ s3c24xx_dma_free_txd(txd); -+ return NULL; -+ } -+ list_add_tail(&dsg->node, &txd->dsg_list); -+ -+ dsg->len = period; -+ /* Check last period length */ -+ if (i == (sg_len - 1)) -+ dsg->len = size - (period * i); -+ if (direction == DMA_MEM_TO_DEV) { -+ dsg->src_addr = addr + (period * i); -+ dsg->dst_addr = slave_addr; -+ } else { /* DMA_DEV_TO_MEM */ -+ dsg->src_addr = slave_addr; -+ dsg->dst_addr = addr + (period * i); -+ } -+ } -+ -+ return vchan_tx_prep(&s3cchan->vc, &txd->vd, flags); -+} -+ - static struct dma_async_tx_descriptor *s3c24xx_dma_prep_slave_sg( - struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_transfer_direction direction, -@@ -1197,6 +1305,7 @@ static int s3c24xx_dma_probe(struct platform_device *pdev) - - /* Initialize slave engine for SoC internal dedicated peripherals */ - dma_cap_set(DMA_SLAVE, s3cdma->slave.cap_mask); -+ dma_cap_set(DMA_CYCLIC, s3cdma->slave.cap_mask); - dma_cap_set(DMA_PRIVATE, s3cdma->slave.cap_mask); - s3cdma->slave.dev = &pdev->dev; - s3cdma->slave.device_alloc_chan_resources = -@@ -1206,6 +1315,7 @@ static int s3c24xx_dma_probe(struct platform_device *pdev) - s3cdma->slave.device_tx_status = s3c24xx_dma_tx_status; - s3cdma->slave.device_issue_pending = s3c24xx_dma_issue_pending; - s3cdma->slave.device_prep_slave_sg = s3c24xx_dma_prep_slave_sg; -+ s3cdma->slave.device_prep_dma_cyclic = s3c24xx_dma_prep_dma_cyclic; - s3cdma->slave.device_control = s3c24xx_dma_control; - - /* Register as many memcpy channels as there are physical channels */ --- -1.9.3 - |