From: Jesse Barnes <[email protected]>

Read the sync polarity from the output configuration when assigning the
initial mode to the current configuration.  This allows a later
set_config call to match the current mode and use a flip instead.

Signed-off-by: Jesse Barnes <[email protected]>
---
 drivers/gpu/drm/i915/intel_crt.c     |   29 +++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_display.c |   28 ++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_dp.c      |   26 ++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |    2 ++
 drivers/gpu/drm/i915/intel_dvo.c     |    1 +
 drivers/gpu/drm/i915/intel_hdmi.c    |   25 +++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_lvds.c    |    7 +++++++
 drivers/gpu/drm/i915/intel_sdvo.c    |   28 ++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_tv.c      |    2 ++
 9 files changed, 148 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 75a70c4..f0223d0 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -523,6 +523,33 @@ static void intel_crt_reset(struct drm_connector 
*connector)
                crt->force_hotplug_required = 1;
 }
 
+static u32 intel_crt_mode_flags(struct intel_encoder *intel_encoder)
+{
+       struct drm_device *dev = intel_encoder->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int adpa_reg;
+       u32 val, flags = 0;
+
+       if (HAS_PCH_SPLIT(dev))
+               adpa_reg = PCH_ADPA;
+       else
+               adpa_reg = ADPA;
+
+       val = I915_READ(adpa_reg);
+
+       if (val & ADPA_HSYNC_ACTIVE_HIGH)
+               flags |= DRM_MODE_FLAG_PHSYNC;
+       else
+               flags |= DRM_MODE_FLAG_NHSYNC;
+
+       if (val & ADPA_VSYNC_ACTIVE_HIGH)
+               flags |= DRM_MODE_FLAG_PVSYNC;
+       else
+               flags |= DRM_MODE_FLAG_NVSYNC;
+
+       return flags;
+}
+
 /*
  * Routines for controlling stuff on the analog port
  */
@@ -641,6 +668,8 @@ void intel_crt_init(struct drm_device *dev)
        else
                connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 
+       crt->base.mode_flags = intel_crt_mode_flags;
+
        /*
         * Configure the automatic hotplug detection stuff
         */
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 6b3ce6d2..874507c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5625,6 +5625,33 @@ static int intel_crtc_clock_get(struct drm_device *dev, 
struct drm_crtc *crtc)
        return clock.dot;
 }
 
+u32 intel_mode_flags_none(struct intel_encoder *intel_encoder)
+{
+       return 0;
+}
+
+/* Get the sync polarity for the mode on this crtc */
+static u32 intel_crtc_mode_flags(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_connector *connector;
+       struct intel_encoder *intel_encoder;
+
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               if (connector->status != connector_status_connected ||
+                   !connector->encoder)
+                       continue;
+
+               if (connector->encoder->crtc != crtc)
+                       continue;
+
+               intel_encoder = to_intel_encoder(connector->encoder);
+               return intel_encoder->mode_flags(intel_encoder);
+       }
+
+       return 0;
+}
+
 /** Returns the currently programmed mode of the given pipe. */
 struct drm_display_mode *intel_crtc_mode_get(struct drm_crtc *crtc)
 {
@@ -5651,6 +5678,7 @@ struct drm_display_mode *intel_crtc_mode_get(struct 
drm_crtc *crtc)
        mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
        mode->vsync_start = (vsync & 0xffff) + 1;
        mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
+       mode->flags = intel_crtc_mode_flags(crtc);
 
        drm_mode_set_name(mode);
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 924dc27..0885ced 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2336,6 +2336,31 @@ intel_dp_hot_plug(struct intel_encoder *intel_encoder)
        intel_dp_check_link_status(intel_dp);
 }
 
+static u32
+intel_dp_mode_flags(struct intel_encoder *intel_encoder)
+{
+       struct drm_device *dev = intel_encoder->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_dp *intel_dp = container_of(intel_encoder,
+                                                struct intel_dp, base);
+       int reg = intel_dp->output_reg;
+       u32 val, flags = 0;
+
+       val = I915_READ(reg);
+
+       if (val & DP_SYNC_HS_HIGH)
+               flags |= DRM_MODE_FLAG_PHSYNC;
+       else
+               flags |= DRM_MODE_FLAG_NHSYNC;
+
+       if (val & DP_SYNC_VS_HIGH)
+               flags |= DRM_MODE_FLAG_PVSYNC;
+       else
+               flags |= DRM_MODE_FLAG_NVSYNC;
+
+       return flags;
+}
+
 /* Return which DP Port should be selected for Transcoder DP control */
 int
 intel_trans_dp_port_sel(struct drm_crtc *crtc)
@@ -2574,6 +2599,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)
        intel_dp_i2c_init(intel_dp, intel_connector, name);
 
        intel_encoder->hot_plug = intel_dp_hot_plug;
+       intel_encoder->mode_flags = intel_dp_mode_flags;
 
        if (is_edp(intel_dp)) {
                dev_priv->int_edp_connector = connector;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1337733..cae7716 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -155,6 +155,7 @@ struct intel_encoder {
        int type;
        bool needs_tv_clock;
        void (*hot_plug)(struct intel_encoder *);
+       u32 (*mode_flags)(struct intel_encoder *);
        int crtc_mask;
        int clone_mask;
 };
@@ -468,6 +469,7 @@ extern void intel_cpt_verify_modeset(struct drm_device 
*dev, int pipe);
 extern void intel_prepare_ddi(struct drm_device *dev);
 extern void hsw_fdi_link_train(struct drm_crtc *crtc);
 extern void intel_ddi_init(struct drm_device *dev, enum port port);
+extern u32 intel_mode_flags_none(struct intel_encoder *intel_encoder);
 
 /* For use by IVB LP watermark workaround in intel_sprite.c */
 extern void intel_update_watermarks(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 8ff2841..7cb05d2 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -363,6 +363,7 @@ void intel_dvo_init(struct drm_device *dev)
        intel_encoder = &intel_dvo->base;
        drm_encoder_init(dev, &intel_encoder->base,
                         &intel_dvo_enc_funcs, encoder_type);
+       intel_encoder->mode_flags = intel_mode_flags_none;
 
        /* Now, try to find a controller */
        for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c 
b/drivers/gpu/drm/i915/intel_hdmi.c
index 4c6f141..1e9dfea 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -602,6 +602,29 @@ done:
        return 0;
 }
 
+static u32 intel_hdmi_mode_flags(struct intel_encoder *intel_encoder)
+{
+       struct drm_device *dev = intel_encoder->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_hdmi *intel_hdmi = container_of(intel_encoder,
+                                                    struct intel_hdmi, base);
+       u32 val, flags = 0;
+
+       val = I915_READ(intel_hdmi->sdvox_reg);
+
+       if (val & SDVO_HSYNC_ACTIVE_HIGH)
+               flags |= DRM_MODE_FLAG_PHSYNC;
+       else
+               flags |= DRM_MODE_FLAG_NHSYNC;
+
+       if (val & SDVO_VSYNC_ACTIVE_HIGH)
+               flags |= DRM_MODE_FLAG_PVSYNC;
+       else
+               flags |= DRM_MODE_FLAG_NVSYNC;
+
+       return flags;
+}
+
 static void intel_hdmi_destroy(struct drm_connector *connector)
 {
        drm_sysfs_connector_remove(connector);
@@ -766,6 +789,8 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
        intel_connector_attach_encoder(intel_connector, intel_encoder);
        drm_sysfs_connector_add(connector);
 
+       intel_hdmi->base.mode_flags = intel_hdmi_mode_flags;
+
        /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
         * 0xd.  Failure to do so will result in spurious interrupts being
         * generated on the port when a cable is not attached.
diff --git a/drivers/gpu/drm/i915/intel_lvds.c 
b/drivers/gpu/drm/i915/intel_lvds.c
index 2a731eb..da3fcf8 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -888,6 +888,11 @@ static bool intel_lvds_supported(struct drm_device *dev)
        return IS_MOBILE(dev) && !IS_I830(dev);
 }
 
+static u32 intel_lvds_mode_flags(struct intel_encoder *encoder)
+{
+       return 0;
+}
+
 static int intel_lvds_get_pipe(struct intel_lvds *intel_lvds)
 {
        struct intel_encoder *intel_encoder = &intel_lvds->base;
@@ -1126,6 +1131,8 @@ out:
        dev_priv->int_lvds_connector = connector;
        drm_sysfs_connector_add(connector);
 
+       intel_lvds->base.mode_flags = intel_lvds_mode_flags;
+
        intel_panel_setup_backlight(dev);
 
        connector->status = intel_lvds_detect(connector, 0);
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c 
b/drivers/gpu/drm/i915/intel_sdvo.c
index a1840f4..ae32c1d 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2474,6 +2474,32 @@ static bool intel_sdvo_create_enhance_property(struct 
intel_sdvo *intel_sdvo,
                return true;
 }
 
+static u32 intel_sdvo_mode_flags(struct intel_encoder *intel_encoder)
+{
+       struct drm_device *dev = intel_encoder->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_sdvo *intel_sdvo = container_of(intel_encoder,
+                                                    struct intel_sdvo, base);
+       u32 val, flags = 0;
+
+       if (INTEL_INFO(dev)->gen < 4)
+               return 0;
+
+       val = I915_READ(intel_sdvo->sdvo_reg);
+
+       if (val & SDVO_HSYNC_ACTIVE_HIGH)
+               flags |= DRM_MODE_FLAG_PHSYNC;
+       else
+               flags |= DRM_MODE_FLAG_NHSYNC;
+
+       if (val & SDVO_VSYNC_ACTIVE_HIGH)
+               flags |= DRM_MODE_FLAG_PVSYNC;
+       else
+               flags |= DRM_MODE_FLAG_NVSYNC;
+
+       return flags;
+}
+
 static int intel_sdvo_ddc_proxy_xfer(struct i2c_adapter *adapter,
                                     struct i2c_msg *msgs,
                                     int num)
@@ -2593,6 +2619,8 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t 
sdvo_reg, bool is_sdvob)
                                                    
&intel_sdvo->pixel_clock_max))
                goto err;
 
+       intel_sdvo->base.mode_flags = intel_sdvo_mode_flags;
+
        DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, "
                        "clock range %dMHz - %dMHz, "
                        "input 1: %c, input 2: %c, "
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 3346612..4435083 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1552,6 +1552,8 @@ intel_tv_init(struct drm_device *dev)
        intel_encoder = &intel_tv->base;
        connector = &intel_connector->base;
 
+       intel_encoder->mode_flags = intel_mode_flags_none;
+
        /* The documentation, for the older chipsets at least, recommend
         * using a polling method rather than hotplug detection for TVs.
         * This is because in order to perform the hotplug detection, the PLLs
-- 
1.7.10

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to