diff options
-rw-r--r-- | drivers/gpu/drm/i915/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/display/g4x_dp.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_ddi.c | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_display_types.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_dp.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_dp.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_dp_link_training.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_encoder.c | 39 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_encoder.h | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/xe/Makefile | 1 |
10 files changed, 124 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 06e6486c07b5..23840e53acba 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -329,6 +329,7 @@ i915-y += \ display/intel_dsi_dcs_backlight.o \ display/intel_dsi_vbt.o \ display/intel_dvo.o \ + display/intel_encoder.o \ display/intel_gmbus.o \ display/intel_hdmi.o \ display/intel_lspcon.o \ diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c index 40fee8380a81..4d279cadf7e2 100644 --- a/drivers/gpu/drm/i915/display/g4x_dp.c +++ b/drivers/gpu/drm/i915/display/g4x_dp.c @@ -20,6 +20,7 @@ #include "intel_dp_aux.h" #include "intel_dp_link_training.h" #include "intel_dpio_phy.h" +#include "intel_encoder.h" #include "intel_fifo_underrun.h" #include "intel_hdmi.h" #include "intel_hotplug.h" @@ -1239,6 +1240,15 @@ static bool ilk_digital_port_connected(struct intel_encoder *encoder) return intel_de_read(dev_priv, DEISR) & bit; } +static void g4x_dp_suspend_complete(struct intel_encoder *encoder) +{ + /* + * TODO: Move this to intel_dp_encoder_suspend(), + * once modeset locking around that is removed. + */ + intel_encoder_link_check_flush_work(encoder); +} + static void intel_dp_encoder_destroy(struct drm_encoder *encoder) { intel_dp_encoder_flush_work(encoder); @@ -1325,6 +1335,8 @@ bool g4x_dp_init(struct drm_i915_private *dev_priv, "DP %c", port_name(port))) goto err_encoder_init; + intel_encoder_link_check_init(intel_encoder, intel_dp_link_check); + intel_encoder->hotplug = intel_dp_hotplug; intel_encoder->compute_config = intel_dp_compute_config; intel_encoder->get_hw_state = intel_dp_get_hw_state; @@ -1333,6 +1345,7 @@ bool g4x_dp_init(struct drm_i915_private *dev_priv, intel_encoder->initial_fastset_check = intel_dp_initial_fastset_check; intel_encoder->update_pipe = intel_backlight_update; intel_encoder->suspend = intel_dp_encoder_suspend; + intel_encoder->suspend_complete = g4x_dp_suspend_complete; intel_encoder->shutdown = intel_dp_encoder_shutdown; if (IS_CHERRYVIEW(dev_priv)) { intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable; diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 4e033e4066b1..823c66ad8988 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -57,6 +57,7 @@ #include "intel_dp_tunnel.h" #include "intel_dpio_phy.h" #include "intel_dsi.h" +#include "intel_encoder.h" #include "intel_fdi.h" #include "intel_fifo_underrun.h" #include "intel_gmbus.h" @@ -4525,6 +4526,17 @@ static int intel_hdmi_reset_link(struct intel_encoder *encoder, return intel_modeset_commit_pipes(dev_priv, BIT(crtc->pipe), ctx); } +static void intel_ddi_link_check(struct intel_encoder *encoder) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); + + /* TODO: Move checking the HDMI link state here as well. */ + drm_WARN_ON(&i915->drm, !dig_port->dp.attached_connector); + + intel_dp_link_check(encoder); +} + static enum intel_hotplug_state intel_ddi_hotplug(struct intel_encoder *encoder, struct intel_connector *connector) @@ -4768,6 +4780,11 @@ static void intel_ddi_tc_encoder_suspend_complete(struct intel_encoder *encoder) struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + /* + * TODO: Move this to intel_dp_encoder_suspend(), + * once modeset locking around that is removed. + */ + intel_encoder_link_check_flush_work(encoder); intel_tc_port_suspend(dig_port); } @@ -4958,6 +4975,8 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, "DDI %c/PHY %c", port_name(port), phy_name(phy)); } + intel_encoder_link_check_init(encoder, intel_ddi_link_check); + mutex_init(&dig_port->hdcp_mutex); dig_port->num_hdcp_streams = 0; diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 3e493472cf06..1af3d48a7b86 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -161,6 +161,11 @@ struct intel_encoder { enum port port; u16 cloneable; u8 pipe_mask; + + /* Check and recover a bad link state. */ + struct delayed_work link_check_work; + void (*link_check)(struct intel_encoder *encoder); + enum intel_hotplug_state (*hotplug)(struct intel_encoder *encoder, struct intel_connector *connector); enum intel_output_type (*compute_output_type)(struct intel_encoder *, diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index edd3e0e7085f..0833302baabc 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -69,6 +69,7 @@ #include "intel_dpio_phy.h" #include "intel_dpll.h" #include "intel_drrs.h" +#include "intel_encoder.h" #include "intel_fifo_underrun.h" #include "intel_hdcp.h" #include "intel_hdmi.h" @@ -76,6 +77,7 @@ #include "intel_hotplug_irq.h" #include "intel_lspcon.h" #include "intel_lvds.h" +#include "intel_modeset_lock.h" #include "intel_panel.h" #include "intel_pch_display.h" #include "intel_pps.h" @@ -5248,6 +5250,18 @@ int intel_dp_retrain_link(struct intel_encoder *encoder, return 0; } +void intel_dp_link_check(struct intel_encoder *encoder) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct drm_modeset_acquire_ctx ctx; + int ret; + + intel_modeset_lock_ctx_retry(&ctx, NULL, 0, ret) + ret = intel_dp_retrain_link(encoder, &ctx); + + drm_WARN_ON(&i915->drm, ret); +} + static int intel_dp_prep_phy_test(struct intel_dp *intel_dp, struct drm_modeset_acquire_ctx *ctx, u8 *pipe_mask) @@ -6014,11 +6028,14 @@ void intel_dp_connector_sync_state(struct intel_connector *connector, } } -void intel_dp_encoder_flush_work(struct drm_encoder *encoder) +void intel_dp_encoder_flush_work(struct drm_encoder *_encoder) { - struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder)); + struct intel_encoder *encoder = to_intel_encoder(_encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct intel_dp *intel_dp = &dig_port->dp; + intel_encoder_link_check_flush_work(encoder); + intel_dp_mst_encoder_cleanup(dig_port); intel_dp_tunnel_destroy(intel_dp); diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 0d169027067f..79193af55518 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -60,6 +60,7 @@ int intel_dp_get_active_pipes(struct intel_dp *intel_dp, u8 *pipe_mask); int intel_dp_retrain_link(struct intel_encoder *encoder, struct drm_modeset_acquire_ctx *ctx); +void intel_dp_link_check(struct intel_encoder *encoder); void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode); void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index 190372cf76e5..1164255cf5f2 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -25,6 +25,7 @@ #include "intel_display_types.h" #include "intel_dp.h" #include "intel_dp_link_training.h" +#include "intel_encoder.h" #include "intel_panel.h" #define LT_MSG_PREFIX "[CONNECTOR:%d:%s][ENCODER:%d:%s][%s] " @@ -1464,6 +1465,8 @@ void intel_dp_start_link_train(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct intel_encoder *encoder = &dig_port->base; bool passed; /* @@ -1483,6 +1486,11 @@ void intel_dp_start_link_train(struct intel_dp *intel_dp, else passed = intel_dp_link_train_all_phys(intel_dp, crtc_state, lttpr_count); + if (passed) { + intel_encoder_link_check_queue_work(encoder, 2000); + return; + } + /* * Ignore the link failure in CI * @@ -1495,13 +1503,12 @@ void intel_dp_start_link_train(struct intel_dp *intel_dp, * For test cases which rely on the link training or processing of HPDs * ignore_long_hpd flag can unset from the testcase. */ - if (!passed && i915->display.hotplug.ignore_long_hpd) { + if (i915->display.hotplug.ignore_long_hpd) { lt_dbg(intel_dp, DP_PHY_DPRX, "Ignore the link failure\n"); return; } - if (!passed) - intel_dp_schedule_fallback_link_training(intel_dp, crtc_state); + intel_dp_schedule_fallback_link_training(intel_dp, crtc_state); } void intel_dp_128b132b_sdp_crc16(struct intel_dp *intel_dp, diff --git a/drivers/gpu/drm/i915/display/intel_encoder.c b/drivers/gpu/drm/i915/display/intel_encoder.c new file mode 100644 index 000000000000..dee55f56960f --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_encoder.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2024 Intel Corporation + */ + +#include <linux/workqueue.h> + +#include "i915_drv.h" + +#include "intel_display_types.h" +#include "intel_encoder.h" + +static void intel_encoder_link_check_work_fn(struct work_struct *work) +{ + struct intel_encoder *encoder = + container_of(work, typeof(*encoder), link_check_work.work); + + encoder->link_check(encoder); +} + +void intel_encoder_link_check_init(struct intel_encoder *encoder, + void (*callback)(struct intel_encoder *encoder)) +{ + INIT_DELAYED_WORK(&encoder->link_check_work, intel_encoder_link_check_work_fn); + encoder->link_check = callback; +} + +void intel_encoder_link_check_flush_work(struct intel_encoder *encoder) +{ + cancel_delayed_work_sync(&encoder->link_check_work); +} + +void intel_encoder_link_check_queue_work(struct intel_encoder *encoder, int delay_ms) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + mod_delayed_work(i915->unordered_wq, + &encoder->link_check_work, msecs_to_jiffies(delay_ms)); +} diff --git a/drivers/gpu/drm/i915/display/intel_encoder.h b/drivers/gpu/drm/i915/display/intel_encoder.h new file mode 100644 index 000000000000..2cda054e2b15 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_encoder.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2024 Intel Corporation + */ + +#ifndef __INTEL_ENCODER_H__ +#define __INTEL_ENCODER_H__ + +struct intel_encoder; + +void intel_encoder_link_check_init(struct intel_encoder *encoder, + void (*callback)(struct intel_encoder *encoder)); +void intel_encoder_link_check_queue_work(struct intel_encoder *encoder, int delay_ms); +void intel_encoder_link_check_flush_work(struct intel_encoder *encoder); + +#endif /* __INTEL_ENCODER_H__ */ diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 0132397a1a31..1e5d88d6a152 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -258,6 +258,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_dsi.o \ i915-display/intel_dsi_dcs_backlight.o \ i915-display/intel_dsi_vbt.o \ + i915-display/intel_encoder.o \ i915-display/intel_fb.o \ i915-display/intel_fbc.o \ i915-display/intel_fdi.o \ |