diff options
Diffstat (limited to 'shared-core')
-rw-r--r-- | shared-core/drm.h | 108 | ||||
-rw-r--r-- | shared-core/i915_dma.c | 167 | ||||
-rw-r--r-- | shared-core/i915_drm.h | 10 | ||||
-rw-r--r-- | shared-core/i915_drv.h | 153 | ||||
-rw-r--r-- | shared-core/i915_init.c | 329 | ||||
-rw-r--r-- | shared-core/i915_irq.c | 91 | ||||
-rw-r--r-- | shared-core/i915_mem.c | 22 | ||||
-rw-r--r-- | shared-core/radeon_cp.c | 25 | ||||
-rw-r--r-- | shared-core/radeon_drm.h | 9 | ||||
-rw-r--r-- | shared-core/radeon_drv.h | 51 | ||||
-rw-r--r-- | shared-core/radeon_irq.c | 20 |
11 files changed, 769 insertions, 216 deletions
diff --git a/shared-core/drm.h b/shared-core/drm.h index 39414902..e10ceb14 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -249,7 +249,8 @@ enum drm_map_flags { _DRM_KERNEL = 0x08, /**< kernel requires access */ _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */ _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */ - _DRM_REMOVABLE = 0x40 /**< Removable mapping */ + _DRM_REMOVABLE = 0x40, /**< Removable mapping */ + _DRM_DRIVER = 0x80 /**< Driver will take care of it */ }; struct drm_ctx_priv_map { @@ -890,6 +891,99 @@ struct drm_mm_init_arg { uint64_t p_size; }; +/* + * Drm mode setting + */ +#define DRM_DISPLAY_INFO_LEN 32 +#define DRM_OUTPUT_NAME_LEN 32 +#define DRM_DISPLAY_MODE_LEN 32 + +struct drm_mode_modeinfo { + + unsigned int id; + + unsigned int clock; + unsigned short hdisplay, hsync_start, hsync_end, htotal, hskew; + unsigned short vdisplay, vsync_start, vsync_end, vtotal, vscan; + + unsigned int vrefresh; /* vertical refresh * 1000 */ + + unsigned int flags; + + char name[DRM_DISPLAY_MODE_LEN]; +}; + +struct drm_mode_card_res { + + int count_fbs; + unsigned int __user *fb_id; + + int count_crtcs; + unsigned int __user *crtc_id; + + int count_outputs; + unsigned int __user *output_id; + + int count_modes; + struct drm_mode_modeinfo __user *modes; + +}; + +struct drm_mode_crtc { + unsigned int crtc_id; /**< Id */ + unsigned int fb_id; /**< Id of framebuffer */ + + int x, y; /**< Position on the frameuffer */ + + unsigned int mode; /**< Current mode used */ + + int count_outputs; + unsigned int outputs; /**< Outputs that are connected */ + + int count_possibles; + unsigned int possibles; /**< Outputs that can be connected */ + + unsigned int __user *set_outputs; /**< Outputs to be connected */ + + int gamma_size; + +}; + +struct drm_mode_get_output { + + unsigned int output; /**< Id */ + unsigned int crtc; /**< Id of crtc */ + unsigned char name[DRM_OUTPUT_NAME_LEN]; + + unsigned int connection; + unsigned int mm_width, mm_height; /**< HxW in millimeters */ + unsigned int subpixel; + + int count_crtcs; + unsigned int crtcs; /**< possible crtc to connect to */ + + int count_clones; + unsigned int clones; /**< list of clones */ + + int count_modes; + unsigned int __user *modes; /**< list of modes it supports */ + +}; + +struct drm_mode_fb_cmd { + unsigned int buffer_id; + unsigned int width, height; + unsigned int pitch; + unsigned int bpp; + unsigned int handle; + unsigned int depth; +}; + +struct drm_mode_mode_cmd { + unsigned int output_id; + unsigned int mode_id; +}; + /** * \name Ioctls Definitions */ @@ -982,6 +1076,18 @@ struct drm_mm_init_arg { #define DRM_IOCTL_BO_VERSION DRM_IOR(0xd6, struct drm_bo_version_arg) +#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res) +#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc) +#define DRM_IOCTL_MODE_GETOUTPUT DRM_IOWR(0xA2, struct drm_mode_get_output) +#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA3, struct drm_mode_crtc) +#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xA4, struct drm_mode_fb_cmd) +#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xA5, unsigned int) +#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xA6, struct drm_mode_fb_cmd) + +#define DRM_IOCTL_MODE_ADDMODE DRM_IOWR(0xA7, struct drm_mode_modeinfo) +#define DRM_IOCTL_MODE_RMMODE DRM_IOWR(0xA8, unsigned int) +#define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd) +#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xAA, struct drm_mode_mode_cmd) /*@}*/ /** diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 541b4ccb..47befeb5 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -38,8 +38,8 @@ */ int i915_wait_ring(struct drm_device * dev, int n, const char *caller) { - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_ring_buffer_t *ring = &(dev_priv->ring); + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_ring_buffer *ring = &(dev_priv->ring); u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR; int i; @@ -65,8 +65,8 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller) void i915_kernel_lost_context(struct drm_device * dev) { - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_ring_buffer_t *ring = &(dev_priv->ring); + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_ring_buffer *ring = &(dev_priv->ring); ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR; ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR; @@ -78,9 +78,8 @@ void i915_kernel_lost_context(struct drm_device * dev) dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY; } -static int i915_dma_cleanup(struct drm_device * dev) +int i915_dma_cleanup(struct drm_device * dev) { - drm_i915_private_t *dev_priv = dev->dev_private; /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. @@ -88,32 +87,12 @@ static int i915_dma_cleanup(struct drm_device * dev) if (dev->irq) drm_irq_uninstall(dev); - if (dev_priv->ring.virtual_start) { - drm_core_ioremapfree(&dev_priv->ring.map, dev); - dev_priv->ring.virtual_start = 0; - dev_priv->ring.map.handle = 0; - dev_priv->ring.map.size = 0; - } - - if (dev_priv->status_page_dmah) { - drm_pci_free(dev, dev_priv->status_page_dmah); - dev_priv->status_page_dmah = NULL; - /* Need to rewrite hardware status page */ - I915_WRITE(0x02080, 0x1ffff000); - } - - if (dev_priv->status_gfx_addr) { - dev_priv->status_gfx_addr = 0; - drm_core_ioremapfree(&dev_priv->hws_map, dev); - I915_WRITE(0x02080, 0x1ffff000); - } - return 0; } static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) { - drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; dev_priv->sarea = drm_getsarea(dev); if (!dev_priv->sarea) { @@ -198,7 +177,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) static int i915_dma_resume(struct drm_device * dev) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; DRM_DEBUG("%s\n", __FUNCTION__); @@ -237,7 +216,7 @@ static int i915_dma_resume(struct drm_device * dev) static int i915_dma_init(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_init_t *init = data; + struct drm_i915_init *init = data; int retcode = 0; switch (init->func) { @@ -337,7 +316,7 @@ static int validate_cmd(int cmd) static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwords) { - drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; int i; RING_LOCALS; @@ -378,7 +357,7 @@ static int i915_emit_box(struct drm_device * dev, struct drm_clip_rect __user * boxes, int i, int DR1, int DR4) { - drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; struct drm_clip_rect box; RING_LOCALS; @@ -419,7 +398,7 @@ static int i915_emit_box(struct drm_device * dev, void i915_emit_breadcrumb(struct drm_device *dev) { - drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; RING_LOCALS; if (++dev_priv->counter > BREADCRUMB_MASK) { @@ -440,7 +419,7 @@ void i915_emit_breadcrumb(struct drm_device *dev) int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush) { - drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; uint32_t flush_cmd = CMD_MI_FLUSH; RING_LOCALS; @@ -460,10 +439,10 @@ int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush) static int i915_dispatch_cmdbuffer(struct drm_device * dev, - drm_i915_cmdbuffer_t * cmd) + struct drm_i915_cmdbuffer * cmd) { #ifdef I915_HAVE_FENCE - drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; #endif int nbox = cmd->num_cliprects; int i = 0, count, ret; @@ -500,7 +479,7 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev, static int i915_dispatch_batchbuffer(struct drm_device * dev, drm_i915_batchbuffer_t * batch) { - drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; struct drm_clip_rect __user *boxes = batch->cliprects; int nbox = batch->num_cliprects; int i = 0, count; @@ -553,7 +532,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync) { - drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; u32 num_pages, current_page, next_page, dspbase; int shift = 2 * plane, x, y; RING_LOCALS; @@ -605,7 +584,7 @@ static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync) void i915_dispatch_flip(struct drm_device * dev, int planes, int sync) { - drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; int i; DRM_DEBUG("%s: planes=0x%x pfCurrentPage=%d\n", @@ -627,7 +606,7 @@ void i915_dispatch_flip(struct drm_device * dev, int planes, int sync) static int i915_quiescent(struct drm_device * dev) { - drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; i915_kernel_lost_context(dev); return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__); @@ -645,7 +624,7 @@ static int i915_flush_ioctl(struct drm_device *dev, void *data, static int i915_batchbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) dev_priv->sarea_priv; drm_i915_batchbuffer_t *batch = data; @@ -675,10 +654,10 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, static int i915_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; + struct drm_i915_sarea *sarea_priv = (struct drm_i915_sarea *) dev_priv->sarea_priv; - drm_i915_cmdbuffer_t *cmdbuf = data; + struct drm_i915_cmdbuffer *cmdbuf = data; int ret; DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n", @@ -985,11 +964,11 @@ out_err: static int i915_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) dev_priv->sarea_priv; struct drm_i915_execbuffer *exec_buf = data; - struct _drm_i915_batchbuffer *batch = &exec_buf->batch; + struct drm_i915_batchbuffer *batch = &exec_buf->batch; struct drm_fence_arg *fence_arg = &exec_buf->fence_arg; int num_buffers; int ret; @@ -1088,14 +1067,14 @@ out_free: } #endif -static int i915_do_cleanup_pageflip(struct drm_device * dev) +int i915_do_cleanup_pageflip(struct drm_device * dev) { - drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; int i, planes, num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2; DRM_DEBUG("%s\n", __FUNCTION__); - for (i = 0, planes = 0; i < 2; i++) + for (i = 0, planes = 0; i < 2; i++) { if (dev_priv->sarea_priv->pf_current_page & (0x3 << (2 * i))) { dev_priv->sarea_priv->pf_current_page = (dev_priv->sarea_priv->pf_current_page & @@ -1103,6 +1082,7 @@ static int i915_do_cleanup_pageflip(struct drm_device * dev) planes |= 1 << i; } + } if (planes) i915_dispatch_flip(dev, planes, 0); @@ -1112,7 +1092,7 @@ static int i915_do_cleanup_pageflip(struct drm_device * dev) static int i915_flip_bufs(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_flip_t *param = data; + struct drm_i915_flip *param = data; DRM_DEBUG("%s\n", __FUNCTION__); @@ -1134,8 +1114,8 @@ static int i915_flip_bufs(struct drm_device *dev, void *data, struct drm_file *f static int i915_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_getparam_t *param = data; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_getparam *param = data; int value; if (!dev_priv) { @@ -1169,7 +1149,7 @@ static int i915_getparam(struct drm_device *dev, void *data, static int i915_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; drm_i915_setparam_t *param = data; if (!dev_priv) { @@ -1209,8 +1189,8 @@ static int i915_mmio(struct drm_device *dev, void *data, struct drm_file *file_priv) { uint32_t buf[8]; - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_mmio_entry_t *e; + struct drm_i915_private *dev_priv = dev->dev_private; + drm_i915_mmio_entry_t *e; drm_i915_mmio_t *mmio = data; void __iomem *base; int i; @@ -1255,7 +1235,7 @@ static int i915_mmio(struct drm_device *dev, void *data, static int i915_set_status_page(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; drm_i915_hws_addr_t *hws = data; if (!dev_priv) { @@ -1283,80 +1263,13 @@ static int i915_set_status_page(struct drm_device *dev, void *data, dev_priv->hw_status_page = dev_priv->hws_map.handle; memset(dev_priv->hw_status_page, 0, PAGE_SIZE); - I915_WRITE(0x02080, dev_priv->status_gfx_addr); + I915_WRITE(I915REG_HWS_PGA, dev_priv->status_gfx_addr); DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n", dev_priv->status_gfx_addr); DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page); return 0; } -int i915_driver_load(struct drm_device *dev, unsigned long flags) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - unsigned long base, size; - int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1; - - /* i915 has 4 more counters */ - dev->counters += 4; - dev->types[6] = _DRM_STAT_IRQ; - dev->types[7] = _DRM_STAT_PRIMARY; - dev->types[8] = _DRM_STAT_SECONDARY; - dev->types[9] = _DRM_STAT_DMA; - - dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER); - if (dev_priv == NULL) - return -ENOMEM; - - memset(dev_priv, 0, sizeof(drm_i915_private_t)); - - dev->dev_private = (void *)dev_priv; - - /* Add register map (needed for suspend/resume) */ - base = drm_get_resource_start(dev, mmio_bar); - size = drm_get_resource_len(dev, mmio_bar); - - ret = drm_addmap(dev, base, size, _DRM_REGISTERS, _DRM_KERNEL, - &dev_priv->mmio_map); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) - intel_init_chipset_flush_compat(dev); -#endif - return ret; -} - -int i915_driver_unload(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (dev_priv->mmio_map) - drm_rmmap(dev, dev_priv->mmio_map); - - drm_free(dev->dev_private, sizeof(drm_i915_private_t), - DRM_MEM_DRIVER); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) - intel_fini_chipset_flush_compat(dev); -#endif - return 0; -} - -void i915_driver_lastclose(struct drm_device * dev) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - - if (drm_getsarea(dev) && dev_priv->sarea_priv) - i915_do_cleanup_pageflip(dev); - if (dev_priv->agp_heap) - i915_mem_takedown(&(dev_priv->agp_heap)); - - i915_dma_cleanup(dev); -} - -void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - i915_mem_release(dev, file_priv, dev_priv->agp_heap); -} - struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH), @@ -1399,11 +1312,3 @@ int i915_driver_device_is_agp(struct drm_device * dev) return 1; } -int i915_driver_firstopen(struct drm_device *dev) -{ -#ifdef I915_HAVE_BUFFER - if (!IS_I9XX(dev)) - drm_bo_driver_init(dev); -#endif - return 0; -} diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 56977ff3..3a1dcad6 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -39,7 +39,7 @@ * of chars for next/prev indices */ #define I915_LOG_MIN_TEX_REGION_SIZE 14 -typedef struct _drm_i915_init { +typedef struct drm_i915_init { enum { I915_INIT_DMA = 0x01, I915_CLEANUP_DMA = 0x02, @@ -63,7 +63,7 @@ typedef struct _drm_i915_init { unsigned int chipset; } drm_i915_init_t; -typedef struct _drm_i915_sarea { +typedef struct drm_i915_sarea { struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1]; int last_upload; /* last time texture was uploaded */ int last_enqueue; /* last time a buffer was enqueued */ @@ -195,7 +195,7 @@ typedef struct drm_i915_flip { /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. */ -typedef struct _drm_i915_batchbuffer { +typedef struct drm_i915_batchbuffer { int start; /* agp offset */ int used; /* nr bytes in use */ int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ @@ -207,7 +207,7 @@ typedef struct _drm_i915_batchbuffer { /* As above, but pass a pointer to userspace buffer which can be * validated by the kernel prior to sending to hardware. */ -typedef struct _drm_i915_cmdbuffer { +typedef struct drm_i915_cmdbuffer { char __user *buf; /* pointer to userspace command buffer */ int sz; /* nr bytes in buf */ int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ @@ -358,7 +358,7 @@ struct drm_i915_op_arg { struct drm_i915_execbuffer { uint64_t ops_list; uint32_t num_buffers; - struct _drm_i915_batchbuffer batch; + struct drm_i915_batchbuffer batch; struct drm_fence_arg fence_arg; }; diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index c66b0651..19b5ab26 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -70,7 +70,7 @@ #define I915_MAX_VALIDATE_BUFFERS 4096 #endif -typedef struct _drm_i915_ring_buffer { +struct drm_i915_ring_buffer { int tail_mask; unsigned long Start; unsigned long End; @@ -80,7 +80,7 @@ typedef struct _drm_i915_ring_buffer { int tail; int space; drm_local_map_t map; -} drm_i915_ring_buffer_t; +}; struct mem_block { struct mem_block *next; @@ -90,22 +90,26 @@ struct mem_block { struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */ }; -typedef struct _drm_i915_vbl_swap { +struct drm_i915_vbl_swap { struct list_head head; drm_drawable_t drw_id; unsigned int plane; unsigned int sequence; int flip; -} drm_i915_vbl_swap_t; +}; -typedef struct drm_i915_private { +struct drm_i915_private { + struct drm_buffer_object *ring_buffer; drm_local_map_t *sarea; drm_local_map_t *mmio_map; - drm_i915_sarea_t *sarea_priv; - drm_i915_ring_buffer_t ring; + unsigned long mmiobase; + unsigned long mmiolen; + + struct drm_i915_sarea *sarea_priv; + struct drm_i915_ring_buffer ring; - drm_dma_handle_t *status_page_dmah; + struct drm_dma_handle *status_page_dmah; void *hw_status_page; dma_addr_t dma_status_page; uint32_t counter; @@ -143,10 +147,15 @@ typedef struct drm_i915_private { #endif DRM_SPINTYPE swaps_lock; - drm_i915_vbl_swap_t vbl_swaps; + struct drm_i915_vbl_swap vbl_swaps; unsigned int swaps_pending; - /* Register state */ + /* LVDS info */ + int backlight_duty_cycle; /* restore backlight to this value */ + bool panel_wants_dither; + struct drm_display_mode *panel_fixed_mode; + + /* Register state */ u8 saveLBB; u32 saveDSPACNTR; u32 saveDSPBCNTR; @@ -224,7 +233,7 @@ typedef struct drm_i915_private { u8 saveDACMASK; u8 saveDACDATA[256*3]; /* 256 3-byte colors */ u8 saveCR[36]; -} drm_i915_private_t; +}; enum intel_chip_family { CHIP_I8XX = 0x01, @@ -239,7 +248,7 @@ extern int i915_max_ioctl; /* i915_dma.c */ extern void i915_kernel_lost_context(struct drm_device * dev); extern int i915_driver_load(struct drm_device *, unsigned long flags); -extern int i915_driver_unload(struct drm_device *); +extern int i915_driver_unload(struct drm_device *dev); extern void i915_driver_lastclose(struct drm_device * dev); extern void i915_driver_preclose(struct drm_device *dev, struct drm_file *file_priv); @@ -250,6 +259,8 @@ 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_do_cleanup_pageflip(struct drm_device *dev); +extern int i915_dma_cleanup(struct drm_device *dev); /* i915_irq.c */ extern int i915_irq_emit(struct drm_device *dev, void *data, @@ -257,6 +268,7 @@ extern int i915_irq_emit(struct drm_device *dev, void *data, extern int i915_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern void i915_driver_wait_next_vblank(struct drm_device *dev, int pipe); extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence); extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence); extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); @@ -267,9 +279,10 @@ extern int i915_vblank_pipe_set(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int i915_vblank_pipe_get(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int i915_emit_irq(struct drm_device *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_emit_irq(struct drm_device * dev); +extern void i915_user_irq_on(struct drm_i915_private *dev_priv); +extern void i915_user_irq_off(struct drm_i915_private *dev_priv); +extern void i915_enable_interrupt (struct drm_device *dev); extern int i915_vblank_swap(struct drm_device *dev, void *data, struct drm_file *file_priv); @@ -318,6 +331,12 @@ extern void intel_init_chipset_flush_compat(struct drm_device *dev); extern void intel_fini_chipset_flush_compat(struct drm_device *dev); #endif + +/* modesetting */ +extern void intel_modeset_init(struct drm_device *dev); +extern void intel_modeset_cleanup(struct drm_device *dev); + + #define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg)) #define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val)) #define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, (reg)) @@ -355,8 +374,31 @@ extern void intel_fini_chipset_flush_compat(struct drm_device *dev); I915_WRITE(LP_RING + RING_TAIL, outring); \ } while(0) +#define MI_NOOP (0x00 << 23) + extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); +/* + * The Bridge device's PCI config space has information about the + * fb aperture size and the amount of pre-reserved memory. + */ +#define INTEL_GMCH_CTRL 0x52 +#define INTEL_GMCH_ENABLED 0x4 +#define INTEL_GMCH_MEM_MASK 0x1 +#define INTEL_GMCH_MEM_64M 0x1 +#define INTEL_GMCH_MEM_128M 0 + +#define INTEL_855_GMCH_GMS_MASK (0x7 << 4) +#define INTEL_855_GMCH_GMS_DISABLED (0x0 << 4) +#define INTEL_855_GMCH_GMS_STOLEN_1M (0x1 << 4) +#define INTEL_855_GMCH_GMS_STOLEN_4M (0x2 << 4) +#define INTEL_855_GMCH_GMS_STOLEN_8M (0x3 << 4) +#define INTEL_855_GMCH_GMS_STOLEN_16M (0x4 << 4) +#define INTEL_855_GMCH_GMS_STOLEN_32M (0x5 << 4) + +#define INTEL_915G_GMCH_GMS_STOLEN_48M (0x6 << 4) +#define INTEL_915G_GMCH_GMS_STOLEN_64M (0x7 << 4) + /* Extended config space */ #define LBB 0xf4 @@ -423,6 +465,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define BB1_UNPROTECTED (0<<0) #define BB2_END_ADDR_MASK (~0x7) +#define I915REG_HWS_PGA 0x02080 + /* Framebuffer compression */ #define FBC_CFB_BASE 0x03200 /* 4k page aligned */ #define FBC_LL_BASE 0x03204 /* 4k page aligned */ @@ -473,6 +517,63 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17) #define I915_VBLANK_CLEAR (1UL<<1) +#define GPIOA 0x5010 +#define GPIOB 0x5014 +#define GPIOC 0x5018 +#define GPIOD 0x501c +#define GPIOE 0x5020 +#define GPIOF 0x5024 +#define GPIOG 0x5028 +#define GPIOH 0x502c +# define GPIO_CLOCK_DIR_MASK (1 << 0) +# define GPIO_CLOCK_DIR_IN (0 << 1) +# define GPIO_CLOCK_DIR_OUT (1 << 1) +# define GPIO_CLOCK_VAL_MASK (1 << 2) +# define GPIO_CLOCK_VAL_OUT (1 << 3) +# define GPIO_CLOCK_VAL_IN (1 << 4) +# define GPIO_CLOCK_PULLUP_DISABLE (1 << 5) +# define GPIO_DATA_DIR_MASK (1 << 8) +# define GPIO_DATA_DIR_IN (0 << 9) +# define GPIO_DATA_DIR_OUT (1 << 9) +# define GPIO_DATA_VAL_MASK (1 << 10) +# define GPIO_DATA_VAL_OUT (1 << 11) +# define GPIO_DATA_VAL_IN (1 << 12) +# define GPIO_DATA_PULLUP_DISABLE (1 << 13) + +/* p317, 319 + */ +#define VCLK2_VCO_M 0x6008 /* treat as 16 bit? (includes msbs) */ +#define VCLK2_VCO_N 0x600a +#define VCLK2_VCO_DIV_SEL 0x6012 + +#define VCLK_DIVISOR_VGA0 0x6000 +#define VCLK_DIVISOR_VGA1 0x6004 +#define VCLK_POST_DIV 0x6010 +/** Selects a post divisor of 4 instead of 2. */ +# define VGA1_PD_P2_DIV_4 (1 << 15) +/** Overrides the p2 post divisor field */ +# define VGA1_PD_P1_DIV_2 (1 << 13) +# define VGA1_PD_P1_SHIFT 8 +/** P1 value is 2 greater than this field */ +# define VGA1_PD_P1_MASK (0x1f << 8) +/** Selects a post divisor of 4 instead of 2. */ +# define VGA0_PD_P2_DIV_4 (1 << 7) +/** Overrides the p2 post divisor field */ +# define VGA0_PD_P1_DIV_2 (1 << 5) +# define VGA0_PD_P1_SHIFT 0 +/** P1 value is 2 greater than this field */ +# define VGA0_PD_P1_MASK (0x1f << 0) + +#define POST_DIV_SELECT 0x70 +#define POST_DIV_1 0x00 +#define POST_DIV_2 0x10 +#define POST_DIV_4 0x20 +#define POST_DIV_8 0x30 +#define POST_DIV_16 0x40 +#define POST_DIV_32 0x50 +#define VCO_LOOP_DIV_BY_4M 0x00 +#define VCO_LOOP_DIV_BY_16M 0x04 + #define SRX_INDEX 0x3c4 #define SRX_DATA 0x3c5 #define SR01 1 @@ -481,6 +582,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define PPCR 0x61204 #define PPCR_ON (1<<0) +#define DVOA 0x61120 +#define DVOA_ON (1<<31) #define DVOB 0x61140 #define DVOB_ON (1<<31) #define DVOC 0x61160 @@ -637,8 +740,14 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define SRC_COPY_BLT_CMD ((2<<29)|(0x43<<22)|4) #define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6) +#define XY_MONO_SRC_COPY_IMM_BLT ((2<<29)|(0x71<<22)|5) #define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21) #define XY_SRC_COPY_BLT_WRITE_RGB (1<<20) +#define BLT_DEPTH_8 (0<<24) +#define BLT_DEPTH_16_565 (1<<24) +#define BLT_DEPTH_16_1555 (2<<24) +#define BLT_DEPTH_32 (3<<24) +#define BLT_ROP_GXCOPY (0xcc<<16) #define MI_BATCH_BUFFER ((0x30<<23)|1) #define MI_BATCH_BUFFER_START (0x31<<23) @@ -680,6 +789,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define BACKLIGHT_MODULATION_FREQ_SHIFT (17) #define BLC_PWM_CTL2 0x61250 + /** * This is the most significant 15 bits of the number of backlight cycles in a * complete cycle of the modulated backlight control. @@ -1119,13 +1229,17 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); */ #define SWF0 0x71410 +#define SWF1 0x71414 +#define SWF2 0x71418 +#define SWF3 0x7141c +#define SWF4 0x71420 +#define SWF5 0x71424 +#define SWF6 0x71428 -/* - * 855 scratch registers. - */ #define SWF10 0x70410 - #define SWF30 0x72414 +#define SWF31 0x72418 +#define SWF32 0x7241c /* * Overlay registers. These are overlay registers accessed via MMIO. @@ -1142,6 +1256,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define OGAMC2 0x3001c #define OGAMC1 0x30020 #define OGAMC0 0x30024 + /* * Palette registers */ diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c new file mode 100644 index 00000000..3b43c722 --- /dev/null +++ b/shared-core/i915_init.c @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2007 Intel Corporation + * Jesse Barnes <jesse.barnes@intel.com> + * + * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org> + * 2004 Sylvain Meyer + * + * GPL/BSD dual license + */ +#include "drmP.h" +#include "drm.h" +#include "drm_sarea.h" +#include "i915_drm.h" +#include "i915_drv.h" + +/** + * i915_probe_agp - get AGP bootup configuration + * @pdev: PCI device + * @aperture_size: returns AGP aperture configured size + * @preallocated_size: returns size of BIOS preallocated AGP space + * + * Since Intel integrated graphics are UMA, the BIOS has to set aside + * some RAM for the framebuffer at early boot. This code figures out + * how much was set aside so we can use it for our own purposes. + */ +int i915_probe_agp(struct pci_dev *pdev, unsigned long *aperture_size, + unsigned long *preallocated_size) +{ + struct pci_dev *bridge_dev; + u16 tmp = 0; + unsigned long overhead; + + bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0)); + if (!bridge_dev) { + DRM_ERROR("bridge device not found\n"); + return -1; + } + + /* Get the fb aperture size and "stolen" memory amount. */ + pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp); + pci_dev_put(bridge_dev); + + *aperture_size = 1024 * 1024; + *preallocated_size = 1024 * 1024; + + switch (pdev->device) { + case PCI_DEVICE_ID_INTEL_82830_CGC: + case PCI_DEVICE_ID_INTEL_82845G_IG: + case PCI_DEVICE_ID_INTEL_82855GM_IG: + case PCI_DEVICE_ID_INTEL_82865_IG: + if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M) + *aperture_size *= 64; + else + *aperture_size *= 128; + break; + default: + /* 9xx supports large sizes, just look at the length */ + *aperture_size = pci_resource_len(pdev, 2); + break; + } + + /* + * Some of the preallocated space is taken by the GTT + * and popup. GTT is 1K per MB of aperture size, and popup is 4K. + */ + overhead = (*aperture_size / 1024) + 4096; + switch (tmp & INTEL_855_GMCH_GMS_MASK) { + case INTEL_855_GMCH_GMS_STOLEN_1M: + break; /* 1M already */ + case INTEL_855_GMCH_GMS_STOLEN_4M: + *preallocated_size *= 4; + break; + case INTEL_855_GMCH_GMS_STOLEN_8M: + *preallocated_size *= 8; + break; + case INTEL_855_GMCH_GMS_STOLEN_16M: + *preallocated_size *= 16; + break; + case INTEL_855_GMCH_GMS_STOLEN_32M: + *preallocated_size *= 32; + break; + case INTEL_915G_GMCH_GMS_STOLEN_48M: + *preallocated_size *= 48; + break; + case INTEL_915G_GMCH_GMS_STOLEN_64M: + *preallocated_size *= 64; + break; + case INTEL_855_GMCH_GMS_DISABLED: + DRM_ERROR("video memory is disabled\n"); + return -1; + default: + DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n", + tmp & INTEL_855_GMCH_GMS_MASK); + return -1; + } + *preallocated_size -= overhead; + + return 0; +} + +/** + * i915_driver_load - setup chip and create an initial config + * @dev: DRM device + * @flags: startup flags + * + * The driver load routine has to do several things: + * - drive output discovery via intel_modeset_init() + * - initialize the memory manager + * - allocate initial config memory + * - setup the DRM framebuffer with the allocated memory + */ +int i915_driver_load(struct drm_device *dev, unsigned long flags) +{ + struct drm_i915_private *dev_priv; + unsigned long agp_size, prealloc_size; + unsigned long sareapage; + int size, ret; + + dev_priv = drm_alloc(sizeof(struct drm_i915_private), DRM_MEM_DRIVER); + if (dev_priv == NULL) + return -ENOMEM; + + memset(dev_priv, 0, sizeof(struct drm_i915_private)); + dev->dev_private = (void *)dev_priv; +// dev_priv->flags = flags; + + /* i915 has 4 more counters */ + dev->counters += 4; + dev->types[6] = _DRM_STAT_IRQ; + dev->types[7] = _DRM_STAT_PRIMARY; + dev->types[8] = _DRM_STAT_SECONDARY; + dev->types[9] = _DRM_STAT_DMA; + + if (IS_I9XX(dev)) { + dev_priv->mmiobase = drm_get_resource_start(dev, 0); + dev_priv->mmiolen = drm_get_resource_len(dev, 0); + dev->mode_config.fb_base = + drm_get_resource_start(dev, 2) & 0xff000000; + } else if (drm_get_resource_start(dev, 1)) { + dev_priv->mmiobase = drm_get_resource_start(dev, 1); + dev_priv->mmiolen = drm_get_resource_len(dev, 1); + dev->mode_config.fb_base = + drm_get_resource_start(dev, 0) & 0xff000000; + } else { + DRM_ERROR("Unable to find MMIO registers\n"); + return -ENODEV; + } + + DRM_DEBUG("fb_base: 0x%08lx\n", dev->mode_config.fb_base); + + ret = drm_addmap(dev, dev_priv->mmiobase, dev_priv->mmiolen, + _DRM_REGISTERS, _DRM_READ_ONLY|_DRM_DRIVER, &dev_priv->mmio_map); + if (ret != 0) { + DRM_ERROR("Cannot add mapping for MMIO registers\n"); + return ret; + } + + /* prebuild the SAREA */ + sareapage = max(SAREA_MAX, PAGE_SIZE); + ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK|_DRM_DRIVER, + &dev_priv->sarea); + if (ret) { + DRM_ERROR("SAREA setup failed\n"); + return ret; + } + + init_waitqueue_head(&dev->lock.lock_queue); + + /* FIXME: assume sarea_priv is right after SAREA */ + dev_priv->sarea_priv = dev_priv->sarea->handle + sizeof(struct drm_sarea); + + /* + * Initialize the memory manager for local and AGP space + */ + drm_bo_driver_init(dev); + + i915_probe_agp(dev->pdev, &agp_size, &prealloc_size); + printk("setting up %ld bytes of VRAM space\n", prealloc_size); + printk("setting up %ld bytes of TT space\n", (agp_size - prealloc_size)); + drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, 0, prealloc_size >> PAGE_SHIFT); + drm_bo_init_mm(dev, DRM_BO_MEM_TT, prealloc_size >> PAGE_SHIFT, (agp_size - prealloc_size) >> PAGE_SHIFT); + + I915_WRITE(LP_RING + RING_LEN, 0); + I915_WRITE(LP_RING + RING_HEAD, 0); + I915_WRITE(LP_RING + RING_TAIL, 0); + + size = PRIMARY_RINGBUFFER_SIZE; + ret = drm_buffer_object_create(dev, size, drm_bo_type_kernel, + DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | + DRM_BO_FLAG_MEM_VRAM | + DRM_BO_FLAG_NO_EVICT | + DRM_BO_HINT_DONT_FENCE, 0, 0x1, 0, + &dev_priv->ring_buffer); + if (ret < 0) { + DRM_ERROR("Unable to allocate or pin ring buffer\n"); + return -EINVAL; + } + + /* remap the buffer object properly */ + dev_priv->ring.Start = dev_priv->ring_buffer->offset; + dev_priv->ring.End = dev_priv->ring.Start + size; + dev_priv->ring.Size = size; + dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; + + /* FIXME: need wrapper with PCI mem checks */ + ret = drm_mem_reg_ioremap(dev, &dev_priv->ring_buffer->mem, + (void **) &dev_priv->ring.virtual_start); + if (ret) + DRM_ERROR("error mapping ring buffer: %d\n", ret); + + DRM_DEBUG("ring start %08lX, %p, %08lX\n", dev_priv->ring.Start, + dev_priv->ring.virtual_start, dev_priv->ring.Size); + + dev_priv->sarea_priv->pf_current_page = 0; + + memset((void *)(dev_priv->ring.virtual_start), 0, dev_priv->ring.Size); + + I915_WRITE(LP_RING + RING_START, dev_priv->ring.Start); + I915_WRITE(LP_RING + RING_LEN, + ((dev_priv->ring.Size - 4096) & RING_NR_PAGES) | + (RING_NO_REPORT | RING_VALID)); + + /* We are using separate values as placeholders for mechanisms for + * private backbuffer/depthbuffer usage. + */ + dev_priv->use_mi_batchbuffer_start = 0; + + /* Allow hardware batchbuffers unless told otherwise. + */ + dev_priv->allow_batchbuffer = 1; + + /* Program Hardware Status Page */ + if (!IS_G33(dev)) { + dev_priv->status_page_dmah = + drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff); + + if (!dev_priv->status_page_dmah) { + dev->dev_private = (void *)dev_priv; + i915_dma_cleanup(dev); + DRM_ERROR("Can not allocate hardware status page\n"); + return -ENOMEM; + } + dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; + dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; + + memset(dev_priv->hw_status_page, 0, PAGE_SIZE); + + I915_WRITE(I915REG_HWS_PGA, dev_priv->dma_status_page); + } + DRM_DEBUG("Enabled hardware status page\n"); + + intel_modeset_init(dev); + drm_initial_config(dev, false); + + return 0; +} + +int i915_driver_unload(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (dev_priv->ring.virtual_start) { + drm_core_ioremapfree(&dev_priv->ring.map, dev); + } + + if (dev_priv->status_page_dmah) { + drm_pci_free(dev, dev_priv->status_page_dmah); + dev_priv->status_page_dmah = NULL; + dev_priv->hw_status_page = NULL; + dev_priv->dma_status_page = 0; + /* Need to rewrite hardware status page */ + I915_WRITE(I915REG_HWS_PGA, 0x1ffff000); + } + + if (dev_priv->status_gfx_addr) { + dev_priv->status_gfx_addr = 0; + drm_core_ioremapfree(&dev_priv->hws_map, dev); + I915_WRITE(I915REG_HWS_PGA, 0x1ffff000); + } + + I915_WRITE(LP_RING + RING_LEN, 0); + + intel_modeset_cleanup(dev); + + drm_mem_reg_iounmap(dev, &dev_priv->ring_buffer->mem, + dev_priv->ring.virtual_start); + + DRM_DEBUG("usage is %d\n", atomic_read(&dev_priv->ring_buffer->usage)); + mutex_lock(&dev->struct_mutex); + drm_bo_usage_deref_locked(&dev_priv->ring_buffer); + + if (drm_bo_clean_mm(dev, DRM_BO_MEM_TT)) { + DRM_ERROR("Memory manager type 3 not clean. " + "Delaying takedown\n"); + } + if (drm_bo_clean_mm(dev, DRM_BO_MEM_VRAM)) { + DRM_ERROR("Memory manager type 3 not clean. " + "Delaying takedown\n"); + } + mutex_unlock(&dev->struct_mutex); + + drm_bo_driver_finish(dev); + + DRM_DEBUG("%p, %p\n", dev_priv->mmio_map, dev_priv->sarea); + drm_rmmap(dev, dev_priv->mmio_map); + drm_rmmap(dev, dev_priv->sarea); + + drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); + + dev->dev_private = NULL; + return 0; +} + +void i915_driver_lastclose(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + i915_do_cleanup_pageflip(dev); + //i915_mem_takedown(&(dev_priv->agp_heap)); + i915_dma_cleanup(dev); +} + +void i915_driver_preclose(struct drm_device *dev, struct drm_file *filp) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + //i915_mem_release(dev, filp, dev_priv->agp_heap); +} + diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 2c699ecd..bd576078 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -49,7 +49,7 @@ static int i915_get_pipe(struct drm_device *dev, int plane) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; u32 dspcntr; dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR); @@ -66,8 +66,8 @@ static void i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw, int plane) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv; + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; + struct drm_i915_sarea *sarea_priv = dev_priv->sarea_priv; u16 x1, y1, x2, y2; int pf_planes = 1 << plane; @@ -111,13 +111,13 @@ i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw, */ static void i915_vblank_tasklet(struct drm_device *dev) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; struct list_head *list, *tmp, hits, *hit; int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages; unsigned counter[2] = { atomic_read(&dev->vbl_received), atomic_read(&dev->vbl_received2) }; struct drm_drawable_info *drw; - drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv; + struct drm_i915_sarea *sarea_priv = dev_priv->sarea_priv; u32 cpp = dev_priv->cpp, offsets[3]; u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | @@ -142,8 +142,8 @@ static void i915_vblank_tasklet(struct drm_device *dev) /* Find buffer swaps scheduled for this vertical blank */ list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) { - drm_i915_vbl_swap_t *vbl_swap = - list_entry(list, drm_i915_vbl_swap_t, head); + struct drm_i915_vbl_swap *vbl_swap = + list_entry(list, struct drm_i915_vbl_swap, head); int pipe = i915_get_pipe(dev, vbl_swap->plane); if ((counter[pipe] - vbl_swap->sequence) > (1<<23)) @@ -165,8 +165,8 @@ static void i915_vblank_tasklet(struct drm_device *dev) } list_for_each(hit, &hits) { - drm_i915_vbl_swap_t *swap_cmp = - list_entry(hit, drm_i915_vbl_swap_t, head); + struct drm_i915_vbl_swap *swap_cmp = + list_entry(hit, struct drm_i915_vbl_swap, head); struct drm_drawable_info *drw_cmp = drm_get_drawable_info(dev, swap_cmp->drw_id); @@ -223,8 +223,8 @@ static void i915_vblank_tasklet(struct drm_device *dev) lower[0] = lower[1] = sarea_priv->height; list_for_each(hit, &hits) { - drm_i915_vbl_swap_t *swap_hit = - list_entry(hit, drm_i915_vbl_swap_t, head); + struct drm_i915_vbl_swap *swap_hit = + list_entry(hit, struct drm_i915_vbl_swap, head); struct drm_clip_rect *rect; int num_rects, plane, front, back; unsigned short top, bottom; @@ -292,8 +292,8 @@ static void i915_vblank_tasklet(struct drm_device *dev) DRM_SPINUNLOCK(&dev->drw_lock); list_for_each_safe(hit, tmp, &hits) { - drm_i915_vbl_swap_t *swap_hit = - list_entry(hit, drm_i915_vbl_swap_t, head); + struct drm_i915_vbl_swap *swap_hit = + list_entry(hit, struct drm_i915_vbl_swap, head); list_del(hit); @@ -304,7 +304,7 @@ static void i915_vblank_tasklet(struct drm_device *dev) irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; u16 temp; u32 pipea_stats, pipeb_stats; @@ -367,7 +367,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) int i915_emit_irq(struct drm_device *dev) { - drm_i915_private_t *dev_priv = dev->dev_private; + + struct drm_i915_private *dev_priv = dev->dev_private; RING_LOCALS; i915_kernel_lost_context(dev); @@ -384,7 +385,7 @@ int i915_emit_irq(struct drm_device *dev) return dev_priv->counter; } -void i915_user_irq_on(drm_i915_private_t *dev_priv) +void i915_user_irq_on(struct drm_i915_private *dev_priv) { DRM_SPINLOCK(&dev_priv->user_irq_lock); if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){ @@ -394,8 +395,8 @@ void i915_user_irq_on(drm_i915_private_t *dev_priv) DRM_SPINUNLOCK(&dev_priv->user_irq_lock); } - -void i915_user_irq_off(drm_i915_private_t *dev_priv) + +void i915_user_irq_off(struct drm_i915_private *dev_priv) { DRM_SPINLOCK(&dev_priv->user_irq_lock); if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) { @@ -408,7 +409,7 @@ void i915_user_irq_off(drm_i915_private_t *dev_priv) 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; + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; int ret = 0; DRM_DEBUG("%s irq_nr=%d breadcrumb=%d\n", __FUNCTION__, irq_nr, @@ -438,7 +439,7 @@ static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequence, atomic_t *counter) { - drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; unsigned int cur_vblank; int ret = 0; @@ -456,6 +457,19 @@ static int i915_driver_vblank_do_wait(struct drm_device *dev, return ret; } +void i915_driver_wait_next_vblank(struct drm_device *dev, int pipe) +{ + unsigned int seq; + + seq = pipe ? atomic_read(&dev->vbl_received2) + 1 : + atomic_read(&dev->vbl_received) + 1; + + if (!pipe) + i915_driver_vblank_do_wait(dev, &seq, &dev->vbl_received); + else + i915_driver_vblank_do_wait(dev, &seq, &dev->vbl_received2); +} + int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence) { return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received); @@ -471,8 +485,8 @@ int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence) int i915_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_irq_emit_t *emit = data; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_irq_emit *emit = data; int result; LOCK_TEST_WITH_RETURN(dev, file_priv); @@ -497,8 +511,8 @@ int i915_irq_emit(struct drm_device *dev, void *data, int i915_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_irq_wait_t *irqwait = data; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_irq_wait *irqwait = data; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); @@ -508,11 +522,12 @@ int i915_irq_wait(struct drm_device *dev, void *data, return i915_wait_irq(dev, irqwait->irq_seq); } -static void i915_enable_interrupt (struct drm_device *dev) +void i915_enable_interrupt (struct drm_device *dev) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; + + dev_priv->irq_enable_reg = USER_INT_FLAG; - dev_priv->irq_enable_reg = USER_INT_FLAG; if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A) dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG; if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B) @@ -527,8 +542,8 @@ static void i915_enable_interrupt (struct drm_device *dev) int i915_vblank_pipe_set(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_vblank_pipe_t *pipe = data; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_vblank_pipe *pipe = data; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); @@ -551,8 +566,8 @@ int i915_vblank_pipe_set(struct drm_device *dev, void *data, int i915_vblank_pipe_get(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_vblank_pipe_t *pipe = data; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_vblank_pipe *pipe = data; u16 flag; if (!dev_priv) { @@ -576,9 +591,9 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data, int i915_vblank_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_vblank_swap_t *swap = data; - drm_i915_vbl_swap_t *vbl_swap; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_vblank_swap *swap = data; + struct drm_i915_vbl_swap *vbl_swap; unsigned int pipe, seqtype, curseq, plane; unsigned long irqflags; struct list_head *list; @@ -670,7 +685,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data, DRM_SPINLOCK_IRQSAVE(&dev_priv->swaps_lock, irqflags); list_for_each(list, &dev_priv->vbl_swaps.head) { - vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); + vbl_swap = list_entry(list, struct drm_i915_vbl_swap, head); if (vbl_swap->drw_id == swap->drawable && vbl_swap->plane == plane && @@ -720,7 +735,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data, */ void i915_driver_irq_preinstall(struct drm_device * dev) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; I915_WRITE16(I915REG_HWSTAM, 0xeffe); I915_WRITE16(I915REG_INT_MASK_R, 0x0); @@ -729,7 +744,7 @@ void i915_driver_irq_preinstall(struct drm_device * dev) void i915_driver_irq_postinstall(struct drm_device * dev) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; DRM_SPININIT(&dev_priv->swaps_lock, "swap"); INIT_LIST_HEAD(&dev_priv->vbl_swaps.head); @@ -750,7 +765,7 @@ void i915_driver_irq_postinstall(struct drm_device * dev) void i915_driver_irq_uninstall(struct drm_device * dev) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; u16 temp; if (!dev_priv) diff --git a/shared-core/i915_mem.c b/shared-core/i915_mem.c index d360896f..4c7ced24 100644 --- a/shared-core/i915_mem.c +++ b/shared-core/i915_mem.c @@ -45,8 +45,8 @@ */ static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use) { - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_sarea *sarea_priv = dev_priv->sarea_priv; struct drm_tex_region *list; unsigned shift, nr; unsigned start; @@ -256,7 +256,7 @@ void i915_mem_takedown(struct mem_block **heap) *heap = NULL; } -static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region) +static struct mem_block **get_heap(struct drm_i915_private * dev_priv, int region) { switch (region) { case I915_MEM_REGION_AGP: @@ -271,8 +271,8 @@ static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region) int i915_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_mem_alloc_t *alloc = data; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_mem_alloc *alloc = data; struct mem_block *block, **heap; if (!dev_priv) { @@ -309,8 +309,8 @@ int i915_mem_alloc(struct drm_device *dev, void *data, int i915_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_mem_free_t *memfree = data; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_mem_free *memfree = data; struct mem_block *block, **heap; if (!dev_priv) { @@ -337,8 +337,8 @@ int i915_mem_free(struct drm_device *dev, void *data, int i915_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_mem_init_heap_t *initheap = data; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_mem_init_heap *initheap = data; struct mem_block **heap; if (!dev_priv) { @@ -361,8 +361,8 @@ int i915_mem_init_heap(struct drm_device *dev, void *data, int i915_mem_destroy_heap( struct drm_device *dev, void *data, struct drm_file *file_priv ) { - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_mem_destroy_heap_t *destroyheap = data; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_mem_destroy_heap *destroyheap = data; struct mem_block **heap; if ( !dev_priv ) { diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 958a179f..9395bb2a 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -1390,6 +1390,28 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) } } +void radeon_gart_flush(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + if (dev_priv->flags & RADEON_IS_IGPGART) { + RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_FLUSH); + RADEON_WRITE_IGPGART(RADEON_IGPGART_FLUSH, 0x1); + RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_FLUSH); + RADEON_WRITE_IGPGART(RADEON_IGPGART_FLUSH, 0x0); + } else if (dev_priv->flags & RADEON_IS_PCIE) { + u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL); + tmp |= RADEON_PCIE_TX_GART_INVALIDATE_TLB; + RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); + tmp &= ~RADEON_PCIE_TX_GART_INVALIDATE_TLB; + RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); + } else { + + + } + +} + static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) { drm_radeon_private_t *dev_priv = dev->dev_private; @@ -2302,6 +2324,9 @@ int radeon_driver_firstopen(struct drm_device *dev) if (ret != 0) return ret; +#ifdef RADEON_HAVE_BUFFER + drm_bo_driver_init(dev); +#endif return 0; } diff --git a/shared-core/radeon_drm.h b/shared-core/radeon_drm.h index 4594a837..50e561af 100644 --- a/shared-core/radeon_drm.h +++ b/shared-core/radeon_drm.h @@ -434,8 +434,17 @@ typedef struct { int pfCurrentPage; /* which buffer is being displayed? */ int crtc2_base; /* CRTC2 frame offset */ int tiling_enabled; /* set by drm, read by 2d + 3d clients */ + + unsigned int last_fence; } drm_radeon_sarea_t; +/* The only fence class we support */ +#define DRM_RADEON_FENCE_CLASS_ACCEL 0 +/* Fence type that guarantees read-write flush */ +#define DRM_RADEON_FENCE_TYPE_RW 2 +/* cache flushes programmed just before the fence */ +#define DRM_RADEON_FENCE_FLAG_FLUSHED 0x01000000 + /* WARNING: If you change any of these defines, make sure to change the * defines in the Xserver file (xf86drmRadeon.h) * diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index a1745cdd..5332a386 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -104,6 +104,11 @@ #define DRIVER_MINOR 28 #define DRIVER_PATCHLEVEL 0 +#if defined(__linux__) +#define RADEON_HAVE_FENCE +#define RADEON_HAVE_BUFFER +#endif + /* * Radeon chip families */ @@ -284,8 +289,9 @@ typedef struct drm_radeon_private { struct mem_block *fb_heap; /* SW interrupt */ - wait_queue_head_t swi_queue; - atomic_t swi_emitted; + wait_queue_head_t irq_queue; + int counter; + int vblank_crtc; uint32_t irq_enable_reg; int irq_enabled; @@ -345,6 +351,7 @@ extern int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file extern int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern void radeon_gart_flush(struct drm_device *dev); extern void radeon_freelist_reset(struct drm_device * dev); extern struct drm_buf *radeon_freelist_get(struct drm_device * dev); @@ -363,6 +370,7 @@ extern void radeon_mem_release(struct drm_file *file_priv, /* radeon_irq.c */ extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_emit_irq(struct drm_device * dev); extern void radeon_do_release(struct drm_device * dev); extern int radeon_driver_vblank_wait(struct drm_device * dev, @@ -396,6 +404,30 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev, struct drm_file *file_priv, drm_radeon_kcmd_buffer_t* cmdbuf); + +#ifdef RADEON_HAVE_FENCE +/* i915_fence.c */ + + +extern void radeon_fence_handler(struct drm_device *dev); +extern int radeon_fence_emit_sequence(struct drm_device *dev, uint32_t class, + uint32_t flags, uint32_t *sequence, + uint32_t *native_type); +extern void radeon_poke_flush(struct drm_device *dev, uint32_t class); +extern int radeon_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t flags); +#endif + +#ifdef RADEON_HAVE_BUFFER +/* radeon_buffer.c */ +extern struct drm_ttm_backend *radeon_create_ttm_backend_entry(struct drm_device *dev); +extern int radeon_fence_types(struct drm_buffer_object *bo, uint32_t *class, uint32_t *type); +extern int radeon_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags); +extern uint32_t radeon_evict_mask(struct drm_buffer_object *bo); +extern int radeon_init_mem_type(struct drm_device * dev, uint32_t type, + struct drm_mem_type_manager * man); +extern int radeon_move(struct drm_buffer_object * bo, + int evict, int no_wait, struct drm_bo_mem_reg * new_mem); +#endif /* Flags for stats.boxes */ #define RADEON_BOX_DMA_IDLE 0x1 @@ -1267,4 +1299,19 @@ do { \ write &= mask; \ } while (0) +/* Breadcrumb - swi irq */ +#define READ_BREADCRUMB(dev_priv) RADEON_READ(RADEON_LAST_SWI_REG) + +static inline int radeon_update_breadcrumb(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + dev_priv->sarea_priv->last_fence = ++dev_priv->counter; + + if (dev_priv->counter > 0x7FFFFFFFUL) + dev_priv->sarea_priv->last_fence = dev_priv->counter = 1; + + return dev_priv->counter; +} + #endif /* __RADEON_DRV_H__ */ diff --git a/shared-core/radeon_irq.c b/shared-core/radeon_irq.c index 1ece6399..3162e266 100644 --- a/shared-core/radeon_irq.c +++ b/shared-core/radeon_irq.c @@ -82,7 +82,10 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) /* SW interrupt */ if (stat & RADEON_SW_INT_TEST) { - DRM_WAKEUP(&dev_priv->swi_queue); + DRM_WAKEUP(&dev_priv->irq_queue); +#ifdef RADEON_HAVE_FENCE + radeon_fence_handler(dev); +#endif } /* VBLANK interrupt */ @@ -109,14 +112,13 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) return IRQ_HANDLED; } -static int radeon_emit_irq(struct drm_device * dev) +int radeon_emit_irq(struct drm_device * dev) { drm_radeon_private_t *dev_priv = dev->dev_private; unsigned int ret; RING_LOCALS; - atomic_inc(&dev_priv->swi_emitted); - ret = atomic_read(&dev_priv->swi_emitted); + ret = radeon_update_breadcrumb(dev); BEGIN_RING(4); OUT_RING_REG(RADEON_LAST_SWI_REG, ret); @@ -133,13 +135,13 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr) (drm_radeon_private_t *) dev->dev_private; int ret = 0; - if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr) + if (READ_BREADCRUMB(dev_priv) >= swi_nr) return 0; dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ, - RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr); + DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ, + READ_BREADCRUMB(dev_priv) >= swi_nr); return ret; } @@ -271,8 +273,8 @@ void radeon_driver_irq_postinstall(struct drm_device * dev) drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; - atomic_set(&dev_priv->swi_emitted, 0); - DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); + dev_priv->counter = 0; + DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); radeon_enable_interrupt(dev); } |