All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jesse Barnes <jbarnes@virtuousgeek.org>
To: intel-gfx@lists.freedesktop.org
Subject: [PATCH 06/13] drm/i915: Retrieve the current mode upon KMS takeover
Date: Tue, 19 Feb 2013 13:31:41 -0800	[thread overview]
Message-ID: <1361309508-4901-7-git-send-email-jbarnes@virtuousgeek.org> (raw)
In-Reply-To: <1361309508-4901-1-git-send-email-jbarnes@virtuousgeek.org>

From: Chris Wilson <chris@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@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]);
+			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))
-- 
1.7.9.5

  parent reply	other threads:[~2013-02-19 21:32 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-02-19 21:31 More fastboot bits Jesse Barnes
2013-02-19 21:31 ` [PATCH 01/13] drm/i915: Skip modifying PCH DREF if not changing clock sources Jesse Barnes
2013-03-20 12:17   ` Imre Deak
2013-03-26 22:57     ` Jesse Barnes
2013-02-19 21:31 ` [PATCH 02/13] drm/i915: Introduce i915_gem_object_create_stolen_for_preallocated Jesse Barnes
2013-03-26 19:46   ` Daniel Vetter
2013-03-26 20:58     ` Jesse Barnes
2013-02-19 21:31 ` [PATCH 03/13] drm/i915: Split the framebuffer_info creation into a separate routine Jesse Barnes
2013-03-20 12:23   ` Imre Deak
2013-03-26 23:07     ` Jesse Barnes
2013-03-27 11:49       ` Imre Deak
2013-03-27 13:48         ` Chris Wilson
2013-02-19 21:31 ` [PATCH 04/13] drm: add initial_config function to fb helper Jesse Barnes
2013-03-26 20:34   ` Daniel Vetter
2013-03-26 20:52     ` Chris Wilson
2013-03-26 20:57       ` Jesse Barnes
2013-02-19 21:31 ` [PATCH 05/13] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon Jesse Barnes
2013-03-20 12:31   ` Imre Deak
2013-03-26 23:20     ` Jesse Barnes
2013-02-19 21:31 ` Jesse Barnes [this message]
2013-03-20 12:36   ` [PATCH 06/13] drm/i915: Retrieve the current mode upon KMS takeover Imre Deak
2013-03-26 23:24     ` Jesse Barnes
2013-03-26 23:52       ` Daniel Vetter
2013-03-26 23:59         ` Jesse Barnes
2013-02-19 21:31 ` [PATCH 07/13] drm/i915: Only preserve the BIOS modes if they are the preferred ones Jesse Barnes
2013-02-19 21:31 ` [PATCH 08/13] drm/i915: Validate that the framebuffer accommodates the current mode Jesse Barnes
2013-02-19 21:31 ` [PATCH 09/13] drm/i915: fix build in intel_display.c Jesse Barnes
2013-03-20 12:41   ` Imre Deak
2013-03-26 23:26     ` Jesse Barnes
2013-02-19 21:31 ` [PATCH 10/13] drm/i915: check panel fit status at update_plane time Jesse Barnes
2013-03-20 12:46   ` Imre Deak
2013-02-19 21:31 ` [PATCH 11/13] drm/i915: add clock_get for ironlake+ Jesse Barnes
2013-03-20 12:48   ` Imre Deak
2013-03-26 23:29     ` Jesse Barnes
2013-02-19 21:31 ` [PATCH 12/13] drm/i915: treat no fb -> fb as simple flip instead of full mode set Jesse Barnes
2013-02-19 21:31 ` [PATCH 13/13] drm/i915: check for non-native modes when inheriting a BIOS fb Jesse Barnes
2013-03-20 12:51   ` Imre Deak
2013-03-26 23:29     ` Jesse Barnes
2013-03-20 12:15 ` More fastboot bits Imre Deak
2013-03-20 15:20   ` Jesse Barnes

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1361309508-4901-7-git-send-email-jbarnes@virtuousgeek.org \
    --to=jbarnes@virtuousgeek.org \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.