From patchwork Thu Nov 30 03:08:56 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Paul X-Patchwork-Id: 10084151 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 4B9CF60311 for ; Thu, 30 Nov 2017 03:10:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3FA2D29D17 for ; Thu, 30 Nov 2017 03:10:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3480529D5C; Thu, 30 Nov 2017 03:10:14 +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.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 5F28329D17 for ; Thu, 30 Nov 2017 03:10:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=bwnNlKtFPfd0xe1//E9z3WAjW1gr9XKOHyIOI5VO2kY=; b=nAAzy2TleCYZfx/vS1JUOFVwQ4 OdSUVCmzSWrwvcrTRq2qO2iKYLf59W2+jsNltUXZf7+ERP+3mTc0O1F2dItEojlWOFWqH1sKdZS8f 73r+bdG60thtDXaoENOAOrdlnvAJA4eVzEsvtr9fX684HocHL14lmB/igCaKi7Ung11vC9bfuhNHx 2j2uhcCsd2qJZ4ogwIEoB6EpZpqVpUVpOIHl6d0uUK2nyQWTkK6YE/0mJKIfXWksocB39HvSz/TS/ zIp8zOeY+NNXMDv6Sv4UtmP52r+Sx+FXrIDyyWy/3up63mWj8o+ss0wWDF3eCs9wvzJtZm/a15Uqr uLhOQiXQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1eKFEp-0006NB-3m; Thu, 30 Nov 2017 03:10:11 +0000 Received: from mail-yw0-x244.google.com ([2607:f8b0:4002:c05::244]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1eKFEj-00054r-L6 for linux-mediatek@lists.infradead.org; Thu, 30 Nov 2017 03:10:09 +0000 Received: by mail-yw0-x244.google.com with SMTP id m81so2201287ywd.2 for ; Wed, 29 Nov 2017 19:09:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=uEGyBrnqyLd23mwYBxHWweFYCp9bsiunG9qVd4iEUnA=; b=H7sXO3jjz2utxD6REIYw+zZToLtO8IqUZiwEsv2I5cjsaogsEbXGPUYSrnlzzUiBiG 57COyb84tpF/fohjVIG1fNXNKXJ0T5Zvo2LDYJI5DMUmXk1KS8ugDd7l8Q1TbXQ78enu wc55IE5ThvExzcoUbKnp7w5POAOe+yb21lLgw= 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=uEGyBrnqyLd23mwYBxHWweFYCp9bsiunG9qVd4iEUnA=; b=Uh50ju8aIoCkCds/l/t7EOkIrUBMAtNtfGvlWBuIIsbo3eA64bwCc+ZwjQe7sbrHt3 sW9scHbjENXmJ3iZ+JMkYOjCr4P3/nHeuWTBfGhpiE1XtEpQdt54W1mx7sGz5RKpq0jf G+7yCQh6JO7WMTdQ2Ip8/E5N9AkxLg8TF176Yfnx4+P9F1bmLWQRe9tujVjIQwqf5H5a PZBBhU8GB9vmtGGU3L5XxnWDyaWY/ms01tgK2R7QVc4xPQNeyBFsQumRGzdB1pMA9Mru IJtSw+CZ+7Z8GvYoPgtasdHim4bQozik8Gf8c8sfHhoNMxc/vtMZ8XerVePHGNqZKonH HQuw== X-Gm-Message-State: AJaThX6Fj57JW48WZ2RKzVRlLIyE/KBXBU2zWG/eIJ5yLH33c2W6fJSj LxgW9COMFB8pWx5jrP4uJjqphewbsQc= X-Google-Smtp-Source: AGs4zMZEqAdmRdKA/XEf45LB7csg16pD5H34JKgiPf1i5jdN/7Pu2Ykn6rSmMzm8HIFHKml70qOlug== X-Received: by 10.129.166.193 with SMTP id d184mr639243ywh.241.1512011383918; Wed, 29 Nov 2017 19:09:43 -0800 (PST) Received: from rosewood.cam.corp.google.com ([2620:0:1013:11:d3af:69ac:1964:28e8]) by smtp.gmail.com with ESMTPSA id u24sm1460752ywh.84.2017.11.29.19.09.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 29 Nov 2017 19:09:43 -0800 (PST) From: Sean Paul To: dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org Subject: [RFC PATCH 1/6] drm: Add Content Protection property Date: Wed, 29 Nov 2017 22:08:56 -0500 Message-Id: <20171130030907.26848-2-seanpaul@chromium.org> X-Mailer: git-send-email 2.15.0.531.g2ccb3012c9-goog In-Reply-To: <20171130030907.26848-1-seanpaul@chromium.org> References: <20171130030907.26848-1-seanpaul@chromium.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171129_191005_830639_CBE2DC56 X-CRM114-Status: GOOD ( 19.62 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: David Airlie , Gustavo Padovan , linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Jani Nikula , Sean Paul , Daniel Vetter , linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds a new optional connector property to allow userspace to enable protection over the content it is displaying. This will typically be implemented by the driver using HDCP. The property is a tri-state with the following values: - OFF: Self explanatory, no content protection - DESIRED: Userspace requests that the driver enable protection - ENABLED: Once the driver has authenticated the link, it sets this value The driver is responsible for downgrading ENABLED to DESIRED if the link becomes unprotected. The driver should also maintain the desiredness of protection across hotplug/dpms/suspend. If this looks familiar, I posted [1] this 3 years ago. We have been using this in ChromeOS across exynos, mediatek, and rockchip over that time. Signed-off-by: Sean Paul [1] https://lists.freedesktop.org/archives/dri-devel/2014-December/073336.html --- drivers/gpu/drm/drm_atomic.c | 8 ++++++++ drivers/gpu/drm/drm_connector.c | 43 +++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_sysfs.c | 29 +++++++++++++++++++++++++++ include/drm/drm_connector.h | 16 +++++++++++++++ include/uapi/drm/drm_mode.h | 4 ++++ 5 files changed, 100 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 37445d50816a..2212793eefa6 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1185,6 +1185,12 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, state->picture_aspect_ratio = val; } else if (property == connector->scaling_mode_property) { state->scaling_mode = val; + } else if (property == connector->content_protection_property) { + if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) { + DRM_DEBUG_KMS("only drivers can set CP Enabled\n"); + return -EINVAL; + } + state->content_protection = val; } else if (connector->funcs->atomic_set_property) { return connector->funcs->atomic_set_property(connector, state, property, val); @@ -1264,6 +1270,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector, *val = state->picture_aspect_ratio; } else if (property == connector->scaling_mode_property) { *val = state->scaling_mode; + } else if (property == connector->content_protection_property) { + *val = state->content_protection; } else if (connector->funcs->atomic_get_property) { return connector->funcs->atomic_get_property(connector, state, property, val); diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 704fc8934616..de2345a4a125 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -698,6 +698,13 @@ static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = { DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, drm_tv_subconnector_enum_list) +static struct drm_prop_enum_list drm_cp_enum_list[] = { + { DRM_MODE_CONTENT_PROTECTION_OFF, "Off" }, + { DRM_MODE_CONTENT_PROTECTION_DESIRED, "Desired" }, + { DRM_MODE_CONTENT_PROTECTION_ENABLED, "Enabled" }, +}; +DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list) + /** * DOC: standard connector properties * @@ -1046,6 +1053,42 @@ int drm_connector_attach_scaling_mode_property(struct drm_connector *connector, } EXPORT_SYMBOL(drm_connector_attach_scaling_mode_property); +/** + * drm_connector_attach_content_protection_property - attach content protection + * property + * + * @connector: connector to attach CP property on. + * + * This is used to add support for content protection on select connectors. + * Content Protection is intentionally vague to allow for different underlying + * technologies, however it is most implemented by HDCP. + * + * The content protection will be set to &drm_connector_state.content_protection + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_connector_attach_content_protection_property( + struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_property *prop; + + prop = drm_property_create_enum(dev, 0, "Content Protection", + drm_cp_enum_list, + ARRAY_SIZE(drm_cp_enum_list)); + if (!prop) + return -ENOMEM; + + drm_object_attach_property(&connector->base, prop, + DRM_MODE_CONTENT_PROTECTION_OFF); + + connector->content_protection_property = prop; + + return 0; +} +EXPORT_SYMBOL(drm_connector_attach_content_protection_property); + /** * drm_mode_create_aspect_ratio_property - create aspect ratio property * @dev: DRM device diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 1c5b5ce1fd7f..e8e15756dc59 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -21,6 +21,7 @@ #include #include #include "drm_internal.h" +#include "drm_crtc_internal.h" #define to_drm_minor(d) dev_get_drvdata(d) #define to_drm_connector(d) dev_get_drvdata(d) @@ -229,16 +230,44 @@ static ssize_t modes_show(struct device *device, return written; } +static ssize_t content_protection_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct drm_connector *connector = to_drm_connector(device); + struct drm_device *dev = connector->dev; + struct drm_property *prop; + uint64_t cp; + int ret; + + drm_modeset_lock_all(dev); + + prop = connector->content_protection_property; + if (!prop) { + drm_modeset_unlock_all(dev); + return 0; + } + + ret = drm_object_property_get_value(&connector->base, prop, &cp); + drm_modeset_unlock_all(dev); + if (ret) + return 0; + + return snprintf(buf, PAGE_SIZE, "%s\n", + drm_get_content_protection_name((int)cp)); +} + static DEVICE_ATTR_RW(status); static DEVICE_ATTR_RO(enabled); static DEVICE_ATTR_RO(dpms); static DEVICE_ATTR_RO(modes); +static DEVICE_ATTR_RO(content_protection); static struct attribute *connector_dev_attrs[] = { &dev_attr_status.attr, &dev_attr_enabled.attr, &dev_attr_dpms.attr, &dev_attr_modes.attr, + &dev_attr_content_protection.attr, NULL }; diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 1543212b0449..ec6ea3953002 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -375,6 +375,12 @@ struct drm_connector_state { * upscaling, mostly used for built-in panels. */ unsigned int scaling_mode; + + /** + * @content_protection: Connector property to request content + * protection. This is most commonly used for HDCP. + */ + unsigned int content_protection; }; /** @@ -722,6 +728,7 @@ struct drm_cmdline_mode { * @tile_h_size: horizontal size of this tile. * @tile_v_size: vertical size of this tile. * @scaling_mode_property: Optional atomic property to control the upscaling. + * @content_protection_property: Optional property to control content protection * * Each connector may be connected to one or more CRTCs, or may be clonable by * another connector if they can share a CRTC. Each connector also has a specific @@ -812,6 +819,12 @@ struct drm_connector { struct drm_property *scaling_mode_property; + /** + * @content_protection_property: DRM ENUM property for content + * protection + */ + struct drm_property *content_protection_property; + /** * @path_blob_ptr: * @@ -1012,6 +1025,7 @@ const char *drm_get_dvi_i_subconnector_name(int val); const char *drm_get_dvi_i_select_name(int val); const char *drm_get_tv_subconnector_name(int val); const char *drm_get_tv_select_name(int val); +const char *drm_get_content_protection_name(int val); int drm_mode_create_dvi_i_properties(struct drm_device *dev); int drm_mode_create_tv_properties(struct drm_device *dev, @@ -1020,6 +1034,8 @@ int drm_mode_create_tv_properties(struct drm_device *dev, int drm_mode_create_scaling_mode_property(struct drm_device *dev); int drm_connector_attach_scaling_mode_property(struct drm_connector *connector, u32 scaling_mode_mask); +int drm_connector_attach_content_protection_property( + struct drm_connector *connector); int drm_mode_create_aspect_ratio_property(struct drm_device *dev); int drm_mode_create_suggested_offset_properties(struct drm_device *dev); diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 5597a87154e5..03f4d22305c2 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -173,6 +173,10 @@ extern "C" { DRM_MODE_REFLECT_X | \ DRM_MODE_REFLECT_Y) +/* Content Protection Flags */ +#define DRM_MODE_CONTENT_PROTECTION_OFF 0 +#define DRM_MODE_CONTENT_PROTECTION_DESIRED 1 +#define DRM_MODE_CONTENT_PROTECTION_ENABLED 2 struct drm_mode_modeinfo { __u32 clock;