aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2009-08-20 17:27:15 +0100
committerThomas White <taw@bitwiz.org.uk>2009-08-20 17:27:15 +0100
commitb7629bbd863a3de9c7d8c2e699437d517bbd6f1d (patch)
tree324ae7dda8833846e336b2017b749feac45d459a /drivers
parentd64cf0eb8af643de2dd949539de56fcbc95de704 (diff)
Initial buffer wait/IRQ stuff
IRQ stuff brought across from earlier work by Andreas. Signed-off-by: Thomas White <taw@bitwiz.org.uk>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mfd/glamo/glamo-cmdq.c77
1 files changed, 76 insertions, 1 deletions
diff --git a/drivers/mfd/glamo/glamo-cmdq.c b/drivers/mfd/glamo/glamo-cmdq.c
index 80340b100d3..6f14244af11 100644
--- a/drivers/mfd/glamo/glamo-cmdq.c
+++ b/drivers/mfd/glamo/glamo-cmdq.c
@@ -51,6 +51,8 @@
*/
+#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <drm/drmP.h>
#include <drm/glamo_drm.h>
@@ -91,6 +93,31 @@ static u32 glamo_get_write(struct glamodrm_handle *gdrm)
}
+static void glamo_enable_cmdq_irq(struct glamodrm_handle *gdrm)
+{
+ uint16_t irq_status = reg_read(gdrm, GLAMO_REG_IRQ_ENABLE);
+ irq_status |= GLAMO_IRQ_CMDQUEUE;
+ reg_write(gdrm, GLAMO_REG_IRQ_ENABLE, irq_status);
+}
+
+
+static void glamo_set_cmdq_irq(struct glamodrm_handle *gdrm)
+{
+ uint16_t irq_status = reg_read(gdrm, GLAMO_REG_IRQ_SET);
+ irq_status |= GLAMO_IRQ_CMDQUEUE;
+ reg_write(gdrm, GLAMO_REG_IRQ_SET, irq_status);
+}
+
+
+static void glamo_cmdq_irq(unsigned int irq, struct irq_desc *desc)
+{
+ struct glamodrm_handle *gdrm = desc->handler_data;
+
+ if (!gdrm) return;
+ reg_write(gdrm, GLAMO_REG_IRQ_CLEAR, GLAMO_IRQ_CMDQUEUE);
+}
+
+
/* Add commands to the ring buffer */
static int glamo_add_to_ring(struct glamodrm_handle *gdrm, u16 *addr,
unsigned int count)
@@ -227,7 +254,7 @@ static int glamo_do_relocation(struct glamodrm_handle *gdrm,
gobj = obj->driver_private;
if ( gobj == NULL ) {
printk(KERN_WARNING "[glamo-drm] This object has no"
- " private data!\n");
+ " private data!\n");
goto fail;
}
@@ -297,6 +324,7 @@ int glamo_ioctl_cmdbuf(struct drm_device *dev, void *data,
glamo_add_to_ring(gdrm, cmds, count);
+ glamo_set_cmdq_irq(gdrm);
cleanup:
drm_free(cmds, 1, DRM_MEM_DRIVER);
@@ -305,9 +333,49 @@ cleanup:
}
+/* TODO: Banish this to the nether regions of Hades */
+static void glamo_cmdq_wait(struct glamodrm_handle *gdrm,
+ enum glamo_engine engine)
+{
+ u16 mask, val, status;
+ int i;
+
+ switch (engine)
+ {
+ case GLAMO_ENGINE_ALL:
+ mask = 1 << 2;
+ val = mask;
+ break;
+ default:
+ return;
+ }
+
+ for ( i=0; i<1000; i++ ) {
+ status = reg_read(gdrm, GLAMO_REG_CMDQ_STATUS);
+ if ((status & mask) == val) break;
+ mdelay(1);
+ }
+ if ( i == 1000 ) {
+ size_t ring_read;
+ printk(KERN_WARNING "[glamo-drm] CmdQ timeout!\n");
+ printk(KERN_WARNING "[glamo-drm] status = %x\n", status);
+ ring_read = reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRL);
+ ring_read |= ((reg_read(gdrm, GLAMO_REG_CMDQ_READ_ADDRH)
+ & 0x7) << 16);
+ printk(KERN_INFO "[glamo-drm] ring_read now 0x%x\n",
+ ring_read);
+ }
+}
+
+
int glamo_ioctl_gem_wait_rendering(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
+ struct glamodrm_handle *gdrm;
+
+ gdrm = dev->dev_private;
+ glamo_cmdq_wait(gdrm, GLAMO_ENGINE_ALL);
+
return 0;
}
@@ -345,12 +413,19 @@ int glamo_cmdq_init(struct glamodrm_handle *gdrm)
5 << 8 | /* no interrupt */
8 << 4); /* HQ threshold */
+ /* Set up IRQ */
+ set_irq_handler(IRQ_GLAMO(GLAMO_IRQIDX_CMDQUEUE), glamo_cmdq_irq);
+ set_irq_data(IRQ_GLAMO(GLAMO_IRQIDX_CMDQUEUE), gdrm);
+
+ glamo_enable_cmdq_irq(gdrm);
+
return 0;
}
int glamo_cmdq_shutdown(struct glamodrm_handle *gdrm)
{
+ set_irq_handler(IRQ_GLAMO(GLAMO_IRQIDX_CMDQUEUE), handle_level_irq);
return 0;
}