Commit 6c0ae2ab authored by Alex Deucher's avatar Alex Deucher

drm/radeon: properly handle crtc powergating

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: default avatarAlex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
parent 3838f46e
...@@ -259,7 +259,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -259,7 +259,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
/* adjust pm to dpms changes BEFORE enabling crtcs */ /* adjust pm to dpms changes BEFORE enabling crtcs */
radeon_pm_compute_clocks(rdev); radeon_pm_compute_clocks(rdev);
/* disable crtc pair power gating before programming */ /* 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_powergate_crtc(crtc, ATOM_DISABLE);
atombios_enable_crtc(crtc, ATOM_ENABLE); atombios_enable_crtc(crtc, ATOM_ENABLE);
if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev))
...@@ -279,7 +279,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -279,7 +279,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
atombios_enable_crtc(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_DISABLE);
radeon_crtc->enabled = false; radeon_crtc->enabled = false;
/* power gating is per-pair */ /* 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 drm_crtc *other_crtc;
struct radeon_crtc *other_radeon_crtc; struct radeon_crtc *other_radeon_crtc;
list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) { 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, ...@@ -1635,18 +1635,28 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
static void atombios_crtc_prepare(struct drm_crtc *crtc) static void atombios_crtc_prepare(struct drm_crtc *crtc)
{ {
struct radeon_crtc *radeon_crtc = to_radeon_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 */ /* pick pll */
radeon_crtc->pll_id = radeon_atom_pick_pll(crtc); 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_lock_crtc(crtc, ATOM_ENABLE);
atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
} }
static void atombios_crtc_commit(struct drm_crtc *crtc) 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_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
atombios_lock_crtc(crtc, ATOM_DISABLE); atombios_lock_crtc(crtc, ATOM_DISABLE);
radeon_crtc->in_mode_set = false;
} }
static void atombios_crtc_disable(struct drm_crtc *crtc) static void atombios_crtc_disable(struct drm_crtc *crtc)
......
...@@ -1025,9 +1025,11 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc, ...@@ -1025,9 +1025,11 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc,
static void radeon_crtc_prepare(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_device *dev = crtc->dev;
struct drm_crtc *crtci; struct drm_crtc *crtci;
radeon_crtc->in_mode_set = true;
/* /*
* The hardware wedges sometimes if you reconfigure one CRTC * The hardware wedges sometimes if you reconfigure one CRTC
* whilst another is running (see fdo bug #24611). * whilst another is running (see fdo bug #24611).
...@@ -1038,6 +1040,7 @@ static void radeon_crtc_prepare(struct drm_crtc *crtc) ...@@ -1038,6 +1040,7 @@ static void radeon_crtc_prepare(struct drm_crtc *crtc)
static void radeon_crtc_commit(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_device *dev = crtc->dev;
struct drm_crtc *crtci; struct drm_crtc *crtci;
...@@ -1048,6 +1051,7 @@ static void radeon_crtc_commit(struct drm_crtc *crtc) ...@@ -1048,6 +1051,7 @@ static void radeon_crtc_commit(struct drm_crtc *crtc)
if (crtci->enabled) if (crtci->enabled)
radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON); radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON);
} }
radeon_crtc->in_mode_set = false;
} }
static const struct drm_crtc_helper_funcs legacy_helper_funcs = { static const struct drm_crtc_helper_funcs legacy_helper_funcs = {
......
...@@ -275,6 +275,7 @@ struct radeon_crtc { ...@@ -275,6 +275,7 @@ struct radeon_crtc {
u16 lut_r[256], lut_g[256], lut_b[256]; u16 lut_r[256], lut_g[256], lut_b[256];
bool enabled; bool enabled;
bool can_tile; bool can_tile;
bool in_mode_set;
uint32_t crtc_offset; uint32_t crtc_offset;
struct drm_gem_object *cursor_bo; struct drm_gem_object *cursor_bo;
uint64_t cursor_addr; uint64_t cursor_addr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment