aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2009-11-18 11:25:18 -0500
committerEric Anholt <eric@anholt.net>2009-12-01 12:10:35 -0500
commit6b95a207c1fd552e7d017837c5eaf1b0173a48c9 (patch)
tree02aed1633ab954faa3eea4b2a12775c28a1c5410 /drivers/gpu/drm/i915/intel_display.c
parentf40d6817a5c2bf84f5fe7b5d1a83f1e8f8669951 (diff)
drm/i915: Add intel implementation of the pageflip ioctl
Acked-by: Jakob Bornecrantz <jakob@vmware.com> Acked-by: Thomas Hellström <thomas@shipmail.org> Review-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Jesse "Orange Smoothie" Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Kristian Høgsberg <krh@bitplanet.net> Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c228
1 files changed, 196 insertions, 32 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 002c07daf9b8..b63a25f0f86d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1191,6 +1191,51 @@ out_disable:
1191} 1191}
1192 1192
1193static int 1193static int
1194intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj)
1195{
1196 struct drm_i915_gem_object *obj_priv = obj->driver_private;
1197 u32 alignment;
1198 int ret;
1199
1200 switch (obj_priv->tiling_mode) {
1201 case I915_TILING_NONE:
1202 alignment = 64 * 1024;
1203 break;
1204 case I915_TILING_X:
1205 /* pin() will align the object as required by fence */
1206 alignment = 0;
1207 break;
1208 case I915_TILING_Y:
1209 /* FIXME: Is this true? */
1210 DRM_ERROR("Y tiled not allowed for scan out buffers\n");
1211 return -EINVAL;
1212 default:
1213 BUG();
1214 }
1215
1216 alignment = 256 * 1024;
1217 ret = i915_gem_object_pin(obj, alignment);
1218 if (ret != 0)
1219 return ret;
1220
1221 /* Install a fence for tiled scan-out. Pre-i965 always needs a
1222 * fence, whereas 965+ only requires a fence if using
1223 * framebuffer compression. For simplicity, we always install
1224 * a fence as the cost is not that onerous.
1225 */
1226 if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
1227 obj_priv->tiling_mode != I915_TILING_NONE) {
1228 ret = i915_gem_object_get_fence_reg(obj);
1229 if (ret != 0) {
1230 i915_gem_object_unpin(obj);
1231 return ret;
1232 }
1233 }
1234
1235 return 0;
1236}
1237
1238static int
1194intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, 1239intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
1195 struct drm_framebuffer *old_fb) 1240 struct drm_framebuffer *old_fb)
1196{ 1241{
@@ -1209,7 +1254,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
1209 int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE; 1254 int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE;
1210 int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF); 1255 int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF);
1211 int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; 1256 int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
1212 u32 dspcntr, alignment; 1257 u32 dspcntr;
1213 int ret; 1258 int ret;
1214 1259
1215 /* no fb bound */ 1260 /* no fb bound */
@@ -1231,24 +1276,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
1231 obj = intel_fb->obj; 1276 obj = intel_fb->obj;
1232 obj_priv = obj->driver_private; 1277 obj_priv = obj->driver_private;
1233 1278
1234 switch (obj_priv->tiling_mode) {
1235 case I915_TILING_NONE:
1236 alignment = 64 * 1024;
1237 break;
1238 case I915_TILING_X:
1239 /* pin() will align the object as required by fence */
1240 alignment = 0;
1241 break;
1242 case I915_TILING_Y:
1243 /* FIXME: Is this true? */
1244 DRM_ERROR("Y tiled not allowed for scan out buffers\n");
1245 return -EINVAL;
1246 default:
1247 BUG();
1248 }
1249
1250 mutex_lock(&dev->struct_mutex); 1279 mutex_lock(&dev->struct_mutex);
1251 ret = i915_gem_object_pin(obj, alignment); 1280 ret = intel_pin_and_fence_fb_obj(dev, obj);
1252 if (ret != 0) { 1281 if (ret != 0) {
1253 mutex_unlock(&dev->struct_mutex); 1282 mutex_unlock(&dev->struct_mutex);
1254 return ret; 1283 return ret;
@@ -1261,20 +1290,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
1261 return ret; 1290 return ret;
1262 } 1291 }
1263 1292
1264 /* Install a fence for tiled scan-out. Pre-i965 always needs a fence,
1265 * whereas 965+ only requires a fence if using framebuffer compression.
1266 * For simplicity, we always install a fence as the cost is not that onerous.
1267 */
1268 if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
1269 obj_priv->tiling_mode != I915_TILING_NONE) {
1270 ret = i915_gem_object_get_fence_reg(obj);
1271 if (ret != 0) {
1272 i915_gem_object_unpin(obj);
1273 mutex_unlock(&dev->struct_mutex);
1274 return ret;
1275 }
1276 }
1277
1278 dspcntr = I915_READ(dspcntr_reg); 1293 dspcntr = I915_READ(dspcntr_reg);
1279 /* Mask out pixel format bits in case we change it */ 1294 /* Mask out pixel format bits in case we change it */
1280 dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; 1295 dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
@@ -4068,6 +4083,153 @@ static void intel_crtc_destroy(struct drm_crtc *crtc)
4068 kfree(intel_crtc); 4083 kfree(intel_crtc);
4069} 4084}
4070 4085
4086struct intel_unpin_work {
4087 struct work_struct work;
4088 struct drm_device *dev;
4089 struct drm_gem_object *obj;
4090 struct drm_pending_vblank_event *event;
4091 int pending;
4092};
4093
4094static void intel_unpin_work_fn(struct work_struct *__work)
4095{
4096 struct intel_unpin_work *work =
4097 container_of(__work, struct intel_unpin_work, work);
4098
4099 mutex_lock(&work->dev->struct_mutex);
4100 i915_gem_object_unpin(work->obj);
4101 drm_gem_object_unreference(work->obj);
4102 mutex_unlock(&work->dev->struct_mutex);
4103 kfree(work);
4104}
4105
4106void intel_finish_page_flip(struct drm_device *dev, int pipe)
4107{
4108 drm_i915_private_t *dev_priv = dev->dev_private;
4109 struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
4110 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
4111 struct intel_unpin_work *work;
4112 struct drm_i915_gem_object *obj_priv;
4113 struct drm_pending_vblank_event *e;
4114 struct timeval now;
4115 unsigned long flags;
4116
4117 /* Ignore early vblank irqs */
4118 if (intel_crtc == NULL)
4119 return;
4120
4121 spin_lock_irqsave(&dev->event_lock, flags);
4122 work = intel_crtc->unpin_work;
4123 if (work == NULL || !work->pending) {
4124 spin_unlock_irqrestore(&dev->event_lock, flags);
4125 return;
4126 }
4127
4128 intel_crtc->unpin_work = NULL;
4129 drm_vblank_put(dev, intel_crtc->pipe);
4130
4131 if (work->event) {
4132 e = work->event;
4133 do_gettimeofday(&now);
4134 e->event.sequence = drm_vblank_count(dev, intel_crtc->pipe);
4135 e->event.tv_sec = now.tv_sec;
4136 e->event.tv_usec = now.tv_usec;
4137 list_add_tail(&e->base.link,
4138 &e->base.file_priv->event_list);
4139 wake_up_interruptible(&e->base.file_priv->event_wait);
4140 }
4141
4142 spin_unlock_irqrestore(&dev->event_lock, flags);
4143
4144 obj_priv = work->obj->driver_private;
4145 if (atomic_dec_and_test(&obj_priv->pending_flip))
4146 DRM_WAKEUP(&dev_priv->pending_flip_queue);
4147 schedule_work(&work->work);
4148}
4149
4150void intel_prepare_page_flip(struct drm_device *dev, int plane)
4151{
4152 drm_i915_private_t *dev_priv = dev->dev_private;
4153 struct intel_crtc *intel_crtc =
4154 to_intel_crtc(dev_priv->plane_to_crtc_mapping[plane]);
4155 unsigned long flags;
4156
4157 spin_lock_irqsave(&dev->event_lock, flags);
4158 if (intel_crtc->unpin_work)
4159 intel_crtc->unpin_work->pending = 1;
4160 spin_unlock_irqrestore(&dev->event_lock, flags);
4161}
4162
4163static int intel_crtc_page_flip(struct drm_crtc *crtc,
4164 struct drm_framebuffer *fb,
4165 struct drm_pending_vblank_event *event)
4166{
4167 struct drm_device *dev = crtc->dev;
4168 struct drm_i915_private *dev_priv = dev->dev_private;
4169 struct intel_framebuffer *intel_fb;
4170 struct drm_i915_gem_object *obj_priv;
4171 struct drm_gem_object *obj;
4172 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
4173 struct intel_unpin_work *work;
4174 unsigned long flags;
4175 int ret;
4176 RING_LOCALS;
4177
4178 work = kzalloc(sizeof *work, GFP_KERNEL);
4179 if (work == NULL)
4180 return -ENOMEM;
4181
4182 mutex_lock(&dev->struct_mutex);
4183
4184 work->event = event;
4185 work->dev = crtc->dev;
4186 intel_fb = to_intel_framebuffer(crtc->fb);
4187 work->obj = intel_fb->obj;
4188 INIT_WORK(&work->work, intel_unpin_work_fn);
4189
4190 /* We borrow the event spin lock for protecting unpin_work */
4191 spin_lock_irqsave(&dev->event_lock, flags);
4192 if (intel_crtc->unpin_work) {
4193 spin_unlock_irqrestore(&dev->event_lock, flags);
4194 kfree(work);
4195 mutex_unlock(&dev->struct_mutex);
4196 return -EBUSY;
4197 }
4198 intel_crtc->unpin_work = work;
4199 spin_unlock_irqrestore(&dev->event_lock, flags);
4200
4201 intel_fb = to_intel_framebuffer(fb);
4202 obj = intel_fb->obj;
4203
4204 ret = intel_pin_and_fence_fb_obj(dev, obj);
4205 if (ret != 0) {
4206 kfree(work);
4207 mutex_unlock(&dev->struct_mutex);
4208 return ret;
4209 }
4210
4211 /* Reference the old fb object for the scheduled work. */
4212 drm_gem_object_reference(work->obj);
4213
4214 crtc->fb = fb;
4215 i915_gem_object_flush_write_domain(obj);
4216 drm_vblank_get(dev, intel_crtc->pipe);
4217 obj_priv = obj->driver_private;
4218 atomic_inc(&obj_priv->pending_flip);
4219
4220 BEGIN_LP_RING(4);
4221 OUT_RING(MI_DISPLAY_FLIP |
4222 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
4223 OUT_RING(fb->pitch);
4224 OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode);
4225 OUT_RING((fb->width << 16) | fb->height);
4226 ADVANCE_LP_RING();
4227
4228 mutex_unlock(&dev->struct_mutex);
4229
4230 return 0;
4231}
4232
4071static const struct drm_crtc_helper_funcs intel_helper_funcs = { 4233static const struct drm_crtc_helper_funcs intel_helper_funcs = {
4072 .dpms = intel_crtc_dpms, 4234 .dpms = intel_crtc_dpms,
4073 .mode_fixup = intel_crtc_mode_fixup, 4235 .mode_fixup = intel_crtc_mode_fixup,
@@ -4084,12 +4246,14 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
4084 .gamma_set = intel_crtc_gamma_set, 4246 .gamma_set = intel_crtc_gamma_set,
4085 .set_config = drm_crtc_helper_set_config, 4247 .set_config = drm_crtc_helper_set_config,
4086 .destroy = intel_crtc_destroy, 4248 .destroy = intel_crtc_destroy,
4249 .page_flip = intel_crtc_page_flip,
4087}; 4250};
4088 4251
4089 4252
4090static void intel_crtc_init(struct drm_device *dev, int pipe) 4253static void intel_crtc_init(struct drm_device *dev, int pipe)
4091{ 4254{
4092 struct intel_crtc *intel_crtc; 4255 struct intel_crtc *intel_crtc;
4256 struct drm_i915_private *dev_priv = dev->dev_private;
4093 int i; 4257 int i;
4094 4258
4095 intel_crtc = kzalloc(sizeof(struct intel_crtc) + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL); 4259 intel_crtc = kzalloc(sizeof(struct intel_crtc) + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);