@@ -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
@@ -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)
{
@@ -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);
@@ -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
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(-)