From 67160dae8994f33490d95046c59a5e456b900e15 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 2 Dec 2009 21:01:12 -0500 Subject: [PATCH] drm/radeon/kms/atom: avoid possible hang in crtc tables If the crtc timing isn't set up, you might get stuck in a loop in the crtc command tables waiting for vblank. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/atombios_crtc.c | 25 +++++++++++++++++-------- drivers/gpu/drm/radeon/radeon_device.c | 8 ++++++++ drivers/gpu/drm/radeon/radeon_display.c | 2 ++ drivers/gpu/drm/radeon/radeon_mode.h | 1 + 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 7a8cd93..a2d033b 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -245,10 +245,14 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) switch (mode) { case DRM_MODE_DPMS_ON: - 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 */ + if (radeon_crtc->initialized) { + atombios_enable_crtc(crtc, 1); + if (ASIC_IS_DCE3(rdev)) + atombios_enable_crtc_memreq(crtc, 1); + atombios_blank_crtc(crtc, 0); + radeon_crtc->enabled = true; + } drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); radeon_crtc_load_lut(crtc); break; @@ -256,10 +260,14 @@ 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); - if (ASIC_IS_DCE3(rdev)) - atombios_enable_crtc_memreq(crtc, 0); - atombios_enable_crtc(crtc, 0); + /* make sure we have crtc timing set up and crtc is enabled */ + if (radeon_crtc->initialized && radeon_crtc->enabled) { + atombios_blank_crtc(crtc, 1); + if (ASIC_IS_DCE3(rdev)) + atombios_enable_crtc_memreq(crtc, 0); + atombios_enable_crtc(crtc, 0); + radeon_crtc->enabled = false; + } break; } } @@ -718,6 +726,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..8c69131 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,13 @@ 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_crtc->enabled = 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..ceb2a88 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -177,6 +177,8 @@ 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; + radeon_crtc->enabled = 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..cfd001d 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; /* timing set up */ }; struct radeon_encoder_primary_dac { -- 1.5.6.3