aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_gem.c
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2008-11-07 17:24:08 -0500
committerDave Airlie <airlied@linux.ie>2008-12-29 02:47:23 -0500
commit79e539453b34e35f39299a899d263b0a1f1670bd (patch)
tree6d1285f2b78fab399aab75a3557b7d6bc0dbd112 /drivers/gpu/drm/i915/i915_gem.c
parentf453ba0460742ad027ae0c4c7d61e62817b3e7ef (diff)
DRM: i915: add mode setting support
This commit adds i915 driver support for the DRM mode setting APIs. Currently, VGA, LVDS, SDVO DVI & VGA, TV and DVO LVDS outputs are supported. HDMI, DisplayPort and additional SDVO output support will follow. Support for the mode setting code is controlled by the new 'modeset' module option. A new config option, CONFIG_DRM_I915_KMS controls the default behavior, and whether a PCI ID list is built into the module for use by user level module utilities. Note that if mode setting is enabled, user level drivers that access display registers directly or that don't use the kernel graphics memory manager will likely corrupt kernel graphics memory, disrupt output configuration (possibly leading to hangs and/or blank displays), and prevent panic/oops messages from appearing. So use caution when enabling this code; be sure your user level code supports the new interfaces. A new SysRq key, 'g', provides emergency support for switching back to the kernel's framebuffer console; which is useful for testing. Co-authors: Dave Airlie <airlied@linux.ie>, Hong Liu <hong.liu@intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c132
1 files changed, 88 insertions, 44 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 0ac977112f72..c4ccaf3b3c7f 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -30,6 +30,7 @@
30#include "i915_drm.h" 30#include "i915_drm.h"
31#include "i915_drv.h" 31#include "i915_drv.h"
32#include <linux/swap.h> 32#include <linux/swap.h>
33#include <linux/pci.h>
33 34
34#define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) 35#define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
35 36
@@ -40,8 +41,6 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
40static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); 41static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
41static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); 42static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj);
42static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); 43static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj);
43static int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
44 int write);
45static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, 44static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj,
46 int write); 45 int write);
47static int i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, 46static int i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
@@ -57,33 +56,37 @@ static void i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
57static void i915_gem_clear_fence_reg(struct drm_gem_object *obj); 56static void i915_gem_clear_fence_reg(struct drm_gem_object *obj);
58static int i915_gem_evict_something(struct drm_device *dev); 57static int i915_gem_evict_something(struct drm_device *dev);
59 58
60static void 59int i915_gem_do_init(struct drm_device *dev, unsigned long start,
61i915_gem_cleanup_ringbuffer(struct drm_device *dev); 60 unsigned long end)
62
63int
64i915_gem_init_ioctl(struct drm_device *dev, void *data,
65 struct drm_file *file_priv)
66{ 61{
67 drm_i915_private_t *dev_priv = dev->dev_private; 62 drm_i915_private_t *dev_priv = dev->dev_private;
68 struct drm_i915_gem_init *args = data;
69
70 mutex_lock(&dev->struct_mutex);
71 63
72 if (args->gtt_start >= args->gtt_end || 64 if (start >= end ||
73 (args->gtt_start & (PAGE_SIZE - 1)) != 0 || 65 (start & (PAGE_SIZE - 1)) != 0 ||
74 (args->gtt_end & (PAGE_SIZE - 1)) != 0) { 66 (end & (PAGE_SIZE - 1)) != 0) {
75 mutex_unlock(&dev->struct_mutex);
76 return -EINVAL; 67 return -EINVAL;
77 } 68 }
78 69
79 drm_mm_init(&dev_priv->mm.gtt_space, args->gtt_start, 70 drm_mm_init(&dev_priv->mm.gtt_space, start,
80 args->gtt_end - args->gtt_start); 71 end - start);
81 72
82 dev->gtt_total = (uint32_t) (args->gtt_end - args->gtt_start); 73 dev->gtt_total = (uint32_t) (end - start);
74
75 return 0;
76}
83 77
78int
79i915_gem_init_ioctl(struct drm_device *dev, void *data,
80 struct drm_file *file_priv)
81{
82 struct drm_i915_gem_init *args = data;
83 int ret;
84
85 mutex_lock(&dev->struct_mutex);
86 ret = i915_gem_do_init(dev, args->gtt_start, args->gtt_end);
84 mutex_unlock(&dev->struct_mutex); 87 mutex_unlock(&dev->struct_mutex);
85 88
86 return 0; 89 return ret;
87} 90}
88 91
89int 92int
@@ -1246,7 +1249,8 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
1246 1249
1247 /* blow away mappings if mapped through GTT */ 1250 /* blow away mappings if mapped through GTT */
1248 offset = ((loff_t) obj->map_list.hash.key) << PAGE_SHIFT; 1251 offset = ((loff_t) obj->map_list.hash.key) << PAGE_SHIFT;
1249 unmap_mapping_range(dev->dev_mapping, offset, obj->size, 1); 1252 if (dev->dev_mapping)
1253 unmap_mapping_range(dev->dev_mapping, offset, obj->size, 1);
1250 1254
1251 if (obj_priv->fence_reg != I915_FENCE_REG_NONE) 1255 if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
1252 i915_gem_clear_fence_reg(obj); 1256 i915_gem_clear_fence_reg(obj);
@@ -1508,7 +1512,7 @@ static void
1508i915_gem_object_get_fence_reg(struct drm_gem_object *obj) 1512i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
1509{ 1513{
1510 struct drm_device *dev = obj->dev; 1514 struct drm_device *dev = obj->dev;
1511 drm_i915_private_t *dev_priv = dev->dev_private; 1515 struct drm_i915_private *dev_priv = dev->dev_private;
1512 struct drm_i915_gem_object *obj_priv = obj->driver_private; 1516 struct drm_i915_gem_object *obj_priv = obj->driver_private;
1513 struct drm_i915_fence_reg *reg = NULL; 1517 struct drm_i915_fence_reg *reg = NULL;
1514 int i, ret; 1518 int i, ret;
@@ -1567,8 +1571,9 @@ try_again:
1567 * for this object next time we need it. 1571 * for this object next time we need it.
1568 */ 1572 */
1569 offset = ((loff_t) reg->obj->map_list.hash.key) << PAGE_SHIFT; 1573 offset = ((loff_t) reg->obj->map_list.hash.key) << PAGE_SHIFT;
1570 unmap_mapping_range(dev->dev_mapping, offset, 1574 if (dev->dev_mapping)
1571 reg->obj->size, 1); 1575 unmap_mapping_range(dev->dev_mapping, offset,
1576 reg->obj->size, 1);
1572 old_obj_priv->fence_reg = I915_FENCE_REG_NONE; 1577 old_obj_priv->fence_reg = I915_FENCE_REG_NONE;
1573 } 1578 }
1574 1579
@@ -1594,7 +1599,7 @@ static void
1594i915_gem_clear_fence_reg(struct drm_gem_object *obj) 1599i915_gem_clear_fence_reg(struct drm_gem_object *obj)
1595{ 1600{
1596 struct drm_device *dev = obj->dev; 1601 struct drm_device *dev = obj->dev;
1597 struct drm_i915_private *dev_priv = dev->dev_private; 1602 drm_i915_private_t *dev_priv = dev->dev_private;
1598 struct drm_i915_gem_object *obj_priv = obj->driver_private; 1603 struct drm_i915_gem_object *obj_priv = obj->driver_private;
1599 1604
1600 if (IS_I965G(dev)) 1605 if (IS_I965G(dev))
@@ -1764,7 +1769,7 @@ i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj)
1764 * This function returns when the move is complete, including waiting on 1769 * This function returns when the move is complete, including waiting on
1765 * flushes to occur. 1770 * flushes to occur.
1766 */ 1771 */
1767static int 1772int
1768i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) 1773i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write)
1769{ 1774{
1770 struct drm_i915_gem_object *obj_priv = obj->driver_private; 1775 struct drm_i915_gem_object *obj_priv = obj->driver_private;
@@ -2706,11 +2711,22 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
2706 } 2711 }
2707 obj_priv = obj->driver_private; 2712 obj_priv = obj->driver_private;
2708 2713
2709 ret = i915_gem_object_pin(obj, args->alignment); 2714 if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) {
2710 if (ret != 0) { 2715 DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n",
2711 drm_gem_object_unreference(obj); 2716 args->handle);
2712 mutex_unlock(&dev->struct_mutex); 2717 mutex_unlock(&dev->struct_mutex);
2713 return ret; 2718 return -EINVAL;
2719 }
2720
2721 obj_priv->user_pin_count++;
2722 obj_priv->pin_filp = file_priv;
2723 if (obj_priv->user_pin_count == 1) {
2724 ret = i915_gem_object_pin(obj, args->alignment);
2725 if (ret != 0) {
2726 drm_gem_object_unreference(obj);
2727 mutex_unlock(&dev->struct_mutex);
2728 return ret;
2729 }
2714 } 2730 }
2715 2731
2716 /* XXX - flush the CPU caches for pinned objects 2732 /* XXX - flush the CPU caches for pinned objects
@@ -2730,6 +2746,7 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
2730{ 2746{
2731 struct drm_i915_gem_pin *args = data; 2747 struct drm_i915_gem_pin *args = data;
2732 struct drm_gem_object *obj; 2748 struct drm_gem_object *obj;
2749 struct drm_i915_gem_object *obj_priv;
2733 2750
2734 mutex_lock(&dev->struct_mutex); 2751 mutex_lock(&dev->struct_mutex);
2735 2752
@@ -2741,7 +2758,19 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
2741 return -EBADF; 2758 return -EBADF;
2742 } 2759 }
2743 2760
2744 i915_gem_object_unpin(obj); 2761 obj_priv = obj->driver_private;
2762 if (obj_priv->pin_filp != file_priv) {
2763 DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n",
2764 args->handle);
2765 drm_gem_object_unreference(obj);
2766 mutex_unlock(&dev->struct_mutex);
2767 return -EINVAL;
2768 }
2769 obj_priv->user_pin_count--;
2770 if (obj_priv->user_pin_count == 0) {
2771 obj_priv->pin_filp = NULL;
2772 i915_gem_object_unpin(obj);
2773 }
2745 2774
2746 drm_gem_object_unreference(obj); 2775 drm_gem_object_unreference(obj);
2747 mutex_unlock(&dev->struct_mutex); 2776 mutex_unlock(&dev->struct_mutex);
@@ -3036,12 +3065,13 @@ i915_gem_init_hws(struct drm_device *dev)
3036 return 0; 3065 return 0;
3037} 3066}
3038 3067
3039static int 3068int
3040i915_gem_init_ringbuffer(struct drm_device *dev) 3069i915_gem_init_ringbuffer(struct drm_device *dev)
3041{ 3070{
3042 drm_i915_private_t *dev_priv = dev->dev_private; 3071 drm_i915_private_t *dev_priv = dev->dev_private;
3043 struct drm_gem_object *obj; 3072 struct drm_gem_object *obj;
3044 struct drm_i915_gem_object *obj_priv; 3073 struct drm_i915_gem_object *obj_priv;
3074 drm_i915_ring_buffer_t *ring = &dev_priv->ring;
3045 int ret; 3075 int ret;
3046 u32 head; 3076 u32 head;
3047 3077
@@ -3063,24 +3093,24 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
3063 } 3093 }
3064 3094
3065 /* Set up the kernel mapping for the ring. */ 3095 /* Set up the kernel mapping for the ring. */
3066 dev_priv->ring.Size = obj->size; 3096 ring->Size = obj->size;
3067 dev_priv->ring.tail_mask = obj->size - 1; 3097 ring->tail_mask = obj->size - 1;
3068 3098
3069 dev_priv->ring.map.offset = dev->agp->base + obj_priv->gtt_offset; 3099 ring->map.offset = dev->agp->base + obj_priv->gtt_offset;
3070 dev_priv->ring.map.size = obj->size; 3100 ring->map.size = obj->size;
3071 dev_priv->ring.map.type = 0; 3101 ring->map.type = 0;
3072 dev_priv->ring.map.flags = 0; 3102 ring->map.flags = 0;
3073 dev_priv->ring.map.mtrr = 0; 3103 ring->map.mtrr = 0;
3074 3104
3075 drm_core_ioremap_wc(&dev_priv->ring.map, dev); 3105 drm_core_ioremap_wc(&ring->map, dev);
3076 if (dev_priv->ring.map.handle == NULL) { 3106 if (ring->map.handle == NULL) {
3077 DRM_ERROR("Failed to map ringbuffer.\n"); 3107 DRM_ERROR("Failed to map ringbuffer.\n");
3078 memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); 3108 memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
3079 drm_gem_object_unreference(obj); 3109 drm_gem_object_unreference(obj);
3080 return -EINVAL; 3110 return -EINVAL;
3081 } 3111 }
3082 dev_priv->ring.ring_obj = obj; 3112 ring->ring_obj = obj;
3083 dev_priv->ring.virtual_start = dev_priv->ring.map.handle; 3113 ring->virtual_start = ring->map.handle;
3084 3114
3085 /* Stop the ring if it's running. */ 3115 /* Stop the ring if it's running. */
3086 I915_WRITE(PRB0_CTL, 0); 3116 I915_WRITE(PRB0_CTL, 0);
@@ -3128,12 +3158,20 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
3128 } 3158 }
3129 3159
3130 /* Update our cache of the ring state */ 3160 /* Update our cache of the ring state */
3131 i915_kernel_lost_context(dev); 3161 if (!drm_core_check_feature(dev, DRIVER_MODESET))
3162 i915_kernel_lost_context(dev);
3163 else {
3164 ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
3165 ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
3166 ring->space = ring->head - (ring->tail + 8);
3167 if (ring->space < 0)
3168 ring->space += ring->Size;
3169 }
3132 3170
3133 return 0; 3171 return 0;
3134} 3172}
3135 3173
3136static void 3174void
3137i915_gem_cleanup_ringbuffer(struct drm_device *dev) 3175i915_gem_cleanup_ringbuffer(struct drm_device *dev)
3138{ 3176{
3139 drm_i915_private_t *dev_priv = dev->dev_private; 3177 drm_i915_private_t *dev_priv = dev->dev_private;
@@ -3171,6 +3209,9 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
3171 drm_i915_private_t *dev_priv = dev->dev_private; 3209 drm_i915_private_t *dev_priv = dev->dev_private;
3172 int ret; 3210 int ret;
3173 3211
3212 if (drm_core_check_feature(dev, DRIVER_MODESET))
3213 return 0;
3214
3174 if (dev_priv->mm.wedged) { 3215 if (dev_priv->mm.wedged) {
3175 DRM_ERROR("Reenabling wedged hardware, good luck\n"); 3216 DRM_ERROR("Reenabling wedged hardware, good luck\n");
3176 dev_priv->mm.wedged = 0; 3217 dev_priv->mm.wedged = 0;
@@ -3204,6 +3245,9 @@ i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
3204 drm_i915_private_t *dev_priv = dev->dev_private; 3245 drm_i915_private_t *dev_priv = dev->dev_private;
3205 int ret; 3246 int ret;
3206 3247
3248 if (drm_core_check_feature(dev, DRIVER_MODESET))
3249 return 0;
3250
3207 ret = i915_gem_idle(dev); 3251 ret = i915_gem_idle(dev);
3208 drm_irq_uninstall(dev); 3252 drm_irq_uninstall(dev);
3209 3253