This moves the committing part of the modesetting code to drm_client. Signed-off-by: Noralf Trønnes <noralf@xxxxxxxxxxx> --- drivers/gpu/drm/drm_client.c | 242 ++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_fb_helper.c | 216 +---------------------------------- include/drm/drm_client.h | 8 ++ 3 files changed, 252 insertions(+), 214 deletions(-) diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index 7c31a6efb2f4..c85c13568cf9 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -10,6 +10,8 @@ #include <linux/slab.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_client.h> #include <drm/drm_connector.h> #include <drm/drm_crtc.h> @@ -117,3 +119,243 @@ drm_client_display_find_modeset(struct drm_client_display *display, struct drm_c return NULL; } EXPORT_SYMBOL(drm_client_display_find_modeset); + +/** + * drm_client_display_panel_rotation() - Check panel orientation + * @connector: DRM connector + * @plane: DRM plane + * @rotation: Returned rotation value + * + * This function checks if @plane can hw rotate to match the panel orientation + * on @connector. + * + * Return: + * True if the plane can do the rotation, false otherwise. + */ +bool drm_client_display_panel_rotation(struct drm_connector *connector, + struct drm_plane *plane, + unsigned int *rotation) +{ + uint64_t valid_mask = 0; + unsigned int i; + + if (!connector) + return false; + + switch (connector->display_info.panel_orientation) { + case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP: + *rotation = DRM_MODE_ROTATE_180; + break; + case DRM_MODE_PANEL_ORIENTATION_LEFT_UP: + *rotation = DRM_MODE_ROTATE_90; + break; + case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP: + *rotation = DRM_MODE_ROTATE_270; + break; + default: + *rotation = DRM_MODE_ROTATE_0; + } + + /* + * TODO: support 90 / 270 degree hardware rotation, + * depending on the hardware this may require the framebuffer + * to be in a specific tiling format. + */ + if (*rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property) + return false; + + for (i = 0; i < plane->rotation_property->num_values; i++) + valid_mask |= (1ULL << plane->rotation_property->values[i]); + + if (!(*rotation & valid_mask)) + return false; + + return true; +} +EXPORT_SYMBOL(drm_client_display_panel_rotation); + +static int drm_client_display_restore_atomic(struct drm_client_display *display, bool active) +{ + struct drm_device *dev = display->dev; + struct drm_plane_state *plane_state; + struct drm_mode_set *mode_set; + struct drm_plane *plane; + struct drm_atomic_state *state; + int ret; + unsigned int plane_mask; + struct drm_modeset_acquire_ctx ctx; + + drm_modeset_acquire_init(&ctx, 0); + + state = drm_atomic_state_alloc(dev); + if (!state) { + ret = -ENOMEM; + goto out_ctx; + } + + state->acquire_ctx = &ctx; +retry: + plane_mask = 0; + drm_for_each_plane(plane, dev) { + plane_state = drm_atomic_get_plane_state(state, plane); + if (IS_ERR(plane_state)) { + ret = PTR_ERR(plane_state); + goto out_state; + } + + plane_state->rotation = DRM_MODE_ROTATE_0; + + plane->old_fb = plane->fb; + plane_mask |= 1 << drm_plane_index(plane); + + /* disable non-primary: */ + if (plane->type == DRM_PLANE_TYPE_PRIMARY) + continue; + + ret = drm_atomic_disable_plane(plane, plane_state); + if (ret != 0) + goto out_state; + } + + drm_client_display_for_each_modeset(mode_set, display) { + struct drm_plane *primary = mode_set->crtc->primary; + unsigned int rotation; + + if (drm_client_display_panel_rotation(mode_set->connectors[0], primary, &rotation)) { + /* Cannot fail as we've already gotten the plane state above */ + plane_state = drm_atomic_get_new_plane_state(state, primary); + plane_state->rotation = rotation; + } + + ret = drm_atomic_set_config(mode_set, state); + if (ret != 0) + goto out_state; + + /* + * drm_atomic_set_config() sets active when a + * mode is set, unconditionally clear it if we force DPMS off + */ + if (!active) { + struct drm_crtc *crtc = mode_set->crtc; + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + + crtc_state->active = false; + } + } + + ret = drm_atomic_commit(state); + +out_state: + drm_atomic_clean_old_fb(dev, plane_mask, ret); + + if (ret == -EDEADLK) + goto backoff; + + drm_atomic_state_put(state); +out_ctx: + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + return ret; + +backoff: + drm_atomic_state_clear(state); + drm_modeset_backoff(&ctx); + + goto retry; +} + +static int drm_client_display_restore_legacy(struct drm_client_display *display) +{ + struct drm_device *dev = display->dev; + struct drm_mode_set *mode_set; + struct drm_plane *plane; + int ret = 0; + + drm_modeset_lock_all(dev); + drm_for_each_plane(plane, dev) { + if (plane->type != DRM_PLANE_TYPE_PRIMARY) + drm_plane_force_disable(plane); + + if (plane->rotation_property) + drm_mode_plane_set_obj_prop(plane, + plane->rotation_property, + DRM_MODE_ROTATE_0); + } + + drm_client_display_for_each_modeset(mode_set, display) { + struct drm_crtc *crtc = mode_set->crtc; + + if (crtc->funcs->cursor_set2) { + ret = crtc->funcs->cursor_set2(crtc, NULL, 0, 0, 0, 0, 0); + if (ret) + goto out; + } else if (crtc->funcs->cursor_set) { + ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0); + if (ret) + goto out; + } + + ret = drm_mode_set_config_internal(mode_set); + if (ret) + goto out; + } +out: + drm_modeset_unlock_all(dev); + + return ret; +} + +/** + * drm_client_display_restore() - Restore client display + * @display: Client display + * + * Restore client display using the current modeset configuration. + * + * Return: + * Zero on succes or negative error code on failure. + */ +int drm_client_display_restore(struct drm_client_display *display) +{ + if (drm_drv_uses_atomic_modeset(display->dev)) + return drm_client_display_restore_atomic(display, true); + else + return drm_client_display_restore_legacy(display); +} +EXPORT_SYMBOL(drm_client_display_restore); + +static void drm_client_display_dpms_legacy(struct drm_client_display *display, int dpms_mode) +{ + struct drm_device *dev = display->dev; + struct drm_connector *connector; + struct drm_mode_set *modeset; + int i; + + drm_modeset_lock_all(dev); + drm_client_display_for_each_modeset(modeset, display) { + if (!modeset->crtc->enabled) + continue; + + for (i = 0; i < modeset->num_connectors; i++) { + connector = modeset->connectors[i]; + connector->funcs->dpms(connector, dpms_mode); + drm_object_property_set_value(&connector->base, + dev->mode_config.dpms_property, dpms_mode); + } + } + drm_modeset_unlock_all(dev); +} + +/** + * drm_client_display_dpms() - Set display DPMS mode + * @display: Client display + * @mode: DPMS mode + */ +void drm_client_display_dpms(struct drm_client_display *display, int mode) +{ + if (drm_drv_uses_atomic_modeset(display->dev)) + drm_client_display_restore_atomic(display, mode == DRM_MODE_DPMS_ON); + else + drm_client_display_dpms_legacy(display, mode); +} +EXPORT_SYMBOL(drm_client_display_dpms); diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index bdb4b57d2c12..785a2f5d2647 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -280,188 +280,6 @@ int drm_fb_helper_debug_leave(struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_debug_leave); -/* Check if the plane can hw rotate to match panel orientation */ -static bool drm_fb_helper_panel_rotation(struct drm_connector *connector, - struct drm_plane *plane, - unsigned int *rotation) -{ - uint64_t valid_mask = 0; - unsigned int i; - - if (!connector) - return false; - - switch (connector->display_info.panel_orientation) { - case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP: - *rotation = DRM_MODE_ROTATE_180; - break; - case DRM_MODE_PANEL_ORIENTATION_LEFT_UP: - *rotation = DRM_MODE_ROTATE_90; - break; - case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP: - *rotation = DRM_MODE_ROTATE_270; - break; - default: - *rotation = DRM_MODE_ROTATE_0; - } - - /* - * TODO: support 90 / 270 degree hardware rotation, - * depending on the hardware this may require the framebuffer - * to be in a specific tiling format. - */ - if (*rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property) - return false; - - for (i = 0; i < plane->rotation_property->num_values; i++) - valid_mask |= (1ULL << plane->rotation_property->values[i]); - - if (!(*rotation & valid_mask)) - return false; - - return true; -} - -static int drm_client_display_restore_atomic(struct drm_client_display *display, bool active) -{ - struct drm_device *dev = display->dev; - struct drm_plane_state *plane_state; - struct drm_mode_set *mode_set; - struct drm_plane *plane; - struct drm_atomic_state *state; - int ret; - unsigned int plane_mask; - struct drm_modeset_acquire_ctx ctx; - - drm_modeset_acquire_init(&ctx, 0); - - state = drm_atomic_state_alloc(dev); - if (!state) { - ret = -ENOMEM; - goto out_ctx; - } - - state->acquire_ctx = &ctx; -retry: - plane_mask = 0; - drm_for_each_plane(plane, dev) { - plane_state = drm_atomic_get_plane_state(state, plane); - if (IS_ERR(plane_state)) { - ret = PTR_ERR(plane_state); - goto out_state; - } - - plane_state->rotation = DRM_MODE_ROTATE_0; - - plane->old_fb = plane->fb; - plane_mask |= 1 << drm_plane_index(plane); - - /* disable non-primary: */ - if (plane->type == DRM_PLANE_TYPE_PRIMARY) - continue; - - ret = drm_atomic_disable_plane(plane, plane_state); - if (ret != 0) - goto out_state; - } - - drm_client_display_for_each_modeset(mode_set, display) { - struct drm_plane *primary = mode_set->crtc->primary; - unsigned int rotation; - - if (drm_fb_helper_panel_rotation(mode_set->connectors[0], primary, &rotation)) { - /* Cannot fail as we've already gotten the plane state above */ - plane_state = drm_atomic_get_new_plane_state(state, primary); - plane_state->rotation = rotation; - } - - ret = drm_atomic_set_config(mode_set, state); - if (ret != 0) - goto out_state; - - /* - * drm_atomic_set_config() sets active when a mode is set, - * unconditionally clear it if we force DPMS off - */ - if (!active) { - struct drm_crtc *crtc = mode_set->crtc; - struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); - - crtc_state->active = false; - } - } - - ret = drm_atomic_commit(state); - -out_state: - drm_atomic_clean_old_fb(dev, plane_mask, ret); - - if (ret == -EDEADLK) - goto backoff; - - drm_atomic_state_put(state); -out_ctx: - drm_modeset_drop_locks(&ctx); - drm_modeset_acquire_fini(&ctx); - - return ret; - -backoff: - drm_atomic_state_clear(state); - drm_modeset_backoff(&ctx); - - goto retry; -} - -static int drm_client_display_restore_legacy(struct drm_client_display *display) -{ - struct drm_device *dev = display->dev; - struct drm_mode_set *mode_set; - struct drm_plane *plane; - int ret = 0; - - drm_modeset_lock_all(dev); - drm_for_each_plane(plane, dev) { - if (plane->type != DRM_PLANE_TYPE_PRIMARY) - drm_plane_force_disable(plane); - - if (plane->rotation_property) - drm_mode_plane_set_obj_prop(plane, - plane->rotation_property, - DRM_MODE_ROTATE_0); - } - - drm_client_display_for_each_modeset(mode_set, display) { - struct drm_crtc *crtc = mode_set->crtc; - - if (crtc->funcs->cursor_set2) { - ret = crtc->funcs->cursor_set2(crtc, NULL, 0, 0, 0, 0, 0); - if (ret) - goto out; - } else if (crtc->funcs->cursor_set) { - ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0); - if (ret) - goto out; - } - - ret = drm_mode_set_config_internal(mode_set); - if (ret) - goto out; - } -out: - drm_modeset_unlock_all(dev); - - return ret; -} - -static int drm_client_display_restore(struct drm_client_display *display) -{ - if (drm_drv_uses_atomic_modeset(display->dev)) - return drm_client_display_restore_atomic(display, true); - else - return drm_client_display_restore_legacy(display); -} - /** * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration * @fb_helper: driver-allocated fbdev helper, can be NULL @@ -579,36 +397,6 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { }; #endif -static void drm_client_display_dpms_legacy(struct drm_client_display *display, int dpms_mode) -{ - struct drm_device *dev = display->dev; - struct drm_connector *connector; - struct drm_mode_set *modeset; - int i; - - drm_modeset_lock_all(dev); - drm_client_display_for_each_modeset(modeset, display) { - if (!modeset->crtc->enabled) - continue; - - for (i = 0; i < modeset->num_connectors; i++) { - connector = modeset->connectors[i]; - connector->funcs->dpms(connector, dpms_mode); - drm_object_property_set_value(&connector->base, - dev->mode_config.dpms_property, dpms_mode); - } - } - drm_modeset_unlock_all(dev); -} - -static void drm_client_display_dpms(struct drm_client_display *display, int mode) -{ - if (drm_drv_uses_atomic_modeset(display->dev)) - drm_client_display_restore_atomic(display, mode == DRM_MODE_DPMS_ON); - else - drm_client_display_dpms_legacy(display, mode); -} - static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) { struct drm_fb_helper *fb_helper = info->par; @@ -2487,8 +2275,8 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) modeset->fb = fb_helper->fb; - if (drm_fb_helper_panel_rotation(modeset->connectors[0], - modeset->crtc->primary, &rotation)) + if (drm_client_display_panel_rotation(modeset->connectors[0], + modeset->crtc->primary, &rotation)) /* Rotating in hardware, fbcon should not rotate */ sw_rotations |= DRM_MODE_ROTATE_0; else diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index b6a057802769..ed028f5877d0 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -3,9 +3,11 @@ #ifndef _DRM_CLIENT_H_ #define _DRM_CLIENT_H_ +struct drm_connector; struct drm_crtc; struct drm_device; struct drm_mode_set; +struct drm_plane; /** * struct drm_client_display - DRM client display @@ -41,4 +43,10 @@ drm_client_display_find_modeset(struct drm_client_display *display, struct drm_c #define drm_client_display_for_each_modeset(modeset, display) \ for (modeset = display->modesets; modeset->crtc; modeset++) +bool drm_client_display_panel_rotation(struct drm_connector *connector, + struct drm_plane *plane, + unsigned int *rotation); +int drm_client_display_restore(struct drm_client_display *display); +void drm_client_display_dpms(struct drm_client_display *display, int mode); + #endif -- 2.15.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel