| From 6c0ae2ab85fc4a95cae82047a7db1f688a7737ab Mon Sep 17 00:00:00 2001 |
| From: Alex Deucher <alexander.deucher@amd.com> |
| Date: Thu, 26 Jul 2012 13:38:52 -0400 |
| Subject: drm/radeon: properly handle crtc powergating |
| |
| From: Alex Deucher <alexander.deucher@amd.com> |
| |
| commit 6c0ae2ab85fc4a95cae82047a7db1f688a7737ab upstream. |
| |
| Need to make sure the crtc is gated on before modesetting. |
| Explicitly gate the crtc on in prepare() and set a flag |
| so that the dpms functions don't gate it off during |
| mode set. |
| |
| Noticed by sylware on IRC. |
| |
| Signed-off-by: Alex Deucher <alexander.deucher@amd.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/gpu/drm/radeon/atombios_crtc.c | 14 ++++++++++++-- |
| drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 4 ++++ |
| drivers/gpu/drm/radeon/radeon_mode.h | 1 + |
| 3 files changed, 17 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/gpu/drm/radeon/atombios_crtc.c |
| +++ b/drivers/gpu/drm/radeon/atombios_crtc.c |
| @@ -259,7 +259,7 @@ void atombios_crtc_dpms(struct drm_crtc |
| /* adjust pm to dpms changes BEFORE enabling crtcs */ |
| radeon_pm_compute_clocks(rdev); |
| /* disable crtc pair power gating before programming */ |
| - if (ASIC_IS_DCE6(rdev)) |
| + if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) |
| atombios_powergate_crtc(crtc, ATOM_DISABLE); |
| atombios_enable_crtc(crtc, ATOM_ENABLE); |
| if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) |
| @@ -279,7 +279,7 @@ void atombios_crtc_dpms(struct drm_crtc |
| atombios_enable_crtc(crtc, ATOM_DISABLE); |
| radeon_crtc->enabled = false; |
| /* power gating is per-pair */ |
| - if (ASIC_IS_DCE6(rdev)) { |
| + if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) { |
| struct drm_crtc *other_crtc; |
| struct radeon_crtc *other_radeon_crtc; |
| list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) { |
| @@ -1634,18 +1634,28 @@ static bool atombios_crtc_mode_fixup(str |
| static void atombios_crtc_prepare(struct drm_crtc *crtc) |
| { |
| struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
| + struct drm_device *dev = crtc->dev; |
| + struct radeon_device *rdev = dev->dev_private; |
| |
| + radeon_crtc->in_mode_set = true; |
| /* pick pll */ |
| radeon_crtc->pll_id = radeon_atom_pick_pll(crtc); |
| |
| + /* disable crtc pair power gating before programming */ |
| + if (ASIC_IS_DCE6(rdev)) |
| + atombios_powergate_crtc(crtc, ATOM_DISABLE); |
| + |
| atombios_lock_crtc(crtc, ATOM_ENABLE); |
| atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); |
| } |
| |
| static void atombios_crtc_commit(struct drm_crtc *crtc) |
| { |
| + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
| + |
| atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON); |
| atombios_lock_crtc(crtc, ATOM_DISABLE); |
| + radeon_crtc->in_mode_set = false; |
| } |
| |
| static void atombios_crtc_disable(struct drm_crtc *crtc) |
| --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c |
| +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c |
| @@ -1025,9 +1025,11 @@ static int radeon_crtc_mode_set(struct d |
| |
| static void radeon_crtc_prepare(struct drm_crtc *crtc) |
| { |
| + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
| struct drm_device *dev = crtc->dev; |
| struct drm_crtc *crtci; |
| |
| + radeon_crtc->in_mode_set = true; |
| /* |
| * The hardware wedges sometimes if you reconfigure one CRTC |
| * whilst another is running (see fdo bug #24611). |
| @@ -1038,6 +1040,7 @@ static void radeon_crtc_prepare(struct d |
| |
| static void radeon_crtc_commit(struct drm_crtc *crtc) |
| { |
| + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
| struct drm_device *dev = crtc->dev; |
| struct drm_crtc *crtci; |
| |
| @@ -1048,6 +1051,7 @@ static void radeon_crtc_commit(struct dr |
| if (crtci->enabled) |
| radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON); |
| } |
| + radeon_crtc->in_mode_set = false; |
| } |
| |
| static const struct drm_crtc_helper_funcs legacy_helper_funcs = { |
| --- a/drivers/gpu/drm/radeon/radeon_mode.h |
| +++ b/drivers/gpu/drm/radeon/radeon_mode.h |
| @@ -266,6 +266,7 @@ struct radeon_crtc { |
| u16 lut_r[256], lut_g[256], lut_b[256]; |
| bool enabled; |
| bool can_tile; |
| + bool in_mode_set; |
| uint32_t crtc_offset; |
| struct drm_gem_object *cursor_bo; |
| uint64_t cursor_addr; |