From patchwork Sat Nov 25 19:16:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10074951 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 DCB1F60567 for ; Sat, 25 Nov 2017 19:16:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CE9D528ED2 for ; Sat, 25 Nov 2017 19:16:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C385428F0E; Sat, 25 Nov 2017 19:16:37 +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=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 258B028F0A for ; Sat, 25 Nov 2017 19:16:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751227AbdKYTQg (ORCPT ); Sat, 25 Nov 2017 14:16:36 -0500 Received: from mail-wm0-f67.google.com ([74.125.82.67]:46813 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750775AbdKYTQg (ORCPT ); Sat, 25 Nov 2017 14:16:36 -0500 Received: by mail-wm0-f67.google.com with SMTP id u83so27575574wmb.5 for ; Sat, 25 Nov 2017 11:16:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=PvUo0suyQjnoyhDpEVbd/31RX+bOMoN1a5Umqccudy0=; b=hzQmF+Afg30ykVH5b57ZINDqGk5YxLgczgsJoG7/t34RCi/YeoCUSniKztPoiLMJIn sS4Mn5szM3i+5ou0PZmOtTuCPV6UID2oqog1GLUWPaxwu3imr25rWy7L57pX38lV+b1a loke5LOOKxzdgbvd+CZ6jR4Nt2iZeQbAr0X+E4Narwm8sPTxCtm9R1LC76BfEPCIGTeb 25UNIV2ImQbsD0yobMdRDMGWTwce8mhyiiQkPfJo4wAYQjxd5KRx4eyCOYQE90DogcTs QXabmonAv+DZQouUpSjZb0z6GFZeeyq3uulqe0GEXtiKSKRCliJYGVYYTuwA2myfQIFp KrkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=PvUo0suyQjnoyhDpEVbd/31RX+bOMoN1a5Umqccudy0=; b=I0ivnTr4KNQbtqNtqMUjskjWCRP3lQIDgFLmiHxkWdWXnzEkyEBgtnQ8zSSFWnPR7W /t2ZyX1kyu+WtrvX6Pmhw9+5nlRAuGBGZ4d/DpLMBjRyjZ19pmUbltew8bLihp1Z/90B tDMNSBDFsXgLmZh4eKJHmE9FqgHNMFezxdzXoKCkycr6L8hALR+GP9p4hAy5iWXXn2AK ODRlLitjMezCi4BgR6g2/m7A84yVaAxJmdatRntWFpUr4uoPK3zyNMW9hUdkYnNl672q tQNFYWiAqjmrbWPbMYv94/4JHUrKh4+yyJf+i9zMxpPTQ12VjqolyW4NXNOCNiXx1m2D h2jQ== X-Gm-Message-State: AJaThX69KXj0PUph5xvv9SVdkFP/FOYqErFtgiKAHeGJurmFf7DoWQ3a l6NJK4ZD2G41sxZ/HND/Qo7FWTF3 X-Google-Smtp-Source: AGs4zMY4i7rYmfTJkiZUlihX26I9RNFlC9kDtpPEijkydQO/B+Z30BVpCCdgUOfzFLuvmNyq5cfYNA== X-Received: by 10.28.73.193 with SMTP id w184mr13039084wma.3.1511637394857; Sat, 25 Nov 2017 11:16:34 -0800 (PST) Received: from localhost.localdomain.com ([2001:470:7a95:4242:2c1c:b9eb:f8cb:6ccb]) by smtp.gmail.com with ESMTPSA id 29sm22980796wrz.77.2017.11.25.11.16.33 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 25 Nov 2017 11:16:33 -0800 (PST) From: Hans de Goede X-Google-Original-From: Hans de Goede To: Daniel Vetter , Jani Nikula , Sean Paul , Dave Airlie , Bartlomiej Zolnierkiewicz Cc: Hans de Goede , intel-gfx , dri-devel@lists.freedesktop.org, linux-fbdev@vger.kernel.org Subject: [PATCH v6 4/7] drm/fb-helper: Apply panel orientation connector prop to the primary plane, v6. Date: Sat, 25 Nov 2017 20:16:19 +0100 Message-Id: <20171125191622.16289-5-hdegoede@redhat.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20171125191622.16289-1-hdegoede@redhat.com> References: <20171125191622.16289-1-hdegoede@redhat.com> Sender: linux-fbdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fbdev@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Apply the "panel orientation" drm connector prop to the primary plane so that fbcon and fbdev using userspace programs display the right way up. Changes in v3: -Use a rotation member in struct drm_fb_helper_crtc and set that from drm_setup_crtcs instead of looping over all crtc's to find the right one later -Since we now no longer look at rotation quirks directly in the fbcon code, set fb_info.fbcon_rotate_hint when the panel is not mounted upright and we cannot use hardware rotation Changes in v4: -Make drm_fb_helper_init() init drm_fb_helper_crtc.rotation to DRM_MODE_ROTATE_0 for all crtcs, so that we do not end up setting the plane_state's rotation to an invalid value for disabled crtcs (caught by Fi.CI) Changes in v5: -Only use hardware (crtc primary plane) rotation for DRM_ROTATE_180, 90 / 270 degree rotation requires special handling which we lack atm -Add a TODO comment for 90 / 270 degree hardware rotation -Add some comments to better document the default case when mapping sw_rotations to fbcon_rotate_hints Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=94894 Reviewed-by: Daniel Vetter Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_fb_helper.c | 90 ++++++++++++++++++++++++++++++++++++++++- include/drm/drm_fb_helper.h | 8 ++++ 2 files changed, 96 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 832739ff58bf..57d6bad379f8 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -41,6 +41,7 @@ #include #include +#include "drm_crtc_internal.h" #include "drm_crtc_helper_internal.h" static bool drm_fbdev_emulation = true; @@ -356,6 +357,7 @@ EXPORT_SYMBOL(drm_fb_helper_debug_leave); static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool active) { struct drm_device *dev = fb_helper->dev; + struct drm_plane_state *plane_state; struct drm_plane *plane; struct drm_atomic_state *state; int i, ret; @@ -374,8 +376,6 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ retry: plane_mask = 0; drm_for_each_plane(plane, dev) { - struct drm_plane_state *plane_state; - plane_state = drm_atomic_get_plane_state(state, plane); if (IS_ERR(plane_state)) { ret = PTR_ERR(plane_state); @@ -398,6 +398,11 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ for (i = 0; i < fb_helper->crtc_count; i++) { struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; + struct drm_plane *primary = mode_set->crtc->primary; + + /* Cannot fail as we've already gotten the plane state above */ + plane_state = drm_atomic_get_new_plane_state(state, primary); + plane_state->rotation = fb_helper->crtc_info[i].rotation; ret = __drm_atomic_helper_set_config(mode_set, state); if (ret != 0) @@ -829,6 +834,7 @@ int drm_fb_helper_init(struct drm_device *dev, if (!fb_helper->crtc_info[i].mode_set.connectors) goto out_free; fb_helper->crtc_info[i].mode_set.num_connectors = 0; + fb_helper->crtc_info[i].rotation = DRM_MODE_ROTATE_0; } i = 0; @@ -2353,6 +2359,62 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, return best_score; } +/* + * This function checks if rotation is necessary because of panel orientation + * and if it is, if it is supported. + * If rotation is necessary and supported, its gets set in fb_crtc.rotation. + * If rotation is necessary but not supported, a DRM_MODE_ROTATE_* flag gets + * or-ed into fb_helper->sw_rotations. In drm_setup_crtcs_fb() we check if only + * one bit is set and then we set fb_info.fbcon_rotate_hint to make fbcon do + * the unsupported rotation. + */ +static void drm_setup_crtc_rotation(struct drm_fb_helper *fb_helper, + struct drm_fb_helper_crtc *fb_crtc, + struct drm_connector *connector) +{ + struct drm_plane *plane = fb_crtc->mode_set.crtc->primary; + uint64_t valid_mask = 0; + int i, rotation; + + fb_crtc->rotation = DRM_MODE_ROTATE_0; + + 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) { + fb_helper->sw_rotations |= rotation; + return; + } + + for (i = 0; i < plane->rotation_property->num_values; i++) + valid_mask |= (1ULL << plane->rotation_property->values[i]); + + if (!(rotation & valid_mask)) { + fb_helper->sw_rotations |= rotation; + return; + } + + fb_crtc->rotation = rotation; + /* Rotating in hardware, fbcon should not rotate */ + fb_helper->sw_rotations |= DRM_MODE_ROTATE_0; +} + static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, u32 width, u32 height) { @@ -2412,6 +2474,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, drm_fb_helper_modeset_release(fb_helper, &fb_helper->crtc_info[i].mode_set); + fb_helper->sw_rotations = 0; drm_fb_helper_for_each_connector(fb_helper, i) { struct drm_display_mode *mode = modes[i]; struct drm_fb_helper_crtc *fb_crtc = crtcs[i]; @@ -2431,6 +2494,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, modeset->mode = drm_mode_duplicate(dev, fb_crtc->desired_mode); drm_connector_get(connector); + drm_setup_crtc_rotation(fb_helper, fb_crtc, connector); modeset->connectors[modeset->num_connectors++] = connector; modeset->x = offset->x; modeset->y = offset->y; @@ -2472,6 +2536,28 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) } } mutex_unlock(&fb_helper->dev->mode_config.mutex); + + switch (fb_helper->sw_rotations) { + case DRM_MODE_ROTATE_0: + info->fbcon_rotate_hint = FB_ROTATE_UR; + break; + case DRM_MODE_ROTATE_90: + info->fbcon_rotate_hint = FB_ROTATE_CCW; + break; + case DRM_MODE_ROTATE_180: + info->fbcon_rotate_hint = FB_ROTATE_UD; + break; + case DRM_MODE_ROTATE_270: + info->fbcon_rotate_hint = FB_ROTATE_CW; + break; + default: + /* + * Multiple bits are set / multiple rotations requested + * fbcon cannot handle separate rotation settings per + * output, so fallback to unrotated. + */ + info->fbcon_rotate_hint = FB_ROTATE_UR; + } } /* Note: Drops fb_helper->lock before returning. */ diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 877e5b395c02..1494b12a984a 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -48,6 +48,7 @@ struct drm_fb_helper_crtc { struct drm_mode_set mode_set; struct drm_display_mode *desired_mode; int x, y; + int rotation; }; /** @@ -158,6 +159,13 @@ struct drm_fb_helper { struct drm_fb_helper_crtc *crtc_info; int connector_count; int connector_info_alloc_count; + /** + * @sw_rotations: + * Bitmask of all rotations requested for panel-orientation which + * could not be handled in hardware. If only one bit is set + * fbdev->fbcon_rotate_hint gets set to the requested rotation. + */ + int sw_rotations; /** * @connector_info: *