Skip to content

Commit

Permalink
drm/radeon: properly handle crtc powergating
Browse files Browse the repository at this point in the history
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>
Cc: stable@vger.kernel.org
  • Loading branch information
Alex Deucher committed Aug 13, 2012
1 parent 3838f46 commit 6c0ae2a
Showing 3 changed files with 17 additions and 2 deletions.
14 changes: 12 additions & 2 deletions drivers/gpu/drm/radeon/atombios_crtc.c
Original file line number Diff line number Diff line change
@@ -259,7 +259,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
/* 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 *crtc, int mode)
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) {
@@ -1635,18 +1635,28 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
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)
4 changes: 4 additions & 0 deletions drivers/gpu/drm/radeon/radeon_legacy_crtc.c
Original file line number Diff line number Diff line change
@@ -1025,9 +1025,11 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc,

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 drm_crtc *crtc)

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 drm_crtc *crtc)
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 = {
1 change: 1 addition & 0 deletions drivers/gpu/drm/radeon/radeon_mode.h
Original file line number Diff line number Diff line change
@@ -275,6 +275,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;

0 comments on commit 6c0ae2a

Please sign in to comment.