diff options
author | Thomas White <taw@bitwiz.org.uk> | 2009-08-20 17:27:15 +0100 |
---|---|---|
committer | Thomas White <taw@bitwiz.org.uk> | 2009-08-20 17:27:15 +0100 |
commit | b7629bbd863a3de9c7d8c2e699437d517bbd6f1d (patch) | |
tree | 324ae7dda8833846e336b2017b749feac45d459a | |
parent | d64cf0eb8af643de2dd949539de56fcbc95de704 (diff) |
Initial buffer wait/IRQ stuff
IRQ stuff brought across from earlier work by Andreas.
Signed-off-by: Thomas White <taw@bitwiz.org.uk>
-rw-r--r-- | drivers/mfd/glamo/glamo-cmdq.c | 77 | ||||
-rw-r--r-- | include/drm/glamo_drm.h | 1 |
2 files changed, 77 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; } diff --git a/include/drm/glamo_drm.h b/include/drm/glamo_drm.h index c0bc0e5afc9..ecf35505837 100644 --- a/include/drm/glamo_drm.h +++ b/include/drm/glamo_drm.h @@ -94,6 +94,7 @@ struct drm_glamo_gem_mmap { struct drm_glamo_gem_wait_rendering { uint32_t handle; + int have_handle; }; struct drm_glamo_gem_pin { |