Op 24-05-18 om 14:54 schreef Ville Syrjala:
> From: Ville Syrjälä <ville.syrj...@linux.intel.com>
>
> When encountering a connector with the scaling mode property both
> intel and modesetting ddxs sometimes add tons of DBLSCAN modes
> to the output's mode list. The idea presumably being that since the
> output will be going through the panel fitter anyway we can pretend
> to use any kind of mode.
>
> Sadly that means we can't reject user modes with the DBLSCAN flag
> until we know whether we're going to be using the panel's native
> mode or the user mode directly. Doing otherwise means X clients using
> xf86vidmode/xrandr will get a protocol error (and often self
> terminate as a result) when the kernel refuses to use the requested
> mode with the DBLSCAN flag.
>
> To undo the regression we'll move the DBLSCAN checks into the
> connector->mode_valid() and encoder->compute_config() hooks.
>
> Cc: Vito Caputo <vcap...@pengaru.com>
> Reported-by: Vito Caputo <vcap...@pengaru.com>
> Fixes: e995ca0b8139 ("drm/i915: Provide a device level .mode_valid() hook")
> References: https://lkml.org/lkml/2018/5/21/715
> Signed-off-by: Ville Syrjälä <ville.syrj...@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_crt.c     | 20 ++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_display.c | 16 +++++++++++++---
>  drivers/gpu/drm/i915/intel_dp.c      |  6 ++++++
>  drivers/gpu/drm/i915/intel_dp_mst.c  |  6 ++++++
>  drivers/gpu/drm/i915/intel_dsi.c     |  6 ++++++
>  drivers/gpu/drm/i915/intel_dvo.c     |  6 ++++++
>  drivers/gpu/drm/i915/intel_hdmi.c    |  6 ++++++
>  drivers/gpu/drm/i915/intel_lvds.c    |  5 +++++
>  drivers/gpu/drm/i915/intel_sdvo.c    |  6 ++++++
>  drivers/gpu/drm/i915/intel_tv.c      | 12 ++++++++++--
>  10 files changed, 84 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_crt.c 
> b/drivers/gpu/drm/i915/intel_crt.c
> index 211d601cd1b1..95aa29cf2d9c 100644
> --- a/drivers/gpu/drm/i915/intel_crt.c
> +++ b/drivers/gpu/drm/i915/intel_crt.c
> @@ -304,6 +304,9 @@ intel_crt_mode_valid(struct drm_connector *connector,
>       int max_dotclk = dev_priv->max_dotclk_freq;
>       int max_clock;
>  
> +     if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return MODE_NO_DBLESCAN;
> +
>       if (mode->clock < 25000)
>               return MODE_CLOCK_LOW;
>  
> @@ -337,6 +340,12 @@ static bool intel_crt_compute_config(struct 
> intel_encoder *encoder,
>                                    struct intel_crtc_state *pipe_config,
>                                    struct drm_connector_state *conn_state)
>  {
> +     struct drm_display_mode *adjusted_mode =
> +             &pipe_config->base.adjusted_mode;
> +
> +     if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return false;
> +
>       return true;
>  }
>  
> @@ -344,6 +353,12 @@ static bool pch_crt_compute_config(struct intel_encoder 
> *encoder,
>                                  struct intel_crtc_state *pipe_config,
>                                  struct drm_connector_state *conn_state)
>  {
> +     struct drm_display_mode *adjusted_mode =
> +             &pipe_config->base.adjusted_mode;
> +
> +     if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return false;
> +
>       pipe_config->has_pch_encoder = true;
>  
>       return true;
> @@ -354,6 +369,11 @@ static bool hsw_crt_compute_config(struct intel_encoder 
> *encoder,
>                                  struct drm_connector_state *conn_state)
>  {
>       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +     struct drm_display_mode *adjusted_mode =
> +             &pipe_config->base.adjusted_mode;
> +
> +     if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return false;
>  
>       pipe_config->has_pch_encoder = true;
>  
> diff --git a/drivers/gpu/drm/i915/intel_display.c 
> b/drivers/gpu/drm/i915/intel_display.c
> index 8b385176ce3c..02651298a99b 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -14443,12 +14443,22 @@ static enum drm_mode_status
>  intel_mode_valid(struct drm_device *dev,
>                const struct drm_display_mode *mode)
>  {
> +     /*
> +      * Can't reject DBLSCAN here because Xorg ddxen can add piles
> +      * of DBLSCAN modes to the output's mode list when they detect
> +      * the scaling mode property on the connector. And they don't
> +      * ask the kernel to validate those modes in any way until
> +      * modeset time at which point the client gets a protocol error.
> +      * So in order to not upset those clients we silently ignore the
> +      * DBLSCAN flag on such connectors. For other connectors we will
> +      * reject modes with the DBLSCAN flag in encoder->compute_config().
> +      * And we always reject DBLSCAN modes in connector->mode_valid()
> +      * as we never want such modes on the connector's mode list.
> +      */
> +
>       if (mode->vscan > 1)
>               return MODE_NO_VSCAN;
>  
> -     if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
> -             return MODE_NO_DBLESCAN;
> -
>       if (mode->flags & DRM_MODE_FLAG_HSKEW)
>               return MODE_H_ILLEGAL;
>  
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index ce07bd794aed..91885f2500af 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -420,6 +420,9 @@ intel_dp_mode_valid(struct drm_connector *connector,
>       int max_rate, mode_rate, max_lanes, max_link_clock;
>       int max_dotclk;
>  
> +     if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return MODE_NO_DBLESCAN;
> +
>       max_dotclk = intel_dp_downstream_max_dotclock(intel_dp);
>  
>       if (intel_dp_is_edp(intel_dp) && fixed_mode) {
> @@ -1862,6 +1865,9 @@ intel_dp_compute_config(struct intel_encoder *encoder,
>                                               conn_state->scaling_mode);
>       }
>  
> +     if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return false;
> +
>       if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
>           adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
>               return false;
> diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c 
> b/drivers/gpu/drm/i915/intel_dp_mst.c
> index 9e6956c08688..5890500a3a8b 100644
> --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> @@ -48,6 +48,9 @@ static bool intel_dp_mst_compute_config(struct 
> intel_encoder *encoder,
>       bool reduce_m_n = drm_dp_has_quirk(&intel_dp->desc,
>                                          DP_DPCD_QUIRK_LIMITED_M_N);
>  
> +     if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return false;
> +
>       pipe_config->has_pch_encoder = false;
>       bpp = 24;
>       if (intel_dp->compliance.test_data.bpc) {
> @@ -366,6 +369,9 @@ intel_dp_mst_mode_valid(struct drm_connector *connector,
>       if (!intel_dp)
>               return MODE_ERROR;
>  
> +     if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return MODE_NO_DBLESCAN;
> +
>       max_link_clock = intel_dp_max_link_rate(intel_dp);
>       max_lanes = intel_dp_max_lane_count(intel_dp);
>  
> diff --git a/drivers/gpu/drm/i915/intel_dsi.c 
> b/drivers/gpu/drm/i915/intel_dsi.c
> index cf39ca90d887..f349b3920199 100644
> --- a/drivers/gpu/drm/i915/intel_dsi.c
> +++ b/drivers/gpu/drm/i915/intel_dsi.c
> @@ -326,6 +326,9 @@ static bool intel_dsi_compute_config(struct intel_encoder 
> *encoder,
>                                               conn_state->scaling_mode);
>       }
>  
> +     if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return false;
> +
>       /* DSI uses short packets for sync events, so clear mode flags for DSI 
> */
>       adjusted_mode->flags = 0;
>  
> @@ -1266,6 +1269,9 @@ intel_dsi_mode_valid(struct drm_connector *connector,
>  
>       DRM_DEBUG_KMS("\n");
>  
> +     if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return MODE_NO_DBLESCAN;
> +
>       if (fixed_mode) {
>               if (mode->hdisplay > fixed_mode->hdisplay)
>                       return MODE_PANEL;
> diff --git a/drivers/gpu/drm/i915/intel_dvo.c 
> b/drivers/gpu/drm/i915/intel_dvo.c
> index 7b942b6c1700..27f16db8953a 100644
> --- a/drivers/gpu/drm/i915/intel_dvo.c
> +++ b/drivers/gpu/drm/i915/intel_dvo.c
> @@ -215,6 +215,9 @@ intel_dvo_mode_valid(struct drm_connector *connector,
>       int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
>       int target_clock = mode->clock;
>  
> +     if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return MODE_NO_DBLESCAN;
> +
>       /* XXX: Validate clock range */
>  
>       if (fixed_mode) {
> @@ -250,6 +253,9 @@ static bool intel_dvo_compute_config(struct intel_encoder 
> *encoder,
>       if (fixed_mode)
>               intel_fixed_panel_mode(fixed_mode, adjusted_mode);
>  
> +     if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return false;
> +
>       return true;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c 
> b/drivers/gpu/drm/i915/intel_hdmi.c
> index 0ca4cc877520..47e6cca3e208 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1544,6 +1544,9 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
>       bool force_dvi =
>               
> READ_ONCE(to_intel_digital_connector_state(connector->state)->force_audio) == 
> HDMI_AUDIO_OFF_DVI;
>  
> +     if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return MODE_NO_DBLESCAN;
> +
>       clock = mode->clock;
>  
>       if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == 
> DRM_MODE_FLAG_3D_FRAME_PACKING)
> @@ -1664,6 +1667,9 @@ bool intel_hdmi_compute_config(struct intel_encoder 
> *encoder,
>       int desired_bpp;
>       bool force_dvi = intel_conn_state->force_audio == HDMI_AUDIO_OFF_DVI;
>  
> +     if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return false;
> +
>       pipe_config->has_hdmi_sink = !force_dvi && intel_hdmi->has_hdmi_sink;
>  
>       if (pipe_config->has_hdmi_sink)
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c 
> b/drivers/gpu/drm/i915/intel_lvds.c
> index bacad88ad7ae..5b4a35299531 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -378,6 +378,8 @@ intel_lvds_mode_valid(struct drm_connector *connector,
>       struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
>       int max_pixclk = to_i915(connector->dev)->max_dotclk_freq;
>  
> +     if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return MODE_NO_DBLESCAN;
>       if (mode->hdisplay > fixed_mode->hdisplay)
>               return MODE_PANEL;
>       if (mode->vdisplay > fixed_mode->vdisplay)
> @@ -427,6 +429,9 @@ static bool intel_lvds_compute_config(struct 
> intel_encoder *intel_encoder,
>       intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
>                              adjusted_mode);
>  
> +     if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return false;
> +
>       if (HAS_PCH_SPLIT(dev_priv)) {
>               pipe_config->has_pch_encoder = true;
>  
> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c 
> b/drivers/gpu/drm/i915/intel_sdvo.c
> index a02e4d73c7a4..e6a64b3ecd91 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -1160,6 +1160,9 @@ static bool intel_sdvo_compute_config(struct 
> intel_encoder *encoder,
>                                                          adjusted_mode);
>       }
>  
> +     if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return false;
> +
>       /*
>        * Make the CRTC code factor in the SDVO pixel multiplier.  The
>        * SDVO device will factor out the multiplier during mode_set.
> @@ -1631,6 +1634,9 @@ intel_sdvo_mode_valid(struct drm_connector *connector,
>       struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
>       int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
>  
> +     if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return MODE_NO_DBLESCAN;
> +
>       if (intel_sdvo->pixel_clock_min > mode->clock)
>               return MODE_CLOCK_LOW;
>  
> diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
> index 99bc2368dda0..24dc368fdaa1 100644
> --- a/drivers/gpu/drm/i915/intel_tv.c
> +++ b/drivers/gpu/drm/i915/intel_tv.c
> @@ -846,6 +846,9 @@ intel_tv_mode_valid(struct drm_connector *connector,
>       const struct tv_mode *tv_mode = intel_tv_mode_find(connector->state);
>       int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
>  
> +     if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return MODE_NO_DBLESCAN;
> +
>       if (mode->clock > max_dotclk)
>               return MODE_CLOCK_HIGH;
>  
> @@ -873,16 +876,21 @@ intel_tv_compute_config(struct intel_encoder *encoder,
>                       struct drm_connector_state *conn_state)
>  {
>       const struct tv_mode *tv_mode = intel_tv_mode_find(conn_state);
> +     struct drm_display_mode *adjusted_mode =
> +             &pipe_config->base.adjusted_mode;
>  
>       if (!tv_mode)
>               return false;
>  
> -     pipe_config->base.adjusted_mode.crtc_clock = tv_mode->clock;
> +     if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +             return false;
> +
> +     adjusted_mode->crtc_clock = tv_mode->clock;
>       DRM_DEBUG_KMS("forcing bpc to 8 for TV\n");
>       pipe_config->pipe_bpp = 8*3;
>  
>       /* TV has it's own notion of sync and other mode flags, so clear them. 
> */
> -     pipe_config->base.adjusted_mode.flags = 0;
> +     adjusted_mode->flags = 0;
>  
>       /*
>        * FIXME: We don't check whether the input mode is actually what we want


Reviewed-by: Maarten Lankhorst <maarten.lankho...@linux.intel.com>

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to