On Tue, 2013-02-19 at 13:31 -0800, Jesse Barnes wrote: > From: Chris Wilson <chris at chris-wilson.co.uk> > > Read the current hardware state to retrieve the active mode and populate > our CRTC config if that mode matches our presumptions. > > Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk> > --- > drivers/gpu/drm/i915/i915_drv.h | 2 + > drivers/gpu/drm/i915/intel_crt.c | 27 +++++++- > drivers/gpu/drm/i915/intel_display.c | 119 ++++++++++++++++++++++++++-------- > drivers/gpu/drm/i915/intel_dp.c | 22 +++++++ > drivers/gpu/drm/i915/intel_drv.h | 7 +- > drivers/gpu/drm/i915/intel_dvo.c | 36 ++++++---- > drivers/gpu/drm/i915/intel_hdmi.c | 22 +++++++ > drivers/gpu/drm/i915/intel_lvds.c | 27 +++++++- > drivers/gpu/drm/i915/intel_sdvo.c | 23 +++++++ > 9 files changed, 242 insertions(+), 43 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 30cf7e6..8473db4 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -283,6 +283,8 @@ struct drm_i915_display_funcs { > void (*update_linetime_wm)(struct drm_device *dev, int pipe, > struct drm_display_mode *mode); > void (*modeset_global_resources)(struct drm_device *dev); > + bool (*crtc_get_mode)(struct drm_crtc *crtc, > + struct drm_display_mode *mode); > int (*crtc_mode_set)(struct drm_crtc *crtc, > struct drm_display_mode *mode, > struct drm_display_mode *adjusted_mode, > diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c > index cfc9687..f1d68e8 100644 > --- a/drivers/gpu/drm/i915/intel_crt.c > +++ b/drivers/gpu/drm/i915/intel_crt.c > @@ -81,6 +81,27 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder, > return true; > } > > +static unsigned intel_crt_get_mode_flags(struct intel_encoder *encoder) > +{ > + 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; > + > + return flags; > +} > + > static void intel_disable_crt(struct intel_encoder *encoder) > { > struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; > @@ -777,10 +798,12 @@ void intel_crt_init(struct drm_device *dev) > > crt->base.disable = intel_disable_crt; > crt->base.enable = intel_enable_crt; > - if (HAS_DDI(dev)) > + if (HAS_DDI(dev)) { > crt->base.get_hw_state = intel_ddi_get_hw_state; > - else > + } else { > crt->base.get_hw_state = intel_crt_get_hw_state; > + crt->base.get_mode_flags = intel_crt_get_mode_flags; > + } > intel_connector->get_hw_state = intel_connector_get_hw_state; > > drm_encoder_helper_add(&crt->base.base, &crt_encoder_funcs); > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index 9793e66..e19b637 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -6618,11 +6618,12 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, > } > > /* Returns the clock of the currently programmed mode of the given pipe. */ > -static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) > +static int i9xx_crtc_clock_get(struct drm_crtc *crtc) > { > + struct drm_device *dev = crtc->dev; > struct drm_i915_private *dev_priv = dev->dev_private; > struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > - int pipe = intel_crtc->pipe; > + enum pipe pipe = intel_crtc->pipe; > u32 dpll = I915_READ(DPLL(pipe)); > u32 fp; > intel_clock_t clock; > @@ -6705,35 +6706,84 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) > } > > /** Returns the currently programmed mode of the given pipe. */ > -struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, > - struct drm_crtc *crtc) > +static bool i9xx_crtc_get_mode(struct drm_crtc *crtc, > + struct drm_display_mode *mode) > { > - struct drm_i915_private *dev_priv = dev->dev_private; > + struct drm_i915_private *dev_priv = crtc->dev->dev_private; > struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder; > - struct drm_display_mode *mode; > - int htot = I915_READ(HTOTAL(cpu_transcoder)); > - int hsync = I915_READ(HSYNC(cpu_transcoder)); > - int vtot = I915_READ(VTOTAL(cpu_transcoder)); > - int vsync = I915_READ(VSYNC(cpu_transcoder)); > + u32 tmp; > > - mode = kzalloc(sizeof(*mode), GFP_KERNEL); > - if (!mode) > - return NULL; > + memset(mode, 0, sizeof(*mode)); > + > + tmp = I915_READ(HTOTAL(cpu_transcoder)); > + mode->hdisplay = (tmp & 0xffff) + 1; > + mode->htotal = ((tmp & 0xffff0000) >> 16) + 1; > + > + tmp = I915_READ(HSYNC(cpu_transcoder)); > + mode->hsync_start = (tmp & 0xffff) + 1; > + mode->hsync_end = ((tmp & 0xffff0000) >> 16) + 1; > + > + tmp = I915_READ(VTOTAL(cpu_transcoder)); > + mode->vdisplay = (tmp & 0xffff) + 1; > + mode->vtotal = ((tmp & 0xffff0000) >> 16) + 1; > + > + tmp = I915_READ(VSYNC(cpu_transcoder)); > + mode->vsync_start = (tmp & 0xffff) + 1; > + mode->vsync_end = ((tmp & 0xffff0000) >> 16) + 1; > + > + mode->clock = i9xx_crtc_clock_get(crtc); > + > + drm_mode_set_name(mode); > + > + return true; > +} > + > +static bool ironlake_crtc_get_mode(struct drm_crtc *crtc, > + struct drm_display_mode *mode) > +{ > + struct drm_i915_private *dev_priv = crtc->dev->dev_private; > + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > + enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder; > + u32 tmp; > + > + memset(mode, 0, sizeof(*mode)); > + > + tmp = I915_READ(HTOTAL(cpu_transcoder)); > + mode->hdisplay = (tmp & 0xffff) + 1; > + mode->htotal = ((tmp & 0xffff0000) >> 16) + 1; > + > + tmp = I915_READ(HSYNC(cpu_transcoder)); > + mode->hsync_start = (tmp & 0xffff) + 1; > + mode->hsync_end = ((tmp & 0xffff0000) >> 16) + 1; > + > + tmp = I915_READ(VTOTAL(cpu_transcoder)); > + mode->vdisplay = (tmp & 0xffff) + 1; > + mode->vtotal = ((tmp & 0xffff0000) >> 16) + 1; > > - mode->clock = intel_crtc_clock_get(dev, crtc); > - mode->hdisplay = (htot & 0xffff) + 1; > - mode->htotal = ((htot & 0xffff0000) >> 16) + 1; > - mode->hsync_start = (hsync & 0xffff) + 1; > - mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; > - mode->vdisplay = (vtot & 0xffff) + 1; > - mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; > - mode->vsync_start = (vsync & 0xffff) + 1; > - mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; > + tmp = I915_READ(VSYNC(cpu_transcoder)); > + mode->vsync_start = (tmp & 0xffff) + 1; > + mode->vsync_end = ((tmp & 0xffff0000) >> 16) + 1; > + > + //mode->clock = i9xx_crtc_clock_get(crtc); > + //mode->clock = 69300; > > drm_mode_set_name(mode); > > - return mode; > + return false; /* XXX mode->clock unset */ > +} > + > +static __maybe_unused bool no_crtc_get_mode(struct drm_crtc *crtc, > + struct drm_display_mode *mode) > +{ > + return false; > +} > + > +bool intel_crtc_get_mode(struct drm_crtc *crtc, > + struct drm_display_mode *mode) > +{ > + struct drm_i915_private *dev_priv = crtc->dev->dev_private; > + return dev_priv->display.crtc_get_mode(crtc, mode); > } > > static void intel_increase_pllclock(struct drm_crtc *crtc) > @@ -8515,20 +8565,25 @@ static void intel_init_display(struct drm_device *dev) > { > struct drm_i915_private *dev_priv = dev->dev_private; > > + dev_priv->display.crtc_get_mode = no_crtc_get_mode; > + > /* We always want a DPMS function */ > if (HAS_DDI(dev)) { > + dev_priv->display.crtc_get_mode = ironlake_crtc_get_mode; > dev_priv->display.crtc_mode_set = haswell_crtc_mode_set; > dev_priv->display.crtc_enable = haswell_crtc_enable; > dev_priv->display.crtc_disable = haswell_crtc_disable; > dev_priv->display.off = haswell_crtc_off; > dev_priv->display.update_plane = ironlake_update_plane; > } else if (HAS_PCH_SPLIT(dev)) { > + dev_priv->display.crtc_get_mode = ironlake_crtc_get_mode; > dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set; > dev_priv->display.crtc_enable = ironlake_crtc_enable; > dev_priv->display.crtc_disable = ironlake_crtc_disable; > dev_priv->display.off = ironlake_crtc_off; > dev_priv->display.update_plane = ironlake_update_plane; > } else { > + dev_priv->display.crtc_get_mode = i9xx_crtc_get_mode; > dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set; > dev_priv->display.crtc_enable = i9xx_crtc_enable; > dev_priv->display.crtc_disable = i9xx_crtc_disable; > @@ -9068,6 +9123,14 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, > DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n", > crtc->base.base.id, > crtc->active ? "enabled" : "disabled"); > + > + > + if (crtc->base.enabled) > + crtc->mode_valid = intel_crtc_get_mode(&crtc->base, &crtc->base.mode); > + if (crtc->mode_valid) { > + DRM_DEBUG_KMS("found active mode: "); > + drm_mode_debug_printmodeline(&crtc->base.mode); > + } > } > > if (HAS_DDI(dev)) > @@ -9075,12 +9138,14 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, > > list_for_each_entry(encoder, &dev->mode_config.encoder_list, > base.head) { > - pipe = 0; > + pipe = -1; > > if (encoder->get_hw_state(encoder, &pipe)) { > - encoder->base.crtc = > - dev_priv->pipe_to_crtc_mapping[pipe]; > - } else { > + crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); get_hw_state() can return true and still leave pipe at -1, causing an invalid access here. > + if (crtc->mode_valid && encoder->get_mode_flags) > + crtc->base.mode.flags |= encoder->get_mode_flags(encoder); > + encoder->base.crtc = &crtc->base; > + } else > encoder->base.crtc = NULL; > } > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c > index 7b8bfe8..e84d4dd 100644 > --- a/drivers/gpu/drm/i915/intel_dp.c > +++ b/drivers/gpu/drm/i915/intel_dp.c > @@ -1411,6 +1411,27 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder, > return true; > } > > +static unsigned intel_dp_get_mode_flags(struct intel_encoder *encoder) > +{ > + 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; > + > + return flags; > +} > + > static void intel_disable_dp(struct intel_encoder *encoder) > { > struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); > @@ -2966,6 +2987,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_mode_flags = intel_dp_get_mode_flags; > > intel_dig_port->port = port; > intel_dig_port->dp.output_reg = output_reg; > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index 9cf794f..de8928b 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -176,6 +176,9 @@ 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. */ > + unsigned (*get_mode_flags)(struct intel_encoder *); > int crtc_mask; > }; > > @@ -581,8 +584,8 @@ extern void intel_connector_attach_encoder(struct intel_connector *connector, > struct intel_encoder *encoder); > extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector); > > -extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, > - struct drm_crtc *crtc); > +extern bool intel_crtc_get_mode(struct drm_crtc *crtc, > + struct drm_display_mode *mode); > int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, > struct drm_file *file_priv); > extern enum transcoder > diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c > index 15da995..46b549e 100644 > --- a/drivers/gpu/drm/i915/intel_dvo.c > +++ b/drivers/gpu/drm/i915/intel_dvo.c > @@ -129,6 +129,22 @@ static bool intel_dvo_get_hw_state(struct intel_encoder *encoder, > return true; > } > > +static unsigned > +intel_dvo_get_mode_flags(struct intel_encoder *encoder) > +{ > + 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; > + if (tmp & DVO_VSYNC_ACTIVE_HIGH) > + flags |= DRM_MODE_FLAG_PVSYNC; > + > + return flags; > +} > + > static void intel_disable_dvo(struct intel_encoder *encoder) > { > struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; > @@ -390,29 +406,26 @@ intel_dvo_get_current_mode(struct drm_connector *connector) > struct drm_i915_private *dev_priv = dev->dev_private; > struct intel_dvo *intel_dvo = intel_attached_dvo(connector); > uint32_t dvo_val = I915_READ(intel_dvo->dev.dvo_reg); > - struct drm_display_mode *mode = NULL; > + struct drm_display_mode *fixed_mode = NULL; > > /* If the DVO port is active, that'll be the LVDS, so we can pull out > * its timings to get how the BIOS set up the panel. > */ > if (dvo_val & DVO_ENABLE) { > + struct drm_display_mode mode; > struct drm_crtc *crtc; > int pipe = (dvo_val & DVO_PIPE_B_SELECT) ? 1 : 0; > > crtc = intel_get_crtc_for_pipe(dev, pipe); > - if (crtc) { > - mode = intel_crtc_mode_get(dev, crtc); > - if (mode) { > - mode->type |= DRM_MODE_TYPE_PREFERRED; > - if (dvo_val & DVO_HSYNC_ACTIVE_HIGH) > - mode->flags |= DRM_MODE_FLAG_PHSYNC; > - if (dvo_val & DVO_VSYNC_ACTIVE_HIGH) > - mode->flags |= DRM_MODE_FLAG_PVSYNC; > - } > + if (intel_crtc_get_mode(crtc, &mode)) > + fixed_mode = drm_mode_duplicate(dev, &mode); > + if (fixed_mode) { > + fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; > + fixed_mode->flags = intel_dvo_get_mode_flags(&intel_dvo->base); > } > } > > - return mode; > + return fixed_mode; > } > > void intel_dvo_init(struct drm_device *dev) > @@ -441,6 +454,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_mode_flags = intel_dvo_get_mode_flags; > 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 5a6138c..005b9f9 100644 > --- a/drivers/gpu/drm/i915/intel_hdmi.c > +++ b/drivers/gpu/drm/i915/intel_hdmi.c > @@ -656,6 +656,27 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder, > return true; > } > > +static unsigned intel_hdmi_get_mode_flags(struct intel_encoder *encoder) > +{ > + 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->sdvox_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; > + > + return flags; > +} > + > static void intel_enable_hdmi(struct intel_encoder *encoder) > { > struct drm_device *dev = encoder->base.dev; > @@ -1102,6 +1123,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_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_mode_flags = intel_hdmi_get_mode_flags; > > intel_encoder->type = INTEL_OUTPUT_HDMI; > intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); > diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c > index c7154bf..400afa4 100644 > --- a/drivers/gpu/drm/i915/intel_lvds.c > +++ b/drivers/gpu/drm/i915/intel_lvds.c > @@ -88,6 +88,26 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder, > return true; > } > > +static unsigned intel_lvds_get_mode_flags(struct intel_encoder *encoder) > +{ > + 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; > + if (tmp & LVDS_VSYNC_POLARITY) > + flags |= DRM_MODE_FLAG_NVSYNC; > + > + return 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. > @@ -1105,6 +1125,7 @@ bool intel_lvds_init(struct drm_device *dev) > intel_encoder->pre_pll_enable = intel_pre_pll_enable_lvds; > intel_encoder->disable = intel_disable_lvds; > intel_encoder->get_hw_state = intel_lvds_get_hw_state; > + intel_encoder->get_mode_flags = intel_lvds_get_mode_flags; > intel_connector->get_hw_state = intel_connector_get_hw_state; > > intel_connector_attach_encoder(intel_connector, intel_encoder); > @@ -1216,11 +1237,15 @@ bool intel_lvds_init(struct drm_device *dev) > crtc = intel_get_crtc_for_pipe(dev, pipe); > > if (crtc && (lvds & LVDS_PORT_EN)) { > - fixed_mode = intel_crtc_mode_get(dev, crtc); > + struct drm_display_mode mode; > + > + if (intel_crtc_get_mode(crtc, &mode)) > + fixed_mode = drm_mode_duplicate(dev, &mode); > if (fixed_mode) { > DRM_DEBUG_KMS("using current (BIOS) mode: "); > drm_mode_debug_printmodeline(fixed_mode); > fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; > + fixed_mode->flags = intel_lvds_get_mode_flags(intel_encoder); > goto out; > } > } > diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c > index f01063a..918c269 100644 > --- a/drivers/gpu/drm/i915/intel_sdvo.c > +++ b/drivers/gpu/drm/i915/intel_sdvo.c > @@ -1250,6 +1250,27 @@ static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder, > return true; > } > > +static unsigned intel_sdvo_get_mode_flags(struct intel_encoder *encoder) > +{ > + struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base); > + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; > + u32 tmp, flags = 0; > + > + tmp = I915_READ(intel_sdvo->sdvo_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; > + > + return flags; > +} > + > static void intel_disable_sdvo(struct intel_encoder *encoder) > { > struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; > @@ -2785,6 +2806,8 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) > intel_encoder->disable = intel_disable_sdvo; > intel_encoder->enable = intel_enable_sdvo; > intel_encoder->get_hw_state = intel_sdvo_get_hw_state; > + if (INTEL_INFO(dev)->gen >= 4) > + intel_encoder->get_mode_flags = intel_sdvo_get_mode_flags; > > /* In default case sdvo lvds is false */ > if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))