-----Original Message----- From: dri-devel [mailto:dri-devel-bounces@lists.freedesktop.org] On Behalf Of Ramalingam C Sent: Thursday, January 31, 2019 12:29 PM To: intel-gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; daniel.vetter@ffwll.ch; Winkler, Tomas tomas.winkler@intel.com; Shankar, Uma uma.shankar@intel.com Subject: [PATCH v10 08/40] drm/i915: Enable and Disable of HDCP2.2
Considering that HDCP2.2 is more secure than HDCP1.4, When a setup supports HDCP2.2 and HDCP1.4, HDCP2.2 will be enabled.
When HDCP2.2 enabling fails and HDCP1.4 is supported, HDCP1.4 is enabled.
This change implements a sequence of enabling and disabling of HDCP2.2 authentication and HDCP2.2 port encryption.
v2: Included few optimization suggestions [Chris Wilson] Commit message is updated as per the rebased version. intel_wait_for_register is used instead of wait_for. [Chris Wilson] v3: Extra comment added and Style issue fixed [Uma] v4: Rebased as part of patch reordering. HDCP2 encryption status is tracked. HW state check is moved into WARN_ON [Daniel] v5: Redefined the mei service functions as per comp redesign. Merged patches related to hdcp2.2 enabling and disabling [Sean Paul]. Required shim functionality is defined [Sean Paul] v6: Return values are handles [Uma] Realigned the code. Check for comp_master is removed. v7: HDCP2.2 is attempted only if mei interface is up. Adjust to the new interface Avoid bool usage in struct [Tomas] v8: mei_binded status check is removed. %s/hdcp2_in_use/hdcp2_encrypted v9: bool is used in struct intel_hdcp. [Daniel]
Signed-off-by: Ramalingam C ramalingam.c@intel.com Reviewed-by: Daniel Vetter daniel.vetter@ffwll.ch
drivers/gpu/drm/i915/intel_drv.h | 7 ++ drivers/gpu/drm/i915/intel_hdcp.c | 202 +++++++++++++++++++++++++++++++++++--- 2 files changed, 195 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 13a41e8cf4ff..31c7a4577ca9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -389,6 +389,10 @@ struct intel_hdcp_shim {
/* HDCP adaptation(DP/HDMI) required on the port */ enum hdcp_wired_protocol protocol;
- /* Detects whether Panel is HDCP2.2 capable */
Make Panel as Sink.
- int (*hdcp_2_2_capable)(struct intel_digital_port *intel_dig_port,
bool *capable);
};
struct intel_hdcp { @@ -406,6 +410,9 @@ struct intel_hdcp { /* Flag indicates whether this connector supports HDCP2.2 or not. */ bool hdcp2_supported;
- /* HDCP2.2 Encryption status */
- bool hdcp2_encrypted;
- /*
- Content Stream Type defined by content owner. TYPE0(0x0) content
can * flow in the link protected by HDCP2.2 or HDCP1.4, where as TYPE1(0x1) diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c index c1b057f1501b..fbf8b7893bfa 100644 --- a/drivers/gpu/drm/i915/intel_hdcp.c +++ b/drivers/gpu/drm/i915/intel_hdcp.c @@ -74,6 +74,23 @@ bool intel_hdcp_capable(struct intel_connector *connector) return capable; }
+/* Is HDCP2.2 capable on Platform and Sink */ static bool +intel_hdcp2_capable(struct intel_connector *connector) {
- struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
- struct intel_hdcp *hdcp = &connector->hdcp;
- bool capable = false;
- /* I915 support for HDCP2.2 */
- if (!hdcp->hdcp2_supported)
return false;
- /* Sink's capability for HDCP2.2 */
- hdcp->shim->hdcp_2_2_capable(intel_dig_port, &capable);
- return capable;
+}
static inline bool intel_hdcp_in_use(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); @@ -1094,8 +1111,7 @@ int hdcp2_authenticate_port(struct intel_connector *connector) return ret; }
-static __attribute__((unused)) -int hdcp2_close_mei_session(struct intel_connector *connector) +static int hdcp2_close_mei_session(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct i915_hdcp_comp_master *comp; @@ -1116,12 +1132,157 @@ int hdcp2_close_mei_session(struct intel_connector *connector) return ret; }
-static __attribute__((unused)) -int hdcp2_deauthenticate_port(struct intel_connector *connector) +static int hdcp2_deauthenticate_port(struct intel_connector *connector) { return hdcp2_close_mei_session(connector); }
+static int hdcp2_authenticate_sink(struct intel_connector *connector) {
- DRM_ERROR("Sink authentication is done in subsequent patches\n");
- return -EINVAL;
+}
+static int hdcp2_enable_encryption(struct intel_connector *connector) {
- struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- struct intel_hdcp *hdcp = &connector->hdcp;
- enum port port = connector->encoder->port;
- int ret;
- WARN_ON(I915_READ(HDCP2_STATUS_DDI(port)) &
LINK_ENCRYPTION_STATUS);
- if (hdcp->shim->toggle_signalling) {
ret = hdcp->shim->toggle_signalling(intel_dig_port, true);
if (ret) {
DRM_ERROR("Failed to enable HDCP signalling. %d\n",
ret);
return ret;
}
- }
- if (I915_READ(HDCP2_STATUS_DDI(port)) & LINK_AUTH_STATUS) {
/* Link is Authenticated. Now set for Encryption */
I915_WRITE(HDCP2_CTL_DDI(port),
I915_READ(HDCP2_CTL_DDI(port)) |
CTL_LINK_ENCRYPTION_REQ);
- }
- ret = intel_wait_for_register(dev_priv, HDCP2_STATUS_DDI(port),
LINK_ENCRYPTION_STATUS,
LINK_ENCRYPTION_STATUS,
ENCRYPT_STATUS_CHANGE_TIMEOUT_MS);
- return ret;
+}
+static int hdcp2_disable_encryption(struct intel_connector *connector) +{
- struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- struct intel_hdcp *hdcp = &connector->hdcp;
- enum port port = connector->encoder->port;
- int ret;
- WARN_ON(!(I915_READ(HDCP2_STATUS_DDI(port)) &
+LINK_ENCRYPTION_STATUS));
- I915_WRITE(HDCP2_CTL_DDI(port),
I915_READ(HDCP2_CTL_DDI(port)) &
~CTL_LINK_ENCRYPTION_REQ);
- ret = intel_wait_for_register(dev_priv, HDCP2_STATUS_DDI(port),
LINK_ENCRYPTION_STATUS, 0x0,
ENCRYPT_STATUS_CHANGE_TIMEOUT_MS);
- if (ret == -ETIMEDOUT)
DRM_DEBUG_KMS("Disable Encryption Timedout");
- if (hdcp->shim->toggle_signalling) {
ret = hdcp->shim->toggle_signalling(intel_dig_port, false);
if (ret) {
DRM_ERROR("Failed to disable HDCP signalling. %d\n",
ret);
return ret;
}
- }
- return ret;
+}
+static int hdcp2_authenticate_and_encrypt(struct intel_connector +*connector) {
- int ret, i, tries = 3;
- for (i = 0; i < tries; i++) {
ret = hdcp2_authenticate_sink(connector);
if (!ret)
break;
/* Clearing the mei hdcp session */
DRM_DEBUG_KMS("HDCP2.2 Auth %d of %d Failed.(%d)\n",
i + 1, tries, ret);
if (hdcp2_deauthenticate_port(connector) < 0)
DRM_DEBUG_KMS("Port deauth failed.\n");
- }
- if (i != tries) {
/*
* Ensuring the required 200mSec min time interval between
* Session Key Exchange and encryption.
*/
msleep(HDCP_2_2_DELAY_BEFORE_ENCRYPTION_EN);
ret = hdcp2_enable_encryption(connector);
if (ret < 0) {
DRM_DEBUG_KMS("Encryption Enable Failed.(%d)\n",
ret);
if (hdcp2_deauthenticate_port(connector) < 0)
DRM_DEBUG_KMS("Port deauth failed.\n");
}
- }
- return ret;
+}
+static int _intel_hdcp2_enable(struct intel_connector *connector) {
- struct intel_hdcp *hdcp = &connector->hdcp;
- int ret;
- DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is being enabled. Type: %d\n",
connector->base.name, connector->base.base.id,
hdcp->content_type);
- ret = hdcp2_authenticate_and_encrypt(connector);
- if (ret) {
DRM_DEBUG_KMS("HDCP2 Type%d Enabling Failed. (%d)\n",
hdcp->content_type, ret);
return ret;
- }
- DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is enabled. Type %d\n",
connector->base.name, connector->base.base.id,
hdcp->content_type);
- hdcp->hdcp2_encrypted = true;
- return 0;
+}
+static int _intel_hdcp2_disable(struct intel_connector *connector) {
- int ret;
- DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is being Disabled\n",
connector->base.name, connector->base.base.id);
- ret = hdcp2_disable_encryption(connector);
- if (hdcp2_deauthenticate_port(connector) < 0)
DRM_DEBUG_KMS("Port deauth failed.\n");
- connector->hdcp.hdcp2_encrypted = false;
- return ret;
+}
static void intel_hdcp_check_work(struct work_struct *work) { struct intel_hdcp *hdcp = container_of(to_delayed_work(work), @@ -1270,22 +1431,33 @@ int intel_hdcp_init(struct intel_connector *connector, int intel_hdcp_enable(struct intel_connector *connector) { struct intel_hdcp *hdcp = &connector->hdcp;
- int ret;
int ret = -EINVAL;
if (!hdcp->shim) return -ENOENT;
mutex_lock(&hdcp->mutex);
- ret = _intel_hdcp_enable(connector);
- if (ret)
goto out;
- /*
* Considering that HDCP2.2 is more secure than HDCP1.4, If the setup
* is capable of HDCP2.2, it is preferred to use HDCP2.2.
*/
- if (intel_hdcp2_capable(connector))
ret = _intel_hdcp2_enable(connector);
- /* When HDCP2.2 fails, HDCP1.4 will be attempted */
- if (ret && intel_hdcp_capable(connector)) {
ret = _intel_hdcp_enable(connector);
if (!ret)
schedule_delayed_work(&hdcp->check_work,
DRM_HDCP_CHECK_PERIOD_MS);
- }
- if (!ret) {
hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
schedule_work(&hdcp->prop_work);
Looks like check_work is not called for 2.2. Fix this.
With this fixed. Reviewed-by: Uma Shankar uma.shankar@intel.com
- }
- hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED;
- schedule_work(&hdcp->prop_work);
- schedule_delayed_work(&hdcp->check_work,
DRM_HDCP_CHECK_PERIOD_MS);
-out: mutex_unlock(&hdcp->mutex); return ret; } @@ -1302,7 +1474,9 @@ int intel_hdcp_disable(struct intel_connector *connector)
if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { hdcp->value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
if (hdcp->hdcp_encrypted)
if (hdcp->hdcp2_encrypted)
ret = _intel_hdcp2_disable(connector);
}else if (hdcp->hdcp_encrypted) ret = _intel_hdcp_disable(connector);
-- 2.7.4
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel