diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8c6f4e2a2cb8638dc5b3390531118a47cc97ed2d..b6bb43875a03c6b726844ae994518566c7546b17 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14708,6 +14708,11 @@ static void intel_setup_outputs(struct drm_device *dev) struct intel_encoder *encoder; bool dpd_is_edp = false; + /* + * intel_edp_init_connector() depends on this completing first, to + * prevent the registeration of both eDP and LVDS and the incorrect + * sharing of the PPS. + */ intel_lvds_init(dev); if (intel_crt_present(dev)) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3cdea4d7a917ce520dae03a416289b2a051e9068..9493c8f765383e0b53bfad9ee2e7b5a960b417e9 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5313,6 +5313,19 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, if (!is_edp(intel_dp)) return true; + /* + * On IBX/CPT we may get here with LVDS already registered. Since the + * driver uses the only internal power sequencer available for both + * eDP and LVDS bail out early in this case to prevent interfering + * with an already powered-on LVDS power sequencer. + */ + if (intel_get_lvds_encoder(dev)) { + WARN_ON(!(HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))); + DRM_INFO("LVDS was detected, not registering eDP\n"); + + return false; + } + pps_lock(intel_dp); intel_edp_panel_vdd_sanitize(intel_dp); pps_unlock(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 06fa25db3d32f4665f8ded28be8b3f4e1edb6033..21ba3df05241380068b74d3c3ec1cd214559facb 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1460,6 +1460,7 @@ void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable); /* intel_lvds.c */ void intel_lvds_init(struct drm_device *dev); +struct intel_encoder *intel_get_lvds_encoder(struct drm_device *dev); bool intel_is_dual_link_lvds(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index e06b9036bebc6d3bddf41fd82aad9297e31c6d5e..72096fd28023c5d061a9ddafe1f9b27c6ce4a3a8 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -809,20 +809,22 @@ static const struct dmi_system_id intel_dual_link_lvds[] = { { } /* terminating entry */ }; -bool intel_is_dual_link_lvds(struct drm_device *dev) +struct intel_encoder *intel_get_lvds_encoder(struct drm_device *dev) { - struct intel_encoder *encoder; - struct intel_lvds_encoder *lvds_encoder; + struct intel_encoder *intel_encoder; - for_each_intel_encoder(dev, encoder) { - if (encoder->type == INTEL_OUTPUT_LVDS) { - lvds_encoder = to_lvds_encoder(&encoder->base); + for_each_intel_encoder(dev, intel_encoder) + if (intel_encoder->type == INTEL_OUTPUT_LVDS) + return intel_encoder; - return lvds_encoder->is_dual_link; - } - } + return NULL; +} - return false; +bool intel_is_dual_link_lvds(struct drm_device *dev) +{ + struct intel_encoder *encoder = intel_get_lvds_encoder(dev); + + return encoder && to_lvds_encoder(&encoder->base)->is_dual_link; } static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)