diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 721f80e9568dfd5766179a698ad229b6576dffe5..8e32c5891be10f757fc18d2ba326c82bc3b2d4a4 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1492,16 +1492,16 @@ static u32 radeon_get_pll_use_mask(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_crtc *test_crtc; - struct radeon_crtc *radeon_test_crtc; + struct radeon_crtc *test_radeon_crtc; u32 pll_in_use = 0; list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { if (crtc == test_crtc) continue; - radeon_test_crtc = to_radeon_crtc(test_crtc); - if (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID) - pll_in_use |= (1 << radeon_test_crtc->pll_id); + test_radeon_crtc = to_radeon_crtc(test_crtc); + if (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID) + pll_in_use |= (1 << test_radeon_crtc->pll_id); } return pll_in_use; } @@ -1518,17 +1518,18 @@ static u32 radeon_get_pll_use_mask(struct drm_crtc *crtc) static int radeon_get_shared_dp_ppll(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; - struct drm_encoder *test_encoder; + struct drm_crtc *test_crtc; struct radeon_crtc *test_radeon_crtc; - list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { - if (test_encoder->crtc && (test_encoder->crtc != crtc)) { - if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { - /* for DP use the same PLL for all */ - test_radeon_crtc = to_radeon_crtc(test_encoder->crtc); - if (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID) - return test_radeon_crtc->pll_id; - } + list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { + if (crtc == test_crtc) + continue; + test_radeon_crtc = to_radeon_crtc(test_crtc); + if (test_radeon_crtc->encoder && + ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_radeon_crtc->encoder))) { + /* for DP use the same PLL for all */ + if (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID) + return test_radeon_crtc->pll_id; } } return ATOM_PPLL_INVALID; @@ -1547,10 +1548,8 @@ static int radeon_get_shared_nondp_ppll(struct drm_crtc *crtc) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; - struct drm_encoder *test_encoder; struct drm_crtc *test_crtc; struct radeon_crtc *test_radeon_crtc; - struct radeon_encoder *test_radeon_encoder; u32 adjusted_clock, test_adjusted_clock; adjusted_clock = radeon_crtc->adjusted_clock; @@ -1558,20 +1557,25 @@ static int radeon_get_shared_nondp_ppll(struct drm_crtc *crtc) if (adjusted_clock == 0) return ATOM_PPLL_INVALID; - list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { - if (test_encoder->crtc && (test_encoder->crtc != crtc)) { - if (!ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { - test_radeon_encoder = to_radeon_encoder(test_encoder); - test_crtc = test_encoder->crtc; - test_radeon_crtc = to_radeon_crtc(test_crtc); - /* for non-DP check the clock */ - test_adjusted_clock = test_radeon_crtc->adjusted_clock; - if ((crtc->mode.clock == test_crtc->mode.clock) && - (adjusted_clock == test_adjusted_clock) && - (radeon_crtc->ss_enabled == test_radeon_crtc->ss_enabled) && - (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID)) + list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { + if (crtc == test_crtc) + continue; + test_radeon_crtc = to_radeon_crtc(test_crtc); + if (test_radeon_crtc->encoder && + !ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_radeon_crtc->encoder))) { + /* check if we are already driving this connector with another crtc */ + if (test_radeon_crtc->connector == radeon_crtc->connector) { + /* if we are, return that pll */ + if (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID) return test_radeon_crtc->pll_id; } + /* for non-DP check the clock */ + test_adjusted_clock = test_radeon_crtc->adjusted_clock; + if ((crtc->mode.clock == test_crtc->mode.clock) && + (adjusted_clock == test_adjusted_clock) && + (radeon_crtc->ss_enabled == test_radeon_crtc->ss_enabled) && + (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID)) + return test_radeon_crtc->pll_id; } } return ATOM_PPLL_INVALID; @@ -1793,11 +1797,15 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { if (encoder->crtc == crtc) { radeon_crtc->encoder = encoder; + radeon_crtc->connector = radeon_get_connector_for_encoder(encoder); break; } } - if (radeon_crtc->encoder == NULL) + if ((radeon_crtc->encoder == NULL) || (radeon_crtc->connector == NULL)) { + radeon_crtc->encoder = NULL; + radeon_crtc->connector = NULL; return false; + } if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) return false; if (!atombios_crtc_prepare_pll(crtc, adjusted_mode)) @@ -1874,6 +1882,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) radeon_crtc->pll_id = ATOM_PPLL_INVALID; radeon_crtc->adjusted_clock = 0; radeon_crtc->encoder = NULL; + radeon_crtc->connector = NULL; } static const struct drm_crtc_helper_funcs atombios_helper_funcs = { @@ -1925,5 +1934,6 @@ void radeon_atombios_init_crtc(struct drm_device *dev, radeon_crtc->pll_id = ATOM_PPLL_INVALID; radeon_crtc->adjusted_clock = 0; radeon_crtc->encoder = NULL; + radeon_crtc->connector = NULL; drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); } diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 2d78645576d7fb3768e3b12b5373d8f91e902cff..917d02750cf7ccfd591929af5b477fdd20ad229f 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -327,6 +327,7 @@ struct radeon_crtc { u32 pll_post_div; u32 pll_flags; struct drm_encoder *encoder; + struct drm_connector *connector; }; struct radeon_encoder_primary_dac {