drm/i915: Skip some timing checks on BXT/GLK DSI transcoders
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Mon, 27 Nov 2023 14:50:25 +0000 (16:50 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Dec 2023 17:39:30 +0000 (18:39 +0100)
[ Upstream commit 20c2dbff342aec13bf93c2f6c951da198916a455 ]

Apparently some BXT/GLK systems have DSI panels whose timings
don't agree with the normal cpu transcoder hblank>=32 limitation.
This is perhaps fine as there are no specific hblank/etc. limits
listed for the BXT/GLK DSI transcoders.

Move those checks out from the global intel_mode_valid() into
into connector specific .mode_valid() hooks, skipping BXT/GLK
DSI connectors. We'll leave the basic [hv]display/[hv]total
checks in intel_mode_valid() as those seem like sensible upper
limits regardless of the transcoder used.

Cc: stable@vger.kernel.org
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/9720
Fixes: 8f4b1068e7fc ("drm/i915: Check some transcoder timing minimum limits")
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231127145028.4899-1-ville.syrjala@linux.intel.com
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
(cherry picked from commit e0ef2daa8ca8ce4dbc2fd0959e383b753a87fd7d)
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
12 files changed:
drivers/gpu/drm/i915/display/icl_dsi.c
drivers/gpu/drm/i915/display/intel_crt.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_display.h
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/display/intel_dp_mst.c
drivers/gpu/drm/i915/display/intel_dvo.c
drivers/gpu/drm/i915/display/intel_hdmi.c
drivers/gpu/drm/i915/display/intel_lvds.c
drivers/gpu/drm/i915/display/intel_sdvo.c
drivers/gpu/drm/i915/display/intel_tv.c
drivers/gpu/drm/i915/display/vlv_dsi.c

index 8219310..f7422f0 100644 (file)
@@ -1500,6 +1500,13 @@ static void gen11_dsi_post_disable(struct intel_atomic_state *state,
 static enum drm_mode_status gen11_dsi_mode_valid(struct drm_connector *connector,
                                                 struct drm_display_mode *mode)
 {
+       struct drm_i915_private *i915 = to_i915(connector->dev);
+       enum drm_mode_status status;
+
+       status = intel_cpu_transcoder_mode_valid(i915, mode);
+       if (status != MODE_OK)
+               return status;
+
        /* FIXME: DSC? */
        return intel_dsi_mode_valid(connector, mode);
 }
index 4a8ff2f..e60b2cf 100644 (file)
@@ -343,8 +343,13 @@ intel_crt_mode_valid(struct drm_connector *connector,
        struct drm_device *dev = connector->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        int max_dotclk = dev_priv->max_dotclk_freq;
+       enum drm_mode_status status;
        int max_clock;
 
+       status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
+       if (status != MODE_OK)
+               return status;
+
        if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
                return MODE_NO_DBLESCAN;
 
index 96e679a..1777a12 100644 (file)
@@ -8229,6 +8229,16 @@ intel_mode_valid(struct drm_device *dev,
            mode->vtotal > vtotal_max)
                return MODE_V_ILLEGAL;
 
+       return MODE_OK;
+}
+
+enum drm_mode_status intel_cpu_transcoder_mode_valid(struct drm_i915_private *dev_priv,
+                                                    const struct drm_display_mode *mode)
+{
+       /*
+        * Additional transcoder timing limits,
+        * excluding BXT/GLK DSI transcoders.
+        */
        if (DISPLAY_VER(dev_priv) >= 5) {
                if (mode->hdisplay < 64 ||
                    mode->htotal - mode->hdisplay < 32)
index 884e8e6..b4f9416 100644 (file)
@@ -554,6 +554,9 @@ enum drm_mode_status
 intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
                                const struct drm_display_mode *mode,
                                bool bigjoiner);
+enum drm_mode_status
+intel_cpu_transcoder_mode_valid(struct drm_i915_private *i915,
+                               const struct drm_display_mode *mode);
 enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port);
 bool is_trans_port_sync_mode(const struct intel_crtc_state *state);
 bool intel_crtc_is_bigjoiner_slave(const struct intel_crtc_state *crtc_state);
index fd7c360..5970f41 100644 (file)
@@ -973,6 +973,10 @@ intel_dp_mode_valid(struct drm_connector *_connector,
        enum drm_mode_status status;
        bool dsc = false, bigjoiner = false;
 
+       status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
+       if (status != MODE_OK)
+               return status;
+
        if (mode->flags & DRM_MODE_FLAG_DBLCLK)
                return MODE_H_ILLEGAL;
 
index 9a68222..eec32f6 100644 (file)
@@ -703,6 +703,10 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
                return 0;
        }
 
+       *status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
+       if (*status != MODE_OK)
+               return 0;
+
        if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
                *status = MODE_NO_DBLESCAN;
                return 0;
index 5572e43..511c589 100644 (file)
@@ -225,10 +225,16 @@ intel_dvo_mode_valid(struct drm_connector *connector,
 {
        struct intel_connector *intel_connector = to_intel_connector(connector);
        struct intel_dvo *intel_dvo = intel_attached_dvo(intel_connector);
+       struct drm_i915_private *i915 = to_i915(intel_connector->base.dev);
        const struct drm_display_mode *fixed_mode =
                intel_panel_fixed_mode(intel_connector, mode);
        int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
        int target_clock = mode->clock;
+       enum drm_mode_status status;
+
+       status = intel_cpu_transcoder_mode_valid(i915, mode);
+       if (status != MODE_OK)
+               return status;
 
        if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
                return MODE_NO_DBLESCAN;
index 4f31355..2600019 100644 (file)
@@ -1987,6 +1987,10 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
        bool has_hdmi_sink = intel_has_hdmi_sink(hdmi, connector->state);
        bool ycbcr_420_only;
 
+       status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
+       if (status != MODE_OK)
+               return status;
+
        if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING)
                clock *= 2;
 
index e4606d9..40b5d3d 100644 (file)
@@ -389,11 +389,16 @@ intel_lvds_mode_valid(struct drm_connector *connector,
                      struct drm_display_mode *mode)
 {
        struct intel_connector *intel_connector = to_intel_connector(connector);
+       struct drm_i915_private *i915 = to_i915(intel_connector->base.dev);
        const struct drm_display_mode *fixed_mode =
                intel_panel_fixed_mode(intel_connector, mode);
        int max_pixclk = to_i915(connector->dev)->max_dotclk_freq;
        enum drm_mode_status status;
 
+       status = intel_cpu_transcoder_mode_valid(i915, mode);
+       if (status != MODE_OK)
+               return status;
+
        if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
                return MODE_NO_DBLESCAN;
 
index c1a8512..8294ddd 100644 (file)
@@ -1873,13 +1873,19 @@ static enum drm_mode_status
 intel_sdvo_mode_valid(struct drm_connector *connector,
                      struct drm_display_mode *mode)
 {
+       struct drm_i915_private *i915 = to_i915(connector->dev);
        struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector));
        struct intel_sdvo_connector *intel_sdvo_connector =
                to_intel_sdvo_connector(connector);
-       int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
        bool has_hdmi_sink = intel_has_hdmi_sink(intel_sdvo_connector, connector->state);
+       int max_dotclk = i915->max_dotclk_freq;
+       enum drm_mode_status status;
        int clock = mode->clock;
 
+       status = intel_cpu_transcoder_mode_valid(i915, mode);
+       if (status != MODE_OK)
+               return status;
+
        if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
                return MODE_NO_DBLESCAN;
 
index dcf89d7..fb25be8 100644 (file)
@@ -956,8 +956,14 @@ static enum drm_mode_status
 intel_tv_mode_valid(struct drm_connector *connector,
                    struct drm_display_mode *mode)
 {
+       struct drm_i915_private *i915 = to_i915(connector->dev);
        const struct tv_mode *tv_mode = intel_tv_mode_find(connector->state);
-       int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
+       int max_dotclk = i915->max_dotclk_freq;
+       enum drm_mode_status status;
+
+       status = intel_cpu_transcoder_mode_valid(i915, mode);
+       if (status != MODE_OK)
+               return status;
 
        if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
                return MODE_NO_DBLESCAN;
index 00c80f2..114088c 100644 (file)
@@ -1627,9 +1627,25 @@ static const struct drm_encoder_funcs intel_dsi_funcs = {
        .destroy = intel_dsi_encoder_destroy,
 };
 
+static enum drm_mode_status vlv_dsi_mode_valid(struct drm_connector *connector,
+                                              struct drm_display_mode *mode)
+{
+       struct drm_i915_private *i915 = to_i915(connector->dev);
+
+       if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
+               enum drm_mode_status status;
+
+               status = intel_cpu_transcoder_mode_valid(i915, mode);
+               if (status != MODE_OK)
+                       return status;
+       }
+
+       return intel_dsi_mode_valid(connector, mode);
+}
+
 static const struct drm_connector_helper_funcs intel_dsi_connector_helper_funcs = {
        .get_modes = intel_dsi_get_modes,
-       .mode_valid = intel_dsi_mode_valid,
+       .mode_valid = vlv_dsi_mode_valid,
        .atomic_check = intel_digital_connector_atomic_check,
 };