From patchwork Fri Feb 3 16:11:13 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Javier Martin X-Patchwork-Id: 139416 Return-Path: X-Original-To: incoming-imx@patchwork.ozlabs.org Delivered-To: patchwork-incoming-imx@bilbo.ozlabs.org Received: from merlin.infradead.org (unknown [IPv6:2001:4978:20e::2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id E10CC104792 for ; Sat, 4 Feb 2012 03:14:12 +1100 (EST) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1RtLjb-0004Wz-3W; Fri, 03 Feb 2012 16:11:35 +0000 Received: from mail-wi0-f177.google.com ([209.85.212.177]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1RtLjS-0004WY-6B for linux-arm-kernel@lists.infradead.org; Fri, 03 Feb 2012 16:11:27 +0000 Received: by wico1 with SMTP id o1so3348897wic.36 for ; Fri, 03 Feb 2012 08:11:24 -0800 (PST) Received: by 10.180.84.201 with SMTP id b9mr12613915wiz.4.1328285484115; Fri, 03 Feb 2012 08:11:24 -0800 (PST) Received: from localhost.localdomain (182.50.18.95.dynamic.jazztel.es. [95.18.50.182]) by mx.google.com with ESMTPS id q2sm7544052wiy.7.2012.02.03.08.11.22 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 03 Feb 2012 08:11:23 -0800 (PST) From: Javier Martin To: linux-kernel@vger.kernel.org Subject: [PATCH 1/2] i.MX DMA: Add support for 2D transfers. Date: Fri, 3 Feb 2012 17:11:13 +0100 Message-Id: <1328285474-26365-1-git-send-email-javier.martin@vista-silicon.com> X-Mailer: git-send-email 1.7.0.4 X-Spam-Note: CRM114 invocation failed X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.212.177 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: linux@arm.linux.org.uk, vinod.koul@intel.com, Javier Martin , kernel@pengutronix.de, dan.j.williams@intel.com, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org List-Id: linux-imx-kernel.lists.patchwork.ozlabs.org DMAC present in i.MX2 and i.MX1 chips have two 2D configuration slots that any DMA channel can use to make 2D DMA transfers. Signed-off-by: Javier Martin --- arch/arm/mach-imx/dma-v1.c | 86 +++++++++++++++++++++++++++++++ arch/arm/mach-imx/include/mach/dma-v1.h | 7 +++ 2 files changed, 93 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-imx/dma-v1.c b/arch/arm/mach-imx/dma-v1.c index 42afc29..7401138 100644 --- a/arch/arm/mach-imx/dma-v1.c +++ b/arch/arm/mach-imx/dma-v1.c @@ -121,6 +121,9 @@ struct imx_dma_channel { int in_use; + bool enabled_2d; + int slot_2d; + u32 ccr_from_device; u32 ccr_to_device; @@ -129,6 +132,13 @@ struct imx_dma_channel { int hw_chaining; }; +struct imx_dma_2d_config { + u16 xsr; + u16 ysr; + u16 wsr; + int count; +}; + static void __iomem *imx_dmav1_baseaddr; static void imx_dmav1_writel(unsigned val, unsigned offset) @@ -143,6 +153,9 @@ static unsigned imx_dmav1_readl(unsigned offset) static struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS]; +static struct imx_dma_2d_config imx_dma_2d_slots[IMX_DMA_2D_SLOTS]; +static spinlock_t lock_2d; + static struct clk *dma_clk; static int imx_dma_hw_chain(struct imx_dma_channel *imxdma) @@ -369,6 +382,11 @@ imx_dma_config_channel(int channel, unsigned int config_port, imxdma->ccr_from_device = config_port | (config_mem << 2) | dreq; imxdma->ccr_to_device = config_mem | (config_port << 2) | dreq; + if (imxdma->enabled_2d && (imxdma->slot_2d == IMX_DMA_2D_SLOT_B)) { + imxdma->ccr_from_device |= CCR_MSEL_B; + imxdma->ccr_to_device |= CCR_MSEL_B; + } + imx_dmav1_writel(dmareq, DMA_RSSR(channel)); return 0; @@ -382,6 +400,63 @@ void imx_dma_config_burstlen(int channel, unsigned int burstlen) EXPORT_SYMBOL(imx_dma_config_burstlen); /** + * imx_dma_config_2d - prepare i.MX DMA channel for a 2D transfer. + * @channel: i.MX DMA channel number + * @x: x-size of the 2D window. + * @y: number of rows that make up the 2D window. + * @w: display size of the 2D window + */ +int imx_dma_config_2d(int channel, unsigned int x, unsigned int y, + unsigned int w) +{ + struct imx_dma_channel *imxdma = &imx_dma_channels[channel]; + int slot = -1; + int i; + + spin_lock(&lock_2d); + /* If the channel already owns a slot, free it first */ + if (imxdma->enabled_2d) { + imx_dma_2d_slots[imxdma->slot_2d].count--; + imxdma->enabled_2d = false; + } + /* Try to get free 2D slot */ + for (i = 0; i < IMX_DMA_2D_SLOTS; i++) { + if ((imx_dma_2d_slots[i].count > 0) && + ((imx_dma_2d_slots[i].xsr != x) || + (imx_dma_2d_slots[i].ysr != y) || + (imx_dma_2d_slots[i].wsr != w))) + continue; + slot = i; + break; + } + if (slot < 0) + return -EBUSY; + + imx_dma_2d_slots[slot].xsr = x; + imx_dma_2d_slots[slot].ysr = y; + imx_dma_2d_slots[slot].wsr = w; + imx_dma_2d_slots[slot].count++; + + spin_unlock(&lock_2d); + + imxdma->slot_2d = slot; + imxdma->enabled_2d = true; + + if (slot == IMX_DMA_2D_SLOT_A) { + imx_dmav1_writel(x, DMA_XSRA); + imx_dmav1_writel(y, DMA_YSRA); + imx_dmav1_writel(w, DMA_WSRA); + } else { + imx_dmav1_writel(x, DMA_XSRB); + imx_dmav1_writel(y, DMA_YSRB); + imx_dmav1_writel(w, DMA_WSRB); + } + + return 0; +} +EXPORT_SYMBOL(imx_dma_config_2d); + +/** * imx_dma_setup_handlers - setup i.MX DMA channel end and error notification * handlers * @channel: i.MX DMA channel number @@ -732,6 +807,13 @@ void imx_dma_free(int channel) return; } + spin_lock(&lock_2d); + if (imxdma->enabled_2d) { + imx_dma_2d_slots[imxdma->slot_2d].count--; + imxdma->enabled_2d = false; + } + spin_unlock(&lock_2d); + local_irq_save(flags); /* Disable interrupts */ imx_dma_disable(channel); @@ -840,6 +922,10 @@ static int __init imx_dma_init(void) imx_dma_channels[i].dma_num = i; } + for (i = 0; i < IMX_DMA_2D_SLOTS; i++) + imx_dma_2d_slots[i].count = 0; + spin_lock_init(&lock_2d); + return ret; } diff --git a/arch/arm/mach-imx/include/mach/dma-v1.h b/arch/arm/mach-imx/include/mach/dma-v1.h index ac6fd71..bab9183 100644 --- a/arch/arm/mach-imx/include/mach/dma-v1.h +++ b/arch/arm/mach-imx/include/mach/dma-v1.h @@ -30,6 +30,10 @@ #include #define IMX_DMA_CHANNELS 16 +#define IMX_DMA_2D_SLOTS 2 + +#define IMX_DMA_2D_SLOT_A 0 +#define IMX_DMA_2D_SLOT_B 1 #define DMA_MODE_READ 0 #define DMA_MODE_WRITE 1 @@ -64,6 +68,9 @@ void imx_dma_config_burstlen(int channel, unsigned int burstlen); int +imx_dma_config_2d(int channel, unsigned int x, unsigned int y, unsigned int w); + +int imx_dma_setup_single(int channel, dma_addr_t dma_address, unsigned int dma_length, unsigned int dev_addr, unsigned int dmamode);