diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2009-02-11 08:25:09 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-02-19 21:21:12 -0500 |
commit | 5c3b82e2b229e78eb32f4ea12d16f3ebeeab3fc7 (patch) | |
tree | 1717b0b529629df1287e5a4ce08501fd92415a56 | |
parent | e62fb64e6187ea9d8bcedb17ccaa045ed92d4b55 (diff) |
drm: Propagate failure from setting crtc base.
Check the error paths within intel_pipe_set_base() to first cleanup and
then report back the error.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
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 | 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 { |