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: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org
This commit is contained in:
Родитель
3838f46e36
Коммит
6c0ae2ab85
|
@ -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)
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче