aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-02-11 08:25:09 -0500
committerDave Airlie <airlied@redhat.com>2009-02-19 21:21:12 -0500
commit5c3b82e2b229e78eb32f4ea12d16f3ebeeab3fc7 (patch)
tree1717b0b529629df1287e5a4ce08501fd92415a56
parente62fb64e6187ea9d8bcedb17ccaa045ed92d4b55 (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.c15
-rw-r--r--drivers/gpu/drm/i915/intel_display.c84
-rw-r--r--include/drm/drm_crtc_helper.h10
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
346static void 346static int
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 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
709static void intel_crtc_mode_set(struct drm_crtc *crtc, 726static 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
66struct drm_encoder_helper_funcs { 66struct drm_encoder_helper_funcs {