From 42e5e65765265485ecf2a480c244d76c2c624449 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 13 Nov 2017 17:01:40 +0100 Subject: drm/i915: sync dp link status checks against atomic commmits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bits: - check actual atomic state, the legacy stuff can only be looked at from within the atomic_commit_tail function, since it's only protected by ordering and not by any locks. - Make sure we don't wreak the work an ongoing nonblocking commit is doing. v2: We need the crtc lock too, because a plane update might change it without having to acquire the connection_mutex (Maarten). Use Maarten's changes for this locking, while keeping the logic that uses the connection->commit->hw_done signal for syncing with nonblocking commits. v3: The initial state objects from the hw state readout do not have a commit object. Check for that (spotted by CI). v4: Fix deadlock from jumping to put_power with locks still held. (mlankhorst) Cc: Manasi Navare Cc: Maarten Lankhorst Cc: Ville Syrjälä References: https://bugs.freedesktop.org/show_bug.cgi?id=103336 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99272 Signed-off-by: Daniel Vetter Signed-off-by: Maarten Lankhorst Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20171113160140.22679-1-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/intel_dp.c | 61 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index bc61f38b131d..dd0b3a018792 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4277,6 +4277,8 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base; + struct drm_connector_state *conn_state = + intel_dp->attached_connector->base.state; u8 link_status[DP_LINK_STATUS_SIZE]; WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex)); @@ -4286,10 +4288,16 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) return; } - if (!intel_encoder->base.crtc) + if (!conn_state->crtc) return; - if (!to_intel_crtc(intel_encoder->base.crtc)->active) + WARN_ON(!drm_modeset_is_locked(&conn_state->crtc->mutex)); + + if (!conn_state->crtc->state->active) + return; + + if (conn_state->commit && + !try_wait_for_completion(&conn_state->commit->hw_done)) return; /* @@ -4364,9 +4372,8 @@ intel_dp_short_pulse(struct intel_dp *intel_dp) DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n"); } - drm_modeset_lock(&dev_priv->drm.mode_config.connection_mutex, NULL); intel_dp_check_link_status(intel_dp); - drm_modeset_unlock(&dev_priv->drm.mode_config.connection_mutex); + if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) { DRM_DEBUG_KMS("Link Training Compliance Test requested\n"); /* Send a Hotplug Uevent to userspace to start modeset */ @@ -4814,8 +4821,19 @@ intel_dp_detect(struct drm_connector *connector, connector->base.id, connector->name); /* If full detect is not performed yet, do a full detect */ - if (!intel_dp->detect_done) + if (!intel_dp->detect_done) { + struct drm_crtc *crtc; + int ret; + + crtc = connector->state->crtc; + if (crtc) { + ret = drm_modeset_lock(&crtc->mutex, ctx); + if (ret) + return ret; + } + status = intel_dp_long_pulse(intel_dp->attached_connector); + } intel_dp->detect_done = false; @@ -5097,7 +5115,38 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) } if (!intel_dp->is_mst) { - if (!intel_dp_short_pulse(intel_dp)) { + struct drm_modeset_acquire_ctx ctx; + struct drm_connector *connector = &intel_dp->attached_connector->base; + struct drm_crtc *crtc; + int iret; + bool handled = false; + + drm_modeset_acquire_init(&ctx, 0); +retry: + iret = drm_modeset_lock(&dev_priv->drm.mode_config.connection_mutex, &ctx); + if (iret) + goto err; + + crtc = connector->state->crtc; + if (crtc) { + iret = drm_modeset_lock(&crtc->mutex, &ctx); + if (iret) + goto err; + } + + handled = intel_dp_short_pulse(intel_dp); + +err: + if (iret == -EDEADLK) { + drm_modeset_backoff(&ctx); + goto retry; + } + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + WARN(iret, "Acquiring modeset locks failed with %i\n", iret); + + if (!handled) { intel_dp->detect_done = false; goto put_power; } -- cgit v1.2.3 From 5643205c6340b565a3be0fe0e7305dc4aa551c74 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 29 Nov 2017 19:51:37 +0200 Subject: drm/i915: Avoid PPS HW/SW state mismatch due to rounding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We store a SW state of the t11_t12 timing in 100usec units but have to program it in 100msec as required by HW. The rounding used during programming means there will be a mismatch between the SW and HW states of this value triggering a "PPS state mismatch" error. Avoid this by storing the already rounded-up value in the SW state. Note that we still calculate panel_power_cycle_delay with the finer 100usec granularity to avoid any needless waits using that version of the delay. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103903 Cc: joks Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20171129175137.2889-1-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index dd0b3a018792..c603d4c903e1 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5355,6 +5355,12 @@ intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp) */ final->t8 = 1; final->t9 = 1; + + /* + * HW has only a 100msec granularity for t11_t12 so round it up + * accordingly. + */ + final->t11_t12 = roundup(final->t11_t12, 100 * 10); } static void -- cgit v1.2.3 From 20ff39fa4312dfaee8d1314a208e6a5a3ee51cbc Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 29 Nov 2017 18:43:01 +0200 Subject: drm/i915: Disable DP audio for g4x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apparently g4x doesn't support audio over DP. Bspec lists the bit as "Reserved for Audio Output Enable", and empirical evidence tells us that the bit won't stick. So stop trying to enable DP audio on g4x. Link: https://patchwork.freedesktop.org/patch/msgid/20171129164303.18793-1-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103989 Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c603d4c903e1..01c848bbd795 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1643,7 +1643,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, pipe_config->has_pch_encoder = true; pipe_config->has_drrs = false; - if (port == PORT_A) + if (IS_G4X(dev_priv) || port == PORT_A) pipe_config->has_audio = false; else if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO) pipe_config->has_audio = intel_dp->has_audio; -- cgit v1.2.3 From 68ec0736a00d38f2ac4907ffe8ad141ead15c075 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 29 Nov 2017 18:43:02 +0200 Subject: drm/i915: Don't add the "force audio" property to DP connectors that don't support audio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No point in adding the "force audio" property to DP connectors that don't support audio (g4x or port A). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20171129164303.18793-2-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 01c848bbd795..bf93991c2fcc 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5180,8 +5180,11 @@ static void intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->dev); + enum port port = dp_to_dig_port(intel_dp)->base.port; + + if (!IS_G4X(dev_priv) && port != PORT_A) + intel_attach_force_audio_property(connector); - intel_attach_force_audio_property(connector); intel_attach_broadcast_rgb_property(connector); if (intel_dp_is_edp(intel_dp)) { -- cgit v1.2.3 From 050213893307e661933a315a3c6e82658a68ffee Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 29 Nov 2017 20:08:47 +0200 Subject: drm/i915: Interlaced DP output doesn't work on VLV/CHV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reject interlaced modes on VLV/CHV DP outputs. This simply does not work correctly in the hardware. We do get some output, but it's quite corrupted. The available documentation fails to mention this fact. I contacted some hardware people who eventually managed to locate the relevant HSD for VLV, which was resolved by declaring interlaced DP output as not supported. The HSD was never cloned for CHV even though it inherited most of the hardware and thus has the same problems with interlaced DP output. Cc: Dennis Vshivkov Reported-by: Dennis Vshivkov Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103922 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20171129180847.30613-1-ville.syrjala@linux.intel.com Acked-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_dp.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_dp.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index bf93991c2fcc..90e8f35cc886 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1677,6 +1677,10 @@ intel_dp_compute_config(struct intel_encoder *encoder, conn_state->scaling_mode); } + if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && + adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) + return false; + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) return false; @@ -6093,7 +6097,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, drm_connector_init(dev, connector, &intel_dp_connector_funcs, type); drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs); - connector->interlace_allowed = true; + if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) + connector->interlace_allowed = true; connector->doublescan_allowed = 0; intel_dp_init_connector_port_info(intel_dig_port); -- cgit v1.2.3