From patchwork Sat Nov 4 14:08:25 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: 10041601 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 E1A1660384 for ; Sat, 4 Nov 2017 14:08:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D2BB029438 for ; Sat, 4 Nov 2017 14:08:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C7B11294B0; Sat, 4 Nov 2017 14:08: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=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, 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 2F45529438 for ; Sat, 4 Nov 2017 14:08:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756732AbdKDOIn (ORCPT ); Sat, 4 Nov 2017 10:08:43 -0400 Received: from mail-wr0-f194.google.com ([209.85.128.194]:50945 "EHLO mail-wr0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752089AbdKDOIm (ORCPT ); Sat, 4 Nov 2017 10:08:42 -0400 Received: by mail-wr0-f194.google.com with SMTP id p96so4758734wrb.7 for ; Sat, 04 Nov 2017 07:08:41 -0700 (PDT) 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=b9zaYDtecPMhY+Rs3dK28a6TDbZEHkwAOGU1E+5RlL8=; b=d5C+aKXjDFWD4vND1z1FXMOS2/cP3ysiHqdKEL9nKj93r2kCoiX0oXCjQC2/gDpChk Vm/gyVimwThXW5WXvc5TS8DPNJ9IpB3sB+8vySM6ox+kzJvR2WjhyZMhBMGmNh3SLRGR AmguyRzUwo6w55AJd0k4q1gTPOxH73Rz3e5IQ705vOFpab1hwOmJ9+DyJWD8sJFzyp+H bS6y7Ii7uEWcZjRCVIkZHdLeG7PPLDuYyWfgct7IwmSSCz6JGCxumt2PfDvwba8LgPAJ NtxQT+GqLYeZ+HuQEepP0l68YALybSo+cAr7nyUwH0/NOkY9HE1MRoyY6YkGJFRitW/o CsCw== 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=b9zaYDtecPMhY+Rs3dK28a6TDbZEHkwAOGU1E+5RlL8=; b=S6E/SkuwHfxz5oRxfpU7/myPYxNQI+occ+wvcB12pWMpn1CCc9oyLuuvZ7EOD7ZStY uhIk/sw4NVTZkAAdRFo9r8AnHpVI/weTMADx9qOZU/AediEDmkWsA4ZohjSZxv5a9x8g QRSb03CVUJwcPqZK6ZGqFCHEDmEQyi7repaeXmkDe3yoh24gafLCKvWmUG5Vad1tuyTs /dKgG4iFUyqn7wYgmCPwtjVKXfXB5Cx74Qz6Lp8ALcSGbr/uUOfRHs9npeqNf8M7tPOd pLmHzxhHh9IdPnoz3LrCmld9fMsTN8itH7gCyR6Kwqns+JXQtx9+wq2+QaFfDy1IvyIq 7pJg== X-Gm-Message-State: AMCzsaV+NMcYC4+2Vj6F/lS1HITv2Qbv5jtIpH9YCrAvzPoxyZbcBAcd yTwZ3iCphSkHqP2d8xjmNmE= X-Google-Smtp-Source: ABhQp+RmoOXn+PE+MG8a9Y3sjM++4xyxpzRRNLFLiFXdqEtkqxZ0maAHqMhFcb78tLo+te3Uo2u1hQ== X-Received: by 10.223.179.20 with SMTP id j20mr9106978wrd.116.1509804521161; Sat, 04 Nov 2017 07:08:41 -0700 (PDT) Received: from shalem.localdomain.com (546A5441.cm-12-3b.dynamic.ziggo.nl. [84.106.84.65]) by smtp.gmail.com with ESMTPSA id p128sm4672674wmb.1.2017.11.04.07.08.39 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 04 Nov 2017 07:08:40 -0700 (PDT) From: Hans de Goede X-Google-Original-From: Hans de Goede To: Daniel Vetter , Jani Nikula , Sean Paul , David Airlie , Bartlomiej Zolnierkiewicz Cc: Hans de Goede , Bastien Nocera , Daniel Drake , Carlo Caione , Robert McQueen , intel-gfx , dri-devel@lists.freedesktop.org, linux-fbdev@vger.kernel.org Subject: [PATCH v5 4/7] drm/fb-helper: Apply panel orientation connector prop to the primary plane Date: Sat, 4 Nov 2017 15:08:25 +0100 Message-Id: <20171104140828.32469-5-hdegoede@redhat.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20171104140828.32469-1-hdegoede@redhat.com> References: <20171104140828.32469-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. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=94894 Signed-off-by: Hans de Goede Reviewed-by: Daniel Vetter --- Changes in v2: -New patch in v2 of this patch-set 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 --- 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 116d1f1337c7..5a557488bff4 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; @@ -350,6 +351,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; @@ -368,8 +370,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); @@ -392,6 +392,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) @@ -821,6 +826,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; @@ -2334,6 +2340,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) { @@ -2393,6 +2455,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]; @@ -2412,6 +2475,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; @@ -2453,6 +2517,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 33fe95927742..7fca941c2c57 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; + /** + * @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: *