@@ -3495,7 +3495,8 @@ static void intel_enable_ddi(struct intel_encoder *encoder,
/* Enable hdcp if it's desired */
if (conn_state->content_protection ==
DRM_MODE_CONTENT_PROTECTION_DESIRED)
- intel_hdcp_enable(to_intel_connector(conn_state->connector));
+ intel_hdcp_enable(to_intel_connector(conn_state->connector),
+ (u8)conn_state->hdcp_content_type);
}
static void intel_disable_ddi_dp(struct intel_encoder *encoder,
@@ -3562,15 +3563,44 @@ static void intel_ddi_update_pipe(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
+ struct intel_connector *connector =
+ to_intel_connector(conn_state->connector);
+ struct intel_hdcp *hdcp = &connector->hdcp;
+ bool re_enable_hdcp = false;
+ int ret = -EINVAL;
+
if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
intel_ddi_update_pipe_dp(encoder, crtc_state, conn_state);
+ /*
+ * During the HDCP encryption session if Type change is requested,
+ * disable the HDCP and reenable it with new TYPE value.
+ */
if (conn_state->content_protection ==
- DRM_MODE_CONTENT_PROTECTION_DESIRED)
- intel_hdcp_enable(to_intel_connector(conn_state->connector));
+ DRM_MODE_CONTENT_PROTECTION_ENABLED &&
+ conn_state->hdcp_content_type != hdcp->content_type) {
+ intel_hdcp_disable(to_intel_connector(conn_state->connector));
+ re_enable_hdcp = true;
+ }
+
+ if (conn_state->content_protection ==
+ DRM_MODE_CONTENT_PROTECTION_DESIRED || re_enable_hdcp)
+ ret = intel_hdcp_enable(connector,
+ (u8)conn_state->hdcp_content_type);
else if (conn_state->content_protection ==
DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
- intel_hdcp_disable(to_intel_connector(conn_state->connector));
+ intel_hdcp_disable(connector);
+
+ /*
+ * During Type change handling re-enabling of the HDCP failed. Hence
+ * changes state as ENABLED->DESIRED.
+ */
+ if (ret && re_enable_hdcp) {
+ mutex_lock(&hdcp->mutex);
+ hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+ schedule_work(&hdcp->prop_work);
+ mutex_unlock(&hdcp->mutex);
+ }
}
static void intel_ddi_set_fia_lane_count(struct intel_encoder *encoder,
@@ -2178,7 +2178,7 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
struct drm_connector_state *new_state);
int intel_hdcp_init(struct intel_connector *connector,
const struct intel_hdcp_shim *hdcp_shim);
-int intel_hdcp_enable(struct intel_connector *connector);
+int intel_hdcp_enable(struct intel_connector *connector, u8 content_type);
int intel_hdcp_disable(struct intel_connector *connector);
bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
bool intel_hdcp_capable(struct intel_connector *connector);
@@ -1714,14 +1714,15 @@ static const struct component_ops i915_hdcp_component_ops = {
.unbind = i915_hdcp_component_unbind,
};
-static inline int initialize_hdcp_port_data(struct intel_connector *connector)
+static inline int initialize_hdcp_port_data(struct intel_connector *connector,
+ const struct intel_hdcp_shim *shim)
{
struct intel_hdcp *hdcp = &connector->hdcp;
struct hdcp_port_data *data = &hdcp->port_data;
data->port = connector->encoder->port;
data->port_type = (u8)HDCP_PORT_TYPE_INTEGRATED;
- data->protocol = (u8)hdcp->shim->protocol;
+ data->protocol = (u8)shim->protocol;
data->k = 1;
if (!data->streams)
@@ -1771,12 +1772,13 @@ void intel_hdcp_component_init(struct drm_i915_private *dev_priv)
}
}
-static void intel_hdcp2_init(struct intel_connector *connector)
+static void intel_hdcp2_init(struct intel_connector *connector,
+ const struct intel_hdcp_shim *shim)
{
struct intel_hdcp *hdcp = &connector->hdcp;
int ret;
- ret = initialize_hdcp_port_data(connector);
+ ret = initialize_hdcp_port_data(connector, shim);
if (ret) {
DRM_DEBUG_KMS("Mei hdcp data init failed\n");
return;
@@ -1795,25 +1797,28 @@ int intel_hdcp_init(struct intel_connector *connector,
if (!shim)
return -EINVAL;
+ if (is_hdcp2_supported(dev_priv))
+ intel_hdcp2_init(connector, shim);
+
ret =
drm_connector_attach_content_protection_property(&connector->base,
- false);
- if (ret)
+ hdcp->hdcp2_supported);
+ if (ret) {
+ hdcp->hdcp2_supported = false;
+ kfree(hdcp->port_data.streams);
return ret;
+ }
hdcp->shim = shim;
mutex_init(&hdcp->mutex);
INIT_DELAYED_WORK(&hdcp->check_work, intel_hdcp_check_work);
INIT_WORK(&hdcp->prop_work, intel_hdcp_prop_work);
-
- if (is_hdcp2_supported(dev_priv))
- intel_hdcp2_init(connector);
init_waitqueue_head(&hdcp->cp_irq_queue);
return 0;
}
-int intel_hdcp_enable(struct intel_connector *connector)
+int intel_hdcp_enable(struct intel_connector *connector, u8 content_type)
{
struct intel_hdcp *hdcp = &connector->hdcp;
unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS;
@@ -1824,6 +1829,7 @@ int intel_hdcp_enable(struct intel_connector *connector)
mutex_lock(&hdcp->mutex);
WARN_ON(hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED);
+ hdcp->content_type = content_type;
/*
* Considering that HDCP2.2 is more secure than HDCP1.4, If the setup
@@ -1835,8 +1841,12 @@ int intel_hdcp_enable(struct intel_connector *connector)
check_link_interval = DRM_HDCP2_CHECK_PERIOD_MS;
}
- /* When HDCP2.2 fails, HDCP1.4 will be attempted */
- if (ret && intel_hdcp_capable(connector)) {
+ /*
+ * When HDCP2.2 fails and Content Type is not Type1, HDCP1.4 will
+ * be attempted.
+ */
+ if (ret && intel_hdcp_capable(connector) &&
+ hdcp->content_type != DRM_MODE_HDCP_CONTENT_TYPE1) {
ret = _intel_hdcp_enable(connector);
}
@@ -1918,12 +1928,15 @@ void intel_hdcp_atomic_check(struct drm_connector *connector,
/*
* Nothing to do if the state didn't change, or HDCP was activated since
- * the last commit
+ * the last commit. And also no change in hdcp content type.
*/
if (old_cp == new_cp ||
(old_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
- new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED))
- return;
+ new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)) {
+ if (old_state->hdcp_content_type ==
+ new_state->hdcp_content_type)
+ return;
+ }
crtc_state = drm_atomic_get_new_crtc_state(new_state->state,
new_state->crtc);
Attaches the content type property for HDCP2.2 capable connectors. Implements the update of content type from property and apply the restriction on HDCP version selection. v2: s/cp_content_type/content_protection_type [daniel] disable at hdcp_atomic_check to avoid check at atomic_set_property [Maarten] v3: s/content_protection_type/hdcp_content_type [Pekka] v4: hdcp disable incase of type change is moved into commit [daniel]. Signed-off-by: Ramalingam C <ramalingam.c@intel.com> --- drivers/gpu/drm/i915/intel_ddi.c | 38 ++++++++++++++++++++++++--- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_hdcp.c | 43 ++++++++++++++++++++----------- 3 files changed, 63 insertions(+), 20 deletions(-)