[4/6,drm/i915] : require_pipe_a helper functions
diff mbox

Message ID 96d19ab778fc7b9ae5c6b94d8f4a83d6bc3609b7.1249997742.git.daniel.vetter@ffwll.ch
State Superseded
Headers show

Commit Message

Daniel Vetter Aug. 11, 2009, 2:05 p.m. UTC
These will be used to ensure that the clock of pipe a is running
when the overlay is switched on. Programming logic more or less
directly ported over from userspace.

Also export the already existing helper function drm_encoder_crtc_ok.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/drm_crtc_helper.c    |    3 +-
 drivers/gpu/drm/i915/intel_display.c |   83 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |    5 ++
 include/drm/drm_crtc_helper.h        |    2 +
 4 files changed, 92 insertions(+), 1 deletions(-)

Patch
diff mbox

diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 6aaa2cb..2d837a5 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -511,7 +511,7 @@  static void drm_setup_crtcs(struct drm_device *dev)
  *
  * Return false if @encoder can't be driven by @crtc, true otherwise.
  */
-static bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
+bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
 				struct drm_crtc *crtc)
 {
 	struct drm_device *dev;
@@ -532,6 +532,7 @@  static bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
 		return true;
 	return false;
 }
+EXPORT_SYMBOL(drm_encoder_crtc_ok);
 
 /*
  * Check the CRTC we're going to map each output to vs. its current
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 818c703..cb709b8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2936,6 +2936,89 @@  void intel_release_load_detect_pipe(struct intel_output *intel_output, int dpms_
 	}
 }
 
+/** Ensure that pipe A is enabled. Returns the crtc that runs pipe a or NULL
+ * if pipe a is already enabled */
+struct drm_crtc *intel_require_pipe_a_start(struct drm_device *dev,
+					    int *dpms_mode)
+{
+	struct drm_crtc *crtc;
+	struct intel_crtc *intel_crtc;
+	struct drm_connector *connector;
+	struct drm_crtc_helper_funcs *crtc_funcs;
+	struct intel_output *intel_output;
+
+	crtc = intel_get_crtc_from_pipe(dev, 0);
+	intel_crtc = to_intel_crtc(crtc);
+	BUG_ON(intel_crtc->pipe != 0);
+
+	if (crtc->enabled && intel_crtc->dpms_mode == DRM_MODE_DPMS_ON)
+		return NULL;
+
+	DRM_DEBUG("i915: require PIPEA, switching on crtc ...\n");
+
+	*dpms_mode = intel_crtc->dpms_mode;
+
+	if (crtc->enabled && intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) {
+		/* just switch it on */
+		crtc_funcs = crtc->helper_private;
+		crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
+
+		return crtc;
+	}
+
+	if (!drm_helper_crtc_in_use(crtc)) {
+		/* look for an encoder/connector */
+		list_for_each_entry(connector,
+				&dev->mode_config.connector_list, head) {
+			intel_output = to_intel_output(connector);
+
+			if (intel_output->enc.crtc)
+				/* don't steal connectors */
+				continue;
+
+			if (!drm_encoder_crtc_ok(&intel_output->enc, crtc))
+				continue;
+
+			intel_output->enc.crtc = crtc;
+			break;
+		}
+	}
+
+	drm_crtc_helper_set_mode(crtc, &load_detect_mode, 0, 0, crtc->fb);
+	BUG_ON(crtc->enabled);
+
+	return crtc;
+}
+
+void intel_require_pipe_a_end(struct drm_device *dev,
+			      struct drm_crtc *crtc,
+			      int dpms_mode)
+{
+	struct drm_encoder_helper_funcs *encoder_funcs;
+	struct drm_encoder *encoder;
+	struct drm_crtc_helper_funcs *crtc_funcs;
+
+	if (!crtc)
+		return;
+
+	crtc_funcs = crtc->helper_private;
+
+	DRM_DEBUG("i915: require PIPEA, switching off crtc ...\n");
+
+	/* Switch crtc and output back off if necessary */
+	if (crtc->enabled && dpms_mode != DRM_MODE_DPMS_ON) {
+		list_for_each_entry(encoder,
+				&dev->mode_config.encoder_list, head) {
+			if (encoder->crtc != crtc)
+				continue;
+			encoder_funcs = encoder->helper_private;
+			encoder_funcs->dpms(encoder, dpms_mode);
+		}
+
+		crtc_funcs->dpms(crtc, dpms_mode);
+	}
+}
+
 /* 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)
 {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d6f92ea..f747dd4 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -142,6 +142,11 @@  extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_ou
 						   int *dpms_mode);
 extern void intel_release_load_detect_pipe(struct intel_output *intel_output,
 					   int dpms_mode);
+extern struct drm_crtc *intel_require_pipe_a_start(struct drm_device *dev,
+					    int *dpms_mode);
+extern void intel_require_pipe_a_end(struct drm_device *dev,
+			      struct drm_crtc *crtc,
+			      int dpms_mode);
 
 extern struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB);
 extern int intel_sdvo_supports_hotplug(struct drm_connector *connector);
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index 6769ff6..26c457f 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -123,4 +123,6 @@  static inline void drm_connector_helper_add(struct drm_connector *connector,
 }
 
 extern int drm_helper_resume_force_mode(struct drm_device *dev);
+extern bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
+				struct drm_crtc *crtc);
 #endif