diff mbox

[RFC,04/30] drm/i915: implement DDI disable function

Message ID 1346191621-12996-5-git-send-email-przanoni@gmail.com (mailing list archive)
State RFC
Headers show

Commit Message

Paulo Zanoni Aug. 28, 2012, 10:06 p.m. UTC
From: Paulo Zanoni <paulo.r.zanoni@intel.com>

It follows the "mode unset" sequence recommended by the documentation.
This is necessary so we can make PLLs available for the other mode
sets and it also helps preventing machine hangs.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c  | 31 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h  |  1 +
 drivers/gpu/drm/i915/intel_hdmi.c |  1 +
 3 files changed, 33 insertions(+)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 4fd22ae..e3dac45 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -841,6 +841,37 @@  static void intel_ddi_disable_port(struct drm_i915_private *dev_priv,
 	I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
 }
 
+static bool intel_ddi_port_disabled(struct drm_i915_private *dev_priv,
+				    enum port port)
+{
+	return (I915_READ(PORT_CLK_SEL(port)) == PORT_CLK_SEL_NONE);
+}
+
+void intel_ddi_disable(struct drm_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
+	struct drm_crtc *crtc = encoder->crtc;
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	int port = intel_hdmi->ddi_port;
+
+	if (intel_ddi_port_disabled(dev_priv, port))
+		return;
+
+	if (!crtc) {
+		WARN(1, "Disabling encoder on port %c without CRTC\n",
+		     port_name(port));
+	} else {
+		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+		int pipe = intel_crtc->pipe;
+		struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+
+		(*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
+		intel_ddi_disable_pipe(dev_priv, pipe);
+	}
+
+	intel_ddi_disable_port(dev_priv, port);
+}
+
 void intel_ddi_pll_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 2578158..b99af38 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -526,5 +526,6 @@  extern void intel_ddi_mode_set(struct drm_encoder *encoder,
 				struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode);
 extern void intel_ddi_pll_init(struct drm_device *dev);
+extern void intel_ddi_disable(struct drm_encoder *encoder);
 
 #endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index e4c37bb..c56d213 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -854,6 +854,7 @@  static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs_hsw = {
 	.prepare = intel_encoder_prepare,
 	.mode_set = intel_ddi_mode_set,
 	.commit = intel_encoder_commit,
+	.disable = intel_ddi_disable,
 };
 
 static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {