Add functions to check core plane/crtc state. Signed-off-by: Rob Clark <robdclark@xxxxxxxxx> --- drivers/gpu/drm/drm_atomic.c | 87 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_atomic_helper.c | 47 ++++++++++++++------ include/drm/drm_atomic.h | 4 ++ 3 files changed, 124 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 4099b44..afb830d 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -261,6 +261,27 @@ int drm_atomic_crtc_get_property(struct drm_crtc *crtc, EXPORT_SYMBOL(drm_atomic_crtc_get_property); /** + * drm_atomic_crtc_check - check crtc state + * @crtc: crtc to check + * @state: crtc state to check + * + * Provides core sanity checks for crtc state. + * + * RETURNS: + * Zero on success, error code on failure + */ +int drm_atomic_crtc_check(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + /* TODO anything to check? I think if drivers want to enforce that + * primary layer covers entire screen, they should do that in their + * own crtc->atomic_check() vfunc.. + */ + return 0; +} +EXPORT_SYMBOL(drm_atomic_crtc_check); + +/** * drm_atomic_get_plane_state - get plane state * @state: global atomic state object * @plane: plane to get state object for @@ -360,6 +381,72 @@ int drm_atomic_plane_get_property(struct drm_plane *plane, EXPORT_SYMBOL(drm_atomic_plane_get_property); /** + * drm_atomic_plane_check - check plane state + * @plane: plane to check + * @state: plane state to check + * + * Provides core sanity checks for plane state. + * + * RETURNS: + * Zero on success, error code on failure + */ +int drm_atomic_plane_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + unsigned int fb_width, fb_height; + unsigned int i; + + /* either *both* CRTC and FB must be set, or neither */ + if (WARN_ON(state->crtc && !state->fb)) { + DRM_DEBUG_KMS("CRTC set but no FB\n"); + return -EINVAL; + } else if (WARN_ON(state->fb && !state->crtc)) { + DRM_DEBUG_KMS("FB set but no CRTC\n"); + return -EINVAL; + } + + /* if disabled, we don't care about the rest of the state: */ + if (!state->crtc) + return 0; + + /* Check whether this plane is usable on this CRTC */ + if (!(plane->possible_crtcs & drm_crtc_mask(state->crtc))) { + DRM_DEBUG_KMS("Invalid crtc for plane\n"); + return -EINVAL; + } + + /* Check whether this plane supports the fb pixel format. */ + for (i = 0; i < plane->format_count; i++) + if (state->fb->pixel_format == plane->format_types[i]) + break; + if (i == plane->format_count) { + DRM_DEBUG_KMS("Invalid pixel format %s\n", + drm_get_format_name(state->fb->pixel_format)); + return -EINVAL; + } + + fb_width = state->fb->width << 16; + fb_height = state->fb->height << 16; + + /* Make sure source coordinates are inside the fb. */ + if (state->src_w > fb_width || + state->src_x > fb_width - state->src_w || + state->src_h > fb_height || + state->src_y > fb_height - state->src_h) { + DRM_DEBUG_KMS("Invalid source coordinates " + "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", + state->src_w >> 16, ((state->src_w & 0xffff) * 15625) >> 10, + state->src_h >> 16, ((state->src_h & 0xffff) * 15625) >> 10, + state->src_x >> 16, ((state->src_x & 0xffff) * 15625) >> 10, + state->src_y >> 16, ((state->src_y & 0xffff) * 15625) >> 10); + return -ENOSPC; + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_plane_check); + +/** * drm_atomic_get_connector_state - get connector state * @state: global atomic state object * @connector: connector to get state object for diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 1a1ab34..55b6981 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -407,6 +407,37 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, return mode_fixup(state); } +static int plane_check(struct drm_plane *plane, struct drm_plane_state *state) +{ + struct drm_plane_helper_funcs *funcs = plane->helper_private; + int ret; + + ret = drm_atomic_plane_check(plane, state); + if (ret) + return ret; + + + if (funcs && funcs->atomic_check) + ret = funcs->atomic_check(plane, state); + + return ret; +} + +static int crtc_check(struct drm_crtc *crtc, struct drm_crtc_state *state) +{ + struct drm_crtc_helper_funcs *funcs = crtc->helper_private; + int ret; + + ret = drm_atomic_crtc_check(crtc, state); + if (ret) + return ret; + + if (funcs && funcs->atomic_check) + ret = funcs->atomic_check(crtc, state); + + return ret; +} + /** * drm_atomic_helper_check - validate state object * @dev: DRM device @@ -429,21 +460,15 @@ int drm_atomic_helper_check(struct drm_device *dev, int i, ret = 0; 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]; if (!plane) continue; - funcs = plane->helper_private; - drm_atomic_helper_plane_changed(state, plane_state, plane); - if (!funcs || !funcs->atomic_check) - continue; - - ret = funcs->atomic_check(plane, plane_state); + ret = plane_check(plane, plane_state); if (ret) { DRM_DEBUG_KMS("[PLANE:%d] atomic check failed\n", plane->base.id); @@ -452,18 +477,12 @@ int drm_atomic_helper_check(struct drm_device *dev, } for (i = 0; i < ncrtcs; i++) { - struct drm_crtc_helper_funcs *funcs; struct drm_crtc *crtc = state->crtcs[i]; if (!crtc) continue; - funcs = crtc->helper_private; - - if (!funcs || !funcs->atomic_check) - continue; - - ret = funcs->atomic_check(crtc, state->crtc_states[i]); + ret = crtc_check(crtc, state->crtc_states[i]); if (ret) { DRM_DEBUG_KMS("[CRTC:%d] atomic check failed\n", crtc->base.id); diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index b34224a..742d027 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -44,6 +44,8 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, int drm_atomic_crtc_get_property(struct drm_crtc *crtc, const struct drm_crtc_state *state, struct drm_property *property, uint64_t *val); +int drm_atomic_crtc_check(struct drm_crtc *crtc, + struct drm_crtc_state *state); struct drm_plane_state * __must_check drm_atomic_get_plane_state(struct drm_atomic_state *state, struct drm_plane *plane); @@ -53,6 +55,8 @@ int drm_atomic_plane_set_property(struct drm_plane *plane, int drm_atomic_plane_get_property(struct drm_plane *plane, const struct drm_plane_state *state, struct drm_property *property, uint64_t *val); +int drm_atomic_plane_check(struct drm_plane *plane, + struct drm_plane_state *state); struct drm_connector_state * __must_check drm_atomic_get_connector_state(struct drm_atomic_state *state, struct drm_connector *connector); -- 2.1.0 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel