diff options
| -rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 15 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 84 | ||||
| -rw-r--r-- | include/drm/drm_crtc_helper.h | 10 |
3 files changed, 69 insertions, 40 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 8ba22c039a11..733028b4d45e 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
| @@ -512,8 +512,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, | |||
| 512 | if (drm_mode_equal(&saved_mode, &crtc->mode)) { | 512 | if (drm_mode_equal(&saved_mode, &crtc->mode)) { |
| 513 | if (saved_x != crtc->x || saved_y != crtc->y || | 513 | if (saved_x != crtc->x || saved_y != crtc->y || |
| 514 | depth_changed || bpp_changed) { | 514 | depth_changed || bpp_changed) { |
| 515 | crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, | 515 | ret = !crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, |
| 516 | old_fb); | 516 | old_fb); |
| 517 | goto done; | 517 | goto done; |
| 518 | } | 518 | } |
| 519 | } | 519 | } |
| @@ -552,7 +552,9 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, | |||
| 552 | /* Set up the DPLL and any encoders state that needs to adjust or depend | 552 | /* Set up the DPLL and any encoders state that needs to adjust or depend |
| 553 | * on the DPLL. | 553 | * on the DPLL. |
| 554 | */ | 554 | */ |
| 555 | crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb); | 555 | ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb); |
| 556 | if (!ret) | ||
| 557 | goto done; | ||
| 556 | 558 | ||
| 557 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 559 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
| 558 | 560 | ||
| @@ -752,6 +754,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 752 | if (!drm_crtc_helper_set_mode(set->crtc, set->mode, | 754 | if (!drm_crtc_helper_set_mode(set->crtc, set->mode, |
| 753 | set->x, set->y, | 755 | set->x, set->y, |
| 754 | old_fb)) { | 756 | old_fb)) { |
| 757 | DRM_ERROR("failed to set mode on crtc %p\n", | ||
| 758 | set->crtc); | ||
| 755 | ret = -EINVAL; | 759 | ret = -EINVAL; |
| 756 | goto fail_set_mode; | 760 | goto fail_set_mode; |
| 757 | } | 761 | } |
| @@ -765,7 +769,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 765 | old_fb = set->crtc->fb; | 769 | old_fb = set->crtc->fb; |
| 766 | if (set->crtc->fb != set->fb) | 770 | if (set->crtc->fb != set->fb) |
| 767 | set->crtc->fb = set->fb; | 771 | set->crtc->fb = set->fb; |
| 768 | crtc_funcs->mode_set_base(set->crtc, set->x, set->y, old_fb); | 772 | ret = crtc_funcs->mode_set_base(set->crtc, |
| 773 | set->x, set->y, old_fb); | ||
| 774 | if (ret != 0) | ||
| 775 | goto fail_set_mode; | ||
| 769 | } | 776 | } |
| 770 | 777 | ||
| 771 | kfree(save_encoders); | 778 | kfree(save_encoders); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a440d0db5ccc..ac92799fa8a1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -343,7 +343,7 @@ intel_wait_for_vblank(struct drm_device *dev) | |||
| 343 | udelay(20000); | 343 | udelay(20000); |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | static void | 346 | static int |
| 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 | struct drm_framebuffer *old_fb) |
| 349 | { | 349 | { |
| @@ -361,11 +361,21 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
| 361 | int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; | 361 | int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; |
| 362 | int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | 362 | int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; |
| 363 | u32 dspcntr, alignment; | 363 | u32 dspcntr, alignment; |
| 364 | int ret; | ||
| 364 | 365 | ||
| 365 | /* no fb bound */ | 366 | /* no fb bound */ |
| 366 | if (!crtc->fb) { | 367 | if (!crtc->fb) { |
| 367 | DRM_DEBUG("No FB bound\n"); | 368 | DRM_DEBUG("No FB bound\n"); |
| 368 | return; | 369 | return 0; |
| 370 | } | ||
| 371 | |||
| 372 | switch (pipe) { | ||
| 373 | case 0: | ||
| 374 | case 1: | ||
| 375 | break; | ||
| 376 | default: | ||
| 377 | DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); | ||
| 378 | return -EINVAL; | ||
| 369 | } | 379 | } |
| 370 | 380 | ||
| 371 | intel_fb = to_intel_framebuffer(crtc->fb); | 381 | intel_fb = to_intel_framebuffer(crtc->fb); |
| @@ -383,20 +393,24 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
| 383 | case I915_TILING_Y: | 393 | case I915_TILING_Y: |
| 384 | /* FIXME: Is this true? */ | 394 | /* FIXME: Is this true? */ |
| 385 | DRM_ERROR("Y tiled not allowed for scan out buffers\n"); | 395 | DRM_ERROR("Y tiled not allowed for scan out buffers\n"); |
| 386 | return; | 396 | return -EINVAL; |
| 387 | default: | 397 | default: |
| 388 | BUG(); | 398 | BUG(); |
| 389 | } | 399 | } |
| 390 | 400 | ||
| 391 | if (i915_gem_object_pin(intel_fb->obj, alignment)) | 401 | mutex_lock(&dev->struct_mutex); |
| 392 | return; | 402 | ret = i915_gem_object_pin(intel_fb->obj, alignment); |
| 393 | 403 | if (ret != 0) { | |
| 394 | i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1); | 404 | mutex_unlock(&dev->struct_mutex); |
| 395 | 405 | return ret; | |
| 396 | Start = obj_priv->gtt_offset; | 406 | } |
| 397 | Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); | ||
| 398 | 407 | ||
| 399 | I915_WRITE(dspstride, crtc->fb->pitch); | 408 | ret = i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1); |
| 409 | if (ret != 0) { | ||
| 410 | i915_gem_object_unpin(intel_fb->obj); | ||
| 411 | mutex_unlock(&dev->struct_mutex); | ||
| 412 | return ret; | ||
| 413 | } | ||
| 400 | 414 | ||
| 401 | dspcntr = I915_READ(dspcntr_reg); | 415 | dspcntr = I915_READ(dspcntr_reg); |
| 402 | /* Mask out pixel format bits in case we change it */ | 416 | /* Mask out pixel format bits in case we change it */ |
| @@ -417,11 +431,17 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
| 417 | break; | 431 | break; |
| 418 | default: | 432 | default: |
| 419 | DRM_ERROR("Unknown color depth\n"); | 433 | DRM_ERROR("Unknown color depth\n"); |
| 420 | return; | 434 | i915_gem_object_unpin(intel_fb->obj); |
| 435 | mutex_unlock(&dev->struct_mutex); | ||
| 436 | return -EINVAL; | ||
| 421 | } | 437 | } |
| 422 | I915_WRITE(dspcntr_reg, dspcntr); | 438 | I915_WRITE(dspcntr_reg, dspcntr); |
| 423 | 439 | ||
| 440 | Start = obj_priv->gtt_offset; | ||
| 441 | Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); | ||
| 442 | |||
| 424 | DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); | 443 | DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); |
| 444 | I915_WRITE(dspstride, crtc->fb->pitch); | ||
| 425 | if (IS_I965G(dev)) { | 445 | if (IS_I965G(dev)) { |
| 426 | I915_WRITE(dspbase, Offset); | 446 | I915_WRITE(dspbase, Offset); |
| 427 | I915_READ(dspbase); | 447 | I915_READ(dspbase); |
| @@ -438,27 +458,24 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
| 438 | intel_fb = to_intel_framebuffer(old_fb); | 458 | intel_fb = to_intel_framebuffer(old_fb); |
| 439 | i915_gem_object_unpin(intel_fb->obj); | 459 | i915_gem_object_unpin(intel_fb->obj); |
| 440 | } | 460 | } |
| 461 | mutex_unlock(&dev->struct_mutex); | ||
| 441 | 462 | ||
| 442 | if (!dev->primary->master) | 463 | if (!dev->primary->master) |
| 443 | return; | 464 | return 0; |
| 444 | 465 | ||
| 445 | master_priv = dev->primary->master->driver_priv; | 466 | master_priv = dev->primary->master->driver_priv; |
| 446 | if (!master_priv->sarea_priv) | 467 | if (!master_priv->sarea_priv) |
| 447 | return; | 468 | return 0; |
| 448 | 469 | ||
| 449 | switch (pipe) { | 470 | if (pipe) { |
| 450 | case 0: | ||
| 451 | master_priv->sarea_priv->pipeA_x = x; | ||
| 452 | master_priv->sarea_priv->pipeA_y = y; | ||
| 453 | break; | ||
| 454 | case 1: | ||
| 455 | master_priv->sarea_priv->pipeB_x = x; | 471 | master_priv->sarea_priv->pipeB_x = x; |
| 456 | master_priv->sarea_priv->pipeB_y = y; | 472 | master_priv->sarea_priv->pipeB_y = y; |
| 457 | break; | 473 | } else { |
| 458 | default: | 474 | master_priv->sarea_priv->pipeA_x = x; |
| 459 | DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); | 475 | master_priv->sarea_priv->pipeA_y = y; |
| 460 | break; | ||
| 461 | } | 476 | } |
| 477 | |||
| 478 | return 0; | ||
| 462 | } | 479 | } |
| 463 | 480 | ||
| 464 | 481 | ||
| @@ -706,11 +723,11 @@ static int intel_panel_fitter_pipe (struct drm_device *dev) | |||
| 706 | return 1; | 723 | return 1; |
| 707 | } | 724 | } |
| 708 | 725 | ||
| 709 | static void intel_crtc_mode_set(struct drm_crtc *crtc, | 726 | static int intel_crtc_mode_set(struct drm_crtc *crtc, |
| 710 | struct drm_display_mode *mode, | 727 | struct drm_display_mode *mode, |
| 711 | struct drm_display_mode *adjusted_mode, | 728 | struct drm_display_mode *adjusted_mode, |
| 712 | int x, int y, | 729 | int x, int y, |
| 713 | struct drm_framebuffer *old_fb) | 730 | struct drm_framebuffer *old_fb) |
| 714 | { | 731 | { |
| 715 | struct drm_device *dev = crtc->dev; | 732 | struct drm_device *dev = crtc->dev; |
| 716 | struct drm_i915_private *dev_priv = dev->dev_private; | 733 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -737,6 +754,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 737 | bool is_crt = false, is_lvds = false, is_tv = false; | 754 | bool is_crt = false, is_lvds = false, is_tv = false; |
| 738 | struct drm_mode_config *mode_config = &dev->mode_config; | 755 | struct drm_mode_config *mode_config = &dev->mode_config; |
| 739 | struct drm_connector *connector; | 756 | struct drm_connector *connector; |
| 757 | int ret; | ||
| 740 | 758 | ||
| 741 | drm_vblank_pre_modeset(dev, pipe); | 759 | drm_vblank_pre_modeset(dev, pipe); |
| 742 | 760 | ||
| @@ -777,7 +795,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 777 | ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock); | 795 | ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock); |
| 778 | if (!ok) { | 796 | if (!ok) { |
| 779 | DRM_ERROR("Couldn't find PLL settings for mode!\n"); | 797 | DRM_ERROR("Couldn't find PLL settings for mode!\n"); |
| 780 | return; | 798 | return -EINVAL; |
| 781 | } | 799 | } |
| 782 | 800 | ||
| 783 | fp = clock.n << 16 | clock.m1 << 8 | clock.m2; | 801 | fp = clock.n << 16 | clock.m1 << 8 | clock.m2; |
| @@ -948,9 +966,13 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 948 | I915_WRITE(dspcntr_reg, dspcntr); | 966 | I915_WRITE(dspcntr_reg, dspcntr); |
| 949 | 967 | ||
| 950 | /* Flush the plane changes */ | 968 | /* Flush the plane changes */ |
| 951 | intel_pipe_set_base(crtc, x, y, old_fb); | 969 | ret = intel_pipe_set_base(crtc, x, y, old_fb); |
| 970 | if (ret != 0) | ||
| 971 | return ret; | ||
| 952 | 972 | ||
| 953 | drm_vblank_post_modeset(dev, pipe); | 973 | drm_vblank_post_modeset(dev, pipe); |
| 974 | |||
| 975 | return 0; | ||
| 954 | } | 976 | } |
| 955 | 977 | ||
| 956 | /** Loads the palette/gamma unit for the CRTC with the prepared values */ | 978 | /** Loads the palette/gamma unit for the CRTC with the prepared values */ |
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 0c6f0e11b41b..0b0d236c2154 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h | |||
| @@ -54,13 +54,13 @@ struct drm_crtc_helper_funcs { | |||
| 54 | struct drm_display_mode *mode, | 54 | struct drm_display_mode *mode, |
| 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 | int (*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 | struct drm_framebuffer *old_fb); |
| 60 | 60 | ||
| 61 | /* 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* */ |
| 62 | void (*mode_set_base)(struct drm_crtc *crtc, int x, int y, | 62 | int (*mode_set_base)(struct drm_crtc *crtc, int x, int y, |
| 63 | struct drm_framebuffer *old_fb); | 63 | struct drm_framebuffer *old_fb); |
| 64 | }; | 64 | }; |
| 65 | 65 | ||
| 66 | struct drm_encoder_helper_funcs { | 66 | struct drm_encoder_helper_funcs { |
