drm/i915: Use full atomic modeset.
authorMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Mon, 13 Jul 2015 14:30:30 +0000 (16:30 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 15 Jul 2015 12:55:23 +0000 (14:55 +0200)
Huzzah! \o/

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_params.c
drivers/gpu/drm/i915/intel_atomic.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h

index db48aee7f1405d846d9dc3b18efcc2b6ad2a09fa..f13ed1ef664106efb78cf14301d183148eba4098 100644 (file)
@@ -1731,7 +1731,7 @@ static int __init i915_init(void)
         * to the atomic ioctl and the atomic properties.  Only plane operations on
         * a single CRTC will actually work.
         */
-       if (i915.nuclear_pageflip)
+       if (driver.driver_features & DRIVER_MODESET)
                driver.driver_features |= DRIVER_ATOMIC;
 
        return drm_pci_init(&driver, &i915_pci_driver);
index 2714228e34561c215e85cd76ce687bf745fc727c..4af33d59d507048d113b918c49a0526c1687fa92 100644 (file)
@@ -2614,7 +2614,6 @@ struct i915_params {
        int use_mmio_flip;
        int mmio_debug;
        bool verbose_state_checks;
-       bool nuclear_pageflip;
        int edp_vswing;
 };
 extern struct i915_params i915 __read_mostly;
index 7983fe48a65496bfe7a77b3bd636d6f6024a1107..5f4e7295295ff4904a7207f839abd912f77f0340 100644 (file)
@@ -51,7 +51,6 @@ struct i915_params i915 __read_mostly = {
        .use_mmio_flip = 0,
        .mmio_debug = 0,
        .verbose_state_checks = 1,
-       .nuclear_pageflip = 0,
        .edp_vswing = 0,
 };
 
@@ -176,10 +175,6 @@ module_param_named(verbose_state_checks, i915.verbose_state_checks, bool, 0600);
 MODULE_PARM_DESC(verbose_state_checks,
        "Enable verbose logs (ie. WARN_ON()) in case of unexpected hw state conditions.");
 
-module_param_named_unsafe(nuclear_pageflip, i915.nuclear_pageflip, bool, 0600);
-MODULE_PARM_DESC(nuclear_pageflip,
-                "Force atomic modeset functionality; only planes work for now (default: false).");
-
 /* WA to get away with the default setting in VBT for early platforms.Will be removed */
 module_param_named_unsafe(edp_vswing, i915.edp_vswing, int, 0400);
 MODULE_PARM_DESC(edp_vswing,
index dcf4fb458649ad256b393a469ba9975b4e8b1409..e2531cf59266e77208c766b36c5291d4a939a825 100644 (file)
 #include <drm/drm_plane_helper.h>
 #include "intel_drv.h"
 
-
-/**
- * intel_atomic_check - validate state object
- * @dev: drm device
- * @state: state to validate
- */
-int intel_atomic_check(struct drm_device *dev,
-                      struct drm_atomic_state *state)
-{
-       int nplanes = dev->mode_config.num_total_plane;
-       int ncrtcs = dev->mode_config.num_crtc;
-       int nconnectors = dev->mode_config.num_connector;
-       enum pipe nuclear_pipe = INVALID_PIPE;
-       struct intel_crtc *nuclear_crtc = NULL;
-       struct intel_crtc_state *crtc_state = NULL;
-       int ret;
-       int i;
-       bool not_nuclear = false;
-
-       to_intel_atomic_state(state)->cdclk = to_i915(dev)->cdclk_freq;
-
-       /*
-        * FIXME:  At the moment, we only support "nuclear pageflip" on a
-        * single CRTC.  Cross-crtc updates will be added later.
-        */
-       for (i = 0; i < nplanes; i++) {
-               struct intel_plane *plane = to_intel_plane(state->planes[i]);
-               if (!plane)
-                       continue;
-
-               if (nuclear_pipe == INVALID_PIPE) {
-                       nuclear_pipe = plane->pipe;
-               } else if (nuclear_pipe != plane->pipe) {
-                       DRM_DEBUG_KMS("i915 only support atomic plane operations on a single CRTC at the moment\n");
-                       return -EINVAL;
-               }
-       }
-
-       /*
-        * FIXME:  We only handle planes for now; make sure there are no CRTC's
-        * or connectors involved.
-        */
-       state->allow_modeset = false;
-       for (i = 0; i < ncrtcs; i++) {
-               struct intel_crtc *crtc = to_intel_crtc(state->crtcs[i]);
-               if (crtc)
-                       memset(&crtc->atomic, 0, sizeof(crtc->atomic));
-               if (crtc && crtc->pipe != nuclear_pipe)
-                       not_nuclear = true;
-               if (crtc && crtc->pipe == nuclear_pipe) {
-                       nuclear_crtc = crtc;
-                       crtc_state = to_intel_crtc_state(state->crtc_states[i]);
-               }
-       }
-       for (i = 0; i < nconnectors; i++)
-               if (state->connectors[i] != NULL)
-                       not_nuclear = true;
-
-       if (not_nuclear) {
-               DRM_DEBUG_KMS("i915 only supports atomic plane operations at the moment\n");
-               return -EINVAL;
-       }
-
-       ret = drm_atomic_helper_check_planes(dev, state);
-       if (ret)
-               return ret;
-
-       return ret;
-}
-
-
-/**
- * intel_atomic_commit - commit validated state object
- * @dev: DRM device
- * @state: the top-level driver state object
- * @async: asynchronous commit
- *
- * This function commits a top-level state object that has been validated
- * with drm_atomic_helper_check().
- *
- * FIXME:  Atomic modeset support for i915 is not yet complete.  At the moment
- * we can only handle plane-related operations and do not yet support
- * asynchronous commit.
- *
- * RETURNS
- * Zero for success or -errno.
- */
-int intel_atomic_commit(struct drm_device *dev,
-                       struct drm_atomic_state *state,
-                       bool async)
-{
-       struct drm_crtc_state *crtc_state;
-       struct drm_crtc *crtc;
-       int ret;
-       int i;
-
-       if (async) {
-               DRM_DEBUG_KMS("i915 does not yet support async commit\n");
-               return -EINVAL;
-       }
-
-       ret = drm_atomic_helper_prepare_planes(dev, state);
-       if (ret)
-               return ret;
-
-       /* Point of no return */
-       drm_atomic_helper_swap_state(dev, state);
-
-       for_each_crtc_in_state(state, crtc, crtc_state, i) {
-               to_intel_crtc(crtc)->config = to_intel_crtc_state(crtc->state);
-
-               drm_atomic_helper_commit_planes_on_crtc(crtc_state);
-       }
-
-       /* FIXME: This function should eventually call __intel_set_mode when needed */
-
-       drm_atomic_helper_wait_for_vblanks(dev, state);
-       drm_atomic_helper_cleanup_planes(dev, state);
-       drm_atomic_state_free(state);
-
-       return 0;
-}
-
 /**
  * intel_connector_atomic_get_property - fetch connector property value
  * @connector: connector to fetch property for
index 10a17268113844a7a42583af8d79dcb32c8d11d6..83d7753b8b07f92f9184854d1cae7acedf619302 100644 (file)
@@ -86,7 +86,6 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
 static void ironlake_pch_clock_get(struct intel_crtc *crtc,
                                   struct intel_crtc_state *pipe_config);
 
-static int intel_set_mode(struct drm_atomic_state *state);
 static int intel_framebuffer_init(struct drm_device *dev,
                                  struct intel_framebuffer *ifb,
                                  struct drm_mode_fb_cmd2 *mode_cmd,
@@ -111,14 +110,6 @@ static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state,
                           int num_connectors);
 static void intel_modeset_setup_hw_state(struct drm_device *dev);
 
-static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe)
-{
-       if (!connector->mst_port)
-               return connector->encoder;
-       else
-               return &connector->mst_port->mst_encoders[pipe]->base;
-}
-
 typedef struct {
        int     min, max;
 } intel_range_t;
@@ -6262,7 +6253,7 @@ int intel_display_suspend(struct drm_device *dev)
        }
 
        if (crtc_mask) {
-               ret = intel_set_mode(state);
+               ret = drm_atomic_commit(state);
 
                if (!ret) {
                        for_each_crtc(dev, crtc)
@@ -6316,7 +6307,7 @@ int intel_crtc_control(struct drm_crtc *crtc, bool enable)
        }
        pipe_config->base.active = enable;
 
-       ret = intel_set_mode(state);
+       ret = drm_atomic_commit(state);
        if (!ret)
                return ret;
 
@@ -10430,7 +10421,7 @@ retry:
 
        drm_mode_copy(&crtc_state->base.mode, mode);
 
-       if (intel_set_mode(state)) {
+       if (drm_atomic_commit(state)) {
                DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
                if (old->release_fb)
                        old->release_fb->funcs->destroy(old->release_fb);
@@ -10498,7 +10489,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
                if (ret)
                        goto fail;
 
-               ret = intel_set_mode(state);
+               ret = drm_atomic_commit(state);
                if (ret)
                        goto fail;
 
@@ -13119,7 +13110,6 @@ static int intel_modeset_all_pipes(struct drm_atomic_state *state)
 }
 
 
-/* Code that should eventually be part of atomic_check() */
 static int intel_modeset_checks(struct drm_atomic_state *state)
 {
        struct drm_device *dev = state->dev;
@@ -13160,15 +13150,20 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
        return 0;
 }
 
-static int
-intel_modeset_compute_config(struct drm_atomic_state *state)
+/**
+ * intel_atomic_check - validate state object
+ * @dev: drm device
+ * @state: state to validate
+ */
+static int intel_atomic_check(struct drm_device *dev,
+                             struct drm_atomic_state *state)
 {
        struct drm_crtc *crtc;
        struct drm_crtc_state *crtc_state;
        int ret, i;
        bool any_ms = false;
 
-       ret = drm_atomic_helper_check_modeset(state->dev, state);
+       ret = drm_atomic_helper_check_modeset(dev, state);
        if (ret)
                return ret;
 
@@ -13231,9 +13226,26 @@ intel_modeset_compute_config(struct drm_atomic_state *state)
        return drm_atomic_helper_check_planes(state->dev, state);
 }
 
-static int __intel_set_mode(struct drm_atomic_state *state)
+/**
+ * intel_atomic_commit - commit validated state object
+ * @dev: DRM device
+ * @state: the top-level driver state object
+ * @async: asynchronous commit
+ *
+ * This function commits a top-level state object that has been validated
+ * with drm_atomic_helper_check().
+ *
+ * FIXME:  Atomic modeset support for i915 is not yet complete.  At the moment
+ * we can only handle plane-related operations and do not yet support
+ * asynchronous commit.
+ *
+ * RETURNS
+ * Zero for success or -errno.
+ */
+static int intel_atomic_commit(struct drm_device *dev,
+                              struct drm_atomic_state *state,
+                              bool async)
 {
-       struct drm_device *dev = state->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *crtc;
        struct drm_crtc_state *crtc_state;
@@ -13241,6 +13253,11 @@ static int __intel_set_mode(struct drm_atomic_state *state)
        int i;
        bool any_ms = false;
 
+       if (async) {
+               DRM_DEBUG_KMS("i915 does not yet support async commit\n");
+               return -EINVAL;
+       }
+
        ret = drm_atomic_helper_prepare_planes(dev, state);
        if (ret)
                return ret;
@@ -13285,34 +13302,14 @@ static int __intel_set_mode(struct drm_atomic_state *state)
 
        /* FIXME: add subpixel order */
 
+       drm_atomic_helper_wait_for_vblanks(dev, state);
        drm_atomic_helper_cleanup_planes(dev, state);
-
        drm_atomic_state_free(state);
 
-       return 0;
-}
-
-static int intel_set_mode_checked(struct drm_atomic_state *state)
-{
-       struct drm_device *dev = state->dev;
-       int ret;
-
-       ret = __intel_set_mode(state);
-       if (ret == 0)
+       if (any_ms)
                intel_modeset_check_state(dev);
 
-       return ret;
-}
-
-static int intel_set_mode(struct drm_atomic_state *state)
-{
-       int ret;
-
-       ret = intel_modeset_compute_config(state);
-       if (ret)
-               return ret;
-
-       return intel_set_mode_checked(state);
+       return 0;
 }
 
 void intel_crtc_restore_mode(struct drm_crtc *crtc)
@@ -13339,7 +13336,7 @@ retry:
                        goto out;
 
                crtc_state->mode_changed = true;
-               ret = intel_set_mode(state);
+               ret = drm_atomic_commit(state);
        }
 
        if (ret == -EDEADLK) {
@@ -13355,201 +13352,9 @@ out:
 
 #undef for_each_intel_crtc_masked
 
-static bool intel_connector_in_mode_set(struct intel_connector *connector,
-                                       struct drm_mode_set *set)
-{
-       int ro;
-
-       for (ro = 0; ro < set->num_connectors; ro++)
-               if (set->connectors[ro] == &connector->base)
-                       return true;
-
-       return false;
-}
-
-static int
-intel_modeset_stage_output_state(struct drm_device *dev,
-                                struct drm_mode_set *set,
-                                struct drm_atomic_state *state)
-{
-       struct intel_connector *connector;
-       struct drm_connector *drm_connector;
-       struct drm_connector_state *connector_state;
-       struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
-       int i, ret;
-
-       /* The upper layers ensure that we either disable a crtc or have a list
-        * of connectors. For paranoia, double-check this. */
-       WARN_ON(!set->fb && (set->num_connectors != 0));
-       WARN_ON(set->fb && (set->num_connectors == 0));
-
-       for_each_intel_connector(dev, connector) {
-               bool in_mode_set = intel_connector_in_mode_set(connector, set);
-
-               if (!in_mode_set && connector->base.state->crtc != set->crtc)
-                       continue;
-
-               connector_state =
-                       drm_atomic_get_connector_state(state, &connector->base);
-               if (IS_ERR(connector_state))
-                       return PTR_ERR(connector_state);
-
-               if (in_mode_set) {
-                       int pipe = to_intel_crtc(set->crtc)->pipe;
-                       connector_state->best_encoder =
-                               &intel_find_encoder(connector, pipe)->base;
-               }
-
-               if (connector->base.state->crtc != set->crtc)
-                       continue;
-
-               /* If we disable the crtc, disable all its connectors. Also, if
-                * the connector is on the changing crtc but not on the new
-                * connector list, disable it. */
-               if (!set->fb || !in_mode_set) {
-                       connector_state->best_encoder = NULL;
-
-                       DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
-                               connector->base.base.id,
-                               connector->base.name);
-               }
-       }
-       /* connector->new_encoder is now updated for all connectors. */
-
-       for_each_connector_in_state(state, drm_connector, connector_state, i) {
-               connector = to_intel_connector(drm_connector);
-
-               if (!connector_state->best_encoder) {
-                       ret = drm_atomic_set_crtc_for_connector(connector_state,
-                                                               NULL);
-                       if (ret)
-                               return ret;
-
-                       continue;
-               }
-
-               if (intel_connector_in_mode_set(connector, set)) {
-                       struct drm_crtc *crtc = connector->base.state->crtc;
-
-                       /* If this connector was in a previous crtc, add it
-                        * to the state. We might need to disable it. */
-                       if (crtc) {
-                               crtc_state =
-                                       drm_atomic_get_crtc_state(state, crtc);
-                               if (IS_ERR(crtc_state))
-                                       return PTR_ERR(crtc_state);
-                       }
-
-                       ret = drm_atomic_set_crtc_for_connector(connector_state,
-                                                               set->crtc);
-                       if (ret)
-                               return ret;
-               }
-
-               /* Make sure the new CRTC will work with the encoder */
-               if (!drm_encoder_crtc_ok(connector_state->best_encoder,
-                                        connector_state->crtc)) {
-                       return -EINVAL;
-               }
-
-               DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
-                       connector->base.base.id,
-                       connector->base.name,
-                       connector_state->crtc->base.id);
-
-               if (connector_state->best_encoder != &connector->encoder->base)
-                       connector->encoder =
-                               to_intel_encoder(connector_state->best_encoder);
-       }
-
-       for_each_crtc_in_state(state, crtc, crtc_state, i) {
-               bool has_connectors;
-
-               ret = drm_atomic_add_affected_connectors(state, crtc);
-               if (ret)
-                       return ret;
-
-               has_connectors = !!drm_atomic_connectors_for_crtc(state, crtc);
-               if (has_connectors != crtc_state->enable)
-                       crtc_state->enable =
-                       crtc_state->active = has_connectors;
-       }
-
-       ret = intel_modeset_setup_plane_state(state, set->crtc, set->mode,
-                                             set->fb, set->x, set->y);
-       if (ret)
-               return ret;
-
-       crtc_state = drm_atomic_get_crtc_state(state, set->crtc);
-       if (IS_ERR(crtc_state))
-               return PTR_ERR(crtc_state);
-
-       ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode);
-       if (ret)
-               return ret;
-
-       if (set->num_connectors)
-               crtc_state->active = true;
-
-       return 0;
-}
-
-static int intel_crtc_set_config(struct drm_mode_set *set)
-{
-       struct drm_device *dev;
-       struct drm_atomic_state *state = NULL;
-       int ret;
-
-       BUG_ON(!set);
-       BUG_ON(!set->crtc);
-       BUG_ON(!set->crtc->helper_private);
-
-       /* Enforce sane interface api - has been abused by the fb helper. */
-       BUG_ON(!set->mode && set->fb);
-       BUG_ON(set->fb && set->num_connectors == 0);
-
-       if (set->fb) {
-               DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
-                               set->crtc->base.id, set->fb->base.id,
-                               (int)set->num_connectors, set->x, set->y);
-       } else {
-               DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
-       }
-
-       dev = set->crtc->dev;
-
-       state = drm_atomic_state_alloc(dev);
-       if (!state)
-               return -ENOMEM;
-
-       state->acquire_ctx = dev->mode_config.acquire_ctx;
-
-       ret = intel_modeset_stage_output_state(dev, set, state);
-       if (ret)
-               goto out;
-
-       ret = intel_modeset_compute_config(state);
-       if (ret)
-               goto out;
-
-       intel_update_pipe_size(to_intel_crtc(set->crtc));
-
-       ret = intel_set_mode_checked(state);
-       if (ret) {
-               DRM_DEBUG_KMS("failed to set mode on [CRTC:%d], err = %d\n",
-                             set->crtc->base.id, ret);
-       }
-
-out:
-       if (ret)
-               drm_atomic_state_free(state);
-       return ret;
-}
-
 static const struct drm_crtc_funcs intel_crtc_funcs = {
        .gamma_set = intel_crtc_gamma_set,
-       .set_config = intel_crtc_set_config,
+       .set_config = drm_atomic_helper_set_config,
        .destroy = intel_crtc_destroy,
        .page_flip = intel_crtc_page_flip,
        .atomic_duplicate_state = intel_crtc_duplicate_state,
@@ -15654,7 +15459,7 @@ void intel_display_resume(struct drm_device *dev)
        intel_modeset_setup_hw_state(dev);
 
        i915_redisable_vga(dev);
-       ret = intel_set_mode(state);
+       ret = drm_atomic_commit(state);
        if (!ret)
                return;
 
index f4abce103221745252641939329a3c07935c47e1..cc91ea370c99ff671e1f910efa830a75429808f1 100644 (file)
@@ -1393,11 +1393,6 @@ void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count);
 void intel_tv_init(struct drm_device *dev);
 
 /* intel_atomic.c */
-int intel_atomic_check(struct drm_device *dev,
-                      struct drm_atomic_state *state);
-int intel_atomic_commit(struct drm_device *dev,
-                       struct drm_atomic_state *state,
-                       bool async);
 int intel_connector_atomic_get_property(struct drm_connector *connector,
                                        const struct drm_connector_state *state,
                                        struct drm_property *property,