aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-3.10/0149-bcm2708_fb-use-IRQ-for-DMA-copies.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm2708/patches-3.10/0149-bcm2708_fb-use-IRQ-for-DMA-copies.patch')
-rw-r--r--target/linux/brcm2708/patches-3.10/0149-bcm2708_fb-use-IRQ-for-DMA-copies.patch215
1 files changed, 0 insertions, 215 deletions
diff --git a/target/linux/brcm2708/patches-3.10/0149-bcm2708_fb-use-IRQ-for-DMA-copies.patch b/target/linux/brcm2708/patches-3.10/0149-bcm2708_fb-use-IRQ-for-DMA-copies.patch
deleted file mode 100644
index 90cb5396b7..0000000000
--- a/target/linux/brcm2708/patches-3.10/0149-bcm2708_fb-use-IRQ-for-DMA-copies.patch
+++ /dev/null
@@ -1,215 +0,0 @@
-From 298c1744068079c5174e0c6023a89cb5ad3576c4 Mon Sep 17 00:00:00 2001
-From: Luke Diamand <luked@broadcom.com>
-Date: Wed, 1 Jan 2014 00:45:29 +0000
-Subject: [PATCH 149/196] bcm2708_fb: use IRQ for DMA copies
-
-The copyarea ioctl() uses DMA to speed things along. This
-was busy-waiting for completion. This change supports using
-an interrupt instead for larger transfers. For small
-transfers, busy-waiting is still likely to be faster.
-
-Signed-off-by: Luke Diamand <luke@diamand.org>
----
- arch/arm/mach-bcm2708/dma.c | 8 ++++
- arch/arm/mach-bcm2708/include/mach/dma.h | 2 +
- drivers/video/bcm2708_fb.c | 64 ++++++++++++++++++++++++++++++--
- 3 files changed, 70 insertions(+), 4 deletions(-)
-
-diff --git a/arch/arm/mach-bcm2708/dma.c b/arch/arm/mach-bcm2708/dma.c
-index 51d147a..1da2413 100644
---- a/arch/arm/mach-bcm2708/dma.c
-+++ b/arch/arm/mach-bcm2708/dma.c
-@@ -83,6 +83,14 @@ extern void bcm_dma_wait_idle(void __iomem *dma_chan_base)
-
- EXPORT_SYMBOL_GPL(bcm_dma_start);
-
-+extern bool bcm_dma_is_busy(void __iomem *dma_chan_base)
-+{
-+ dsb();
-+
-+ return readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE;
-+}
-+EXPORT_SYMBOL_GPL(bcm_dma_is_busy);
-+
- /* Complete an ongoing DMA (assuming its results are to be ignored)
- Does nothing if there is no DMA in progress.
- This routine waits for the current AXI transfer to complete before
-diff --git a/arch/arm/mach-bcm2708/include/mach/dma.h b/arch/arm/mach-bcm2708/include/mach/dma.h
-index f2568d4..a4aac4c 100644
---- a/arch/arm/mach-bcm2708/include/mach/dma.h
-+++ b/arch/arm/mach-bcm2708/include/mach/dma.h
-@@ -64,11 +64,13 @@ struct bcm2708_dma_cb {
- unsigned long next;
- unsigned long pad[2];
- };
-+struct scatterlist;
-
- extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len);
- extern void bcm_dma_start(void __iomem *dma_chan_base,
- dma_addr_t control_block);
- extern void bcm_dma_wait_idle(void __iomem *dma_chan_base);
-+extern bool bcm_dma_is_busy(void __iomem *dma_chan_base);
- extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base);
-
- /* When listing features we can ask for when allocating DMA channels give
-diff --git a/drivers/video/bcm2708_fb.c b/drivers/video/bcm2708_fb.c
-index 4d7d963..5758146 100644
---- a/drivers/video/bcm2708_fb.c
-+++ b/drivers/video/bcm2708_fb.c
-@@ -21,6 +21,7 @@
- #include <linux/mm.h>
- #include <linux/fb.h>
- #include <linux/init.h>
-+#include <linux/interrupt.h>
- #include <linux/ioport.h>
- #include <linux/list.h>
- #include <linux/platform_device.h>
-@@ -48,6 +49,11 @@ static const char *bcm2708_name = "BCM2708 FB";
-
- #define DRIVER_NAME "bcm2708_fb"
-
-+static u32 dma_busy_wait_threshold = 1<<15;
-+module_param(dma_busy_wait_threshold, int, 0644);
-+MODULE_PARM_DESC(dma_busy_wait_threshold, "Busy-wait for DMA completion below this area");
-+
-+
- /* this data structure describes each frame buffer device we find */
-
- struct fbinfo_s {
-@@ -77,6 +83,7 @@ struct bcm2708_fb {
- void *cb_base; /* DMA control blocks */
- dma_addr_t cb_handle;
- struct dentry *debugfs_dir;
-+ wait_queue_head_t dma_waitq;
- struct bcm2708_fb_stats stats;
- };
-
-@@ -95,6 +102,10 @@ static int bcm2708_fb_debugfs_init(struct bcm2708_fb *fb)
- "dma_copies",
- offsetof(struct bcm2708_fb_stats, dma_copies)
- },
-+ {
-+ "dma_irqs",
-+ offsetof(struct bcm2708_fb_stats, dma_irqs)
-+ },
- };
-
- fb->debugfs_dir = debugfs_create_dir(DRIVER_NAME, NULL);
-@@ -400,6 +411,7 @@ static void bcm2708_fb_copyarea(struct fb_info *info,
- int bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3;
- /* Channel 0 supports larger bursts and is a bit faster */
- int burst_size = (fb->dma_chan == 0) ? 8 : 2;
-+ int pixels = region->width * region->height;
-
- /* Fallback to cfb_copyarea() if we don't like something */
- if (bytes_per_pixel > 4 ||
-@@ -492,8 +504,20 @@ static void bcm2708_fb_copyarea(struct fb_info *info,
- cb->next = 0;
-
-
-- bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
-- bcm_dma_wait_idle(fb->dma_chan_base);
-+ if (pixels < dma_busy_wait_threshold) {
-+ bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
-+ bcm_dma_wait_idle(fb->dma_chan_base);
-+ } else {
-+ void __iomem *dma_chan = fb->dma_chan_base;
-+ cb->info |= BCM2708_DMA_INT_EN;
-+ bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
-+ while (bcm_dma_is_busy(dma_chan)) {
-+ wait_event_interruptible(
-+ fb->dma_waitq,
-+ !bcm_dma_is_busy(dma_chan));
-+ }
-+ fb->stats.dma_irqs++;
-+ }
- fb->stats.dma_copies++;
- }
-
-@@ -504,6 +528,24 @@ static void bcm2708_fb_imageblit(struct fb_info *info,
- cfb_imageblit(info, image);
- }
-
-+static irqreturn_t bcm2708_fb_dma_irq(int irq, void *cxt)
-+{
-+ struct bcm2708_fb *fb = cxt;
-+
-+ /* FIXME: should read status register to check if this is
-+ * actually interrupting us or not, in case this interrupt
-+ * ever becomes shared amongst several DMA channels
-+ *
-+ * readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_IRQ;
-+ */
-+
-+ /* acknowledge the interrupt */
-+ writel(BCM2708_DMA_INT, fb->dma_chan_base + BCM2708_DMA_CS);
-+
-+ wake_up(&fb->dma_waitq);
-+ return IRQ_HANDLED;
-+}
-+
- static struct fb_ops bcm2708_fb_ops = {
- .owner = THIS_MODULE,
- .fb_check_var = bcm2708_fb_check_var,
-@@ -568,6 +610,7 @@ static int bcm2708_fb_register(struct bcm2708_fb *fb)
- fb->fb.monspecs.dclkmax = 100000000;
-
- bcm2708_fb_set_bitfields(&fb->fb.var);
-+ init_waitqueue_head(&fb->dma_waitq);
-
- /*
- * Allocate colourmap.
-@@ -593,14 +636,15 @@ static int bcm2708_fb_probe(struct platform_device *dev)
- struct bcm2708_fb *fb;
- int ret;
-
-- fb = kmalloc(sizeof(struct bcm2708_fb), GFP_KERNEL);
-+ fb = kzalloc(sizeof(struct bcm2708_fb), GFP_KERNEL);
- if (!fb) {
- dev_err(&dev->dev,
- "could not allocate new bcm2708_fb struct\n");
- ret = -ENOMEM;
- goto free_region;
- }
-- memset(fb, 0, sizeof(struct bcm2708_fb));
-+
-+ bcm2708_fb_debugfs_init(fb);
-
-
- bcm2708_fb_debugfs_init(fb);
-@@ -624,6 +668,14 @@ static int bcm2708_fb_probe(struct platform_device *dev)
- }
- fb->dma_chan = ret;
-
-+ ret = request_irq(fb->dma_irq, bcm2708_fb_dma_irq,
-+ 0, "bcm2708_fb dma", fb);
-+ if (ret) {
-+ pr_err("%s: failed to request DMA irq\n", __func__);
-+ goto free_dma_chan;
-+ }
-+
-+
- pr_info("BCM2708FB: allocated DMA channel %d @ %p\n",
- fb->dma_chan, fb->dma_chan_base);
-
-@@ -635,6 +687,8 @@ static int bcm2708_fb_probe(struct platform_device *dev)
- goto out;
- }
-
-+free_dma_chan:
-+ bcm_dma_chan_free(fb->dma_chan);
- free_cb:
- dma_free_writecombine(&dev->dev, SZ_64K, fb->cb_base, fb->cb_handle);
- free_fb:
-@@ -662,6 +716,8 @@ static int bcm2708_fb_remove(struct platform_device *dev)
- fb->dma);
- bcm2708_fb_debugfs_deinit(fb);
-
-+ free_irq(fb->dma_irq, fb);
-+
- kfree(fb);
-
- return 0;
---
-1.9.1
-