aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2008-12-17 22:14:46 -0500
committerDave Airlie <airlied@linux.ie>2008-12-29 02:47:27 -0500
commit3c4fdcfb2941dc36b6a16bc509a2adb97c131716 (patch)
tree36fba683165c72b36037035f5c383cc18e7e8db8
parentd1e22c6ed05f3bfb3a7de0947498e7f3c868b296 (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>
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c20
-rw-r--r--drivers/gpu/drm/i915/intel_display.c44
-rw-r--r--include/drm/drm_crtc_helper.h9
3 files changed, 55 insertions, 18 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 58e335967617..d8a982b71296 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -432,7 +432,8 @@ static void drm_setup_crtcs(struct drm_device *dev)
432 */ 432 */
433bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, 433bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
434 struct drm_display_mode *mode, 434 struct drm_display_mode *mode,
435 int x, int y) 435 int x, int y,
436 struct drm_framebuffer *old_fb)
436{ 437{
437 struct drm_device *dev = crtc->dev; 438 struct drm_device *dev = crtc->dev;
438 struct drm_display_mode *adjusted_mode, saved_mode; 439 struct drm_display_mode *adjusted_mode, saved_mode;
@@ -462,7 +463,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
462 463
463 if (drm_mode_equal(&saved_mode, &crtc->mode)) { 464 if (drm_mode_equal(&saved_mode, &crtc->mode)) {
464 if (saved_x != crtc->x || saved_y != crtc->y) { 465 if (saved_x != crtc->x || saved_y != crtc->y) {
465 crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y); 466 crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
467 old_fb);
466 goto done; 468 goto done;
467 } 469 }
468 } 470 }
@@ -501,7 +503,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
501 /* Set up the DPLL and any encoders state that needs to adjust or depend 503 /* Set up the DPLL and any encoders state that needs to adjust or depend
502 * on the DPLL. 504 * on the DPLL.
503 */ 505 */
504 crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y); 506 crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
505 507
506 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 508 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
507 509
@@ -564,6 +566,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
564 struct drm_device *dev; 566 struct drm_device *dev;
565 struct drm_crtc **save_crtcs, *new_crtc; 567 struct drm_crtc **save_crtcs, *new_crtc;
566 struct drm_encoder **save_encoders, *new_encoder; 568 struct drm_encoder **save_encoders, *new_encoder;
569 struct drm_framebuffer *old_fb;
567 bool save_enabled; 570 bool save_enabled;
568 bool changed = false; 571 bool changed = false;
569 bool flip_or_move = false; 572 bool flip_or_move = false;
@@ -684,13 +687,15 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
684 changed = true; 687 changed = true;
685 688
686 if (changed) { 689 if (changed) {
690 old_fb = set->crtc->fb;
687 set->crtc->fb = set->fb; 691 set->crtc->fb = set->fb;
688 set->crtc->enabled = (set->mode != NULL); 692 set->crtc->enabled = (set->mode != NULL);
689 if (set->mode != NULL) { 693 if (set->mode != NULL) {
690 DRM_DEBUG("attempting to set mode from userspace\n"); 694 DRM_DEBUG("attempting to set mode from userspace\n");
691 drm_mode_debug_printmodeline(set->mode); 695 drm_mode_debug_printmodeline(set->mode);
692 if (!drm_crtc_helper_set_mode(set->crtc, set->mode, 696 if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
693 set->x, set->y)) { 697 set->x, set->y,
698 old_fb)) {
694 ret = -EINVAL; 699 ret = -EINVAL;
695 goto fail_set_mode; 700 goto fail_set_mode;
696 } 701 }
@@ -701,9 +706,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
701 } 706 }
702 drm_helper_disable_unused_functions(dev); 707 drm_helper_disable_unused_functions(dev);
703 } else if (flip_or_move) { 708 } else if (flip_or_move) {
709 old_fb = set->crtc->fb;
704 if (set->crtc->fb != set->fb) 710 if (set->crtc->fb != set->fb)
705 set->crtc->fb = set->fb; 711 set->crtc->fb = set->fb;
706 crtc_funcs->mode_set_base(set->crtc, set->x, set->y); 712 crtc_funcs->mode_set_base(set->crtc, set->x, set->y, old_fb);
707 } 713 }
708 714
709 kfree(save_encoders); 715 kfree(save_encoders);
@@ -809,8 +815,8 @@ int drm_helper_resume_force_mode(struct drm_device *dev)
809 if (!crtc->enabled) 815 if (!crtc->enabled)
810 continue; 816 continue;
811 817
812 ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x, 818 ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
813 crtc->y); 819 crtc->x, crtc->y, crtc->fb);
814 820
815 if (ret == false) 821 if (ret == false)
816 DRM_ERROR("failed to set mode on crtc %p\n", crtc); 822 DRM_ERROR("failed to set mode on crtc %p\n", crtc);
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
346static void 346static void
347intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) 347intel_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)
680static void intel_crtc_mode_set(struct drm_crtc *crtc, 709static 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;
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index a341828d1d15..4bc04cf460a7 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -55,10 +55,12 @@ struct drm_crtc_helper_funcs {
55 struct drm_display_mode *adjusted_mode); 55 struct drm_display_mode *adjusted_mode);
56 /* Actually set the mode */ 56 /* Actually set the mode */
57 void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, 57 void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
58 struct drm_display_mode *adjusted_mode, int x, int y); 58 struct drm_display_mode *adjusted_mode, int x, int y,
59 struct drm_framebuffer *old_fb);
59 60
60 /* Move the crtc on the current fb to the given position *optional* */ 61 /* Move the crtc on the current fb to the given position *optional* */
61 void (*mode_set_base)(struct drm_crtc *crtc, int x, int y); 62 void (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
63 struct drm_framebuffer *old_fb);
62}; 64};
63 65
64struct drm_encoder_helper_funcs { 66struct drm_encoder_helper_funcs {
@@ -93,7 +95,8 @@ extern bool drm_helper_initial_config(struct drm_device *dev, bool can_grow);
93extern int drm_crtc_helper_set_config(struct drm_mode_set *set); 95extern int drm_crtc_helper_set_config(struct drm_mode_set *set);
94extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, 96extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
95 struct drm_display_mode *mode, 97 struct drm_display_mode *mode,
96 int x, int y); 98 int x, int y,
99 struct drm_framebuffer *old_fb);
97extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc); 100extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
98 101
99extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, 102extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,