From d839240d1b282acaf22efdb8dcfa11fa30c921dc Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 2 Dec 2009 20:16:20 -0500 Subject: [PATCH] drm/radeon/kms/atom: avoid possible hang in blank crtc table If the crtc timing isn't set up, you might get stuck in a loop in the BlankCRTC command table waiting for vblank. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/atombios_crtc.c | 9 +++++++-- drivers/gpu/drm/radeon/radeon_device.c | 7 +++++++ drivers/gpu/drm/radeon/radeon_display.c | 1 + drivers/gpu/drm/radeon/radeon_mode.h | 1 + 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 7a8cd93..e706ea4 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -248,7 +248,9 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) atombios_enable_crtc(crtc, 1); if (ASIC_IS_DCE3(rdev)) atombios_enable_crtc_memreq(crtc, 1); - atombios_blank_crtc(crtc, 0); + /* make sure we have crtc timing set up before calling blank */ + if (radeon_crtc->initialized) + atombios_blank_crtc(crtc, 0); drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); radeon_crtc_load_lut(crtc); break; @@ -256,7 +258,9 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); - atombios_blank_crtc(crtc, 1); + /* make sure we have crtc timing set up before calling blank */ + if (radeon_crtc->initialized) + atombios_blank_crtc(crtc, 1); if (ASIC_IS_DCE3(rdev)) atombios_enable_crtc_memreq(crtc, 0); atombios_enable_crtc(crtc, 0); @@ -718,6 +722,7 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, } atombios_overscan_setup(crtc, mode, adjusted_mode); atombios_scaler_setup(crtc); + radeon_crtc->initialized = true; return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 60ee6a8..166c153 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -707,6 +707,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) int radeon_resume_kms(struct drm_device *dev) { struct radeon_device *rdev = dev->dev_private; + struct drm_crtc *crtc; acquire_console_sem(); pci_set_power_state(dev->pdev, PCI_D0); @@ -718,6 +719,12 @@ int radeon_resume_kms(struct drm_device *dev) pci_set_master(dev->pdev); /* resume AGP if in use */ radeon_agp_resume(rdev); + + /* crtcs aren't initialized yet */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + radeon_crtc->initialized = false; + } radeon_resume(rdev); radeon_restore_bios_scratch_regs(rdev); fb_set_suspend(rdev->fbdev_info, 0); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 62c929e..7e421b2 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -177,6 +177,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index) drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256); radeon_crtc->crtc_id = index; + radeon_crtc->initialized = false; rdev->mode_info.crtcs[index] = radeon_crtc; #if 0 diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 8043aec..aa3289d 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -249,6 +249,7 @@ struct radeon_crtc { fixed20_12 vsc; fixed20_12 hsc; struct drm_display_mode native_mode; + bool initialized; }; struct radeon_encoder_primary_dac { -- 1.5.6.3