[PATCH 40/43] drm/i915: fetch sync polarity when building initial configuration

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Jesse Barnes <jbarnes at virtuousgeek.org>

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 <jbarnes at virtuousgeek.org>
---
 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



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux