Together with the static helpers drm_crtc_prepare_encoders and
drm_encoder_disable (which will be simplified in the next patch, but
for now are 1:1 copies). Again, no changes beside new names for these
functions.
Also call our new set_mode instead of the crtc helper one now in all
the places we've done so far.
Signed-Off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
drivers/gpu/drm/i915/intel_display.c | 160 +-
drivers/gpu/drm/i915/intel_dp.c |6 +-
drivers/gpu/drm/i915/intel_drv.h |4 +
drivers/gpu/drm/i915/intel_hdmi.c|6 +-
drivers/gpu/drm/i915/intel_lvds.c|5 +-
drivers/gpu/drm/i915/intel_sdvo.c|4 +-
drivers/gpu/drm/i915/intel_tv.c |4 +-
7 files changed, 173 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c
b/drivers/gpu/drm/i915/intel_display.c
index 0c15960..574a610 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5653,7 +5653,7 @@ bool intel_get_load_detect_pipe(struct intel_encoder
*intel_encoder,
goto fail;
}
- if (!drm_crtc_helper_set_mode(crtc, mode, 0, 0, old_fb)) {
+ if (!intel_crtc_set_mode(crtc, mode, 0, 0, old_fb)) {
DRM_DEBUG_KMS(failed to set mode on load-detect pipe\n);
if (old-release_fb)
old-release_fb-funcs-destroy(old-release_fb);
@@ -6597,6 +6597,158 @@ intel_crtc_helper_disable(struct drm_crtc *crtc)
return 0;
}
+static void
+intel_encoder_disable_helper(struct drm_encoder *encoder)
+{
+ struct drm_encoder_helper_funcs *encoder_funcs =
encoder-helper_private;
+
+ if (encoder_funcs-disable)
+ (*encoder_funcs-disable)(encoder);
+ else
+ (*encoder_funcs-dpms)(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void
+intel_crtc_prepare_encoders(struct drm_device *dev)
+{
+ struct drm_encoder_helper_funcs *encoder_funcs;
+ struct drm_encoder *encoder;
+
+ list_for_each_entry(encoder, dev-mode_config.encoder_list, head) {
+ encoder_funcs = encoder-helper_private;
+ /* Disable unused encoders */
+ if (encoder-crtc == NULL)
+ intel_encoder_disable_helper(encoder);
+ /* Disable encoders whose CRTC is about to change */
+ if (encoder_funcs-get_crtc
+ encoder-crtc != (*encoder_funcs-get_crtc)(encoder))
+ intel_encoder_disable_helper(encoder);
+ }
+}
+
+bool intel_crtc_set_mode(struct drm_crtc *crtc,
+struct drm_display_mode *mode,
+int x, int y,
+struct drm_framebuffer *old_fb)
+{
+ struct drm_device *dev = crtc-dev;
+ struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
+ struct drm_crtc_helper_funcs *crtc_funcs = crtc-helper_private;
+ struct drm_encoder_helper_funcs *encoder_funcs;
+ int saved_x, saved_y;
+ struct drm_encoder *encoder;
+ bool ret = true;
+
+ crtc-enabled = drm_helper_crtc_in_use(crtc);
+ if (!crtc-enabled)
+ return true;
+
+ adjusted_mode = drm_mode_duplicate(dev, mode);
+ if (!adjusted_mode)
+ return false;
+
+ saved_hwmode = crtc-hwmode;
+ saved_mode = crtc-mode;
+ saved_x = crtc-x;
+ saved_y = crtc-y;
+
+ /* Update crtc values up front so the driver can rely on them for mode
+* setting.
+*/
+ crtc-mode = *mode;
+ crtc-x = x;
+ crtc-y = y;
+
+ /* Pass our mode to the connectors and the CRTC to give them a chance to
+* adjust it according to limitations or connector properties, and also
+* a chance to reject the mode entirely.
+*/
+ list_for_each_entry(encoder, dev-mode_config.encoder_list, head) {
+
+ if (encoder-crtc != crtc)
+ continue;
+ encoder_funcs = encoder-helper_private;
+ if (!(ret = encoder_funcs-mode_fixup(encoder, mode,
+ adjusted_mode))) {
+ DRM_DEBUG_KMS(Encoder fixup failed\n);
+ goto done;
+ }
+ }
+
+ if (!(ret = crtc_funcs-mode_fixup(crtc, mode, adjusted_mode))) {
+ DRM_DEBUG_KMS(CRTC fixup failed\n);
+ goto done;
+ }
+ DRM_DEBUG_KMS([CRTC:%d]\n, crtc-base.id);
+
+ /* Prepare the encoders and CRTCs before setting the mode. */
+ list_for_each_entry(encoder, dev-mode_config.encoder_list, head) {
+
+ if (encoder-crtc != crtc)
+ continue;
+ encoder_funcs = encoder-helper_private;
+ /* Disable the encoders as the first thing we do. */
+ encoder_funcs-prepare(encoder);
+ }
+
+