diff mbox

[2/5,drm/i915] : require_pipe_a helper functions

Message ID a14b571331c69730ef2556b4a4f4f28c0651ea0f.1252660839.git.daniel.vetter@ffwll.ch (mailing list archive)
State Superseded
Headers show

Commit Message

Daniel Vetter Sept. 11, 2009, 12:39 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(-)

Comments

Daniel Vetter Sept. 14, 2009, 9:15 a.m. UTC | #1
Hi all,

Please ignore this patch because it doesn't work as advertised:

a) Under some circumstance it doesn't do what it claims to do.
b) When it does what it claims to do it hangs the chip on drm-intel-next.

_But_ completely disabling this stuff yields a black screen when enabling
the overlay. Looks like I've missed yet another cache flush. I've hacked
up a fix which seems to work, here, but I'd like to give it some more
testing.

Yours, Daniel
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index ff447f1..13afdfe 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -488,7 +488,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;
@@ -509,6 +509,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 155719f..d0a74e5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3069,6 +3069,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);
+	WARN_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 b9e47f1..33e6980 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -163,6 +163,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 4c8daca..43a0a09 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -126,4 +126,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