From patchwork Thu Apr 12 13:17:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10338533 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 7F3D8603B5 for ; Thu, 12 Apr 2018 13:18:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6950923B23 for ; Thu, 12 Apr 2018 13:18:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5BBF92889B; Thu, 12 Apr 2018 13:18:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 4A35223B23 for ; Thu, 12 Apr 2018 13:18:43 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 626BF6E83C; Thu, 12 Apr 2018 13:18:00 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 029BB6E80E; Thu, 12 Apr 2018 13:17:51 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:48164 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1f6c6m-0002l8-MJ; Thu, 12 Apr 2018 15:17:48 +0200 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [RFC v4 09/25] drm/fb-helper: Move modeset commit code to drm_client Date: Thu, 12 Apr 2018 15:17:11 +0200 Message-Id: <20180412131727.8914-10-noralf@tronnes.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180412131727.8914-1-noralf@tronnes.org> References: <20180412131727.8914-1-noralf@tronnes.org> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: daniel.vetter@ffwll.ch, intel-gfx@lists.freedesktop.org, laurent.pinchart@ideasonboard.com, mstaudt@suse.de Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP This moves the committing part of the modesetting code to drm_client. Signed-off-by: Noralf Trønnes --- 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 +#include +#include #include #include #include @@ -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