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 | |
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>
-rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 44 | ||||
-rw-r--r-- | include/drm/drm_crtc_helper.h | 9 |
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 | */ |
433 | bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, | 433 | bool 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 | ||
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; |
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 | ||
64 | struct drm_encoder_helper_funcs { | 66 | struct drm_encoder_helper_funcs { |
@@ -93,7 +95,8 @@ extern bool drm_helper_initial_config(struct drm_device *dev, bool can_grow); | |||
93 | extern int drm_crtc_helper_set_config(struct drm_mode_set *set); | 95 | extern int drm_crtc_helper_set_config(struct drm_mode_set *set); |
94 | extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, | 96 | extern 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); | ||
97 | extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc); | 100 | extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc); |
98 | 101 | ||
99 | extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, | 102 | extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, |