diff mbox

[1/6] drm/i915: add encoder get_config function v5

Message ID 1368576511-10675-2-git-send-email-jbarnes@virtuousgeek.org (mailing list archive)
State New, archived
Headers show

Commit Message

Jesse Barnes May 15, 2013, 12:08 a.m. UTC
We can use this for fetching encoder specific pipe_config state, like
mode flags, adjusted clock, etc.

Just used for mode flags atm, so we can check the pipe config state at
mode set time.

v2: get_config when checking hw state too
v3: fix DVO and LVDS mode flags (Ville)
    get SDVO DTD for flag fetch (Ville)
v4: use input timings (Ville)
    correct command used (Ville)
    remove gen4 check (Ville)
v5: get DDI flag config too

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_crt.c     |   23 +++++++++++++++++++
 drivers/gpu/drm/i915/intel_ddi.c     |   23 +++++++++++++++++++
 drivers/gpu/drm/i915/intel_display.c |   20 +++++++++++++---
 drivers/gpu/drm/i915/intel_dp.c      |   23 +++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |    4 ++++
 drivers/gpu/drm/i915/intel_dvo.c     |   21 +++++++++++++++++
 drivers/gpu/drm/i915/intel_hdmi.c    |   23 +++++++++++++++++++
 drivers/gpu/drm/i915/intel_lvds.c    |   26 +++++++++++++++++++++
 drivers/gpu/drm/i915/intel_sdvo.c    |   42 ++++++++++++++++++++++++++++++++++
 9 files changed, 202 insertions(+), 3 deletions(-)

Comments

Paulo Zanoni May 15, 2013, 9:45 p.m. UTC | #1
2013/5/14 Jesse Barnes <jbarnes@virtuousgeek.org>:
> We can use this for fetching encoder specific pipe_config state, like
> mode flags, adjusted clock, etc.
>
> Just used for mode flags atm, so we can check the pipe config state at
> mode set time.
>
> v2: get_config when checking hw state too
> v3: fix DVO and LVDS mode flags (Ville)
>     get SDVO DTD for flag fetch (Ville)
> v4: use input timings (Ville)
>     correct command used (Ville)
>     remove gen4 check (Ville)
> v5: get DDI flag config too
>
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

I applied this on my Haswell machine and booted it with both eDP-only
and eDP+DP and now I don't see those error messages anymore.


> ---
>  drivers/gpu/drm/i915/intel_crt.c     |   23 +++++++++++++++++++
>  drivers/gpu/drm/i915/intel_ddi.c     |   23 +++++++++++++++++++
>  drivers/gpu/drm/i915/intel_display.c |   20 +++++++++++++---
>  drivers/gpu/drm/i915/intel_dp.c      |   23 +++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h     |    4 ++++
>  drivers/gpu/drm/i915/intel_dvo.c     |   21 +++++++++++++++++
>  drivers/gpu/drm/i915/intel_hdmi.c    |   23 +++++++++++++++++++
>  drivers/gpu/drm/i915/intel_lvds.c    |   26 +++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_sdvo.c    |   42 ++++++++++++++++++++++++++++++++++
>  9 files changed, 202 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
> index cc414f1..789c4ef 100644
> --- a/drivers/gpu/drm/i915/intel_crt.c
> +++ b/drivers/gpu/drm/i915/intel_crt.c
> @@ -81,6 +81,28 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
>         return true;
>  }
>
> +static void intel_crt_get_config(struct intel_encoder *encoder,
> +                                struct intel_crtc_config *pipe_config)
> +{
> +       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> +       struct intel_crt *crt = intel_encoder_to_crt(encoder);
> +       u32 tmp, flags = 0;
> +
> +       tmp = I915_READ(crt->adpa_reg);
> +
> +       if (tmp & ADPA_HSYNC_ACTIVE_HIGH)
> +               flags |= DRM_MODE_FLAG_PHSYNC;
> +       else
> +               flags |= DRM_MODE_FLAG_NHSYNC;
> +
> +       if (tmp & ADPA_VSYNC_ACTIVE_HIGH)
> +               flags |= DRM_MODE_FLAG_PVSYNC;
> +       else
> +               flags |= DRM_MODE_FLAG_NVSYNC;
> +
> +       pipe_config->adjusted_mode.flags |= flags;
> +}
> +
>  static void intel_disable_crt(struct intel_encoder *encoder)
>  {
>         struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> @@ -784,6 +806,7 @@ void intel_crt_init(struct drm_device *dev)
>         crt->base.compute_config = intel_crt_compute_config;
>         crt->base.disable = intel_disable_crt;
>         crt->base.enable = intel_enable_crt;
> +       crt->base.get_config = intel_crt_get_config;
>         if (I915_HAS_HOTPLUG(dev))
>                 crt->base.hpd_pin = HPD_CRT;
>         if (HAS_DDI(dev))
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index cddcf4a..27a74a9 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -1254,6 +1254,28 @@ static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder)
>                 intel_dp_check_link_status(intel_dp);
>  }
>
> +static void intel_ddi_get_config(struct intel_encoder *encoder,
> +                                struct intel_crtc_config *pipe_config)
> +{
> +       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> +       struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
> +       enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
> +       u32 temp, flags = 0;
> +
> +       temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
> +       if (temp & TRANS_DDI_PHSYNC)
> +               flags |= DRM_MODE_FLAG_PHSYNC;
> +       else
> +               flags |= DRM_MODE_FLAG_NHSYNC;
> +       if (temp & TRANS_DDI_PVSYNC)
> +               flags |= DRM_MODE_FLAG_PVSYNC;
> +       else
> +               flags |= DRM_MODE_FLAG_NVSYNC;
> +
> +       pipe_config->adjusted_mode.flags |= flags;
> +       pipe_config->pixel_multiplier = 1;
> +}
> +
>  static void intel_ddi_destroy(struct drm_encoder *encoder)
>  {
>         /* HDMI has nothing special to destroy, so we can go with this. */
> @@ -1313,6 +1335,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
>         intel_encoder->disable = intel_disable_ddi;
>         intel_encoder->post_disable = intel_ddi_post_disable;
>         intel_encoder->get_hw_state = intel_ddi_get_hw_state;
> +       intel_encoder->get_config = intel_ddi_get_config;
>
>         intel_dig_port->port = port;
>         intel_dig_port->port_reversal = I915_READ(DDI_BUF_CTL(port)) &
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 7358e4e..163b97e 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -8057,6 +8057,15 @@ intel_pipe_config_compare(struct drm_device *dev,
>         PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
>                               DRM_MODE_FLAG_INTERLACE);
>
> +       PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
> +                             DRM_MODE_FLAG_PHSYNC);
> +       PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
> +                             DRM_MODE_FLAG_NHSYNC);
> +       PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
> +                             DRM_MODE_FLAG_PVSYNC);
> +       PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
> +                             DRM_MODE_FLAG_NVSYNC);
> +
>         PIPE_CONF_CHECK_I(requested_mode.hdisplay);
>         PIPE_CONF_CHECK_I(requested_mode.vdisplay);
>
> @@ -8149,6 +8158,8 @@ intel_modeset_check_state(struct drm_device *dev)
>                 bool enabled = false;
>                 bool active = false;
>
> +               memset(&pipe_config, 0, sizeof(pipe_config));
> +
>                 DRM_DEBUG_KMS("[CRTC:%d]\n",
>                               crtc->base.base.id);
>
> @@ -8162,6 +8173,8 @@ intel_modeset_check_state(struct drm_device *dev)
>                         enabled = true;
>                         if (encoder->connectors_active)
>                                 active = true;
> +                       if (encoder->get_config)
> +                               encoder->get_config(encoder, &pipe_config);
>                 }
>                 WARN(active != crtc->active,
>                      "crtc's computed active state doesn't match tracked active state "
> @@ -8170,7 +8183,6 @@ intel_modeset_check_state(struct drm_device *dev)
>                      "crtc's computed enabled state doesn't match tracked enabled state "
>                      "(expected %i, found %i)\n", enabled, crtc->base.enabled);
>
> -               memset(&pipe_config, 0, sizeof(pipe_config));
>                 pipe_config.cpu_transcoder = crtc->config.cpu_transcoder;
>                 active = dev_priv->display.get_pipe_config(crtc,
>                                                            &pipe_config);
> @@ -9579,8 +9591,10 @@ setup_pipes:
>                 pipe = 0;
>
>                 if (encoder->get_hw_state(encoder, &pipe)) {
> -                       encoder->base.crtc =
> -                               dev_priv->pipe_to_crtc_mapping[pipe];
> +                       crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
> +                       encoder->base.crtc = &crtc->base;
> +                       if (encoder->get_config)
> +                               encoder->get_config(encoder, &crtc->config);
>                 } else {
>                         encoder->base.crtc = NULL;
>                 }
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 2bb4009..a423256 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1356,6 +1356,28 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
>         return true;
>  }
>
> +static void intel_dp_get_config(struct intel_encoder *encoder,
> +                               struct intel_crtc_config *pipe_config)
> +{
> +       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> +       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> +       u32 tmp, flags = 0;
> +
> +       tmp = I915_READ(intel_dp->output_reg);
> +
> +       if (tmp & DP_SYNC_HS_HIGH)
> +               flags |= DRM_MODE_FLAG_PHSYNC;
> +       else
> +               flags |= DRM_MODE_FLAG_NHSYNC;
> +
> +       if (tmp & DP_SYNC_VS_HIGH)
> +               flags |= DRM_MODE_FLAG_PVSYNC;
> +       else
> +               flags |= DRM_MODE_FLAG_NVSYNC;
> +
> +       pipe_config->adjusted_mode.flags |= flags;
> +}
> +
>  static void intel_disable_dp(struct intel_encoder *encoder)
>  {
>         struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> @@ -3154,6 +3176,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
>         intel_encoder->disable = intel_disable_dp;
>         intel_encoder->post_disable = intel_post_disable_dp;
>         intel_encoder->get_hw_state = intel_dp_get_hw_state;
> +       intel_encoder->get_config = intel_dp_get_config;
>         if (IS_VALLEYVIEW(dev))
>                 intel_encoder->pre_pll_enable = intel_dp_pre_pll_enable;
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 0f35545..4802483 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -139,6 +139,10 @@ struct intel_encoder {
>          * the encoder is active. If the encoder is enabled it also set the pipe
>          * it is connected to in the pipe parameter. */
>         bool (*get_hw_state)(struct intel_encoder *, enum pipe *pipe);
> +       /* Reconstructs the equivalent mode flags for the current hardware
> +        * state. */
> +       void (*get_config)(struct intel_encoder *,
> +                          struct intel_crtc_config *pipe_config);
>         int crtc_mask;
>         enum hpd_pin hpd_pin;
>  };
> diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
> index 00e70db..91e9905 100644
> --- a/drivers/gpu/drm/i915/intel_dvo.c
> +++ b/drivers/gpu/drm/i915/intel_dvo.c
> @@ -129,6 +129,26 @@ static bool intel_dvo_get_hw_state(struct intel_encoder *encoder,
>         return true;
>  }
>
> +static void intel_dvo_get_config(struct intel_encoder *encoder,
> +                                struct intel_crtc_config *pipe_config)
> +{
> +       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> +       struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
> +       u32 tmp, flags = 0;
> +
> +       tmp = I915_READ(intel_dvo->dev.dvo_reg);
> +       if (tmp & DVO_HSYNC_ACTIVE_HIGH)
> +               flags |= DRM_MODE_FLAG_PHSYNC;
> +       else
> +               flags |= DRM_MODE_FLAG_NHSYNC;
> +       if (tmp & DVO_VSYNC_ACTIVE_HIGH)
> +               flags |= DRM_MODE_FLAG_PVSYNC;
> +       else
> +               flags |= DRM_MODE_FLAG_NVSYNC;
> +
> +       pipe_config->adjusted_mode.flags |= flags;
> +}
> +
>  static void intel_disable_dvo(struct intel_encoder *encoder)
>  {
>         struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> @@ -440,6 +460,7 @@ void intel_dvo_init(struct drm_device *dev)
>         intel_encoder->disable = intel_disable_dvo;
>         intel_encoder->enable = intel_enable_dvo;
>         intel_encoder->get_hw_state = intel_dvo_get_hw_state;
> +       intel_encoder->get_config = intel_dvo_get_config;
>         intel_connector->get_hw_state = intel_dvo_connector_get_hw_state;
>
>         /* Now, try to find a controller */
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index 93de5ff..9091655 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -658,6 +658,28 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
>         return true;
>  }
>
> +static void intel_hdmi_get_config(struct intel_encoder *encoder,
> +                                 struct intel_crtc_config *pipe_config)
> +{
> +       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
> +       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> +       u32 tmp, flags = 0;
> +
> +       tmp = I915_READ(intel_hdmi->hdmi_reg);
> +
> +       if (tmp & SDVO_HSYNC_ACTIVE_HIGH)
> +               flags |= DRM_MODE_FLAG_PHSYNC;
> +       else
> +               flags |= DRM_MODE_FLAG_NHSYNC;
> +
> +       if (tmp & SDVO_VSYNC_ACTIVE_HIGH)
> +               flags |= DRM_MODE_FLAG_PVSYNC;
> +       else
> +               flags |= DRM_MODE_FLAG_NVSYNC;
> +
> +       pipe_config->adjusted_mode.flags |= flags;
> +}
> +
>  static void intel_enable_hdmi(struct intel_encoder *encoder)
>  {
>         struct drm_device *dev = encoder->base.dev;
> @@ -1208,6 +1230,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
>         intel_encoder->enable = intel_enable_hdmi;
>         intel_encoder->disable = intel_disable_hdmi;
>         intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
> +       intel_encoder->get_config = intel_hdmi_get_config;
>         if (IS_VALLEYVIEW(dev)) {
>                 intel_encoder->pre_enable = intel_hdmi_pre_enable;
>                 intel_encoder->pre_pll_enable = intel_hdmi_pre_pll_enable;
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index 36fe291..6554860 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -86,6 +86,31 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
>         return true;
>  }
>
> +static void intel_lvds_get_config(struct intel_encoder *encoder,
> +                                 struct intel_crtc_config *pipe_config)
> +{
> +       struct drm_device *dev = encoder->base.dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       u32 lvds_reg, tmp, flags = 0;
> +
> +       if (HAS_PCH_SPLIT(dev))
> +               lvds_reg = PCH_LVDS;
> +       else
> +               lvds_reg = LVDS;
> +
> +       tmp = I915_READ(lvds_reg);
> +       if (tmp & LVDS_HSYNC_POLARITY)
> +               flags |= DRM_MODE_FLAG_NHSYNC;
> +       else
> +               flags |= DRM_MODE_FLAG_PHSYNC;
> +       if (tmp & LVDS_VSYNC_POLARITY)
> +               flags |= DRM_MODE_FLAG_NVSYNC;
> +       else
> +               flags |= DRM_MODE_FLAG_PVSYNC;
> +
> +       pipe_config->adjusted_mode.flags |= flags;
> +}
> +
>  /* The LVDS pin pair needs to be on before the DPLLs are enabled.
>   * This is an exception to the general rule that mode_set doesn't turn
>   * things on.
> @@ -921,6 +946,7 @@ bool intel_lvds_init(struct drm_device *dev)
>         intel_encoder->compute_config = intel_lvds_compute_config;
>         intel_encoder->disable = intel_disable_lvds;
>         intel_encoder->get_hw_state = intel_lvds_get_hw_state;
> +       intel_encoder->get_config = intel_lvds_get_config;
>         intel_connector->get_hw_state = intel_connector_get_hw_state;
>
>         intel_connector_attach_encoder(intel_connector, intel_encoder);
> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> index 2f54dc3..416d23c 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -712,6 +712,13 @@ static bool intel_sdvo_set_timing(struct intel_sdvo *intel_sdvo, u8 cmd,
>                 intel_sdvo_set_value(intel_sdvo, cmd + 1, &dtd->part2, sizeof(dtd->part2));
>  }
>
> +static bool intel_sdvo_get_timing(struct intel_sdvo *intel_sdvo, u8 cmd,
> +                                 struct intel_sdvo_dtd *dtd)
> +{
> +       return intel_sdvo_get_value(intel_sdvo, cmd, &dtd->part1, sizeof(dtd->part1)) &&
> +               intel_sdvo_get_value(intel_sdvo, cmd + 1, &dtd->part2, sizeof(dtd->part2));
> +}
> +
>  static bool intel_sdvo_set_input_timing(struct intel_sdvo *intel_sdvo,
>                                          struct intel_sdvo_dtd *dtd)
>  {
> @@ -726,6 +733,13 @@ static bool intel_sdvo_set_output_timing(struct intel_sdvo *intel_sdvo,
>                                      SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd);
>  }
>
> +static bool intel_sdvo_get_input_timing(struct intel_sdvo *intel_sdvo,
> +                                       struct intel_sdvo_dtd *dtd)
> +{
> +       return intel_sdvo_get_timing(intel_sdvo,
> +                                    SDVO_CMD_GET_INPUT_TIMINGS_PART1, dtd);
> +}
> +
>  static bool
>  intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo,
>                                          uint16_t clock,
> @@ -1295,6 +1309,33 @@ static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder,
>         return true;
>  }
>
> +static void intel_sdvo_get_config(struct intel_encoder *encoder,
> +                                 struct intel_crtc_config *pipe_config)
> +{
> +       struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
> +       struct intel_sdvo_dtd dtd;
> +       u32 flags = 0;
> +       bool ret;
> +
> +       ret = intel_sdvo_get_input_timing(intel_sdvo, &dtd);
> +       if (!ret) {
> +               DRM_DEBUG_DRIVER("failed to retrieve SDVO DTD\n");
> +               return;
> +       }
> +
> +       if (dtd.part2.dtd_flags & DTD_FLAG_HSYNC_POSITIVE)
> +               flags |= DRM_MODE_FLAG_PHSYNC;
> +       else
> +               flags |= DRM_MODE_FLAG_NHSYNC;
> +
> +       if (dtd.part2.dtd_flags & DTD_FLAG_VSYNC_POSITIVE)
> +               flags |= DRM_MODE_FLAG_PVSYNC;
> +       else
> +               flags |= DRM_MODE_FLAG_NVSYNC;
> +
> +       pipe_config->adjusted_mode.flags |= flags;
> +}
> +
>  static void intel_disable_sdvo(struct intel_encoder *encoder)
>  {
>         struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> @@ -2819,6 +2860,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
>         intel_encoder->mode_set = intel_sdvo_mode_set;
>         intel_encoder->enable = intel_enable_sdvo;
>         intel_encoder->get_hw_state = intel_sdvo_get_hw_state;
> +       intel_encoder->get_config = intel_sdvo_get_config;
>
>         /* In default case sdvo lvds is false */
>         if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))
> --
> 1.7.9.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Daniel Vetter May 21, 2013, 7:51 a.m. UTC | #2
On Wed, May 15, 2013 at 06:45:35PM -0300, Paulo Zanoni wrote:
> 2013/5/14 Jesse Barnes <jbarnes@virtuousgeek.org>:
> > We can use this for fetching encoder specific pipe_config state, like
> > mode flags, adjusted clock, etc.
> >
> > Just used for mode flags atm, so we can check the pipe config state at
> > mode set time.
> >
> > v2: get_config when checking hw state too
> > v3: fix DVO and LVDS mode flags (Ville)
> >     get SDVO DTD for flag fetch (Ville)
> > v4: use input timings (Ville)
> >     correct command used (Ville)
> >     remove gen4 check (Ville)
> > v5: get DDI flag config too
> >
> > Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> I applied this on my Haswell machine and booted it with both eDP-only
> and eDP+DP and now I don't see those error messages anymore.

Queued for -next, thanks for the patch.
-Daniel
> 
> 
> > ---
> >  drivers/gpu/drm/i915/intel_crt.c     |   23 +++++++++++++++++++
> >  drivers/gpu/drm/i915/intel_ddi.c     |   23 +++++++++++++++++++
> >  drivers/gpu/drm/i915/intel_display.c |   20 +++++++++++++---
> >  drivers/gpu/drm/i915/intel_dp.c      |   23 +++++++++++++++++++
> >  drivers/gpu/drm/i915/intel_drv.h     |    4 ++++
> >  drivers/gpu/drm/i915/intel_dvo.c     |   21 +++++++++++++++++
> >  drivers/gpu/drm/i915/intel_hdmi.c    |   23 +++++++++++++++++++
> >  drivers/gpu/drm/i915/intel_lvds.c    |   26 +++++++++++++++++++++
> >  drivers/gpu/drm/i915/intel_sdvo.c    |   42 ++++++++++++++++++++++++++++++++++
> >  9 files changed, 202 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
> > index cc414f1..789c4ef 100644
> > --- a/drivers/gpu/drm/i915/intel_crt.c
> > +++ b/drivers/gpu/drm/i915/intel_crt.c
> > @@ -81,6 +81,28 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
> >         return true;
> >  }
> >
> > +static void intel_crt_get_config(struct intel_encoder *encoder,
> > +                                struct intel_crtc_config *pipe_config)
> > +{
> > +       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> > +       struct intel_crt *crt = intel_encoder_to_crt(encoder);
> > +       u32 tmp, flags = 0;
> > +
> > +       tmp = I915_READ(crt->adpa_reg);
> > +
> > +       if (tmp & ADPA_HSYNC_ACTIVE_HIGH)
> > +               flags |= DRM_MODE_FLAG_PHSYNC;
> > +       else
> > +               flags |= DRM_MODE_FLAG_NHSYNC;
> > +
> > +       if (tmp & ADPA_VSYNC_ACTIVE_HIGH)
> > +               flags |= DRM_MODE_FLAG_PVSYNC;
> > +       else
> > +               flags |= DRM_MODE_FLAG_NVSYNC;
> > +
> > +       pipe_config->adjusted_mode.flags |= flags;
> > +}
> > +
> >  static void intel_disable_crt(struct intel_encoder *encoder)
> >  {
> >         struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> > @@ -784,6 +806,7 @@ void intel_crt_init(struct drm_device *dev)
> >         crt->base.compute_config = intel_crt_compute_config;
> >         crt->base.disable = intel_disable_crt;
> >         crt->base.enable = intel_enable_crt;
> > +       crt->base.get_config = intel_crt_get_config;
> >         if (I915_HAS_HOTPLUG(dev))
> >                 crt->base.hpd_pin = HPD_CRT;
> >         if (HAS_DDI(dev))
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> > index cddcf4a..27a74a9 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > @@ -1254,6 +1254,28 @@ static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder)
> >                 intel_dp_check_link_status(intel_dp);
> >  }
> >
> > +static void intel_ddi_get_config(struct intel_encoder *encoder,
> > +                                struct intel_crtc_config *pipe_config)
> > +{
> > +       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> > +       struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
> > +       enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
> > +       u32 temp, flags = 0;
> > +
> > +       temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
> > +       if (temp & TRANS_DDI_PHSYNC)
> > +               flags |= DRM_MODE_FLAG_PHSYNC;
> > +       else
> > +               flags |= DRM_MODE_FLAG_NHSYNC;
> > +       if (temp & TRANS_DDI_PVSYNC)
> > +               flags |= DRM_MODE_FLAG_PVSYNC;
> > +       else
> > +               flags |= DRM_MODE_FLAG_NVSYNC;
> > +
> > +       pipe_config->adjusted_mode.flags |= flags;
> > +       pipe_config->pixel_multiplier = 1;
> > +}
> > +
> >  static void intel_ddi_destroy(struct drm_encoder *encoder)
> >  {
> >         /* HDMI has nothing special to destroy, so we can go with this. */
> > @@ -1313,6 +1335,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
> >         intel_encoder->disable = intel_disable_ddi;
> >         intel_encoder->post_disable = intel_ddi_post_disable;
> >         intel_encoder->get_hw_state = intel_ddi_get_hw_state;
> > +       intel_encoder->get_config = intel_ddi_get_config;
> >
> >         intel_dig_port->port = port;
> >         intel_dig_port->port_reversal = I915_READ(DDI_BUF_CTL(port)) &
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 7358e4e..163b97e 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -8057,6 +8057,15 @@ intel_pipe_config_compare(struct drm_device *dev,
> >         PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
> >                               DRM_MODE_FLAG_INTERLACE);
> >
> > +       PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
> > +                             DRM_MODE_FLAG_PHSYNC);
> > +       PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
> > +                             DRM_MODE_FLAG_NHSYNC);
> > +       PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
> > +                             DRM_MODE_FLAG_PVSYNC);
> > +       PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
> > +                             DRM_MODE_FLAG_NVSYNC);
> > +
> >         PIPE_CONF_CHECK_I(requested_mode.hdisplay);
> >         PIPE_CONF_CHECK_I(requested_mode.vdisplay);
> >
> > @@ -8149,6 +8158,8 @@ intel_modeset_check_state(struct drm_device *dev)
> >                 bool enabled = false;
> >                 bool active = false;
> >
> > +               memset(&pipe_config, 0, sizeof(pipe_config));
> > +
> >                 DRM_DEBUG_KMS("[CRTC:%d]\n",
> >                               crtc->base.base.id);
> >
> > @@ -8162,6 +8173,8 @@ intel_modeset_check_state(struct drm_device *dev)
> >                         enabled = true;
> >                         if (encoder->connectors_active)
> >                                 active = true;
> > +                       if (encoder->get_config)
> > +                               encoder->get_config(encoder, &pipe_config);
> >                 }
> >                 WARN(active != crtc->active,
> >                      "crtc's computed active state doesn't match tracked active state "
> > @@ -8170,7 +8183,6 @@ intel_modeset_check_state(struct drm_device *dev)
> >                      "crtc's computed enabled state doesn't match tracked enabled state "
> >                      "(expected %i, found %i)\n", enabled, crtc->base.enabled);
> >
> > -               memset(&pipe_config, 0, sizeof(pipe_config));
> >                 pipe_config.cpu_transcoder = crtc->config.cpu_transcoder;
> >                 active = dev_priv->display.get_pipe_config(crtc,
> >                                                            &pipe_config);
> > @@ -9579,8 +9591,10 @@ setup_pipes:
> >                 pipe = 0;
> >
> >                 if (encoder->get_hw_state(encoder, &pipe)) {
> > -                       encoder->base.crtc =
> > -                               dev_priv->pipe_to_crtc_mapping[pipe];
> > +                       crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
> > +                       encoder->base.crtc = &crtc->base;
> > +                       if (encoder->get_config)
> > +                               encoder->get_config(encoder, &crtc->config);
> >                 } else {
> >                         encoder->base.crtc = NULL;
> >                 }
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 2bb4009..a423256 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -1356,6 +1356,28 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
> >         return true;
> >  }
> >
> > +static void intel_dp_get_config(struct intel_encoder *encoder,
> > +                               struct intel_crtc_config *pipe_config)
> > +{
> > +       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> > +       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> > +       u32 tmp, flags = 0;
> > +
> > +       tmp = I915_READ(intel_dp->output_reg);
> > +
> > +       if (tmp & DP_SYNC_HS_HIGH)
> > +               flags |= DRM_MODE_FLAG_PHSYNC;
> > +       else
> > +               flags |= DRM_MODE_FLAG_NHSYNC;
> > +
> > +       if (tmp & DP_SYNC_VS_HIGH)
> > +               flags |= DRM_MODE_FLAG_PVSYNC;
> > +       else
> > +               flags |= DRM_MODE_FLAG_NVSYNC;
> > +
> > +       pipe_config->adjusted_mode.flags |= flags;
> > +}
> > +
> >  static void intel_disable_dp(struct intel_encoder *encoder)
> >  {
> >         struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> > @@ -3154,6 +3176,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
> >         intel_encoder->disable = intel_disable_dp;
> >         intel_encoder->post_disable = intel_post_disable_dp;
> >         intel_encoder->get_hw_state = intel_dp_get_hw_state;
> > +       intel_encoder->get_config = intel_dp_get_config;
> >         if (IS_VALLEYVIEW(dev))
> >                 intel_encoder->pre_pll_enable = intel_dp_pre_pll_enable;
> >
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 0f35545..4802483 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -139,6 +139,10 @@ struct intel_encoder {
> >          * the encoder is active. If the encoder is enabled it also set the pipe
> >          * it is connected to in the pipe parameter. */
> >         bool (*get_hw_state)(struct intel_encoder *, enum pipe *pipe);
> > +       /* Reconstructs the equivalent mode flags for the current hardware
> > +        * state. */
> > +       void (*get_config)(struct intel_encoder *,
> > +                          struct intel_crtc_config *pipe_config);
> >         int crtc_mask;
> >         enum hpd_pin hpd_pin;
> >  };
> > diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
> > index 00e70db..91e9905 100644
> > --- a/drivers/gpu/drm/i915/intel_dvo.c
> > +++ b/drivers/gpu/drm/i915/intel_dvo.c
> > @@ -129,6 +129,26 @@ static bool intel_dvo_get_hw_state(struct intel_encoder *encoder,
> >         return true;
> >  }
> >
> > +static void intel_dvo_get_config(struct intel_encoder *encoder,
> > +                                struct intel_crtc_config *pipe_config)
> > +{
> > +       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> > +       struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
> > +       u32 tmp, flags = 0;
> > +
> > +       tmp = I915_READ(intel_dvo->dev.dvo_reg);
> > +       if (tmp & DVO_HSYNC_ACTIVE_HIGH)
> > +               flags |= DRM_MODE_FLAG_PHSYNC;
> > +       else
> > +               flags |= DRM_MODE_FLAG_NHSYNC;
> > +       if (tmp & DVO_VSYNC_ACTIVE_HIGH)
> > +               flags |= DRM_MODE_FLAG_PVSYNC;
> > +       else
> > +               flags |= DRM_MODE_FLAG_NVSYNC;
> > +
> > +       pipe_config->adjusted_mode.flags |= flags;
> > +}
> > +
> >  static void intel_disable_dvo(struct intel_encoder *encoder)
> >  {
> >         struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> > @@ -440,6 +460,7 @@ void intel_dvo_init(struct drm_device *dev)
> >         intel_encoder->disable = intel_disable_dvo;
> >         intel_encoder->enable = intel_enable_dvo;
> >         intel_encoder->get_hw_state = intel_dvo_get_hw_state;
> > +       intel_encoder->get_config = intel_dvo_get_config;
> >         intel_connector->get_hw_state = intel_dvo_connector_get_hw_state;
> >
> >         /* Now, try to find a controller */
> > diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> > index 93de5ff..9091655 100644
> > --- a/drivers/gpu/drm/i915/intel_hdmi.c
> > +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> > @@ -658,6 +658,28 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
> >         return true;
> >  }
> >
> > +static void intel_hdmi_get_config(struct intel_encoder *encoder,
> > +                                 struct intel_crtc_config *pipe_config)
> > +{
> > +       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
> > +       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> > +       u32 tmp, flags = 0;
> > +
> > +       tmp = I915_READ(intel_hdmi->hdmi_reg);
> > +
> > +       if (tmp & SDVO_HSYNC_ACTIVE_HIGH)
> > +               flags |= DRM_MODE_FLAG_PHSYNC;
> > +       else
> > +               flags |= DRM_MODE_FLAG_NHSYNC;
> > +
> > +       if (tmp & SDVO_VSYNC_ACTIVE_HIGH)
> > +               flags |= DRM_MODE_FLAG_PVSYNC;
> > +       else
> > +               flags |= DRM_MODE_FLAG_NVSYNC;
> > +
> > +       pipe_config->adjusted_mode.flags |= flags;
> > +}
> > +
> >  static void intel_enable_hdmi(struct intel_encoder *encoder)
> >  {
> >         struct drm_device *dev = encoder->base.dev;
> > @@ -1208,6 +1230,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
> >         intel_encoder->enable = intel_enable_hdmi;
> >         intel_encoder->disable = intel_disable_hdmi;
> >         intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
> > +       intel_encoder->get_config = intel_hdmi_get_config;
> >         if (IS_VALLEYVIEW(dev)) {
> >                 intel_encoder->pre_enable = intel_hdmi_pre_enable;
> >                 intel_encoder->pre_pll_enable = intel_hdmi_pre_pll_enable;
> > diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> > index 36fe291..6554860 100644
> > --- a/drivers/gpu/drm/i915/intel_lvds.c
> > +++ b/drivers/gpu/drm/i915/intel_lvds.c
> > @@ -86,6 +86,31 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
> >         return true;
> >  }
> >
> > +static void intel_lvds_get_config(struct intel_encoder *encoder,
> > +                                 struct intel_crtc_config *pipe_config)
> > +{
> > +       struct drm_device *dev = encoder->base.dev;
> > +       struct drm_i915_private *dev_priv = dev->dev_private;
> > +       u32 lvds_reg, tmp, flags = 0;
> > +
> > +       if (HAS_PCH_SPLIT(dev))
> > +               lvds_reg = PCH_LVDS;
> > +       else
> > +               lvds_reg = LVDS;
> > +
> > +       tmp = I915_READ(lvds_reg);
> > +       if (tmp & LVDS_HSYNC_POLARITY)
> > +               flags |= DRM_MODE_FLAG_NHSYNC;
> > +       else
> > +               flags |= DRM_MODE_FLAG_PHSYNC;
> > +       if (tmp & LVDS_VSYNC_POLARITY)
> > +               flags |= DRM_MODE_FLAG_NVSYNC;
> > +       else
> > +               flags |= DRM_MODE_FLAG_PVSYNC;
> > +
> > +       pipe_config->adjusted_mode.flags |= flags;
> > +}
> > +
> >  /* The LVDS pin pair needs to be on before the DPLLs are enabled.
> >   * This is an exception to the general rule that mode_set doesn't turn
> >   * things on.
> > @@ -921,6 +946,7 @@ bool intel_lvds_init(struct drm_device *dev)
> >         intel_encoder->compute_config = intel_lvds_compute_config;
> >         intel_encoder->disable = intel_disable_lvds;
> >         intel_encoder->get_hw_state = intel_lvds_get_hw_state;
> > +       intel_encoder->get_config = intel_lvds_get_config;
> >         intel_connector->get_hw_state = intel_connector_get_hw_state;
> >
> >         intel_connector_attach_encoder(intel_connector, intel_encoder);
> > diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> > index 2f54dc3..416d23c 100644
> > --- a/drivers/gpu/drm/i915/intel_sdvo.c
> > +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> > @@ -712,6 +712,13 @@ static bool intel_sdvo_set_timing(struct intel_sdvo *intel_sdvo, u8 cmd,
> >                 intel_sdvo_set_value(intel_sdvo, cmd + 1, &dtd->part2, sizeof(dtd->part2));
> >  }
> >
> > +static bool intel_sdvo_get_timing(struct intel_sdvo *intel_sdvo, u8 cmd,
> > +                                 struct intel_sdvo_dtd *dtd)
> > +{
> > +       return intel_sdvo_get_value(intel_sdvo, cmd, &dtd->part1, sizeof(dtd->part1)) &&
> > +               intel_sdvo_get_value(intel_sdvo, cmd + 1, &dtd->part2, sizeof(dtd->part2));
> > +}
> > +
> >  static bool intel_sdvo_set_input_timing(struct intel_sdvo *intel_sdvo,
> >                                          struct intel_sdvo_dtd *dtd)
> >  {
> > @@ -726,6 +733,13 @@ static bool intel_sdvo_set_output_timing(struct intel_sdvo *intel_sdvo,
> >                                      SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd);
> >  }
> >
> > +static bool intel_sdvo_get_input_timing(struct intel_sdvo *intel_sdvo,
> > +                                       struct intel_sdvo_dtd *dtd)
> > +{
> > +       return intel_sdvo_get_timing(intel_sdvo,
> > +                                    SDVO_CMD_GET_INPUT_TIMINGS_PART1, dtd);
> > +}
> > +
> >  static bool
> >  intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo,
> >                                          uint16_t clock,
> > @@ -1295,6 +1309,33 @@ static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder,
> >         return true;
> >  }
> >
> > +static void intel_sdvo_get_config(struct intel_encoder *encoder,
> > +                                 struct intel_crtc_config *pipe_config)
> > +{
> > +       struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
> > +       struct intel_sdvo_dtd dtd;
> > +       u32 flags = 0;
> > +       bool ret;
> > +
> > +       ret = intel_sdvo_get_input_timing(intel_sdvo, &dtd);
> > +       if (!ret) {
> > +               DRM_DEBUG_DRIVER("failed to retrieve SDVO DTD\n");
> > +               return;
> > +       }
> > +
> > +       if (dtd.part2.dtd_flags & DTD_FLAG_HSYNC_POSITIVE)
> > +               flags |= DRM_MODE_FLAG_PHSYNC;
> > +       else
> > +               flags |= DRM_MODE_FLAG_NHSYNC;
> > +
> > +       if (dtd.part2.dtd_flags & DTD_FLAG_VSYNC_POSITIVE)
> > +               flags |= DRM_MODE_FLAG_PVSYNC;
> > +       else
> > +               flags |= DRM_MODE_FLAG_NVSYNC;
> > +
> > +       pipe_config->adjusted_mode.flags |= flags;
> > +}
> > +
> >  static void intel_disable_sdvo(struct intel_encoder *encoder)
> >  {
> >         struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> > @@ -2819,6 +2860,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
> >         intel_encoder->mode_set = intel_sdvo_mode_set;
> >         intel_encoder->enable = intel_enable_sdvo;
> >         intel_encoder->get_hw_state = intel_sdvo_get_hw_state;
> > +       intel_encoder->get_config = intel_sdvo_get_config;
> >
> >         /* In default case sdvo lvds is false */
> >         if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))
> > --
> > 1.7.9.5
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 
> -- 
> Paulo Zanoni
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Daniel Vetter May 21, 2013, 7:55 a.m. UTC | #3
On Wed, May 15, 2013 at 06:45:35PM -0300, Paulo Zanoni wrote:
> 2013/5/14 Jesse Barnes <jbarnes@virtuousgeek.org>:
> > We can use this for fetching encoder specific pipe_config state, like
> > mode flags, adjusted clock, etc.
> >
> > Just used for mode flags atm, so we can check the pipe config state at
> > mode set time.
> >
> > v2: get_config when checking hw state too
> > v3: fix DVO and LVDS mode flags (Ville)
> >     get SDVO DTD for flag fetch (Ville)
> > v4: use input timings (Ville)
> >     correct command used (Ville)
> >     remove gen4 check (Ville)
> > v5: get DDI flag config too
> >
> > Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> I applied this on my Haswell machine and booted it with both eDP-only
> and eDP+DP and now I don't see those error messages anymore.

Queued for -next, thanks for the patch.
-Daniel
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index cc414f1..789c4ef 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -81,6 +81,28 @@  static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
 	return true;
 }
 
+static void intel_crt_get_config(struct intel_encoder *encoder,
+				 struct intel_crtc_config *pipe_config)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_crt *crt = intel_encoder_to_crt(encoder);
+	u32 tmp, flags = 0;
+
+	tmp = I915_READ(crt->adpa_reg);
+
+	if (tmp & ADPA_HSYNC_ACTIVE_HIGH)
+		flags |= DRM_MODE_FLAG_PHSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NHSYNC;
+
+	if (tmp & ADPA_VSYNC_ACTIVE_HIGH)
+		flags |= DRM_MODE_FLAG_PVSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NVSYNC;
+
+	pipe_config->adjusted_mode.flags |= flags;
+}
+
 static void intel_disable_crt(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
@@ -784,6 +806,7 @@  void intel_crt_init(struct drm_device *dev)
 	crt->base.compute_config = intel_crt_compute_config;
 	crt->base.disable = intel_disable_crt;
 	crt->base.enable = intel_enable_crt;
+	crt->base.get_config = intel_crt_get_config;
 	if (I915_HAS_HOTPLUG(dev))
 		crt->base.hpd_pin = HPD_CRT;
 	if (HAS_DDI(dev))
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index cddcf4a..27a74a9 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1254,6 +1254,28 @@  static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder)
 		intel_dp_check_link_status(intel_dp);
 }
 
+static void intel_ddi_get_config(struct intel_encoder *encoder,
+				 struct intel_crtc_config *pipe_config)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+	enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
+	u32 temp, flags = 0;
+
+	temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
+	if (temp & TRANS_DDI_PHSYNC)
+		flags |= DRM_MODE_FLAG_PHSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NHSYNC;
+	if (temp & TRANS_DDI_PVSYNC)
+		flags |= DRM_MODE_FLAG_PVSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NVSYNC;
+
+	pipe_config->adjusted_mode.flags |= flags;
+	pipe_config->pixel_multiplier = 1;
+}
+
 static void intel_ddi_destroy(struct drm_encoder *encoder)
 {
 	/* HDMI has nothing special to destroy, so we can go with this. */
@@ -1313,6 +1335,7 @@  void intel_ddi_init(struct drm_device *dev, enum port port)
 	intel_encoder->disable = intel_disable_ddi;
 	intel_encoder->post_disable = intel_ddi_post_disable;
 	intel_encoder->get_hw_state = intel_ddi_get_hw_state;
+	intel_encoder->get_config = intel_ddi_get_config;
 
 	intel_dig_port->port = port;
 	intel_dig_port->port_reversal = I915_READ(DDI_BUF_CTL(port)) &
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7358e4e..163b97e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8057,6 +8057,15 @@  intel_pipe_config_compare(struct drm_device *dev,
 	PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
 			      DRM_MODE_FLAG_INTERLACE);
 
+	PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
+			      DRM_MODE_FLAG_PHSYNC);
+	PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
+			      DRM_MODE_FLAG_NHSYNC);
+	PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
+			      DRM_MODE_FLAG_PVSYNC);
+	PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
+			      DRM_MODE_FLAG_NVSYNC);
+
 	PIPE_CONF_CHECK_I(requested_mode.hdisplay);
 	PIPE_CONF_CHECK_I(requested_mode.vdisplay);
 
@@ -8149,6 +8158,8 @@  intel_modeset_check_state(struct drm_device *dev)
 		bool enabled = false;
 		bool active = false;
 
+		memset(&pipe_config, 0, sizeof(pipe_config));
+
 		DRM_DEBUG_KMS("[CRTC:%d]\n",
 			      crtc->base.base.id);
 
@@ -8162,6 +8173,8 @@  intel_modeset_check_state(struct drm_device *dev)
 			enabled = true;
 			if (encoder->connectors_active)
 				active = true;
+			if (encoder->get_config)
+				encoder->get_config(encoder, &pipe_config);
 		}
 		WARN(active != crtc->active,
 		     "crtc's computed active state doesn't match tracked active state "
@@ -8170,7 +8183,6 @@  intel_modeset_check_state(struct drm_device *dev)
 		     "crtc's computed enabled state doesn't match tracked enabled state "
 		     "(expected %i, found %i)\n", enabled, crtc->base.enabled);
 
-		memset(&pipe_config, 0, sizeof(pipe_config));
 		pipe_config.cpu_transcoder = crtc->config.cpu_transcoder;
 		active = dev_priv->display.get_pipe_config(crtc,
 							   &pipe_config);
@@ -9579,8 +9591,10 @@  setup_pipes:
 		pipe = 0;
 
 		if (encoder->get_hw_state(encoder, &pipe)) {
-			encoder->base.crtc =
-				dev_priv->pipe_to_crtc_mapping[pipe];
+			crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+			encoder->base.crtc = &crtc->base;
+			if (encoder->get_config)
+				encoder->get_config(encoder, &crtc->config);
 		} else {
 			encoder->base.crtc = NULL;
 		}
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 2bb4009..a423256 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1356,6 +1356,28 @@  static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
 	return true;
 }
 
+static void intel_dp_get_config(struct intel_encoder *encoder,
+				struct intel_crtc_config *pipe_config)
+{
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	u32 tmp, flags = 0;
+
+	tmp = I915_READ(intel_dp->output_reg);
+
+	if (tmp & DP_SYNC_HS_HIGH)
+		flags |= DRM_MODE_FLAG_PHSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NHSYNC;
+
+	if (tmp & DP_SYNC_VS_HIGH)
+		flags |= DRM_MODE_FLAG_PVSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NVSYNC;
+
+	pipe_config->adjusted_mode.flags |= flags;
+}
+
 static void intel_disable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
@@ -3154,6 +3176,7 @@  intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 	intel_encoder->disable = intel_disable_dp;
 	intel_encoder->post_disable = intel_post_disable_dp;
 	intel_encoder->get_hw_state = intel_dp_get_hw_state;
+	intel_encoder->get_config = intel_dp_get_config;
 	if (IS_VALLEYVIEW(dev))
 		intel_encoder->pre_pll_enable = intel_dp_pre_pll_enable;
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0f35545..4802483 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -139,6 +139,10 @@  struct intel_encoder {
 	 * the encoder is active. If the encoder is enabled it also set the pipe
 	 * it is connected to in the pipe parameter. */
 	bool (*get_hw_state)(struct intel_encoder *, enum pipe *pipe);
+	/* Reconstructs the equivalent mode flags for the current hardware
+	 * state. */
+	void (*get_config)(struct intel_encoder *,
+			   struct intel_crtc_config *pipe_config);
 	int crtc_mask;
 	enum hpd_pin hpd_pin;
 };
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 00e70db..91e9905 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -129,6 +129,26 @@  static bool intel_dvo_get_hw_state(struct intel_encoder *encoder,
 	return true;
 }
 
+static void intel_dvo_get_config(struct intel_encoder *encoder,
+				 struct intel_crtc_config *pipe_config)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
+	u32 tmp, flags = 0;
+
+	tmp = I915_READ(intel_dvo->dev.dvo_reg);
+	if (tmp & DVO_HSYNC_ACTIVE_HIGH)
+		flags |= DRM_MODE_FLAG_PHSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NHSYNC;
+	if (tmp & DVO_VSYNC_ACTIVE_HIGH)
+		flags |= DRM_MODE_FLAG_PVSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NVSYNC;
+
+	pipe_config->adjusted_mode.flags |= flags;
+}
+
 static void intel_disable_dvo(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
@@ -440,6 +460,7 @@  void intel_dvo_init(struct drm_device *dev)
 	intel_encoder->disable = intel_disable_dvo;
 	intel_encoder->enable = intel_enable_dvo;
 	intel_encoder->get_hw_state = intel_dvo_get_hw_state;
+	intel_encoder->get_config = intel_dvo_get_config;
 	intel_connector->get_hw_state = intel_dvo_connector_get_hw_state;
 
 	/* Now, try to find a controller */
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 93de5ff..9091655 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -658,6 +658,28 @@  static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
 	return true;
 }
 
+static void intel_hdmi_get_config(struct intel_encoder *encoder,
+				  struct intel_crtc_config *pipe_config)
+{
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	u32 tmp, flags = 0;
+
+	tmp = I915_READ(intel_hdmi->hdmi_reg);
+
+	if (tmp & SDVO_HSYNC_ACTIVE_HIGH)
+		flags |= DRM_MODE_FLAG_PHSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NHSYNC;
+
+	if (tmp & SDVO_VSYNC_ACTIVE_HIGH)
+		flags |= DRM_MODE_FLAG_PVSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NVSYNC;
+
+	pipe_config->adjusted_mode.flags |= flags;
+}
+
 static void intel_enable_hdmi(struct intel_encoder *encoder)
 {
 	struct drm_device *dev = encoder->base.dev;
@@ -1208,6 +1230,7 @@  void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
 	intel_encoder->enable = intel_enable_hdmi;
 	intel_encoder->disable = intel_disable_hdmi;
 	intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
+	intel_encoder->get_config = intel_hdmi_get_config;
 	if (IS_VALLEYVIEW(dev)) {
 		intel_encoder->pre_enable = intel_hdmi_pre_enable;
 		intel_encoder->pre_pll_enable = intel_hdmi_pre_pll_enable;
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 36fe291..6554860 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -86,6 +86,31 @@  static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
 	return true;
 }
 
+static void intel_lvds_get_config(struct intel_encoder *encoder,
+				  struct intel_crtc_config *pipe_config)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 lvds_reg, tmp, flags = 0;
+
+	if (HAS_PCH_SPLIT(dev))
+		lvds_reg = PCH_LVDS;
+	else
+		lvds_reg = LVDS;
+
+	tmp = I915_READ(lvds_reg);
+	if (tmp & LVDS_HSYNC_POLARITY)
+		flags |= DRM_MODE_FLAG_NHSYNC;
+	else
+		flags |= DRM_MODE_FLAG_PHSYNC;
+	if (tmp & LVDS_VSYNC_POLARITY)
+		flags |= DRM_MODE_FLAG_NVSYNC;
+	else
+		flags |= DRM_MODE_FLAG_PVSYNC;
+
+	pipe_config->adjusted_mode.flags |= flags;
+}
+
 /* The LVDS pin pair needs to be on before the DPLLs are enabled.
  * This is an exception to the general rule that mode_set doesn't turn
  * things on.
@@ -921,6 +946,7 @@  bool intel_lvds_init(struct drm_device *dev)
 	intel_encoder->compute_config = intel_lvds_compute_config;
 	intel_encoder->disable = intel_disable_lvds;
 	intel_encoder->get_hw_state = intel_lvds_get_hw_state;
+	intel_encoder->get_config = intel_lvds_get_config;
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 2f54dc3..416d23c 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -712,6 +712,13 @@  static bool intel_sdvo_set_timing(struct intel_sdvo *intel_sdvo, u8 cmd,
 		intel_sdvo_set_value(intel_sdvo, cmd + 1, &dtd->part2, sizeof(dtd->part2));
 }
 
+static bool intel_sdvo_get_timing(struct intel_sdvo *intel_sdvo, u8 cmd,
+				  struct intel_sdvo_dtd *dtd)
+{
+	return intel_sdvo_get_value(intel_sdvo, cmd, &dtd->part1, sizeof(dtd->part1)) &&
+		intel_sdvo_get_value(intel_sdvo, cmd + 1, &dtd->part2, sizeof(dtd->part2));
+}
+
 static bool intel_sdvo_set_input_timing(struct intel_sdvo *intel_sdvo,
 					 struct intel_sdvo_dtd *dtd)
 {
@@ -726,6 +733,13 @@  static bool intel_sdvo_set_output_timing(struct intel_sdvo *intel_sdvo,
 				     SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd);
 }
 
+static bool intel_sdvo_get_input_timing(struct intel_sdvo *intel_sdvo,
+					struct intel_sdvo_dtd *dtd)
+{
+	return intel_sdvo_get_timing(intel_sdvo,
+				     SDVO_CMD_GET_INPUT_TIMINGS_PART1, dtd);
+}
+
 static bool
 intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo,
 					 uint16_t clock,
@@ -1295,6 +1309,33 @@  static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder,
 	return true;
 }
 
+static void intel_sdvo_get_config(struct intel_encoder *encoder,
+				  struct intel_crtc_config *pipe_config)
+{
+	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
+	struct intel_sdvo_dtd dtd;
+	u32 flags = 0;
+	bool ret;
+
+	ret = intel_sdvo_get_input_timing(intel_sdvo, &dtd);
+	if (!ret) {
+		DRM_DEBUG_DRIVER("failed to retrieve SDVO DTD\n");
+		return;
+	}
+
+	if (dtd.part2.dtd_flags & DTD_FLAG_HSYNC_POSITIVE)
+		flags |= DRM_MODE_FLAG_PHSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NHSYNC;
+
+	if (dtd.part2.dtd_flags & DTD_FLAG_VSYNC_POSITIVE)
+		flags |= DRM_MODE_FLAG_PVSYNC;
+	else
+		flags |= DRM_MODE_FLAG_NVSYNC;
+
+	pipe_config->adjusted_mode.flags |= flags;
+}
+
 static void intel_disable_sdvo(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
@@ -2819,6 +2860,7 @@  bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
 	intel_encoder->mode_set = intel_sdvo_mode_set;
 	intel_encoder->enable = intel_enable_sdvo;
 	intel_encoder->get_hw_state = intel_sdvo_get_hw_state;
+	intel_encoder->get_config = intel_sdvo_get_config;
 
 	/* In default case sdvo lvds is false */
 	if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))