diff options
Diffstat (limited to 'drivers/gpu/drm/drm_atomic_helper.c')
-rw-r--r-- | drivers/gpu/drm/drm_atomic_helper.c | 205 |
1 files changed, 111 insertions, 94 deletions
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 7e3a52b97c7d..7715c40d4e74 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -116,9 +116,9 @@ steal_encoder(struct drm_atomic_state *state, */ WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); - DRM_DEBUG_KMS("[ENCODER:%d:%s] in use on [CRTC:%d], stealing it\n", - encoder->base.id, encoder->name, - encoder_crtc->base.id); + DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d], stealing it\n", + encoder->base.id, encoder->name, + encoder_crtc->base.id); crtc_state = drm_atomic_get_crtc_state(state, encoder_crtc); if (IS_ERR(crtc_state)) @@ -130,9 +130,9 @@ steal_encoder(struct drm_atomic_state *state, if (connector->state->best_encoder != encoder) continue; - DRM_DEBUG_KMS("Stealing encoder from [CONNECTOR:%d:%s]\n", - connector->base.id, - connector->name); + DRM_DEBUG_ATOMIC("Stealing encoder from [CONNECTOR:%d:%s]\n", + connector->base.id, + connector->name); connector_state = drm_atomic_get_connector_state(state, connector); @@ -165,9 +165,9 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx) if (!connector) return 0; - DRM_DEBUG_KMS("Updating routing for [CONNECTOR:%d:%s]\n", - connector->base.id, - connector->name); + DRM_DEBUG_ATOMIC("Updating routing for [CONNECTOR:%d:%s]\n", + connector->base.id, + connector->name); if (connector->state->crtc != connector_state->crtc) { if (connector->state->crtc) { @@ -186,7 +186,7 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx) } if (!connector_state->crtc) { - DRM_DEBUG_KMS("Disabling [CONNECTOR:%d:%s]\n", + DRM_DEBUG_ATOMIC("Disabling [CONNECTOR:%d:%s]\n", connector->base.id, connector->name); @@ -199,19 +199,19 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx) new_encoder = funcs->best_encoder(connector); if (!new_encoder) { - DRM_DEBUG_KMS("No suitable encoder found for [CONNECTOR:%d:%s]\n", - connector->base.id, - connector->name); + DRM_DEBUG_ATOMIC("No suitable encoder found for [CONNECTOR:%d:%s]\n", + connector->base.id, + connector->name); return -EINVAL; } if (new_encoder == connector_state->best_encoder) { - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d]\n", - connector->base.id, - connector->name, - new_encoder->base.id, - new_encoder->name, - connector_state->crtc->base.id); + DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d]\n", + connector->base.id, + connector->name, + new_encoder->base.id, + new_encoder->name, + connector_state->crtc->base.id); return 0; } @@ -222,9 +222,9 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx) if (encoder_crtc) { ret = steal_encoder(state, new_encoder, encoder_crtc); if (ret) { - DRM_DEBUG_KMS("Encoder stealing failed for [CONNECTOR:%d:%s]\n", - connector->base.id, - connector->name); + DRM_DEBUG_ATOMIC("Encoder stealing failed for [CONNECTOR:%d:%s]\n", + connector->base.id, + connector->name); return ret; } } @@ -235,12 +235,12 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx) crtc_state = state->crtc_states[idx]; crtc_state->mode_changed = true; - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d]\n", - connector->base.id, - connector->name, - new_encoder->base.id, - new_encoder->name, - connector_state->crtc->base.id); + DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d]\n", + connector->base.id, + connector->name, + new_encoder->base.id, + new_encoder->name, + connector_state->crtc->base.id); return 0; } @@ -292,7 +292,7 @@ mode_fixup(struct drm_atomic_state *state) encoder->bridge, &crtc_state->mode, &crtc_state->adjusted_mode); if (!ret) { - DRM_DEBUG_KMS("Bridge fixup failed\n"); + DRM_DEBUG_ATOMIC("Bridge fixup failed\n"); return -EINVAL; } } @@ -301,16 +301,16 @@ mode_fixup(struct drm_atomic_state *state) ret = funcs->atomic_check(encoder, crtc_state, conn_state); if (ret) { - DRM_DEBUG_KMS("[ENCODER:%d:%s] check failed\n", - encoder->base.id, encoder->name); + DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] check failed\n", + encoder->base.id, encoder->name); return ret; } } else { ret = funcs->mode_fixup(encoder, &crtc_state->mode, &crtc_state->adjusted_mode); if (!ret) { - DRM_DEBUG_KMS("[ENCODER:%d:%s] fixup failed\n", - encoder->base.id, encoder->name); + DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] fixup failed\n", + encoder->base.id, encoder->name); return -EINVAL; } } @@ -330,8 +330,8 @@ mode_fixup(struct drm_atomic_state *state) ret = funcs->mode_fixup(crtc, &crtc_state->mode, &crtc_state->adjusted_mode); if (!ret) { - DRM_DEBUG_KMS("[CRTC:%d] fixup failed\n", - crtc->base.id); + DRM_DEBUG_ATOMIC("[CRTC:%d] fixup failed\n", + crtc->base.id); return -EINVAL; } } @@ -384,14 +384,14 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, continue; if (!drm_mode_equal(&crtc->state->mode, &crtc_state->mode)) { - DRM_DEBUG_KMS("[CRTC:%d] mode changed\n", - crtc->base.id); + DRM_DEBUG_ATOMIC("[CRTC:%d] mode changed\n", + crtc->base.id); crtc_state->mode_changed = true; } if (crtc->state->enable != crtc_state->enable) { - DRM_DEBUG_KMS("[CRTC:%d] enable changed\n", - crtc->base.id); + DRM_DEBUG_ATOMIC("[CRTC:%d] enable changed\n", + crtc->base.id); crtc_state->mode_changed = true; } } @@ -428,17 +428,17 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, * a full modeset because update_connector_routing force that. */ if (crtc->state->active != crtc_state->active) { - DRM_DEBUG_KMS("[CRTC:%d] active changed\n", - crtc->base.id); + DRM_DEBUG_ATOMIC("[CRTC:%d] active changed\n", + crtc->base.id); crtc_state->active_changed = true; } if (!needs_modeset(crtc_state)) continue; - DRM_DEBUG_KMS("[CRTC:%d] needs all connectors, enable: %c, active: %c\n", - crtc->base.id, - crtc_state->enable ? 'y' : 'n', + DRM_DEBUG_ATOMIC("[CRTC:%d] needs all connectors, enable: %c, active: %c\n", + crtc->base.id, + crtc_state->enable ? 'y' : 'n', crtc_state->active ? 'y' : 'n'); ret = drm_atomic_add_affected_connectors(state, crtc); @@ -449,8 +449,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, crtc); if (crtc_state->enable != !!num_connectors) { - DRM_DEBUG_KMS("[CRTC:%d] enabled/connectors mismatch\n", - crtc->base.id); + DRM_DEBUG_ATOMIC("[CRTC:%d] enabled/connectors mismatch\n", + crtc->base.id); return -EINVAL; } @@ -497,8 +497,8 @@ drm_atomic_helper_check_planes(struct drm_device *dev, ret = funcs->atomic_check(plane, plane_state); if (ret) { - DRM_DEBUG_KMS("[PLANE:%d] atomic driver check failed\n", - plane->base.id); + DRM_DEBUG_ATOMIC("[PLANE:%d] atomic driver check failed\n", + plane->base.id); return ret; } } @@ -517,8 +517,8 @@ drm_atomic_helper_check_planes(struct drm_device *dev, ret = funcs->atomic_check(crtc, state->crtc_states[i]); if (ret) { - DRM_DEBUG_KMS("[CRTC:%d] atomic driver check failed\n", - crtc->base.id); + DRM_DEBUG_ATOMIC("[CRTC:%d] atomic driver check failed\n", + crtc->base.id); return ret; } } @@ -600,8 +600,8 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) funcs = encoder->helper_private; - DRM_DEBUG_KMS("disabling [ENCODER:%d:%s]\n", - encoder->base.id, encoder->name); + DRM_DEBUG_ATOMIC("disabling [ENCODER:%d:%s]\n", + encoder->base.id, encoder->name); /* * Each encoder has at most one connector (since we always steal @@ -639,8 +639,8 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) funcs = crtc->helper_private; - DRM_DEBUG_KMS("disabling [CRTC:%d]\n", - crtc->base.id); + DRM_DEBUG_ATOMIC("disabling [CRTC:%d]\n", + crtc->base.id); /* Right function depends upon target state. */ @@ -723,9 +723,9 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) funcs = crtc->helper_private; - if (crtc->state->enable) { - DRM_DEBUG_KMS("modeset on [CRTC:%d]\n", - crtc->base.id); + if (crtc->state->enable && funcs->mode_set_nofb) { + DRM_DEBUG_ATOMIC("modeset on [CRTC:%d]\n", + crtc->base.id); funcs->mode_set_nofb(crtc); } @@ -752,14 +752,15 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) if (!new_crtc_state->mode_changed) continue; - DRM_DEBUG_KMS("modeset on [ENCODER:%d:%s]\n", - encoder->base.id, encoder->name); + DRM_DEBUG_ATOMIC("modeset on [ENCODER:%d:%s]\n", + encoder->base.id, encoder->name); /* * Each encoder has at most one connector (since we always steal * it away), so we won't call call mode_set hooks twice. */ - funcs->mode_set(encoder, mode, adjusted_mode); + if (funcs->mode_set) + funcs->mode_set(encoder, mode, adjusted_mode); if (encoder->bridge && encoder->bridge->funcs->mode_set) encoder->bridge->funcs->mode_set(encoder->bridge, @@ -768,34 +769,44 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) } /** - * drm_atomic_helper_commit_pre_planes - modeset commit before plane updates + * drm_atomic_helper_commit_modeset_disables - modeset commit to disable outputs * @dev: DRM device - * @state: atomic state + * @old_state: atomic state object with old state structures * - * This function commits the modeset changes that need to be committed before - * updating planes. It shuts down all the outputs that need to be shut down and + * This function shuts down all the outputs that need to be shut down and * prepares them (if required) with the new mode. + * + * For compatability with legacy crtc helpers this should be called before + * drm_atomic_helper_commit_planes(), which is what the default commit function + * does. But drivers with different needs can group the modeset commits together + * and do the plane commits at the end. This is useful for drivers doing runtime + * PM since planes updates then only happen when the CRTC is actually enabled. */ -void drm_atomic_helper_commit_pre_planes(struct drm_device *dev, - struct drm_atomic_state *state) +void drm_atomic_helper_commit_modeset_disables(struct drm_device *dev, + struct drm_atomic_state *old_state) { - disable_outputs(dev, state); - set_routing_links(dev, state); - crtc_set_mode(dev, state); + disable_outputs(dev, old_state); + set_routing_links(dev, old_state); + crtc_set_mode(dev, old_state); } -EXPORT_SYMBOL(drm_atomic_helper_commit_pre_planes); +EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_disables); /** - * drm_atomic_helper_commit_post_planes - modeset commit after plane updates + * drm_atomic_helper_commit_modeset_enables - modeset commit to enable outputs * @dev: DRM device * @old_state: atomic state object with old state structures * - * This function commits the modeset changes that need to be committed after - * updating planes: It enables all the outputs with the new configuration which - * had to be turned off for the update. + * This function enables all the outputs with the new configuration which had to + * be turned off for the update. + * + * For compatability with legacy crtc helpers this should be called after + * drm_atomic_helper_commit_planes(), which is what the default commit function + * does. But drivers with different needs can group the modeset commits together + * and do the plane commits at the end. This is useful for drivers doing runtime + * PM since planes updates then only happen when the CRTC is actually enabled. */ -void drm_atomic_helper_commit_post_planes(struct drm_device *dev, - struct drm_atomic_state *old_state) +void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, + struct drm_atomic_state *old_state) { int ncrtcs = old_state->dev->mode_config.num_crtc; int i; @@ -816,8 +827,8 @@ void drm_atomic_helper_commit_post_planes(struct drm_device *dev, funcs = crtc->helper_private; if (crtc->state->enable) { - DRM_DEBUG_KMS("enabling [CRTC:%d]\n", - crtc->base.id); + DRM_DEBUG_ATOMIC("enabling [CRTC:%d]\n", + crtc->base.id); if (funcs->enable) funcs->enable(crtc); @@ -842,8 +853,8 @@ void drm_atomic_helper_commit_post_planes(struct drm_device *dev, encoder = connector->state->best_encoder; funcs = encoder->helper_private; - DRM_DEBUG_KMS("enabling [ENCODER:%d:%s]\n", - encoder->base.id, encoder->name); + DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n", + encoder->base.id, encoder->name); /* * Each encoder has at most one connector (since we always steal @@ -861,7 +872,7 @@ void drm_atomic_helper_commit_post_planes(struct drm_device *dev, encoder->bridge->funcs->enable(encoder->bridge); } } -EXPORT_SYMBOL(drm_atomic_helper_commit_post_planes); +EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables); static void wait_for_fences(struct drm_device *dev, struct drm_atomic_state *state) @@ -1030,11 +1041,11 @@ int drm_atomic_helper_commit(struct drm_device *dev, wait_for_fences(dev, state); - drm_atomic_helper_commit_pre_planes(dev, state); + drm_atomic_helper_commit_modeset_disables(dev, state); drm_atomic_helper_commit_planes(dev, state); - drm_atomic_helper_commit_post_planes(dev, state); + drm_atomic_helper_commit_modeset_enables(dev, state); drm_atomic_helper_wait_for_vblanks(dev, state); @@ -1105,6 +1116,7 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev, for (i = 0; i < nplanes; i++) { struct drm_plane_helper_funcs *funcs; struct drm_plane *plane = state->planes[i]; + struct drm_plane_state *plane_state = state->plane_states[i]; struct drm_framebuffer *fb; if (!plane) @@ -1112,10 +1124,10 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev, funcs = plane->helper_private; - fb = state->plane_states[i]->fb; + fb = plane_state->fb; if (fb && funcs->prepare_fb) { - ret = funcs->prepare_fb(plane, fb); + ret = funcs->prepare_fb(plane, fb, plane_state); if (ret) goto fail; } @@ -1127,6 +1139,7 @@ fail: for (i--; i >= 0; i--) { struct drm_plane_helper_funcs *funcs; struct drm_plane *plane = state->planes[i]; + struct drm_plane_state *plane_state = state->plane_states[i]; struct drm_framebuffer *fb; if (!plane) @@ -1137,7 +1150,7 @@ fail: fb = state->plane_states[i]->fb; if (fb && funcs->cleanup_fb) - funcs->cleanup_fb(plane, fb); + funcs->cleanup_fb(plane, fb, plane_state); } @@ -1243,6 +1256,7 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev, for (i = 0; i < nplanes; i++) { struct drm_plane_helper_funcs *funcs; struct drm_plane *plane = old_state->planes[i]; + struct drm_plane_state *plane_state = old_state->plane_states[i]; struct drm_framebuffer *old_fb; if (!plane) @@ -1250,10 +1264,10 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev, funcs = plane->helper_private; - old_fb = old_state->plane_states[i]->fb; + old_fb = plane_state->fb; if (old_fb && funcs->cleanup_fb) - funcs->cleanup_fb(plane, old_fb); + funcs->cleanup_fb(plane, old_fb, plane_state); } } EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes); @@ -1678,12 +1692,13 @@ backoff: EXPORT_SYMBOL(drm_atomic_helper_set_config); /** - * drm_atomic_helper_crtc_set_property - helper for crtc prorties + * drm_atomic_helper_crtc_set_property - helper for crtc properties * @crtc: DRM crtc * @property: DRM property * @val: value of property * - * Provides a default plane disablle handler using the atomic driver interface. + * Provides a default crtc set_property handler using the atomic driver + * interface. * * RETURNS: * Zero on success, error code on failure @@ -1737,12 +1752,13 @@ backoff: EXPORT_SYMBOL(drm_atomic_helper_crtc_set_property); /** - * drm_atomic_helper_plane_set_property - helper for plane prorties + * drm_atomic_helper_plane_set_property - helper for plane properties * @plane: DRM plane * @property: DRM property * @val: value of property * - * Provides a default plane disable handler using the atomic driver interface. + * Provides a default plane set_property handler using the atomic driver + * interface. * * RETURNS: * Zero on success, error code on failure @@ -1796,12 +1812,13 @@ backoff: EXPORT_SYMBOL(drm_atomic_helper_plane_set_property); /** - * drm_atomic_helper_connector_set_property - helper for connector prorties + * drm_atomic_helper_connector_set_property - helper for connector properties * @connector: DRM connector * @property: DRM property * @val: value of property * - * Provides a default plane disablle handler using the atomic driver interface. + * Provides a default connector set_property handler using the atomic driver + * interface. * * RETURNS: * Zero on success, error code on failure |