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 | |
| 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')
| -rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 20 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 44 |
2 files changed, 49 insertions, 15 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; |
