drm/i915: copy&paste drm_crtc_helper_set_mode
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 2 Jul 2012 07:56:42 +0000 (09:56 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 6 Sep 2012 05:56:54 +0000 (07:56 +0200)
Together with the static helper functions 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.

v2: Call the function just intel_set_mode to better differentia it
from intel_crtc_mode_set which really only does the ->mode_set step of
the entire modeset sequence on one crtc. Whereas this function does
the global change.

Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_tv.c

index 9d5c575385b26ac49b97491ae458511789f224ee..3e119a62888da1ebd172435c18e4be252a2ca0b0 100644 (file)
@@ -5767,7 +5767,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
                goto fail;
        }
 
-       if (!drm_crtc_helper_set_mode(crtc, mode, 0, 0, old_fb)) {
+       if (!intel_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);
@@ -6635,6 +6635,157 @@ 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_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);
+       }
+
+       intel_crtc_prepare_encoders(dev);
+
+       crtc_funcs->prepare(crtc);
+
+       /* Set up the DPLL and any encoders state that needs to adjust or depend
+        * on the DPLL.
+        */
+       ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
+       if (!ret)
+           goto done;
+
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+
+               if (encoder->crtc != crtc)
+                       continue;
+
+               DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
+                       encoder->base.id, drm_get_encoder_name(encoder),
+                       mode->base.id, mode->name);
+               encoder_funcs = encoder->helper_private;
+               encoder_funcs->mode_set(encoder, mode, adjusted_mode);
+       }
+
+       /* Now enable the clocks, plane, pipe, and connectors that we set up. */
+       crtc_funcs->commit(crtc);
+
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+
+               if (encoder->crtc != crtc)
+                       continue;
+
+               encoder_funcs = encoder->helper_private;
+               encoder_funcs->commit(encoder);
+
+       }
+
+       /* Store real post-adjustment hardware mode. */
+       crtc->hwmode = *adjusted_mode;
+
+       /* Calculate and store various constants which
+        * are later needed by vblank and swap-completion
+        * timestamping. They are derived from true hwmode.
+        */
+       drm_calc_timestamping_constants(crtc);
+
+       /* FIXME: add subpixel order */
+done:
+       drm_mode_destroy(dev, adjusted_mode);
+       if (!ret) {
+               crtc->hwmode = saved_hwmode;
+               crtc->mode = saved_mode;
+               crtc->x = saved_x;
+               crtc->y = saved_y;
+       }
+
+       return ret;
+}
+
 static int intel_crtc_set_config(struct drm_mode_set *set)
 {
        struct drm_device *dev;
@@ -6817,9 +6968,8 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
                        drm_mode_debug_printmodeline(set->mode);
                        old_fb = set->crtc->fb;
                        set->crtc->fb = set->fb;
-                       if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
-                                                     set->x, set->y,
-                                                     old_fb)) {
+                       if (!intel_set_mode(set->crtc, set->mode,
+                                           set->x, set->y, old_fb)) {
                                DRM_ERROR("failed to set mode on [CRTC:%d]\n",
                                          set->crtc->base.id);
                                set->crtc->fb = old_fb;
@@ -6873,8 +7023,8 @@ fail:
 
        /* Try to restore the config */
        if (mode_changed &&
-           !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
-                                     save_set.y, save_set.fb))
+           !intel_set_mode(save_set.crtc, save_set.mode,
+                           save_set.x, save_set.y, save_set.fb))
                DRM_ERROR("failed to restore config after modeset failure\n");
 
        kfree(save_connectors);
index 7ee954c39c919c6b3d7c36cd386aadfb591a094b..2abaaf65ae8d83c2a1d471e7a01be2a8ad2001b5 100644 (file)
@@ -2312,9 +2312,8 @@ intel_dp_set_property(struct drm_connector *connector,
 done:
        if (intel_dp->base.base.crtc) {
                struct drm_crtc *crtc = intel_dp->base.base.crtc;
-               drm_crtc_helper_set_mode(crtc, &crtc->mode,
-                                        crtc->x, crtc->y,
-                                        crtc->fb);
+               intel_set_mode(crtc, &crtc->mode,
+                              crtc->x, crtc->y, crtc->fb);
        }
 
        return 0;
index e59cac34ec6879091a24770162778e9a42d1fd7e..c28fadae8758171792cae597f500e7e42fbf7430 100644 (file)
@@ -410,6 +410,8 @@ extern void intel_panel_disable_backlight(struct drm_device *dev);
 extern void intel_panel_destroy_backlight(struct drm_device *dev);
 extern enum drm_connector_status intel_panel_detect(struct drm_device *dev);
 
+extern bool intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
+                          int x, int y, struct drm_framebuffer *old_fb);
 extern void intel_crtc_load_lut(struct drm_crtc *crtc);
 extern void intel_crtc_update_dpms(struct drm_crtc *crtc);
 extern void intel_encoder_noop(struct drm_encoder *encoder);
index acddaaa5f04c4b0a5d39d420f507186503e18eed..ef8409794ab6259ccfe1d27f49a78ce5f4d4037d 100644 (file)
@@ -869,9 +869,8 @@ intel_hdmi_set_property(struct drm_connector *connector,
 done:
        if (intel_hdmi->base.base.crtc) {
                struct drm_crtc *crtc = intel_hdmi->base.base.crtc;
-               drm_crtc_helper_set_mode(crtc, &crtc->mode,
-                                        crtc->x, crtc->y,
-                                        crtc->fb);
+               intel_set_mode(crtc, &crtc->mode,
+                              crtc->x, crtc->y, crtc->fb);
        }
 
        return 0;
index 3baa224ab9668e4b3d0bfa0a16f38f1e041f2019..fad82b2721ed79aea1a1286f7754fe4101c7d84c 100644 (file)
@@ -560,8 +560,8 @@ static int intel_lvds_set_property(struct drm_connector *connector,
                         * If the CRTC is enabled, the display will be changed
                         * according to the new panel fitting mode.
                         */
-                       drm_crtc_helper_set_mode(crtc, &crtc->mode,
-                               crtc->x, crtc->y, crtc->fb);
+                       intel_set_mode(crtc, &crtc->mode,
+                                      crtc->x, crtc->y, crtc->fb);
                }
        }
 
index a01c47021f53bad59aa0ab3abf69ed49b81959a8..88fb30dff7587a29bdb7cfeb7d5d48e857637993 100644 (file)
@@ -1879,8 +1879,8 @@ set_value:
 done:
        if (intel_sdvo->base.base.crtc) {
                struct drm_crtc *crtc = intel_sdvo->base.base.crtc;
-               drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
-                                        crtc->y, crtc->fb);
+               intel_set_mode(crtc, &crtc->mode,
+                              crtc->x, crtc->y, crtc->fb);
        }
 
        return 0;
index 281e0cf6f606dd5b36a59c1fe05083367589f7a9..16cb1140506861105dd7bc6fcf8479c62171771b 100644 (file)
@@ -1471,8 +1471,8 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
        }
 
        if (changed && crtc)
-               drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
-                               crtc->y, crtc->fb);
+               intel_set_mode(crtc, &crtc->mode,
+                              crtc->x, crtc->y, crtc->fb);
 out:
        return ret;
 }