diff options
Diffstat (limited to 'shared-core')
-rw-r--r-- | shared-core/drm.h | 204 | ||||
-rw-r--r-- | shared-core/i915_dma.c | 38 | ||||
-rw-r--r-- | shared-core/i915_drm.h | 10 | ||||
-rw-r--r-- | shared-core/i915_drv.h | 57 | ||||
-rw-r--r-- | shared-core/i915_irq.c | 68 |
5 files changed, 352 insertions, 25 deletions
diff --git a/shared-core/drm.h b/shared-core/drm.h index 7d7e2502..5784e59b 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -131,6 +131,12 @@ #define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT)) #if defined(__linux__) +#if defined(__KERNEL__) +typedef __u64 drm_u64_t; +#else +typedef unsigned long long drm_u64_t; +#endif + typedef unsigned int drm_handle_t; #else typedef unsigned long drm_handle_t; /**< To mapped regions */ @@ -264,7 +270,8 @@ typedef enum drm_map_type { _DRM_SHM = 2, /**< shared, cached */ _DRM_AGP = 3, /**< AGP/GART */ _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */ - _DRM_CONSISTENT = 5 /**< Consistent memory for PCI DMA */ + _DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */ + _DRM_TTM = 6 } drm_map_type_t; /** @@ -653,6 +660,191 @@ typedef struct drm_set_version { int drm_dd_minor; } drm_set_version_t; +#ifdef __linux__ + +#define DRM_FENCE_FLAG_EMIT 0x00000001 +#define DRM_FENCE_FLAG_SHAREABLE 0x00000002 +#define DRM_FENCE_FLAG_WAIT_LAZY 0x00000004 +#define DRM_FENCE_FLAG_WAIT_IGNORE_SIGNALS 0x00000008 + +/* Reserved for driver use */ +#define DRM_FENCE_MASK_DRIVER 0xFF000000 + +#define DRM_FENCE_TYPE_EXE 0x00000001 + +typedef struct drm_fence_arg { + unsigned handle; + int class; + unsigned type; + unsigned flags; + unsigned signaled; + unsigned expand_pad[4]; /*Future expansion */ + enum { + drm_fence_create, + drm_fence_destroy, + drm_fence_reference, + drm_fence_unreference, + drm_fence_signaled, + drm_fence_flush, + drm_fence_wait, + drm_fence_emit, + drm_fence_buffers + } op; +} drm_fence_arg_t; + +/* Buffer permissions, referring to how the GPU uses the buffers. + these translate to fence types used for the buffers. + Typically a texture buffer is read, A destination buffer is write and + a command (batch-) buffer is exe. Can be or-ed together. */ + +#define DRM_BO_FLAG_READ 0x00000001 +#define DRM_BO_FLAG_WRITE 0x00000002 +#define DRM_BO_FLAG_EXE 0x00000004 + +/* + * Status flags. Can be read to determine the actual state of a buffer. + */ + +/* + * Cannot evict this buffer. Not even with force. This type of buffer should + * only be available for root, and must be manually removed before buffer + * manager shutdown or swapout. + */ +#define DRM_BO_FLAG_NO_EVICT 0x00000010 +/* Always keep a system memory shadow to a vram buffer */ +#define DRM_BO_FLAG_SHADOW_VRAM 0x00000020 +/* The buffer is shareable with other processes */ +#define DRM_BO_FLAG_SHAREABLE 0x00000040 +/* The buffer is currently cached */ +#define DRM_BO_FLAG_CACHED 0x00000080 +/* Make sure that every time this buffer is validated, it ends up on the same + * location. The buffer will also not be evicted when claiming space for + * other buffers. Basically a pinned buffer but it may be thrown out as + * part of buffer manager shutdown or swapout. Not supported yet.*/ +#define DRM_BO_FLAG_NO_MOVE 0x00000100 + +/* Make sure the buffer is in cached memory when mapped for reading */ +#define DRM_BO_FLAG_READ_CACHED 0x00080000 +/* When there is a choice between VRAM and TT, prefer VRAM. + The default behaviour is to prefer TT. */ +#define DRM_BO_FLAG_PREFER_VRAM 0x00040000 +/* Bind this buffer cached if the hardware supports it. */ +#define DRM_BO_FLAG_BIND_CACHED 0x0002000 + +/* System Memory */ +#define DRM_BO_FLAG_MEM_LOCAL 0x01000000 +/* Translation table memory */ +#define DRM_BO_FLAG_MEM_TT 0x02000000 +/* Vram memory */ +#define DRM_BO_FLAG_MEM_VRAM 0x04000000 +/* Unmappable Vram memory */ +#define DRM_BO_FLAG_MEM_VRAM_NM 0x08000000 +/* Memory flag mask */ +#define DRM_BO_MASK_MEM 0xFF000000 + +/* When creating a buffer, Avoid system storage even if allowed */ +#define DRM_BO_HINT_AVOID_LOCAL 0x00000001 +/* Don't block on validate and map */ +#define DRM_BO_HINT_DONT_BLOCK 0x00000002 +/* Don't place this buffer on the unfenced list.*/ +#define DRM_BO_HINT_DONT_FENCE 0x00000004 +#define DRM_BO_HINT_WAIT_LAZY 0x00000008 +#define DRM_BO_HINT_ALLOW_UNFENCED_MAP 0x00000010 + + +/* Driver specific flags. Could be for example rendering engine */ +#define DRM_BO_MASK_DRIVER 0x00F00000 + +typedef enum { + drm_bo_type_dc, + drm_bo_type_user, + drm_bo_type_fake +}drm_bo_type_t; + + +typedef struct drm_bo_arg_request { + unsigned handle; /* User space handle */ + unsigned mask; + unsigned hint; + drm_u64_t size; + drm_bo_type_t type; + unsigned arg_handle; + drm_u64_t buffer_start; + unsigned expand_pad[4]; /*Future expansion */ + enum { + drm_bo_create, + drm_bo_validate, + drm_bo_map, + drm_bo_unmap, + drm_bo_fence, + drm_bo_destroy, + drm_bo_reference, + drm_bo_unreference, + drm_bo_info, + drm_bo_wait_idle, + drm_bo_ref_fence + } op; +} drm_bo_arg_request_t; + + +/* + * Reply flags + */ + +#define DRM_BO_REP_BUSY 0x00000001 + +typedef struct drm_bo_arg_reply { + int ret; + unsigned handle; + unsigned flags; + drm_u64_t size; + drm_u64_t offset; + drm_u64_t arg_handle; + unsigned mask; + drm_u64_t buffer_start; + unsigned fence_flags; + unsigned rep_flags; + unsigned expand_pad[4]; /*Future expansion */ +}drm_bo_arg_reply_t; + + +typedef struct drm_bo_arg{ + int handled; + drm_u64_t next; + union { + drm_bo_arg_request_t req; + drm_bo_arg_reply_t rep; + } d; +} drm_bo_arg_t; + +#define DRM_BO_MEM_LOCAL 0 +#define DRM_BO_MEM_TT 1 +#define DRM_BO_MEM_VRAM 2 +#define DRM_BO_MEM_VRAM_NM 3 +#define DRM_BO_MEM_TYPES 2 /* For now. */ + +typedef union drm_mm_init_arg{ + struct { + enum { + mm_init, + mm_takedown, + mm_query, + mm_lock, + mm_unlock + } op; + drm_u64_t p_offset; + drm_u64_t p_size; + unsigned mem_type; + unsigned expand_pad[8]; /*Future expansion */ + } req; + struct { + drm_handle_t mm_sarea; + unsigned expand_pad[8]; /*Future expansion */ + } rep; +} drm_mm_init_arg_t; +#endif + + /** * \name Ioctls Definitions */ @@ -718,17 +910,25 @@ typedef struct drm_set_version { #define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t) +#ifdef __linux__ +#define DRM_IOCTL_FENCE DRM_IOWR(0x3b, drm_fence_arg_t) +#define DRM_IOCTL_BUFOBJ DRM_IOWR(0x3d, drm_bo_arg_t) +#define DRM_IOCTL_MM_INIT DRM_IOWR(0x3e, drm_mm_init_arg_t) +#endif + #define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, drm_update_draw_t) /*@}*/ /** * Device specific ioctls should only be in their respective headers - * The device specific ioctl range is from 0x40 to 0x79. + * The device specific ioctl range is from 0x40 to 0x99. + * Generic IOCTLS restart at 0xA0. * * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and * drmCommandReadWrite(). */ #define DRM_COMMAND_BASE 0x40 +#define DRM_COMMAND_END 0xA0 #endif diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index be235c17..60e3e945 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -196,9 +196,10 @@ static int i915_initialize(drm_device_t * dev, I915_WRITE(0x02080, dev_priv->dma_status_page); DRM_DEBUG("Enabled hardware status page\n"); - dev->dev_private = (void *)dev_priv; - +#ifdef I915_HAVE_BUFFER + drm_bo_driver_init(dev); +#endif return 0; } @@ -435,17 +436,39 @@ static void i915_emit_breadcrumb(drm_device_t *dev) dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter; - if (dev_priv->counter > 0x7FFFFFFFUL) - dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1; - BEGIN_LP_RING(4); OUT_RING(CMD_STORE_DWORD_IDX); OUT_RING(20); OUT_RING(dev_priv->counter); OUT_RING(0); ADVANCE_LP_RING(); +#ifdef I915_HAVE_FENCE + drm_fence_flush_old(dev, dev_priv->counter); +#endif } + +int i915_emit_mi_flush(drm_device_t *dev, uint32_t flush) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + uint32_t flush_cmd = CMD_MI_FLUSH; + RING_LOCALS; + + flush_cmd |= flush; + + i915_kernel_lost_context(dev); + + BEGIN_LP_RING(4); + OUT_RING(flush_cmd); + OUT_RING(0); + OUT_RING(0); + OUT_RING(0); + ADVANCE_LP_RING(); + + return 0; +} + + static int i915_dispatch_cmdbuffer(drm_device_t * dev, drm_i915_cmdbuffer_t * cmd) { @@ -566,7 +589,9 @@ static int i915_dispatch_flip(drm_device_t * dev) OUT_RING(dev_priv->counter); OUT_RING(0); ADVANCE_LP_RING(); - +#ifdef I915_HAVE_FENCE + drm_fence_flush_old(dev, dev_priv->counter); +#endif dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; return 0; } @@ -680,6 +705,7 @@ static int i915_flip_bufs(DRM_IOCTL_ARGS) return i915_dispatch_flip(dev); } + static int i915_getparam(DRM_IOCTL_ARGS) { DRM_DEVICE; diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 358b11e2..9eec109e 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -115,6 +115,16 @@ typedef struct _drm_i915_sarea { int pipeB_h; } drm_i915_sarea_t; +/* Driver specific fence types and classes. + */ + +/* The only fence class we support */ +#define DRM_I915_FENCE_CLASS_ACCEL 0 +/* Fence type that guarantees read-write flush */ +#define DRM_I915_FENCE_TYPE_RW 2 +/* MI_FLUSH programmed just before the fence */ +#define DRM_I915_FENCE_FLAG_FLUSHED 0x01000000 + /* Flags for perf_boxes */ #define I915_BOX_RING_EMPTY 0x1 diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index de7f8224..85804ce7 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -35,9 +35,9 @@ #define DRIVER_AUTHOR "Tungsten Graphics, Inc." -#define DRIVER_NAME "i915" +#define DRIVER_NAME "i915-mm" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20060119" +#define DRIVER_DATE "20060929" /* Interface history: * @@ -50,9 +50,14 @@ * - Support vertical blank on secondary display pipe */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 6 +#define DRIVER_MINOR 7 #define DRIVER_PATCHLEVEL 0 +#if defined(__linux__) +#define I915_HAVE_FENCE +#define I915_HAVE_BUFFER +#endif + typedef struct _drm_i915_ring_buffer { int tail_mask; unsigned long Start; @@ -90,7 +95,7 @@ typedef struct drm_i915_private { drm_dma_handle_t *status_page_dmah; void *hw_status_page; dma_addr_t dma_status_page; - unsigned long counter; + uint32_t counter; unsigned int cpp; int back_offset; @@ -108,6 +113,18 @@ typedef struct drm_i915_private { struct mem_block *agp_heap; unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; int vblank_pipe; + spinlock_t user_irq_lock; + int user_irq_refcount; + int fence_irq_on; + uint32_t irq_enable_reg; + int irq_enabled; + +#ifdef I915_HAVE_FENCE + uint32_t flush_sequence; + uint32_t flush_flags; + uint32_t flush_pending; + uint32_t saved_flush_status; +#endif spinlock_t swaps_lock; drm_i915_vbl_swap_t vbl_swaps; @@ -125,6 +142,8 @@ extern void i915_driver_preclose(drm_device_t * dev, DRMFILE filp); extern int i915_driver_device_is_agp(drm_device_t * dev); extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +extern int i915_emit_mi_flush(drm_device_t *dev, uint32_t flush); + /* i915_irq.c */ extern int i915_irq_emit(DRM_IOCTL_ARGS); @@ -138,6 +157,9 @@ extern void i915_driver_irq_postinstall(drm_device_t * dev); extern void i915_driver_irq_uninstall(drm_device_t * dev); extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS); extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS); +extern int i915_emit_irq(drm_device_t * dev); +extern void i915_user_irq_on(drm_i915_private_t *dev_priv); +extern void i915_user_irq_off(drm_i915_private_t *dev_priv); extern int i915_vblank_swap(DRM_IOCTL_ARGS); /* i915_mem.c */ @@ -148,6 +170,23 @@ extern int i915_mem_destroy_heap(DRM_IOCTL_ARGS); extern void i915_mem_takedown(struct mem_block **heap); extern void i915_mem_release(drm_device_t * dev, DRMFILE filp, struct mem_block *heap); +#ifdef I915_HAVE_FENCE +/* i915_fence.c */ + + +extern void i915_fence_handler(drm_device_t *dev); +extern int i915_fence_emit_sequence(drm_device_t *dev, uint32_t flags, + uint32_t *sequence, + uint32_t *native_type); +extern void i915_poke_flush(drm_device_t *dev); +#endif + +#ifdef I915_HAVE_BUFFER +/* i915_buffer.c */ +extern drm_ttm_backend_t *i915_create_ttm_backend_entry(drm_device_t *dev); +extern int i915_fence_types(uint32_t buffer_flags, uint32_t *class, uint32_t *type); +extern int i915_invalidate_caches(drm_device_t *dev, uint32_t buffer_flags); +#endif #define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg)) #define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val)) @@ -198,6 +237,11 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller); #define INST_OP_FLUSH 0x02000000 #define INST_FLUSH_MAP_CACHE 0x00000001 +#define CMD_MI_FLUSH (0x04 << 23) +#define MI_NO_WRITE_FLUSH (1 << 2) +#define MI_READ_FLUSH (1 << 0) +#define MI_EXE_FLUSH (1 << 1) + #define BB1_START_ADDR_MASK (~0x7) #define BB1_PROTECTED (1<<0) #define BB1_UNPROTECTED (0<<0) @@ -207,6 +251,7 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller); #define I915REG_INT_IDENTITY_R 0x020a4 #define I915REG_INT_MASK_R 0x020a8 #define I915REG_INT_ENABLE_R 0x020a0 +#define I915REG_INSTPM 0x020c0 #define SRX_INDEX 0x3c4 #define SRX_DATA 0x3c5 @@ -292,6 +337,6 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller); #define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1) -#define READ_BREADCRUMB(dev_priv) (((u32*)(dev_priv->hw_status_page))[5]) - +#define READ_BREADCRUMB(dev_priv) (((volatile u32*)(dev_priv->hw_status_page))[5]) +#define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->hw_status_page))[reg]) #endif diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index feb7acc7..a48e1ff8 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -138,10 +138,11 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) temp = I915_READ16(I915REG_INT_IDENTITY_R); - temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG); + temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG); +#if 0 DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); - +#endif if (temp == 0) return IRQ_NONE; @@ -149,8 +150,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); - if (temp & USER_INT_FLAG) + if (temp & USER_INT_FLAG) { DRM_WAKEUP(&dev_priv->irq_queue); +#ifdef I915_HAVE_FENCE + i915_fence_handler(dev); +#endif + } if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { int vblank_pipe = dev_priv->vblank_pipe; @@ -178,7 +183,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) return IRQ_HANDLED; } -static int i915_emit_irq(drm_device_t * dev) +int i915_emit_irq(drm_device_t * dev) { drm_i915_private_t *dev_priv = dev->dev_private; @@ -208,6 +213,28 @@ static int i915_emit_irq(drm_device_t * dev) } +void i915_user_irq_on(drm_i915_private_t *dev_priv) +{ + spin_lock(&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); + } + spin_unlock(&dev_priv->user_irq_lock); + +} + +void i915_user_irq_off(drm_i915_private_t *dev_priv) +{ + spin_lock(&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); + } + spin_unlock(&dev_priv->user_irq_lock); +} + + static int i915_wait_irq(drm_device_t * dev, int irq_nr) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -220,9 +247,11 @@ static int i915_wait_irq(drm_device_t * dev, int irq_nr) return 0; dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; - + + i915_user_irq_on(dev_priv); DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ, READ_BREADCRUMB(dev_priv) >= irq_nr); + i915_user_irq_off(dev_priv); if (ret == DRM_ERR(EBUSY)) { DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n", @@ -316,15 +345,15 @@ int i915_irq_wait(DRM_IOCTL_ARGS) static void i915_enable_interrupt (drm_device_t *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u16 flag; - flag = 0; + dev_priv->irq_enable_reg = USER_INT_FLAG; if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A) - flag |= VSYNC_PIPEA_FLAG; + dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG; if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B) - flag |= VSYNC_PIPEB_FLAG; + dev_priv->irq_enable_reg |= VSYNC_PIPEB_FLAG; - I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag); + I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + dev_priv->irq_enabled = 1; } /* Set the vblank monitor pipe @@ -497,7 +526,7 @@ void i915_driver_irq_preinstall(drm_device_t * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - I915_WRITE16(I915REG_HWSTAM, 0xfffe); + I915_WRITE16(I915REG_HWSTAM, 0xeffe); I915_WRITE16(I915REG_INT_MASK_R, 0x0); I915_WRITE16(I915REG_INT_ENABLE_R, 0x0); } @@ -512,8 +541,24 @@ void i915_driver_irq_postinstall(drm_device_t * dev) if (!dev_priv->vblank_pipe) dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A; + + dev_priv->swaps_lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&dev_priv->vbl_swaps.head); + dev_priv->swaps_pending = 0; + + dev_priv->user_irq_lock = SPIN_LOCK_UNLOCKED; + dev_priv->user_irq_refcount = 0; + + if (!dev_priv->vblank_pipe) + dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A; i915_enable_interrupt(dev); DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); + + /* + * Initialize the hardware status page IRQ location. + */ + + I915_WRITE(I915REG_INSTPM, ( 1 << 5) | ( 1 << 21)); } void i915_driver_irq_uninstall(drm_device_t * dev) @@ -523,6 +568,7 @@ void i915_driver_irq_uninstall(drm_device_t * dev) if (!dev_priv) return; + dev_priv->irq_enabled = 0; I915_WRITE16(I915REG_HWSTAM, 0xffff); I915_WRITE16(I915REG_INT_MASK_R, 0xffff); I915_WRITE16(I915REG_INT_ENABLE_R, 0x0); |