From 74c090b1bdc57b1c9f1361908cca5a3d8a80fb08 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 13 Jul 2015 16:30:30 +0200 Subject: [PATCH] drm/i915: Use full atomic modeset. Huzzah! \o/ Signed-off-by: Maarten Lankhorst Reviewed-by: Daniel Stone Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/i915_params.c | 5 - drivers/gpu/drm/i915/intel_atomic.c | 123 ------------ drivers/gpu/drm/i915/intel_display.c | 279 ++++----------------------- drivers/gpu/drm/i915/intel_drv.h | 5 - 6 files changed, 43 insertions(+), 372 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index db48aee7f140..f13ed1ef6641 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -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); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2714228e3456..4af33d59d507 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -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; diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 7983fe48a654..5f4e7295295f 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -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, diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index dcf4fb458649..e2531cf59266 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -35,129 +35,6 @@ #include #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 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 10a172681138..83d7753b8b07 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -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; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f4abce103221..cc91ea370c99 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -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, -- 2.20.1