diff options
-rw-r--r-- | linux-core/Makefile.kernel | 2 | ||||
-rw-r--r-- | linux-core/drm_bo.c | 2 | ||||
-rw-r--r-- | linux-core/drm_bo_move.c | 1 | ||||
-rw-r--r-- | linux-core/drm_memory.c | 1 | ||||
-rw-r--r-- | linux-core/i915_buffer.c | 68 | ||||
-rw-r--r-- | linux-core/i915_drv.c | 8 | ||||
l--------- | linux-core/i915_hwz.c | 1 | ||||
-rw-r--r-- | shared-core/i915_dma.c | 156 | ||||
-rw-r--r-- | shared-core/i915_drm.h | 33 | ||||
-rw-r--r-- | shared-core/i915_drv.h | 77 | ||||
-rw-r--r-- | shared-core/i915_hwz.c | 959 | ||||
-rw-r--r-- | shared-core/i915_irq.c | 54 |
12 files changed, 1260 insertions, 102 deletions
diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index ac77941e..aa3674b0 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -19,7 +19,7 @@ r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o i810-objs := i810_drv.o i810_dma.o i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \ - i915_buffer.o + i915_buffer.o i915_hwz.o nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \ nouveau_object.o nouveau_irq.o nouveau_notifier.o \ nouveau_sgdma.o nouveau_dma.o \ diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 4c2b1541..cb11dff4 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -504,6 +504,7 @@ void drm_bo_usage_deref_locked(struct drm_buffer_object ** bo) drm_bo_destroy_locked(tmp_bo); } } +EXPORT_SYMBOL(drm_bo_usage_deref_locked); static void drm_bo_base_deref_locked(struct drm_file * file_priv, struct drm_user_object * uo) @@ -1490,6 +1491,7 @@ static int drm_buffer_object_validate(struct drm_buffer_object * bo, return 0; } +EXPORT_SYMBOL(drm_buffer_object_validate); static int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle, diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c index 1a613916..21ab4bbb 100644 --- a/linux-core/drm_bo_move.c +++ b/linux-core/drm_bo_move.c @@ -151,6 +151,7 @@ void drm_mem_reg_iounmap(struct drm_device * dev, struct drm_bo_mem_reg * mem, iounmap(virtual); } } +EXPORT_SYMBOL(drm_mem_reg_iounmap); static int drm_copy_io_page(void *dst, void *src, unsigned long page) { diff --git a/linux-core/drm_memory.c b/linux-core/drm_memory.c index f68a3a3e..2f933c32 100644 --- a/linux-core/drm_memory.c +++ b/linux-core/drm_memory.c @@ -152,6 +152,7 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area) } return pt; } +EXPORT_SYMBOL(drm_realloc); /** * Allocate pages. diff --git a/linux-core/i915_buffer.c b/linux-core/i915_buffer.c index bf500cc6..84bd47fc 100644 --- a/linux-core/i915_buffer.c +++ b/linux-core/i915_buffer.c @@ -63,9 +63,50 @@ int i915_invalidate_caches(struct drm_device * dev, uint64_t flags) return i915_emit_mi_flush(dev, flush_cmd); } +#define PRIV1_ORDER 8 +#define PRIV1_SIZE ((1 << PRIV1_ORDER) * PAGE_SIZE) + +int i915_init_priv1(struct drm_device * dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + int ret; + + if (dev_priv->priv1_addr) + return 0; + + dev_priv->priv1_addr = __get_free_pages(__GFP_NOFAIL | __GFP_HIGH, + PRIV1_ORDER); + + if (!dev_priv->priv1_addr) { + DRM_ERROR("Failed to get %lu bytes of physically " + "contiguous memory for PRIV1 type\n", PRIV1_SIZE); + return -ENOMEM; + } else + DRM_INFO("PRIV1 virtual 0x%lx physical 0x%lx\n", + dev_priv->priv1_addr, + virt_to_phys((void*)dev_priv->priv1_addr)); + + dev_priv->priv1_order = PRIV1_ORDER; + + ret = drm_bo_init_mm(dev, DRM_BO_MEM_PRIV1, + virt_to_phys((void*)dev_priv->priv1_addr) + >> PAGE_SHIFT, (1 << dev_priv->priv1_order)); + + if (ret) { + DRM_ERROR("Failed to initialize PRIV1 memory manager\n"); + free_pages(dev_priv->priv1_addr, dev_priv->priv1_order); + dev_priv->priv1_addr = 0; + return ret; + } + + return 0; +} + int i915_init_mem_type(struct drm_device * dev, uint32_t type, struct drm_mem_type_manager * man) { + drm_i915_private_t *dev_priv = dev->dev_private; + switch (type) { case DRM_BO_MEM_LOCAL: man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | @@ -84,6 +125,7 @@ int i915_init_mem_type(struct drm_device * dev, uint32_t type, man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_NEEDS_IOREMAP; man->drm_bus_maptype = _DRM_AGP; + i915_init_priv1(dev); break; case DRM_BO_MEM_PRIV0: if (!(drm_core_has_AGP(dev) && dev->agp)) { @@ -98,6 +140,19 @@ int i915_init_mem_type(struct drm_device * dev, uint32_t type, _DRM_FLAG_MEMTYPE_FIXED | _DRM_FLAG_NEEDS_IOREMAP; man->drm_bus_maptype = _DRM_AGP; break; + case DRM_BO_MEM_PRIV1: + if (!dev_priv) { + DRM_ERROR("called without initialization\n"); + return -EINVAL; + } + man->io_offset = 0; + man->io_size = (1 << dev_priv->priv1_order) << PAGE_SHIFT; + man->io_addr = (void*)dev_priv->priv1_addr; + man->io_addr -= virt_to_phys(man->io_addr); + man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | + _DRM_FLAG_MEMTYPE_FIXED; + man->drm_bus_maptype = _DRM_TTM; + break; default: DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); return -EINVAL; @@ -108,6 +163,7 @@ int i915_init_mem_type(struct drm_device * dev, uint32_t type, uint32_t i915_evict_mask(struct drm_buffer_object *bo) { switch (bo->mem.mem_type) { + case DRM_BO_MEM_PRIV1: case DRM_BO_MEM_LOCAL: case DRM_BO_MEM_TT: return DRM_BO_FLAG_MEM_LOCAL; @@ -129,14 +185,14 @@ static void i915_emit_copy_blit(struct drm_device * dev, if (!dev_priv) return; - i915_kernel_lost_context(dev); + i915_kernel_lost_context(dev_priv, &dev_priv->ring); while (pages > 0) { cur_pages = pages; if (cur_pages > 2048) cur_pages = 2048; pages -= cur_pages; - BEGIN_LP_RING(6); + BEGIN_RING(&dev_priv->ring, 6); OUT_RING(SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB); OUT_RING((stride & 0xffff) | (0xcc << 16) | (1 << 24) | @@ -145,7 +201,7 @@ static void i915_emit_copy_blit(struct drm_device * dev, OUT_RING(dst_offset); OUT_RING(stride & 0xffff); OUT_RING(src_offset); - ADVANCE_LP_RING(); + ADVANCE_RING(); } return; } @@ -156,6 +212,9 @@ static int i915_move_blit(struct drm_buffer_object * bo, struct drm_bo_mem_reg *old_mem = &bo->mem; int dir = 0; + if (new_mem->mem_type == DRM_BO_MEM_PRIV1) + return -EINVAL; + if ((old_mem->mem_type == new_mem->mem_type) && (new_mem->mm_node->start < old_mem->mm_node->start + old_mem->mm_node->size)) { @@ -221,7 +280,8 @@ int i915_move(struct drm_buffer_object * bo, { struct drm_bo_mem_reg *old_mem = &bo->mem; - if (old_mem->mem_type == DRM_BO_MEM_LOCAL) { + if (old_mem->mem_type == DRM_BO_MEM_LOCAL || old_mem->mem_type == + DRM_BO_MEM_PRIV1) { return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); } else if (new_mem->mem_type == DRM_BO_MEM_LOCAL) { if (i915_move_flip(bo, evict, no_wait, new_mem)) diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index e337e1d2..daf94eb2 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -52,8 +52,10 @@ static struct drm_fence_driver i915_fence_driver = { #endif #ifdef I915_HAVE_BUFFER -static uint32_t i915_mem_prios[] = {DRM_BO_MEM_PRIV0, DRM_BO_MEM_TT, DRM_BO_MEM_LOCAL}; -static uint32_t i915_busy_prios[] = {DRM_BO_MEM_TT, DRM_BO_MEM_PRIV0, DRM_BO_MEM_LOCAL}; +static uint32_t i915_mem_prios[] = {DRM_BO_MEM_PRIV0, DRM_BO_MEM_TT, + DRM_BO_MEM_LOCAL, DRM_BO_MEM_PRIV1}; +static uint32_t i915_busy_prios[] = {DRM_BO_MEM_TT, DRM_BO_MEM_PRIV0, + DRM_BO_MEM_LOCAL, DRM_BO_MEM_PRIV1}; static struct drm_bo_driver i915_bo_driver = { .mem_type_prio = i915_mem_prios, @@ -81,6 +83,8 @@ static struct drm_driver driver = { .load = i915_driver_load, .firstopen = i915_driver_firstopen, .lastclose = i915_driver_lastclose, + .open = i915_driver_open, + .postclose = i915_driver_postclose, .preclose = i915_driver_preclose, .device_is_agp = i915_driver_device_is_agp, .vblank_wait = i915_driver_vblank_wait, diff --git a/linux-core/i915_hwz.c b/linux-core/i915_hwz.c new file mode 120000 index 00000000..6b3ccc07 --- /dev/null +++ b/linux-core/i915_hwz.c @@ -0,0 +1 @@ +../shared-core/i915_hwz.c
\ No newline at end of file diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 9f18feee..eee560e9 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -47,15 +47,14 @@ * the head pointer changes, so that EBUSY only happens if the ring * actually stalls for (eg) 3 seconds. */ -int i915_wait_ring(struct drm_device * dev, int n, const char *caller) +int i915_wait_ring(drm_i915_private_t *dev_priv, drm_i915_ring_buffer_t *ring, + int n, const char *caller) { - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_ring_buffer_t *ring = &(dev_priv->ring); - u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR; + u32 last_head = I915_READ(ring->reg + RING_HEAD) & HEAD_ADDR; int i; for (i = 0; i < 10000; i++) { - ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR; + ring->head = I915_READ(ring->reg + RING_HEAD) & HEAD_ADDR; ring->space = ring->head - (ring->tail + 8); if (ring->space < 0) ring->space += ring->Size; @@ -74,13 +73,11 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller) return -EBUSY; } -void i915_kernel_lost_context(struct drm_device * dev) +void i915_kernel_lost_context(drm_i915_private_t * dev_priv, + drm_i915_ring_buffer_t *ring) { - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_ring_buffer_t *ring = &(dev_priv->ring); - - ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR; - ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR; + ring->head = I915_READ(ring->reg + RING_HEAD) & HEAD_ADDR; + ring->tail = I915_READ(ring->reg + RING_TAIL) & TAIL_ADDR; ring->space = ring->head - (ring->tail + 8); if (ring->space < 0) ring->space += ring->Size; @@ -105,12 +102,18 @@ static int i915_dma_cleanup(struct drm_device * dev) if (dev_priv->ring.virtual_start) { drm_core_ioremapfree(&dev_priv->ring.map, dev); } + if (dev_priv->hwb_ring.virtual_start) { + drm_core_ioremapfree(&dev_priv->hwb_ring.map, dev); + } if (dev_priv->status_page_dmah) { drm_pci_free(dev, dev_priv->status_page_dmah); /* Need to rewrite hardware status page */ I915_WRITE(0x02080, 0x1ffff000); } + + i915_bmp_free(dev); + if (dev_priv->status_gfx_addr) { dev_priv->status_gfx_addr = 0; drm_core_ioremapfree(&dev_priv->hws_map, dev); @@ -125,6 +128,33 @@ static int i915_dma_cleanup(struct drm_device * dev) return 0; } +int i915_init_ring(struct drm_device * dev, drm_i915_ring_buffer_t * ring, + unsigned start, unsigned end, unsigned size, u32 reg) +{ + ring->Start = start; + ring->End = end; + ring->Size = size; + ring->tail_mask = ring->Size - 1; + + ring->map.offset = start; + ring->map.size = size; + ring->map.type = 0; + ring->map.flags = 0; + ring->map.mtrr = 0; + + drm_core_ioremap(&ring->map, dev); + + if (ring->map.handle == NULL) { + DRM_ERROR("can not ioremap virtual address for ring buffer\n"); + return -ENOMEM; + } + + ring->virtual_start = ring->map.handle; + ring->reg = reg; + + return 0; +} + static int i915_initialize(struct drm_device * dev, drm_i915_private_t * dev_priv, drm_i915_init_t * init) @@ -150,29 +180,14 @@ static int i915_initialize(struct drm_device * dev, dev_priv->sarea_priv = (drm_i915_sarea_t *) ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset); - dev_priv->ring.Start = init->ring_start; - dev_priv->ring.End = init->ring_end; - dev_priv->ring.Size = init->ring_size; - dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; - - dev_priv->ring.map.offset = init->ring_start; - dev_priv->ring.map.size = init->ring_size; - dev_priv->ring.map.type = 0; - dev_priv->ring.map.flags = 0; - dev_priv->ring.map.mtrr = 0; - - drm_core_ioremap(&dev_priv->ring.map, dev); - - if (dev_priv->ring.map.handle == NULL) { + if (i915_init_ring(dev, &dev_priv->ring, init->ring_start, + init->ring_end, init->ring_size, LP_RING)) { dev->dev_private = (void *)dev_priv; i915_dma_cleanup(dev); - DRM_ERROR("can not ioremap virtual address for" - " ring buffer\n"); + DRM_ERROR("Failed to initialize LP ring buffer\n"); return -ENOMEM; } - dev_priv->ring.virtual_start = dev_priv->ring.map.handle; - dev_priv->cpp = init->cpp; dev_priv->sarea_priv->pf_current_page = 0; @@ -365,7 +380,7 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8) return -EINVAL; - BEGIN_LP_RING((dwords+1)&~1); + BEGIN_RING(&dev_priv->ring, (dwords+1)&~1); for (i = 0; i < dwords;) { int cmd, sz; @@ -390,7 +405,7 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, if (dwords & 1) OUT_RING(0); - ADVANCE_LP_RING(); + ADVANCE_RING(); return 0; } @@ -414,21 +429,21 @@ static int i915_emit_box(struct drm_device * dev, } if (IS_I965G(dev)) { - BEGIN_LP_RING(4); + BEGIN_RING(&dev_priv->ring, 4); OUT_RING(GFX_OP_DRAWRECT_INFO_I965); OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16)); OUT_RING(DR4); - ADVANCE_LP_RING(); + ADVANCE_RING(); } else { - BEGIN_LP_RING(6); + BEGIN_RING(&dev_priv->ring, 6); OUT_RING(GFX_OP_DRAWRECT_INFO); OUT_RING(DR1); OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16)); OUT_RING(DR4); OUT_RING(0); - ADVANCE_LP_RING(); + ADVANCE_RING(); } return 0; @@ -450,12 +465,12 @@ void i915_emit_breadcrumb(struct drm_device *dev) dev_priv->sarea_priv->last_enqueue = dev_priv->counter; - BEGIN_LP_RING(4); + BEGIN_RING(&dev_priv->ring, 4); OUT_RING(CMD_STORE_DWORD_IDX); - OUT_RING(20); + OUT_RING(16 << 2); OUT_RING(dev_priv->counter); OUT_RING(0); - ADVANCE_LP_RING(); + ADVANCE_RING(); } @@ -467,14 +482,14 @@ int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush) flush_cmd |= flush; - i915_kernel_lost_context(dev); + i915_kernel_lost_context(dev_priv, &dev_priv->ring); - BEGIN_LP_RING(4); + BEGIN_RING(&dev_priv->ring, 4); OUT_RING(flush_cmd); OUT_RING(0); OUT_RING(0); OUT_RING(0); - ADVANCE_LP_RING(); + ADVANCE_RING(); return 0; } @@ -494,7 +509,7 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev, return -EINVAL; } - i915_kernel_lost_context(dev); + i915_kernel_lost_context(dev_priv, &dev_priv->ring); count = nbox ? nbox : 1; @@ -532,7 +547,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, return -EINVAL; } - i915_kernel_lost_context(dev); + i915_kernel_lost_context(dev_priv, &dev_priv->ring); count = nbox ? nbox : 1; @@ -545,7 +560,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, } if (dev_priv->use_mi_batchbuffer_start) { - BEGIN_LP_RING(2); + BEGIN_RING(&dev_priv->ring, 2); if (IS_I965G(dev)) { OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965); OUT_RING(batch->start); @@ -553,15 +568,14 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, OUT_RING(MI_BATCH_BUFFER_START | (2 << 6)); OUT_RING(batch->start | MI_BATCH_NON_SECURE); } - ADVANCE_LP_RING(); - + ADVANCE_RING(); } else { - BEGIN_LP_RING(4); + BEGIN_RING(&dev_priv->ring, 4); OUT_RING(MI_BATCH_BUFFER); OUT_RING(batch->start | MI_BATCH_NON_SECURE); OUT_RING(batch->start + batch->used - 4); OUT_RING(0); - ADVANCE_LP_RING(); + ADVANCE_RING(); } } @@ -610,7 +624,7 @@ static void i915_do_dispatch_flip(struct drm_device * dev, int pipe, int sync) DRM_DEBUG("pipe=%d current_page=%d dspbase=0x%x\n", pipe, current_page, dspbase); - BEGIN_LP_RING(4); + BEGIN_RING(&dev_priv->ring, 4); OUT_RING(sync ? 0 : (MI_WAIT_FOR_EVENT | (pipe ? MI_WAIT_FOR_PLANE_B_FLIP : MI_WAIT_FOR_PLANE_A_FLIP))); @@ -618,7 +632,7 @@ static void i915_do_dispatch_flip(struct drm_device * dev, int pipe, int sync) (pipe ? DISPLAY_PLANE_B : DISPLAY_PLANE_A)); OUT_RING(dev_priv->sarea_priv->pitch * dev_priv->cpp); OUT_RING(dspbase); - ADVANCE_LP_RING(); + ADVANCE_RING(); dev_priv->sarea_priv->pf_current_page &= ~(0x3 << shift); dev_priv->sarea_priv->pf_current_page |= next_page << shift; @@ -650,8 +664,9 @@ static int i915_quiescent(struct drm_device * dev) { drm_i915_private_t *dev_priv = dev->dev_private; - i915_kernel_lost_context(dev); - return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__); + i915_kernel_lost_context(dev_priv, &dev_priv->ring); + return i915_wait_ring(dev_priv, &dev_priv->ring, dev_priv->ring.Size - 8, + __FUNCTION__); } static int i915_flush_ioctl(struct drm_device *dev, void *data, @@ -944,7 +959,13 @@ void i915_driver_lastclose(struct drm_device * dev) if (dev->dev_private) { drm_i915_private_t *dev_priv = dev->dev_private; i915_do_cleanup_pageflip(dev); + i915_bmp_free(dev); i915_mem_takedown(&(dev_priv->agp_heap)); + + if (dev_priv->priv1_addr) { + free_pages(dev_priv->priv1_addr, dev_priv->priv1_order); + dev_priv->priv1_addr = 0; + } } i915_dma_cleanup(dev); } @@ -954,6 +975,7 @@ void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) if (dev->dev_private) { drm_i915_private_t *dev_priv = dev->dev_private; i915_mem_release(dev, file_priv, dev_priv->agp_heap); + i915_hwz_free(dev, file_priv->driver_priv); } } @@ -976,6 +998,7 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH), DRM_IOCTL_DEF(DRM_I915_MMIO, i915_mmio, DRM_AUTH), DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_HWZ, i915_hwz, DRM_AUTH), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); @@ -1003,3 +1026,32 @@ int i915_driver_firstopen(struct drm_device *dev) #endif return 0; } + +int i915_driver_open(struct drm_device *dev, struct drm_file *filp_priv) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + + DRM_DEBUG("\n"); + + filp_priv->driver_priv = NULL; + + if (!dev_priv || !dev_priv->bmp) + return 0; + + filp_priv->driver_priv = + drm_calloc(1, sizeof(struct drm_i915_driver_file_fields), + DRM_MEM_FILES); + + if (!filp_priv->driver_priv) + return -ENOMEM; + + return 0; +} + +void i915_driver_postclose(struct drm_device * dev, struct drm_file * filp_priv) +{ + DRM_DEBUG("\n"); + + drm_free(filp_priv->driver_priv, + sizeof(struct drm_i915_driver_file_fields), DRM_MEM_FILES); +} diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 3a90df6e..98ed9cbc 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -160,6 +160,7 @@ typedef struct _drm_i915_sarea { #define DRM_I915_VBLANK_SWAP 0x0f #define DRM_I915_MMIO 0x10 #define DRM_I915_HWS_ADDR 0x11 +#define DRM_I915_HWZ 0x12 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -177,6 +178,7 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t) #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) #define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t) +#define DRM_IOCTL_I915_HWZ DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_HWZ, drm_i915_hwz_t) /* Asynchronous page flipping: @@ -319,4 +321,35 @@ typedef struct drm_i915_hws_addr { uint64_t addr; } drm_i915_hws_addr_t; +/* Hardware Zone Rendering Support: + */ +#define DRM_I915_HWZ_INIT 1 +#define DRM_I915_HWZ_ALLOC 2 +#define DRM_I915_HWZ_RENDER 3 +#define DRM_I915_HWZ_FREE 4 + +typedef struct drm_i915_hwz { + unsigned int op; + union { + struct drm_i915_hwz_init { + unsigned int hwb_start; + unsigned int hwb_end; + unsigned int hwb_size; + } init; + struct drm_i915_hwz_alloc { + unsigned int num_buffers; + unsigned int num_cliprects; + uint64_t cliprects; + } alloc; + struct drm_i915_hwz_render { + unsigned int batch_start; + int DR1; + int DR4; + unsigned int static_state_start; + unsigned int static_state_size; + unsigned int wait_flips; + } render; + } arg; +} drm_i915_hwz_t; + #endif /* _I915_DRM_H_ */ diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index aff03bee..970eb0de 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -55,10 +55,11 @@ * - Support vertical blank on secondary display pipe * 1.8: New ioctl for ARB_Occlusion_Query * 1.9: Usable page flipping and triple buffering + * 1.10: Hardware Zone Rendering support */ #define DRIVER_MAJOR 1 #if defined(I915_HAVE_FENCE) && defined(I915_HAVE_BUFFER) -#define DRIVER_MINOR 9 +#define DRIVER_MINOR 10 #else #define DRIVER_MINOR 6 #endif @@ -74,6 +75,7 @@ typedef struct _drm_i915_ring_buffer { int tail; int space; drm_local_map_t map; + u32 reg; } drm_i915_ring_buffer_t; struct mem_block { @@ -98,6 +100,7 @@ typedef struct drm_i915_private { drm_i915_sarea_t *sarea_priv; drm_i915_ring_buffer_t ring; + drm_i915_ring_buffer_t hwb_ring; drm_dma_handle_t *status_page_dmah; void *hw_status_page; @@ -136,8 +139,32 @@ typedef struct drm_i915_private { DRM_SPINTYPE swaps_lock; drm_i915_vbl_swap_t vbl_swaps; unsigned int swaps_pending; + + int hwb_oom; + + drm_dma_handle_t *bmp, **bmp_pool; + + unsigned long priv1_addr; + unsigned priv1_order; } drm_i915_private_t; +#define VIRTUAL_BPL 0 + +struct drm_i915_driver_file_fields { +#if VIRTUAL_BPL + drm_buffer_object_t *bpl[3]; +#else + drm_dma_handle_t *bpl[3]; +#endif + + drm_dma_handle_t *bmp, **bmp_pool, **bins[3]; + struct drm_clip_rect **bin_rects; + + unsigned int bpl_num, num_bpls, num_bins, num_rects; + unsigned int bin_cols, bin_rows, *bin_nrects; + unsigned short bin_x1, bin_x2, bin_y1, bin_y2; +}; + enum intel_chip_family { CHIP_I8XX = 0x01, CHIP_I9XX = 0x02, @@ -149,7 +176,8 @@ extern struct drm_ioctl_desc i915_ioctls[]; extern int i915_max_ioctl; /* i915_dma.c */ -extern void i915_kernel_lost_context(struct drm_device * dev); +extern void i915_kernel_lost_context(drm_i915_private_t * dev_priv, + drm_i915_ring_buffer_t *ring); extern int i915_driver_load(struct drm_device *, unsigned long flags); extern void i915_driver_lastclose(struct drm_device * dev); extern void i915_driver_preclose(struct drm_device *dev, @@ -161,6 +189,10 @@ extern void i915_emit_breadcrumb(struct drm_device *dev); extern void i915_dispatch_flip(struct drm_device * dev, int pipes, int sync); extern int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush); extern int i915_driver_firstopen(struct drm_device *dev); +extern int i915_driver_open(struct drm_device * dev, struct drm_file * filp_priv); +extern void i915_driver_postclose(struct drm_device * dev, struct drm_file * filp_priv); +extern int i915_init_ring(struct drm_device * dev, drm_i915_ring_buffer_t * ring, + unsigned start, unsigned end, unsigned size, u32 reg); /* i915_irq.c */ extern int i915_irq_emit(struct drm_device *dev, void *data, @@ -184,6 +216,13 @@ extern void i915_user_irq_off(drm_i915_private_t *dev_priv); extern int i915_vblank_swap(struct drm_device *dev, void *data, struct drm_file *file_priv); +/* i915_hwz.c */ +extern int i915_hwz(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int i915_hwz_free(struct drm_device *dev, struct drm_file *filp_priv); +extern void i915_bmp_free(struct drm_device *dev); + + /* i915_mem.c */ extern int i915_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv); @@ -215,6 +254,7 @@ extern int i915_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t f extern struct drm_ttm_backend *i915_create_ttm_backend_entry(struct drm_device *dev); extern int i915_fence_types(struct drm_buffer_object *bo, uint32_t *type); extern int i915_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags); +extern int i915_init_priv1(struct drm_device * dev); extern int i915_init_mem_type(struct drm_device *dev, uint32_t type, struct drm_mem_type_manager *man); extern uint32_t i915_evict_mask(struct drm_buffer_object *bo); @@ -231,18 +271,20 @@ extern int i915_move(struct drm_buffer_object *bo, int evict, #define I915_VERBOSE 0 #define RING_LOCALS unsigned int outring, ringmask, outcount; \ + drm_i915_ring_buffer_t *ringptr; \ volatile char *virt; -#define BEGIN_LP_RING(n) do { \ +#define BEGIN_RING(ring, n) do { \ + ringptr = (ring); \ if (I915_VERBOSE) \ - DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \ - (n), __FUNCTION__); \ - if (dev_priv->ring.space < (n)*4) \ - i915_wait_ring(dev, (n)*4, __FUNCTION__); \ + DRM_DEBUG("BEGIN_RING(%p, %d) in %s\n", \ + ringptr, (n), __FUNCTION__); \ + if (ringptr->space < (n)*4) \ + i915_wait_ring(dev_priv, ringptr, (n)*4, __FUNCTION__); \ outcount = 0; \ - outring = dev_priv->ring.tail; \ - ringmask = dev_priv->ring.tail_mask; \ - virt = dev_priv->ring.virtual_start; \ + outring = ringptr->tail; \ + ringmask = ringptr->tail_mask; \ + virt = ringptr->virtual_start; \ } while (0) #define OUT_RING(n) do { \ @@ -253,14 +295,15 @@ extern int i915_move(struct drm_buffer_object *bo, int evict, outring &= ringmask; \ } while (0) -#define ADVANCE_LP_RING() do { \ - if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring); \ - dev_priv->ring.tail = outring; \ - dev_priv->ring.space -= outcount * 4; \ - I915_WRITE(LP_RING + RING_TAIL, outring); \ +#define ADVANCE_RING() do { \ + if (I915_VERBOSE) DRM_DEBUG("ADVANCE_RING %x\n", outring); \ + ringptr->tail = outring; \ + ringptr->space -= outcount * 4; \ + I915_WRITE(ringptr->reg + RING_TAIL, outring); \ } while(0) -extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); +extern int i915_wait_ring(drm_i915_private_t *dev_priv, drm_i915_ring_buffer_t + *ring, int n, const char *caller); #define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23)) #define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23)) @@ -498,6 +541,6 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define BREADCRUMB_BITS 31 #define BREADCRUMB_MASK ((1U << BREADCRUMB_BITS) - 1) -#define READ_BREADCRUMB(dev_priv) (((volatile u32*)(dev_priv->hw_status_page))[5]) +#define READ_BREADCRUMB(dev_priv) (((volatile u32*)(dev_priv->hw_status_page))[16]) #define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->hw_status_page))[reg]) #endif diff --git a/shared-core/i915_hwz.c b/shared-core/i915_hwz.c new file mode 100644 index 00000000..5d2441c2 --- /dev/null +++ b/shared-core/i915_hwz.c @@ -0,0 +1,959 @@ +/* + Copyright (C) Aristocrat Technologies. 2007. All Rights Reserved. + Copyright (C) Intel Corp. 2007. All Rights Reserved. + + Aristocrat and Intel funded Tungsten Graphics + (http://www.tungstengraphics.com) to support zone rendering in this + 3D driver. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice (including the + next paragraph) shall be included in all copies or substantial + portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + **********************************************************************/ + /* + * Authors: + * Michel D�nzer <michel@tungstengraphics.com> + */ + +#include "drmP.h" +#include "drm.h" +#include "i915_drm.h" +#include "i915_drv.h" + +#define BIN_WIDTH 64 +#define BIN_HEIGHT 32 +#define BIN_HMASK ~(BIN_HEIGHT - 1) +#define BIN_WMASK ~(BIN_WIDTH - 1) + + +#define BMP_SIZE PAGE_SIZE +#define BMP_POOL_SIZE ((BMP_SIZE - 32) / 4) + +void i915_bmp_free(struct drm_device *dev) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + + if (dev_priv->bmp_pool) { + int i; + + for (i = 0; i < BMP_POOL_SIZE; i++) { + if (!dev_priv->bmp_pool[i]) + break; + + drm_pci_free(dev, dev_priv->bmp_pool[i]); + } + + drm_free(dev_priv->bmp_pool, BMP_POOL_SIZE * + sizeof(drm_dma_handle_t*), DRM_MEM_DRIVER); + dev_priv->bmp_pool = NULL; + } + + if (dev_priv->bmp) { + drm_pci_free(dev, dev_priv->bmp); + dev_priv->bmp = NULL; + } + + I915_WRITE(BMP_BUFFER, 0); + + dev_priv->irq_enable_reg &= ~HWB_OOM_FLAG; + I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + + DRM_INFO("BMP freed\n"); +} + + +static int i915_bmp_alloc(struct drm_device *dev) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + int i; + u32 *ring; + + dev_priv->bmp = drm_pci_alloc(dev, BMP_SIZE, PAGE_SIZE, 0xffffffff); + + if (!dev_priv->bmp) { + DRM_ERROR("Failed to allocate BMP ring buffer\n"); + return -ENOMEM; + } + + dev_priv->bmp_pool = drm_calloc(1, BMP_POOL_SIZE * + sizeof(drm_dma_handle_t*), + DRM_MEM_DRIVER); + + if (!dev_priv->bmp_pool) { + DRM_ERROR("Failed to allocate BMP pool\n"); + drm_pci_free(dev, dev_priv->bmp); + dev_priv->bmp = NULL; + return -ENOMEM; + } + + for (i = 0, ring = dev_priv->bmp->vaddr; i < BMP_POOL_SIZE; i++) { + dev_priv->bmp_pool[i] = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, + 0xffffffff); + + if (!dev_priv->bmp_pool[i]) { + DRM_INFO("Failed to allocate page %d for BMP pool\n", + i); + break; + } + + ring[i] = dev_priv->bmp_pool[i]->busaddr /*>> PAGE_SHIFT*/; + } + + I915_WRITE(BMP_PUT, (i / 8) << BMP_OFFSET_SHIFT); + I915_WRITE(BMP_GET, 0 << BMP_OFFSET_SHIFT); + + dev_priv->irq_enable_reg |= HWB_OOM_FLAG; + I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + + I915_WRITE(BMP_BUFFER, dev_priv->bmp->busaddr | BMP_PAGE_SIZE_4K | + ((BMP_SIZE / PAGE_SIZE - 1) << BMP_BUFFER_SIZE_SHIFT) | + BMP_ENABLE); + + DRM_DEBUG("BMP allocated and initialized\n"); + + return 0; +} + +#define BPL_ALIGN (16 * 1024) + +static int i915_bpl_alloc(struct drm_device *dev, + struct drm_i915_driver_file_fields *filp_priv, + int num_bins) +{ + int i, bpl_size = (8 * num_bins + PAGE_SIZE - 1) & PAGE_MASK; + + if (num_bins <= 0) { + DRM_ERROR("Invalid num_bins=%d\n", num_bins); + return -EINVAL; + } + + if (!filp_priv) { + DRM_ERROR("No driver storage associated with file handle\n"); + return -EINVAL; + } + +#if !VIRTUAL_BPL + /* drm_pci_alloc can't handle alignment > size */ + if (bpl_size < BPL_ALIGN) + bpl_size = BPL_ALIGN; +#endif + + for (i = 0; i < filp_priv->num_bpls; i++) { + if (filp_priv->bpl[i]) + continue; +#if VIRTUAL_BPL + if (drm_buffer_object_create(dev, bpl_size, drm_bo_type_kernel, + DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | + DRM_BO_FLAG_MEM_TT, + DRM_BO_HINT_DONT_FENCE, + BPL_ALIGN / PAGE_SIZE, 0, + &filp_priv->bpl[i])) + filp_priv->bpl[i] = NULL; +#else + filp_priv->bpl[i] = drm_pci_alloc(dev, bpl_size, BPL_ALIGN, + 0xffffffff); +#endif + if (!filp_priv->bpl[i]) { + DRM_ERROR("Failed to allocate BPL %d\n", i); + return -ENOMEM; + } +#if VIRTUAL_BPL + if (filp_priv->bpl[i]->offset & (0x7 << 29)) { + DRM_ERROR("BPL %d bus address 0x%lx high bits not 0\n", + i, filp_priv->bpl[i]->offset); + mutex_lock(&dev->struct_mutex); + drm_bo_usage_deref_locked(filp_priv->bpl[i]); + mutex_unlock(&dev->struct_mutex); + filp_priv->bpl[i] = NULL; + return -ENOMEM; + } + + DRM_INFO("BPL %d offset=0x%lx\n", i, filp_priv->bpl[i]->offset); +#endif + } + + DRM_DEBUG("Allocated %d BPLs of %d bytes\n", filp_priv->num_bpls, + bpl_size); + + return 0; +} + +static void i915_bpl_free(struct drm_device *dev, + struct drm_i915_driver_file_fields *filp_priv) +{ + int i; + + if (!filp_priv) + return; + + for (i = 0; i < 3; i++) { + if (!filp_priv->bpl[i]) + return; + +#if VIRTUAL_BPL + mutex_lock(&dev->struct_mutex); + drm_bo_usage_deref_locked(filp_priv->bpl[i]); + mutex_unlock(&dev->struct_mutex); +#else + drm_pci_free(dev, filp_priv->bpl[i]); +#endif + + filp_priv->bpl[i] = NULL; + } +} + +#define DEBUG_HWZ 0 + +static void i915_bpl_print(struct drm_device *dev, + struct drm_i915_driver_file_fields *filp_priv, int i) +{ +#if DEBUG_HWZ + u32 *bpl_vaddr; + int bpl_row; +#if VIRTUAL_BPL + int ret; +#endif + + if (!filp_priv || !filp_priv->bpl[i]) + return; + +#if VIRTUAL_BPL + ret = drm_mem_reg_ioremap(dev, &filp_priv->bpl[i]->mem, + (void*)&bpl_vaddr); + + if (ret) { + DRM_ERROR("Failed to map BPL %d\n", i); + return; + } +#else + bpl_vaddr = filp_priv->bpl[i]->vaddr; +#endif + + DRM_DEBUG("BPL %d contents:\n", i); + + for (bpl_row = 0; bpl_row < filp_priv->bin_rows; bpl_row++) { + int bpl_col; + + DRM_DEBUG("Row %d:", bpl_row); + + for (bpl_col = 0; bpl_col < filp_priv->bin_cols; bpl_col++) { + u32 *bpl = (u32*)bpl_vaddr + + 2 * (bpl_row * filp_priv->bin_cols + bpl_col); + DRM_DEBUG(" %8p(0x%08x, 0x%08x)", bpl, bpl[0], bpl[1]); + } + + DRM_DEBUG("\n"); + } +#if VIRTUAL_BPL + drm_mem_reg_iounmap(dev, &filp_priv->bpl[i]->mem, bpl_vaddr); +#endif + +#endif /* DEBUG_HWZ */ +} + +static int i915_hwb_idle(struct drm_device *dev, + struct drm_i915_driver_file_fields *filp_priv, + unsigned bpl_num) +{ + drm_i915_private_t *dev_priv = dev->dev_private; +#if DEBUG_HWZ + int i, firsttime = 1; +#endif + int ret = 0; + + if (i915_wait_ring(dev_priv, &dev_priv->hwb_ring, + dev_priv->hwb_ring.Size - 8, __FUNCTION__)) { + DRM_ERROR("Timeout waiting for HWB ring to go idle" + ", PRB head: %x tail: %x/%x HWB head: %x tail: %x/%x\n", + I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR, + I915_READ(LP_RING + RING_TAIL) & HEAD_ADDR, + dev_priv->ring.tail, + I915_READ(HWB_RING + RING_HEAD) & HEAD_ADDR, + I915_READ(HWB_RING + RING_TAIL) & HEAD_ADDR, + dev_priv->hwb_ring.tail); + DRM_ERROR("ESR: 0x%x DMA_FADD_S: 0x%x IPEIR: 0x%x SCPD0: 0x%x " + "IIR: 0x%x\n", I915_READ(ESR), I915_READ(DMA_FADD_S), + I915_READ(IPEIR), I915_READ(SCPD0), + I915_READ(I915REG_INT_IDENTITY_R)); + DRM_ERROR("BCPD: 0x%x BMCD: 0x%x BDCD: 0x%x BPCD: 0x%x\n" + "BINSCENE: 0x%x BINSKPD: 0x%x HWBSKPD: 0x%x\n", I915_READ(BCPD), + I915_READ(BMCD), I915_READ(BDCD), I915_READ(BPCD), + I915_READ(BINSCENE), I915_READ(BINSKPD), I915_READ(HWBSKPD)); + + ret = -EBUSY; + } + +#if DEBUG_HWZ + if (!filp_priv) + return ret; + + if (ret) + bpl_num = (bpl_num - 1) % filp_priv->num_bpls; + + i915_bpl_print(dev, filp_priv, bpl_num); + + for (i = 0; i < filp_priv->num_bins; i++) { + u32 *bin; + int k; + + if (!filp_priv->bins[bpl_num] || !filp_priv->bins[bpl_num][i]) + continue; + + bin = filp_priv->bins[bpl_num][i]->vaddr; + + for (k = 0; k < 1024; k++) { + if (bin[k]) { + int j; + + DRM_DEBUG("BPL %d bin %d busaddr=0x%x non-empty:\n", + bpl_num, i, + filp_priv->bins[bpl_num][i]->busaddr); + + if (!firsttime) + break; + + for (j = 0; j < 128; j++) { + u32 *data = filp_priv->bins[bpl_num][i]->vaddr + + j * 8 * 4; + + if (data[0] || data[1] || data[2] || data[3] || + data[4] || data[5] || data[6] || data[7]) + DRM_DEBUG("%p: %8x %8x %8x %8x %8x %8x %8x %8x\n", + data, data[0], data[1], data[2], data[3], + data[4], data[5], data[6], data[7]); + } + + firsttime = 0; + + break; + } + } + } +#endif + + return ret; +} + +static void i915_bin_free(struct drm_device *dev, + struct drm_i915_driver_file_fields *filp_priv) +{ + int i, j; + + if (!filp_priv) + return; + + i915_hwb_idle(dev, filp_priv, 0); + + for (i = 0; i < filp_priv->num_bins; i++) { + if (!filp_priv->bin_rects || !filp_priv->bin_rects) + goto free_arrays; + + for (j = 0; j < filp_priv->bin_nrects[i]; j++) { + drm_free(filp_priv->bin_rects[i], + filp_priv->bin_nrects[i] * + sizeof(struct drm_clip_rect), + DRM_MEM_DRIVER); + } + +free_arrays: + drm_free(filp_priv->bin_rects, filp_priv->num_bins * + sizeof(struct drm_clip_rect*), DRM_MEM_DRIVER); + filp_priv->bin_rects = NULL; + + drm_free(filp_priv->bin_nrects, filp_priv->num_bins * + sizeof(unsigned int), DRM_MEM_DRIVER); + filp_priv->bin_nrects = NULL; + } + + for (i = 0; i < 3; i++) { + if (!filp_priv->bins[i]) + return; + + for (j = 0; j < filp_priv->num_bins; j++) + drm_pci_free(dev, filp_priv->bins[i][j]); + + drm_free(filp_priv->bins[i], filp_priv->num_bins * + sizeof(drm_dma_handle_t*), DRM_MEM_DRIVER); + filp_priv->bins[i] = NULL; + } +} + +static int i915_bin_alloc(struct drm_device *dev, + struct drm_i915_driver_file_fields *filp_priv, + struct drm_clip_rect *cliprects, + unsigned int num_cliprects) +{ + int i, j; + + if (!filp_priv) { + DRM_ERROR("No driver storage associated with file handle\n"); + return -EINVAL; + } + + filp_priv->bin_rects = drm_calloc(1, filp_priv->num_bins * + sizeof(struct drm_clip_rect*), + DRM_MEM_DRIVER); + + if (!filp_priv->bin_rects) { + DRM_ERROR("Failed to allocate bin rects pool\n"); + return -ENOMEM; + } + + filp_priv->bin_nrects = drm_calloc(1, filp_priv->num_bins * + sizeof(unsigned int), + DRM_MEM_DRIVER); + + if (!filp_priv->bin_nrects) { + DRM_ERROR("Failed to allocate bin nrects array\n"); + return -ENOMEM; + } + + filp_priv->num_rects = 0; + + for (i = 0; i < filp_priv->num_bins; i++) { + unsigned short bin_row = i / filp_priv->bin_cols; + unsigned short bin_col = i % filp_priv->bin_cols; + unsigned short bin_y1 = max(filp_priv->bin_y1, (unsigned short) + ((filp_priv->bin_y1 + bin_row * + BIN_HEIGHT) & BIN_HMASK)); + unsigned short bin_x1 = max(filp_priv->bin_x1, (unsigned short) + ((filp_priv->bin_x1 + bin_col * + BIN_WIDTH) & BIN_WMASK)); + unsigned short bin_y2 = min(filp_priv->bin_y2 - 1, + ((bin_y1 + BIN_HEIGHT) & BIN_HMASK) + - 1); + unsigned short bin_x2 = min(filp_priv->bin_x2 - 1, + ((bin_x1 + BIN_WIDTH) & BIN_WMASK) + - 1); + + for (j = 0; j < num_cliprects; j++) { + unsigned short x1 = max(bin_x1, cliprects[j].x1); + unsigned short x2 = min(bin_x2, cliprects[j].x2); + unsigned short y1 = max(bin_y1, cliprects[j].y1); + unsigned short y2 = min(bin_y2, cliprects[j].y2); + struct drm_clip_rect *rect; + + if (x1 >= x2 || y1 >= y2) + continue; + + filp_priv->bin_rects[i] = + drm_realloc(filp_priv->bin_rects[i], + filp_priv->bin_nrects[i] * + sizeof(struct drm_clip_rect), + (filp_priv->bin_nrects[i] + 1) * + sizeof(struct drm_clip_rect), + DRM_MEM_DRIVER); + + rect = &filp_priv->bin_rects[i] + [filp_priv->bin_nrects[i]++]; + + rect->x1 = x1; + rect->x2 = x2; + rect->y1 = y1; + rect->y2 = y2; + + DRM_DEBUG("Bin %d cliprect %d: (%d, %d) - (%d, %d)\n", + i, filp_priv->bin_nrects[i], x1, y1, x2, y2); + + filp_priv->num_rects++; + } + } + + for (i = 0; i < filp_priv->num_bpls; i++) { + filp_priv->bins[i] = drm_calloc(1, filp_priv->num_bins * + sizeof(drm_dma_handle_t*), + DRM_MEM_DRIVER); + + if (!filp_priv->bins[i]) { + DRM_ERROR("Failed to allocate bin pool %d\n", i); + return -ENOMEM; + } + + for (j = 0; j < filp_priv->num_bins; j++) { + filp_priv->bins[i][j] = drm_pci_alloc(dev, PAGE_SIZE, + PAGE_SIZE, + 0xffffffff); + + if (!filp_priv->bins[i][j]) { + DRM_ERROR("Failed to allocate page for bin %d " + "of buffer %d\n", j, i); + return -ENOMEM; + } + } + } + + DRM_INFO("Allocated %d times %d bins and %d cliprects\n", + filp_priv->num_bpls, filp_priv->num_bins, filp_priv->num_rects); + + return 0; +} + +static int i915_hwz_alloc(struct drm_device *dev, + struct drm_i915_driver_file_fields *filp_priv, + struct drm_i915_hwz_alloc *alloc) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned short x1 = dev_priv->sarea_priv->width - 1, x2 = 0; + unsigned short y1 = dev_priv->sarea_priv->height - 1, y2 = 0; + int bin_rows, bin_cols; + struct drm_clip_rect __user *cliprects; + int i, ret; + + if (!dev_priv->bmp) { + DRM_DEBUG("HWZ not initialized\n"); + return -EINVAL; + } + + if (alloc->num_buffers > 3) { + DRM_ERROR("Only up to 3 buffers allowed\n"); + return -EINVAL; + } + + if (!filp_priv) { + DRM_ERROR("No driver storage associated with file handle\n"); + return -EINVAL; + } + + cliprects = drm_alloc(alloc->num_cliprects * sizeof(struct drm_clip_rect), + DRM_MEM_DRIVER); + + if (!cliprects) { + DRM_ERROR("Failed to allocate memory to hold %u cliprects\n", + alloc->num_cliprects); + return -ENOMEM; + } + + if (DRM_COPY_FROM_USER(cliprects, + (void*)(unsigned long)alloc->cliprects, + alloc->num_cliprects * sizeof(struct drm_clip_rect))) { + DRM_ERROR("DRM_COPY_TO_USER failed for %u cliprects\n", + alloc->num_cliprects); + return -EFAULT; + } + + for (i = 0; i < alloc->num_cliprects; i++) { + x1 = min(x1, cliprects[i].x1); + x2 = max(x2, cliprects[i].x2); + y1 = min(y1, cliprects[i].y1); + y2 = max(y2, cliprects[i].y2); + } + + x2 = min(x2, (unsigned short)(dev_priv->sarea_priv->width - 1)); + if (y2 >= dev_priv->sarea_priv->height) + y2 = dev_priv->sarea_priv->height - 1; + + bin_rows = (((y2 + BIN_HEIGHT - 1) & BIN_HMASK) - + (y1 & BIN_HMASK)) / BIN_HEIGHT; + bin_cols = (((x2 + BIN_WIDTH - 1) & BIN_WMASK) - + (x1 & BIN_WMASK)) / BIN_WIDTH; + + if (bin_cols <= 0 || bin_rows <= 0) { + DRM_DEBUG("bin_cols=%d bin_rows=%d => nothing to allocate\n", + bin_cols, bin_rows); + return -EINVAL; + } + + if (filp_priv->num_bpls != alloc->num_buffers || + filp_priv->bin_rows != bin_rows || + filp_priv->bin_cols != bin_cols) { + i915_bpl_free(dev, filp_priv); + } + + filp_priv->bin_x1 = x1; + filp_priv->bin_x2 = x2; + filp_priv->bin_cols = bin_cols; + filp_priv->bin_y1 = y1; + filp_priv->bin_y2 = y2; + filp_priv->bin_rows = bin_rows; + filp_priv->num_bpls = alloc->num_buffers; + + i915_bin_free(dev, filp_priv); + + filp_priv->num_bins = bin_cols * bin_rows; + + ret = i915_bin_alloc(dev, filp_priv, cliprects, alloc->num_cliprects); + + drm_free(cliprects, alloc->num_cliprects * sizeof(struct drm_clip_rect), + DRM_MEM_DRIVER); + + if (ret) { + DRM_ERROR("Failed to allocate bins\n"); + i915_bpl_free(dev, filp_priv); + return ret; + } + + ret = i915_bpl_alloc(dev, filp_priv, bin_cols * ((bin_rows + 3) & ~3)); + + if (ret) { + DRM_ERROR("Failed to allocate BPLs\n"); + return ret; + } + + return 0; +} + +int i915_hwz_free(struct drm_device *dev, struct drm_file *filp_priv) +{ + struct drm_i915_driver_file_fields *filp_i915priv; + + if (!filp_priv || !filp_priv->driver_priv) + return 0; + + filp_i915priv = filp_priv->driver_priv; + + i915_bin_free(dev, filp_i915priv); + i915_bpl_free(dev, filp_i915priv); + + return 0; +} + +static int i915_bin_init(struct drm_device *dev, + struct drm_i915_driver_file_fields *filp_priv, int i) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + u32 *bpl_vaddr; + int bpl_row; + drm_dma_handle_t **bins = filp_priv->bins[i]; +#if VIRTUAL_BPL + int ret; +#endif + + if (!bins) { + DRM_ERROR("Bins not allocated\n"); + return -EINVAL; + } + + if (!filp_priv) { + DRM_ERROR("No driver storage associated with file handle\n"); + return -EINVAL; + } + +#if VIRTUAL_BPL + ret = drm_mem_reg_ioremap(dev, &filp_priv->bpl[i]->mem, + (void*)&bpl_vaddr); + + if (ret) { + DRM_ERROR("Failed to map BPL %d\n", i); + return ret; + } +#else + bpl_vaddr = filp_priv->bpl[i]->vaddr; +#endif + + for (bpl_row = 0; bpl_row < filp_priv->bin_rows; bpl_row += 4) { + int bpl_col; + + for (bpl_col = 0; bpl_col < filp_priv->bin_cols; bpl_col++) { + u32 *bpl = (u32*)bpl_vaddr + + 2 * (bpl_row * filp_priv->bin_cols + 4 * bpl_col); + int j, num_bpls = filp_priv->bin_rows - bpl_row; + + if (num_bpls > 4) + num_bpls = 4; + + DRM_DEBUG("bpl_row=%d bpl_col=%d vaddr=%p => bpl=%p num_bpls = %d\n", + bpl_row, bpl_col, bpl_vaddr, bpl, num_bpls); + + for (j = 0; j < num_bpls; j++) { + unsigned idx = (bpl_row + j) * + filp_priv->bin_cols + bpl_col; + drm_dma_handle_t *bin = bins[idx]; + + DRM_DEBUG("j=%d => idx=%u bpl=%p busaddr=0x%x\n", + j, idx, bpl, bin->busaddr); + + *bpl++ = bin->busaddr; + *bpl++ = 1 << 2 | 1 << 0; + } + } + } + +#if VIRTUAL_BPL + drm_mem_reg_iounmap(dev, &filp_priv->bpl[i]->mem, bpl_vaddr); +#else + flush_agp_cache(); +#endif + + I915_WRITE(GFX_FLSH_CNTL, 1); + + i915_bpl_print(dev, filp_priv, i); + + DRM_DEBUG("BPL %d initialized for %d bins\n", i, filp_priv->bin_rows * + filp_priv->bin_cols); + + return 0; +} + +static int i915_hwz_render(struct drm_device *dev, + struct drm_i915_driver_file_fields *filp_priv, + struct drm_i915_hwz_render *render) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + int ret, i; + int static_state_off = render->static_state_start - + virt_to_phys((void*)dev_priv->priv1_addr); + RING_LOCALS; + + if (static_state_off < 0 || render->static_state_size <= 0 || + static_state_off + 4 * render->static_state_size > + ((1 << dev_priv->priv1_order) * PAGE_SIZE)) { + DRM_ERROR("Invalid static indirect state\n"); + return -EINVAL; + } + + if (!filp_priv) { + DRM_ERROR("No driver storage associated with file handle\n"); + return -EINVAL; + } + + filp_priv->bpl_num = (filp_priv->bpl_num + 1) % filp_priv->num_bpls; + + DRM_DEBUG("bpl_num = %d, batch_start = 0x%x\n", filp_priv->bpl_num, + render->batch_start); + + if (dev_priv->hwb_ring.tail != (I915_READ(HWB_RING + RING_TAIL) + & TAIL_ADDR)) { + DRM_INFO("Refreshing context of HWB ring buffer\n"); + i915_kernel_lost_context(dev_priv, &dev_priv->hwb_ring); + } + + if (i915_hwb_idle(dev, filp_priv, filp_priv->bpl_num)) { + return -EBUSY; + } + + ret = i915_bin_init(dev, filp_priv, filp_priv->bpl_num); + + if (ret) { + DRM_ERROR("Failed to initialize BPL %d\n", filp_priv->bpl_num); + return ret; + } + + /* Write the HWB command stream */ + I915_WRITE(BINSCENE, (filp_priv->bin_rows - 1) << 16 | + (filp_priv->bin_cols - 1) << 10 | BS_MASK); + I915_WRITE(BINSKPD, (VIRTUAL_BPL<<7) | (1<<(7+16))); + +#if VIRTUAL_BPL + ret = drm_buffer_object_validate(filp_priv->bpl[filp_priv->bpl_num], 0, 0); + + if (ret) { + DRM_ERROR("Failed to validate BPL %i\n", filp_priv->bpl_num); + return ret; + } + + DRM_INFO("BPL %d validated to offset 0x%lx\n", filp_priv->bpl_num, + filp_priv->bpl[filp_priv->bpl_num]->offset); + + I915_WRITE(BINCTL, filp_priv->bpl[filp_priv->bpl_num]->offset | BC_MASK); +#else + I915_WRITE(BINCTL, filp_priv->bpl[filp_priv->bpl_num]->busaddr | BC_MASK); +#endif + + BEGIN_RING(&dev_priv->hwb_ring, 16); + + OUT_RING(CMD_OP_BIN_CONTROL); + OUT_RING(0x5 << 4 | 0x6); + OUT_RING((filp_priv->bin_y1 & BIN_HMASK) << 16 | + (filp_priv->bin_x1 & BIN_WMASK)); + OUT_RING((((filp_priv->bin_y2 + BIN_HEIGHT - 1) & BIN_HMASK) - 1) << 16 | + (((filp_priv->bin_x2 + BIN_WIDTH - 1) & BIN_WMASK) - 1)); + OUT_RING(filp_priv->bin_y1 << 16 | filp_priv->bin_x1); + OUT_RING((filp_priv->bin_y2 - 1) << 16 | (filp_priv->bin_x2 - 1)); + + OUT_RING(GFX_OP_DRAWRECT_INFO); + OUT_RING(render->DR1); + OUT_RING((filp_priv->bin_y1 & BIN_HMASK) << 16 | + (filp_priv->bin_x1 & BIN_WMASK)); + OUT_RING((((filp_priv->bin_y2 + BIN_HEIGHT - 1) & BIN_HMASK) - 1) << 16 | + (((filp_priv->bin_x2 + BIN_WIDTH - 1) & BIN_WMASK) - 1)); + OUT_RING(render->DR4); + + OUT_RING(GFX_OP_DESTBUFFER_VARS); + OUT_RING((0x8<<20) | (0x8<<16)); + + OUT_RING(GFX_OP_RASTER_RULES | (1<<5) | (2<<3)); + + OUT_RING(MI_BATCH_BUFFER_START | (2 << 6)); + OUT_RING(render->batch_start | MI_BATCH_NON_SECURE); + + ADVANCE_RING(); + +#if DEBUG_HWZ + i915_hwb_idle(dev, filp_priv, filp_priv->bpl_num); +#endif + + BEGIN_RING(&dev_priv->hwb_ring, 2); + OUT_RING(CMD_MI_FLUSH | MI_END_SCENE | MI_SCENE_COUNT | + MI_NO_WRITE_FLUSH); + OUT_RING(0); + ADVANCE_RING(); + + /* Prepare the Scene Render List */ + DRM_DEBUG("Emitting %d DWORDs of static indirect state\n", + render->static_state_size); + + BEGIN_RING(&dev_priv->ring, (7 * filp_priv->num_rects + 20 + + (render->wait_flips ? 2 : 0) + 1) & ~1); + + OUT_RING(GFX_OP_LOAD_INDIRECT | (0x3f<<8) | (0<<14) | 10); + OUT_RING(render->static_state_start | (1<<1) | (1<<0)); + OUT_RING(render->static_state_size - 1); + OUT_RING(0); + OUT_RING(0); + OUT_RING(0); + OUT_RING(0); + OUT_RING(0); + OUT_RING(0); + OUT_RING(0); + OUT_RING(0); + OUT_RING(0); + OUT_RING(CMD_MI_FLUSH /*| MI_NO_WRITE_FLUSH*/); + OUT_RING(CMD_MI_LOAD_REGISTER_IMM); + OUT_RING(Cache_Mode_0); + OUT_RING(0x221 << 16 | 0x201); + + if (render->wait_flips) { + OUT_RING(render->wait_flips & 0x1 ? + (MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP) : 0); + OUT_RING(render->wait_flips & 0x2 ? + (MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_B_FLIP) : 0); + } + + for (i = 0; i < filp_priv->num_bins; i++) { + int j; + + for (j = 0; j < filp_priv->bin_nrects[i]; j++) { + struct drm_clip_rect *rect = &filp_priv->bin_rects[i][j]; + + OUT_RING(GFX_OP_DRAWRECT_INFO); + OUT_RING(render->DR1); + OUT_RING(rect->y1 << 16 | rect->x1); + OUT_RING(rect->y2 << 16 | rect->x2); + OUT_RING(render->DR4); + OUT_RING(MI_BATCH_BUFFER_START); + OUT_RING(filp_priv->bins[filp_priv->bpl_num][i]->busaddr); + } + } + + OUT_RING(CMD_MI_FLUSH | MI_END_SCENE | MI_SCENE_COUNT); + OUT_RING(CMD_MI_LOAD_REGISTER_IMM); + OUT_RING(Cache_Mode_0); + OUT_RING(0x221 << 16 | 0x20); + + if (filp_priv->num_rects & 0x1) + OUT_RING(0); + + i915_hwb_idle(dev, filp_priv, filp_priv->bpl_num); + + ADVANCE_RING(); + + return ret; +} + +static int i915_hwz_init(struct drm_device *dev, struct drm_i915_hwz_init *init) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + int ret; + RING_LOCALS; + + if (!dev_priv) { + DRM_ERROR("called without initialization\n"); + return -EINVAL; + } + + if (dev_priv->bmp) { + DRM_DEBUG("Already initialized\n"); + return -EBUSY; + } + + ret = i915_init_priv1(dev); + + if (ret) { + DRM_ERROR("Failed to initialize PRIV1 memory type\n"); + return ret; + } + + if (i915_bmp_alloc(dev)) { + DRM_ERROR("Failed to allocate BMP\n"); + return -ENOMEM; + } + + if (i915_init_ring(dev, &dev_priv->hwb_ring, init->hwb_start, + init->hwb_end, init->hwb_size, HWB_RING)) { + DRM_ERROR("Failed to initialize HWB ring buffer\n"); + return -ENOMEM; + } + + DRM_DEBUG("Refreshing context of HWB ring buffer\n"); + i915_kernel_lost_context(dev_priv, &dev_priv->hwb_ring); + + I915_WRITE(BINSCENE, BS_MASK | BS_OP_LOAD); + + BEGIN_RING(&dev_priv->hwb_ring, 2); + OUT_RING(CMD_MI_FLUSH); + OUT_RING(0); + ADVANCE_RING(); + + DRM_INFO("HWZ initialized\n"); + + return 0; +} + +int i915_hwz(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_driver_file_fields *file_i915priv; + drm_i915_hwz_t *hwz = data; + + if (!dev_priv) { + DRM_ERROR("called with no initialization\n"); + return -EINVAL; + } + + if (dev_priv->hwb_oom) { + DRM_ERROR("HWB out of memory\n"); + return -ENOMEM; + } + + if (hwz->op == DRM_I915_HWZ_INIT) { + if (!file_priv->master) { + DRM_ERROR("Only master may initialize HWZ\n"); + return -EINVAL; + } + + return i915_hwz_init(dev, &hwz->arg.init); + } + + if (hwz->op == DRM_I915_HWZ_FREE) + return i915_hwz_free(dev, file_priv); + + file_i915priv = file_priv->driver_priv; + + switch (hwz->op) { + case DRM_I915_HWZ_RENDER: + LOCK_TEST_WITH_RETURN(dev, file_priv); + return i915_hwz_render(dev, file_i915priv, &hwz->arg.render); + case DRM_I915_HWZ_ALLOC: + return i915_hwz_alloc(dev, file_i915priv, &hwz->arg.alloc); + default: + DRM_ERROR("Invalid op 0x%x\n", hwz->op); + return -EINVAL; + } +} diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 1056b3e6..916a72a9 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -31,10 +31,6 @@ #include "i915_drm.h" #include "i915_drv.h" -#define USER_INT_FLAG (1<<1) -#define VSYNC_PIPEB_FLAG (1<<5) -#define VSYNC_PIPEA_FLAG (1<<7) - #define MAX_NOPID ((u32)~0) /** @@ -173,7 +169,9 @@ static void i915_vblank_tasklet(struct drm_device *dev) return; } - i915_kernel_lost_context(dev); + spin_unlock(&dev_priv->swaps_lock); + + i915_kernel_lost_context(dev_priv, &dev_priv->ring); upper[0] = upper[1] = 0; slice[0] = max(sarea_priv->pipeA_h / nhits, 1); @@ -221,7 +219,7 @@ static void i915_vblank_tasklet(struct drm_device *dev) } if (init_drawrect) { - BEGIN_LP_RING(6); + BEGIN_RING(&dev_priv->ring, 6); OUT_RING(GFX_OP_DRAWRECT_INFO); OUT_RING(0); @@ -230,7 +228,7 @@ static void i915_vblank_tasklet(struct drm_device *dev) OUT_RING(sarea_priv->width | sarea_priv->height << 16); OUT_RING(0); - ADVANCE_LP_RING(); + ADVANCE_RING(); sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT; @@ -252,7 +250,7 @@ static void i915_vblank_tasklet(struct drm_device *dev) if (y1 >= y2) continue; - BEGIN_LP_RING(8); + BEGIN_RING(&dev_priv->ring, 8); OUT_RING(cmd); OUT_RING(pitchropcpp); @@ -263,7 +261,7 @@ static void i915_vblank_tasklet(struct drm_device *dev) OUT_RING(pitchropcpp & 0xffff); OUT_RING(offsets[back]); - ADVANCE_LP_RING(); + ADVANCE_RING(); } } } @@ -290,8 +288,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) pipea_stats = I915_READ(I915REG_PIPEASTAT); pipeb_stats = I915_READ(I915REG_PIPEBSTAT); - temp = I915_READ16(I915REG_INT_IDENTITY_R); - temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG); + temp = I915_READ(I915REG_INT_IDENTITY_R); + temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG | HWB_OOM_FLAG); #if 0 DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); @@ -299,8 +297,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) if (temp == 0) return IRQ_NONE; - I915_WRITE16(I915REG_INT_IDENTITY_R, temp); - (void) I915_READ16(I915REG_INT_IDENTITY_R); + I915_WRITE(I915REG_INT_IDENTITY_R, temp); + (void) I915_READ(I915REG_INT_IDENTITY_R); DRM_READMEMORYBARRIER(); dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); @@ -341,6 +339,11 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) I915_VBLANK_CLEAR); } + if ((temp & HWB_OOM_FLAG) && !dev_priv->hwb_oom) { + DRM_ERROR("HWB out of memory\n"); + dev_priv->hwb_oom = TRUE; + } + return IRQ_HANDLED; } @@ -350,16 +353,16 @@ int i915_emit_irq(struct drm_device * dev) drm_i915_private_t *dev_priv = dev->dev_private; RING_LOCALS; - i915_kernel_lost_context(dev); + i915_kernel_lost_context(dev_priv, &dev_priv->ring); DRM_DEBUG("%s\n", __FUNCTION__); i915_emit_breadcrumb(dev); - BEGIN_LP_RING(2); + BEGIN_RING(&dev_priv->ring, 2); OUT_RING(0); OUT_RING(GFX_OP_USER_INTERRUPT); - ADVANCE_LP_RING(); + ADVANCE_RING(); return dev_priv->counter; @@ -371,7 +374,7 @@ void i915_user_irq_on(drm_i915_private_t *dev_priv) DRM_SPINLOCK(&dev_priv->user_irq_lock); if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){ dev_priv->irq_enable_reg |= USER_INT_FLAG; - I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); } DRM_SPINUNLOCK(&dev_priv->user_irq_lock); @@ -382,12 +385,11 @@ void i915_user_irq_off(drm_i915_private_t *dev_priv) DRM_SPINLOCK(&dev_priv->user_irq_lock); if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) { // dev_priv->irq_enable_reg &= ~USER_INT_FLAG; - // I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + // I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); } DRM_SPINUNLOCK(&dev_priv->user_irq_lock); } - static int i915_wait_irq(struct drm_device * dev, int irq_nr) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -499,7 +501,7 @@ static void i915_enable_interrupt (struct drm_device *dev) if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B) dev_priv->irq_enable_reg |= VSYNC_PIPEB_FLAG; - I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); dev_priv->irq_enabled = 1; } @@ -688,8 +690,8 @@ void i915_driver_irq_preinstall(struct drm_device * dev) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; I915_WRITE16(I915REG_HWSTAM, 0xeffe); - I915_WRITE16(I915REG_INT_MASK_R, 0x0); - I915_WRITE16(I915REG_INT_ENABLE_R, 0x0); + I915_WRITE(I915REG_INT_MASK_R, 0x0); + I915_WRITE(I915REG_INT_ENABLE_R, 0x0); } void i915_driver_irq_postinstall(struct drm_device * dev) @@ -722,9 +724,9 @@ void i915_driver_irq_uninstall(struct drm_device * dev) dev_priv->irq_enabled = 0; I915_WRITE16(I915REG_HWSTAM, 0xffff); - I915_WRITE16(I915REG_INT_MASK_R, 0xffff); - I915_WRITE16(I915REG_INT_ENABLE_R, 0x0); + I915_WRITE(I915REG_INT_MASK_R, 0xffffffff); + I915_WRITE(I915REG_INT_ENABLE_R, 0x0); - temp = I915_READ16(I915REG_INT_IDENTITY_R); - I915_WRITE16(I915REG_INT_IDENTITY_R, temp); + temp = I915_READ(I915REG_INT_IDENTITY_R); + I915_WRITE(I915REG_INT_IDENTITY_R, temp); } |