From patchwork Sat Nov 25 19:35:49 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: 10076083 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 D7945602BD for ; Mon, 27 Nov 2017 08:33:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C50C928D7B for ; Mon, 27 Nov 2017 08:33:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B9CC528DB1; Mon, 27 Nov 2017 08:33:55 +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=-4.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=unavailable 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 3026B28DA7 for ; Mon, 27 Nov 2017 08:33:55 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C794A6E213; Mon, 27 Nov 2017 08:33:44 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-wm0-x242.google.com (mail-wm0-x242.google.com [IPv6:2a00:1450:400c:c09::242]) by gabe.freedesktop.org (Postfix) with ESMTPS id BE79F6E14B; Sat, 25 Nov 2017 19:36:03 +0000 (UTC) Received: by mail-wm0-x242.google.com with SMTP id n74so2374247wmi.3; Sat, 25 Nov 2017 11:36:03 -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=bXwJ880DSlM37bmnEADPSfNbbUwBj6YsTzHv4diuciA=; b=hU/vHus5aqF6iURW60lM/okosfRt14fxUdQuqB2mvaHyah5PrzGh+kLctahXgL1yNC UZYBdQEnWtk1uzxnevZ2iixL5DQsg/u/WAooqD0WWgYiYxkRdd/bV154solzE1mg7rWv 2sOYH2JqAqdu0EwFRh9gIez3bsg7bahy2JkMoJyN6DDOpxCy74hoX3QHeV+JBRLDxHva 2bYcrvqa9KZnlF/80O+nLPNDAthL9Af57K7G6aQKMq+xKeoj/JqXjDdIWX6lXwg5Lwo/ NovWOh94PqI73H1W+4DsUK66CzL/7EJ/plV/fsoZ6XhiDEUbCtxds12IINo/kpK3lUgx 0R/Q== 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=bXwJ880DSlM37bmnEADPSfNbbUwBj6YsTzHv4diuciA=; b=DVCc1CNAm0mc1PvF819lCCjF8GFRjO3PEU+w8YKy7Neo5olL4OkVt1tWYEyud2O4yr aUwWMPrQ0uBVD3sPqnDT2YMwGMZRdyXZZBljtH10yXI6Dz22hqtuD3carxxmaZH86OCl iNUuG56i0c42zb2ZIKoaJVXGeUk48dBhrTVJZ9HyZN2W/FpKyCR1q2uTJm9+fuuGUdfr 0WSGoyDTSoO2qMpFWCJ60HMMg+Ecgs5Z9B1l9NQTrNc+1m0pI7ACuU7TXrlPU4+MoPSP UtRnzmsWo+JRLk9o96OCyi3qCmLI0K84snE/K04QkybcqGjfenZc3KihZltG7zIIEY99 aOOw== X-Gm-Message-State: AJaThX426MnK63+MVEg5SpgfhZuUT9pT5hIr9BPJVsuaIMvqOmfJZIz9 gWtwqc6cyG2WJ0Zdb7uqEJ4= X-Google-Smtp-Source: AGs4zMaH3ZpZ8TTH3QqE42mH0FGY51DZmPmNnxSRBc/l606itMZ9PCIpepul6fvw/HnDTFnAdkeiaA== X-Received: by 10.28.131.203 with SMTP id f194mr14016135wmd.39.1511638562298; Sat, 25 Nov 2017 11:36:02 -0800 (PST) Received: from localhost.localdomain.com ([2001:470:7a95:4242:2c1c:b9eb:f8cb:6ccb]) by smtp.gmail.com with ESMTPSA id l142sm1835010wmb.43.2017.11.25.11.36.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 25 Nov 2017 11:36:01 -0800 (PST) From: Hans de Goede X-Google-Original-From: Hans de Goede To: Daniel Vetter , Jani Nikula , Sean Paul , Dave Airlie , Bartlomiej Zolnierkiewicz Subject: [PATCH v7 3/7] drm: Add support for a panel-orientation connector property, v6 Date: Sat, 25 Nov 2017 20:35:49 +0100 Message-Id: <20171125193553.23986-4-hdegoede@redhat.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20171125193553.23986-1-hdegoede@redhat.com> References: <20171125193553.23986-1-hdegoede@redhat.com> X-Mailman-Approved-At: Mon, 27 Nov 2017 08:33:34 +0000 Cc: Hans de Goede , intel-gfx , linux-fbdev@vger.kernel.org, dri-devel@lists.freedesktop.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" 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. Changes in v2: -Store panel_orientation in drm_display_info, so that drm_fb_helper.c can access it easily -Have a single drm_connector_init_panel_orientation_property rather then create and attach functions. The caller is expected to set drm_display_info.panel_orientation before calling this, then this will check for platform specific quirks overriding the panel_orientation and if the panel_orientation is set after this then it will attach the property. Changes in v6: -Use an enum (with kerneldoc) rather then #defines for DRM_MODE_PANEL_ORIENTATION_* Signed-off-by: Hans de Goede Reviewed-by: Daniel Vetter --- drivers/gpu/drm/Kconfig | 1 + drivers/gpu/drm/drm_connector.c | 73 +++++++++++++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 40 ++++++++++++++++++++++ include/drm/drm_mode_config.h | 7 ++++ 4 files changed, 121 insertions(+) diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 9d005ac98c2b..0b166e626eb6 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -7,6 +7,7 @@ menuconfig DRM tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)" depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && HAS_DMA + select DRM_PANEL_ORIENTATION_QUIRKS select HDMI select FB_CMDLINE select I2C diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 25f4b2e9a44f..624edeb5c50d 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "drm_crtc_internal.h" #include "drm_internal.h" @@ -212,6 +213,8 @@ int drm_connector_init(struct drm_device *dev, mutex_init(&connector->mutex); connector->edid_blob_ptr = NULL; connector->status = connector_status_unknown; + connector->display_info.panel_orientation = + DRM_MODE_PANEL_ORIENTATION_UNKNOWN; drm_connector_get_cmdline_mode(connector); @@ -668,6 +671,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 */ @@ -776,6 +786,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) @@ -1251,6 +1273,57 @@ void drm_mode_connector_set_link_status_property(struct drm_connector *connector } EXPORT_SYMBOL(drm_mode_connector_set_link_status_property); +/** + * drm_connector_init_panel_orientation_property - + * initialize the connecters panel_orientation property + * @connector: connector for which to init the panel-orientation property. + * @width: width in pixels of the panel, used for panel quirk detection + * @height: height in pixels of the panel, used for panel quirk detection + * + * This function should only be called for built-in panels, after setting + * connector->display_info.panel_orientation first (if known). + * + * This function will check for platform specific (e.g. DMI based) quirks + * overriding display_info.panel_orientation first, then if panel_orientation + * is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the + * "panel orientation" property to the connector. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_connector_init_panel_orientation_property( + struct drm_connector *connector, int width, int height) +{ + struct drm_device *dev = connector->dev; + struct drm_display_info *info = &connector->display_info; + struct drm_property *prop; + int orientation_quirk; + + orientation_quirk = drm_get_panel_orientation_quirk(width, height); + if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) + info->panel_orientation = orientation_quirk; + + if (info->panel_orientation == DRM_MODE_PANEL_ORIENTATION_UNKNOWN) + return 0; + + prop = dev->mode_config.panel_orientation_property; + if (!prop) { + prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, + "panel orientation", + drm_panel_orientation_enum_list, + ARRAY_SIZE(drm_panel_orientation_enum_list)); + if (!prop) + return -ENOMEM; + + dev->mode_config.panel_orientation_property = prop; + } + + drm_object_attach_property(&connector->base, prop, + info->panel_orientation); + return 0; +} +EXPORT_SYMBOL(drm_connector_init_panel_orientation_property); + int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, struct drm_property *property, uint64_t value) diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 66d6c99d15e5..f39ff52feb3b 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -175,6 +175,35 @@ enum drm_link_status { DRM_LINK_STATUS_BAD = DRM_MODE_LINK_STATUS_BAD, }; +/** + * enum drm_panel_orientation - panel_orientation info for &drm_display_info + * + * This enum is used to track the (LCD) panel orientation. There are no + * separate #defines for the uapi! + * + * @DRM_MODE_PANEL_ORIENTATION_UNKNOWN: The drm driver has not provided any + * panel orientation information (normal + * for non panels) in this case the "panel + * orientation" connector prop will not be + * attached. + * @DRM_MODE_PANEL_ORIENTATION_NORMAL: The top side of the panel matches the + * top side of the device's casing. + * @DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP: The top side of the panel matches the + * bottom side of the device's casing, iow + * the panel is mounted upside-down. + * @DRM_MODE_PANEL_ORIENTATION_LEFT_UP: The left side of the panel matches the + * top side of the device's casing. + * @DRM_MODE_PANEL_ORIENTATION_RIGHT_UP: The right side of the panel matches the + * top side of the device's casing. + */ +enum drm_panel_orientation { + DRM_MODE_PANEL_ORIENTATION_UNKNOWN = -1, + DRM_MODE_PANEL_ORIENTATION_NORMAL = 0, + DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP, + DRM_MODE_PANEL_ORIENTATION_LEFT_UP, + DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, +}; + /** * struct drm_display_info - runtime data about the connected sink * @@ -222,6 +251,15 @@ struct drm_display_info { #define DRM_COLOR_FORMAT_YCRCB422 (1<<2) #define DRM_COLOR_FORMAT_YCRCB420 (1<<3) + /** + * @panel_orientation: Read only connector property for built-in panels, + * indicating the orientation of the panel vs the device's casing. + * drm_connector_init() sets this to DRM_MODE_PANEL_ORIENTATION_UNKNOWN. + * When not UNKNOWN this gets used by the drm_fb_helpers to rotate the + * fb to compensate and gets exported as prop to userspace. + */ + int panel_orientation; + /** * @color_formats: HDMI Color formats, selects between RGB and YCrCb * modes. Used DRM_COLOR_FORMAT\_ defines, which are _not_ the same ones @@ -1035,6 +1073,8 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, const struct edid *edid); void drm_mode_connector_set_link_status_property(struct drm_connector *connector, uint64_t link_status); +int drm_connector_init_panel_orientation_property( + struct drm_connector *connector, int width, int height); /** * struct drm_tile_group - Tile group metadata diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index 5306ebd537b2..cb9ffbda36cc 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -735,6 +735,13 @@ struct drm_mode_config { */ struct drm_property *non_desktop_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;