diff options
author | Kristian Høgsberg <krh@redhat.com> | 2008-12-17 22:14:46 -0500 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2008-12-29 02:47:27 -0500 |
commit | 3c4fdcfb2941dc36b6a16bc509a2adb97c131716 (patch) | |
tree | 36fba683165c72b36037035f5c383cc18e7e8db8 /drivers/gpu/drm/i915/intel_display.c | |
parent | d1e22c6ed05f3bfb3a7de0947498e7f3c868b296 (diff) |
drm: pin new and unpin old buffer when setting a mode.
This removes the requirement for user space to pin a buffer before
setting a mode that is backed by the pixels from that buffer.
Signed-off-by: Kristian Høgsberg <krh@redhat.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6e8b9ab83e97..e5c1c80d1f90 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -344,7 +344,8 @@ intel_wait_for_vblank(struct drm_device *dev) | |||
344 | } | 344 | } |
345 | 345 | ||
346 | static void | 346 | static void |
347 | intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) | 347 | intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, |
348 | struct drm_framebuffer *old_fb) | ||
348 | { | 349 | { |
349 | struct drm_device *dev = crtc->dev; | 350 | struct drm_device *dev = crtc->dev; |
350 | struct drm_i915_private *dev_priv = dev->dev_private; | 351 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -359,7 +360,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) | |||
359 | int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); | 360 | int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); |
360 | int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; | 361 | int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; |
361 | int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | 362 | int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; |
362 | u32 dspcntr; | 363 | u32 dspcntr, alignment; |
363 | 364 | ||
364 | /* no fb bound */ | 365 | /* no fb bound */ |
365 | if (!crtc->fb) { | 366 | if (!crtc->fb) { |
@@ -368,10 +369,32 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) | |||
368 | } | 369 | } |
369 | 370 | ||
370 | intel_fb = to_intel_framebuffer(crtc->fb); | 371 | intel_fb = to_intel_framebuffer(crtc->fb); |
371 | |||
372 | obj = intel_fb->obj; | 372 | obj = intel_fb->obj; |
373 | obj_priv = obj->driver_private; | 373 | obj_priv = obj->driver_private; |
374 | 374 | ||
375 | switch (obj_priv->tiling_mode) { | ||
376 | case I915_TILING_NONE: | ||
377 | alignment = 64 * 1024; | ||
378 | break; | ||
379 | case I915_TILING_X: | ||
380 | if (IS_I9XX(dev)) | ||
381 | alignment = 1024 * 1024; | ||
382 | else | ||
383 | alignment = 512 * 1024; | ||
384 | break; | ||
385 | case I915_TILING_Y: | ||
386 | /* FIXME: Is this true? */ | ||
387 | DRM_ERROR("Y tiled not allowed for scan out buffers\n"); | ||
388 | return; | ||
389 | default: | ||
390 | BUG(); | ||
391 | } | ||
392 | |||
393 | if (i915_gem_object_pin(intel_fb->obj, alignment)) | ||
394 | return; | ||
395 | |||
396 | i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1); | ||
397 | |||
375 | Start = obj_priv->gtt_offset; | 398 | Start = obj_priv->gtt_offset; |
376 | Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); | 399 | Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); |
377 | 400 | ||
@@ -409,6 +432,12 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) | |||
409 | I915_READ(dspbase); | 432 | I915_READ(dspbase); |
410 | } | 433 | } |
411 | 434 | ||
435 | intel_wait_for_vblank(dev); | ||
436 | |||
437 | if (old_fb) { | ||
438 | intel_fb = to_intel_framebuffer(old_fb); | ||
439 | i915_gem_object_unpin(intel_fb->obj); | ||
440 | } | ||
412 | 441 | ||
413 | if (!dev->primary->master) | 442 | if (!dev->primary->master) |
414 | return; | 443 | return; |
@@ -680,7 +709,8 @@ static int intel_panel_fitter_pipe (struct drm_device *dev) | |||
680 | static void intel_crtc_mode_set(struct drm_crtc *crtc, | 709 | static void intel_crtc_mode_set(struct drm_crtc *crtc, |
681 | struct drm_display_mode *mode, | 710 | struct drm_display_mode *mode, |
682 | struct drm_display_mode *adjusted_mode, | 711 | struct drm_display_mode *adjusted_mode, |
683 | int x, int y) | 712 | int x, int y, |
713 | struct drm_framebuffer *old_fb) | ||
684 | { | 714 | { |
685 | struct drm_device *dev = crtc->dev; | 715 | struct drm_device *dev = crtc->dev; |
686 | struct drm_i915_private *dev_priv = dev->dev_private; | 716 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -915,9 +945,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, | |||
915 | I915_WRITE(dspcntr_reg, dspcntr); | 945 | I915_WRITE(dspcntr_reg, dspcntr); |
916 | 946 | ||
917 | /* Flush the plane changes */ | 947 | /* Flush the plane changes */ |
918 | intel_pipe_set_base(crtc, x, y); | 948 | intel_pipe_set_base(crtc, x, y, old_fb); |
919 | |||
920 | intel_wait_for_vblank(dev); | ||
921 | 949 | ||
922 | drm_vblank_post_modeset(dev, pipe); | 950 | drm_vblank_post_modeset(dev, pipe); |
923 | } | 951 | } |
@@ -1153,7 +1181,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output, | |||
1153 | if (!crtc->enabled) { | 1181 | if (!crtc->enabled) { |
1154 | if (!mode) | 1182 | if (!mode) |
1155 | mode = &load_detect_mode; | 1183 | mode = &load_detect_mode; |
1156 | drm_crtc_helper_set_mode(crtc, mode, 0, 0); | 1184 | drm_crtc_helper_set_mode(crtc, mode, 0, 0, crtc->fb); |
1157 | } else { | 1185 | } else { |
1158 | if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) { | 1186 | if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) { |
1159 | crtc_funcs = crtc->helper_private; | 1187 | crtc_funcs = crtc->helper_private; |