From patchwork Fri Sep 8 11:54:43 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: 9943771 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 ECE5E6034B for ; Fri, 8 Sep 2017 11:54:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DF10D28646 for ; Fri, 8 Sep 2017 11:54:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D3DB9286AE; Fri, 8 Sep 2017 11:54:53 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 45538286B0 for ; Fri, 8 Sep 2017 11:54:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752892AbdIHLyw (ORCPT ); Fri, 8 Sep 2017 07:54:52 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51342 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752204AbdIHLyw (ORCPT ); Fri, 8 Sep 2017 07:54:52 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0F20681DFE; Fri, 8 Sep 2017 11:54:52 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 0F20681DFE Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=hdegoede@redhat.com Received: from shalem.localdomain.com (ovpn-117-44.ams2.redhat.com [10.36.117.44]) by smtp.corp.redhat.com (Postfix) with ESMTP id 528965D97C; Fri, 8 Sep 2017 11:54:50 +0000 (UTC) From: Hans de Goede To: Daniel Vetter , Jani Nikula , Sean Paul , David Airlie , Bartlomiej Zolnierkiewicz Cc: Hans de Goede , Bastien Nocera , dri-devel@lists.freedesktop.org, linux-fbdev@vger.kernel.org Subject: [PATCH 2/3] drm: Add support for a panel-orientation connector property Date: Fri, 8 Sep 2017 13:54:43 +0200 Message-Id: <20170908115444.19122-3-hdegoede@redhat.com> In-Reply-To: <20170908115444.19122-1-hdegoede@redhat.com> References: <20170908115444.19122-1-hdegoede@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Fri, 08 Sep 2017 11:54:52 +0000 (UTC) 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 On some devices the LCD panel is mounted in the casing in such a way that the up/top side of the panel does not match with the top side of the device (e.g. it is mounted upside-down). This commit adds the necessary infra for lcd-panel drm_connector-s to have a "panel orientation" property to communicate how the panel is orientated vs the casing. Userspace can use this property to check for non-normal orientation and then adjust the displayed image accordingly by rotating it to compensate. Signed-off-by: Hans de Goede --- drivers/gpu/drm/drm_connector.c | 92 +++++++++++++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 4 ++ include/drm/drm_mode_config.h | 7 ++++ include/uapi/drm/drm_mode.h | 7 ++++ 4 files changed, 110 insertions(+) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index ba9f36cef68c..ea4cded1e328 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -665,6 +665,13 @@ static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = { { DRM_MODE_PICTURE_ASPECT_16_9, "16:9" }, }; +static const struct drm_prop_enum_list drm_panel_orientation_enum_list[] = { + { DRM_MODE_PANEL_ORIENTATION_NORMAL, "Normal" }, + { DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP, "Upside Down" }, + { DRM_MODE_PANEL_ORIENTATION_LEFT_UP, "Left Side Up" }, + { DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, "Right Side Up" }, +}; + static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = { { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ @@ -746,6 +753,18 @@ DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, * * CRTC_ID: * Mode object ID of the &drm_crtc this connector should be connected to. + * + * Connectors for LCD panels may also have one standardized property: + * + * panel orientation: + * On some devices the LCD panel is mounted in the casing in such a way + * that the up/top side of the panel does not match with the top side of + * the device. Userspace can use this property to check for this. + * Note that input coordinates from touchscreens (input devices with + * INPUT_PROP_DIRECT) will still map 1:1 to the actual LCD panel + * coordinates, so if userspace rotates the picture to adjust for + * the orientation it must also apply the same transformation to the + * touchscreen input coordinates. */ int drm_connector_create_standard_properties(struct drm_device *dev) @@ -1148,6 +1167,79 @@ int drm_mode_connector_set_tile_property(struct drm_connector *connector) EXPORT_SYMBOL(drm_mode_connector_set_tile_property); /** + * drm_mode_create_panel_orientation_property - create scaling mode property + * @dev: DRM device + * + * Called by a driver the first time it's needed, must be attached to desired + * connectors. + */ +int drm_connector_create_panel_orientation_property(struct drm_device *dev) +{ + struct drm_property *panel_orientation; + + if (dev->mode_config.panel_orientation_property) + return 0; + + panel_orientation = + drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, + "panel orientation", + drm_panel_orientation_enum_list, + ARRAY_SIZE(drm_panel_orientation_enum_list)); + + dev->mode_config.panel_orientation_property = panel_orientation; + + return 0; +} +EXPORT_SYMBOL(drm_connector_create_panel_orientation_property); + +/** + * drm_connector_attach_panel_orientation_property - + * attach panel-orientation property + * @connector: connector to attach panel-orientation property on. + * @width: width in pixels of the panel, used for panel quirk detection + * @height: height in pixels of the panel, used for panel quirk detection + * @panel_orientation: a DRM_MODE_PANEL_ORIENTATION_* value + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_connector_attach_panel_orientation_property( + struct drm_connector *connector, int width, int height, + int panel_orientation) +{ + int orientation; + + /* + * Note fb_get_panel_rotate_quirk returns the rotation needed to + * *correct* for the panel orientation. + */ + switch (fb_get_panel_rotate_quirk(width, height)) { + case FB_ROTATE_UR: + orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; + break; + case FB_ROTATE_CW: + orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; + break; + case FB_ROTATE_UD: + orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; + break; + case FB_ROTATE_CCW: + orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP; + break; + default: + orientation = panel_orientation; + } + + if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) + drm_object_attach_property(&connector->base, + connector->dev->mode_config.panel_orientation_property, + orientation); + + return 0; +} +EXPORT_SYMBOL(drm_connector_attach_panel_orientation_property); + +/** * drm_mode_connector_update_edid_property - update the edid property of a connector * @connector: drm connector * @edid: new value of the edid property diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index ea8da401c93c..42cd07ee58fb 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1004,6 +1004,10 @@ int drm_connector_attach_scaling_mode_property(struct drm_connector *connector, u32 scaling_mode_mask); int drm_mode_create_aspect_ratio_property(struct drm_device *dev); int drm_mode_create_suggested_offset_properties(struct drm_device *dev); +int drm_connector_create_panel_orientation_property(struct drm_device *dev); +int drm_connector_attach_panel_orientation_property( + struct drm_connector *connector, int width, int height, + int panel_orientation); int drm_mode_connector_set_path_property(struct drm_connector *connector, const char *path); diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index 1b37368416c8..6db187e4c747 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -741,6 +741,13 @@ struct drm_mode_config { */ struct drm_property *suggested_y_property; + /** + * @panel_orientation_property: Optional connector property indicating + * how the lcd-panel is mounted inside the casing (e.g. normal or + * upside-down). + */ + struct drm_property *panel_orientation_property; + /* dumb ioctl parameters */ uint32_t preferred_depth, prefer_shadow; diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index a2bb7161f020..b8b9f5abae53 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -127,6 +127,13 @@ extern "C" { #define DRM_MODE_LINK_STATUS_GOOD 0 #define DRM_MODE_LINK_STATUS_BAD 1 +/* Panel Orientation options */ +#define DRM_MODE_PANEL_ORIENTATION_UNKNOWN -1 +#define DRM_MODE_PANEL_ORIENTATION_NORMAL 0 +#define DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP 1 +#define DRM_MODE_PANEL_ORIENTATION_LEFT_UP 2 +#define DRM_MODE_PANEL_ORIENTATION_RIGHT_UP 3 + /* * DRM_MODE_ROTATE_ *