diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_hdcp.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_hdcp.c | 296 |
1 files changed, 149 insertions, 147 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 39b3f7c0c7..9edac27bab 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -30,7 +30,7 @@ #define KEY_LOAD_TRIES 5 #define HDCP2_LC_RETRY_CNT 3 -static int intel_conn_to_vcpi(struct drm_atomic_state *state, +static int intel_conn_to_vcpi(struct intel_atomic_state *state, struct intel_connector *connector) { struct drm_dp_mst_topology_mgr *mgr; @@ -43,7 +43,7 @@ static int intel_conn_to_vcpi(struct drm_atomic_state *state, return 0; mgr = connector->port->mgr; - drm_modeset_lock(&mgr->base.lock, state->acquire_ctx); + drm_modeset_lock(&mgr->base.lock, state->base.acquire_ctx); mst_state = to_drm_dp_mst_topology_state(mgr->base.state); payload = drm_atomic_get_mst_payload_state(mst_state, connector->port); if (drm_WARN_ON(mgr->dev, !payload)) @@ -68,19 +68,51 @@ out: * DP MST topology. Though it is not compulsory, security fw should change its * policy to mark different content_types for different streams. */ -static void -intel_hdcp_required_content_stream(struct intel_digital_port *dig_port) +static int +intel_hdcp_required_content_stream(struct intel_atomic_state *state, + struct intel_digital_port *dig_port) { + struct drm_connector_list_iter conn_iter; + struct intel_digital_port *conn_dig_port; + struct intel_connector *connector; + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); struct hdcp_port_data *data = &dig_port->hdcp_port_data; bool enforce_type0 = false; int k; if (dig_port->hdcp_auth_status) - return; + return 0; + + data->k = 0; if (!dig_port->hdcp_mst_type1_capable) enforce_type0 = true; + drm_connector_list_iter_begin(&i915->drm, &conn_iter); + for_each_intel_connector_iter(connector, &conn_iter) { + if (connector->base.status == connector_status_disconnected) + continue; + + if (!intel_encoder_is_mst(intel_attached_encoder(connector))) + continue; + + conn_dig_port = intel_attached_dig_port(connector); + if (conn_dig_port != dig_port) + continue; + + data->streams[data->k].stream_id = + intel_conn_to_vcpi(state, connector); + data->k++; + + /* if there is only one active stream */ + if (dig_port->dp.active_mst_links <= 1) + break; + } + drm_connector_list_iter_end(&conn_iter); + + if (drm_WARN_ON(&i915->drm, data->k > INTEL_NUM_PIPES(i915) || data->k == 0)) + return -EINVAL; + /* * Apply common protection level across all streams in DP MST Topology. * Use highest supported content type for all streams in DP MST Topology. @@ -88,19 +120,25 @@ intel_hdcp_required_content_stream(struct intel_digital_port *dig_port) for (k = 0; k < data->k; k++) data->streams[k].stream_type = enforce_type0 ? DRM_MODE_HDCP_CONTENT_TYPE0 : DRM_MODE_HDCP_CONTENT_TYPE1; + + return 0; } -static void intel_hdcp_prepare_streams(struct intel_connector *connector) +static int intel_hdcp_prepare_streams(struct intel_atomic_state *state, + struct intel_connector *connector) { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct hdcp_port_data *data = &dig_port->hdcp_port_data; struct intel_hdcp *hdcp = &connector->hdcp; - if (!intel_encoder_is_mst(intel_attached_encoder(connector))) { - data->streams[0].stream_type = hdcp->content_type; - } else { - intel_hdcp_required_content_stream(dig_port); - } + if (intel_encoder_is_mst(intel_attached_encoder(connector))) + return intel_hdcp_required_content_stream(state, dig_port); + + data->k = 1; + data->streams[0].stream_id = 0; + data->streams[0].stream_type = hdcp->content_type; + + return 0; } static @@ -140,7 +178,7 @@ int intel_hdcp_read_valid_bksv(struct intel_digital_port *dig_port, } /* Is HDCP1.4 capable on Platform and Sink */ -bool intel_hdcp_capable(struct intel_connector *connector) +bool intel_hdcp_get_capability(struct intel_connector *connector) { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); const struct intel_hdcp_shim *shim = connector->hdcp.shim; @@ -150,8 +188,8 @@ bool intel_hdcp_capable(struct intel_connector *connector) if (!shim) return capable; - if (shim->hdcp_capable) { - shim->hdcp_capable(dig_port, &capable); + if (shim->hdcp_get_capability) { + shim->hdcp_get_capability(dig_port, &capable); } else { if (!intel_hdcp_read_valid_bksv(dig_port, shim, bksv)) capable = true; @@ -160,12 +198,14 @@ bool intel_hdcp_capable(struct intel_connector *connector) return capable; } -/* Is HDCP2.2 capable on Platform and Sink */ -bool intel_hdcp2_capable(struct intel_connector *connector) +/* + * Check if the source has all the building blocks ready to make + * HDCP 2.2 work + */ +static bool intel_hdcp2_prerequisite(struct intel_connector *connector) { struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; - bool capable = false; /* I915 support for HDCP2.2 */ if (!hdcp->hdcp2_supported) @@ -185,12 +225,40 @@ bool intel_hdcp2_capable(struct intel_connector *connector) } mutex_unlock(&i915->display.hdcp.hdcp_mutex); + return true; +} + +/* Is HDCP2.2 capable on Platform and Sink */ +bool intel_hdcp2_get_capability(struct intel_connector *connector) +{ + struct intel_hdcp *hdcp = &connector->hdcp; + bool capable = false; + + if (!intel_hdcp2_prerequisite(connector)) + return false; + /* Sink's capability for HDCP2.2 */ - hdcp->shim->hdcp_2_2_capable(connector, &capable); + hdcp->shim->hdcp_2_2_get_capability(connector, &capable); return capable; } +void intel_hdcp_get_remote_capability(struct intel_connector *connector, + bool *hdcp_capable, + bool *hdcp2_capable) +{ + struct intel_hdcp *hdcp = &connector->hdcp; + + if (!hdcp->shim->get_remote_hdcp_capability) + return; + + hdcp->shim->get_remote_hdcp_capability(connector, hdcp_capable, + hdcp2_capable); + + if (!intel_hdcp2_prerequisite(connector)) + *hdcp2_capable = false; +} + static bool intel_hdcp_in_use(struct drm_i915_private *i915, enum transcoder cpu_transcoder, enum port port) { @@ -347,7 +415,7 @@ u32 intel_hdcp_get_repeater_ctl(struct drm_i915_private *i915, default: drm_err(&i915->drm, "Unknown transcoder %d\n", cpu_transcoder); - return -EINVAL; + return 0; } } @@ -364,7 +432,7 @@ u32 intel_hdcp_get_repeater_ctl(struct drm_i915_private *i915, return HDCP_DDIE_REP_PRESENT | HDCP_DDIE_SHA1_M0; default: drm_err(&i915->drm, "Unknown port %d\n", port); - return -EINVAL; + return 0; } } @@ -726,8 +794,8 @@ static int intel_hdcp_auth(struct intel_connector *connector) * whether the display supports HDCP before we write An. For HDMI * displays, this is not necessary. */ - if (shim->hdcp_capable) { - ret = shim->hdcp_capable(dig_port, &hdcp_capable); + if (shim->hdcp_get_capability) { + ret = shim->hdcp_get_capability(dig_port, &hdcp_capable); if (ret) return ret; if (!hdcp_capable) { @@ -853,8 +921,8 @@ static int intel_hdcp_auth(struct intel_connector *connector) if (shim->stream_encryption) { ret = shim->stream_encryption(connector, true); if (ret) { - drm_err(&i915->drm, "[%s:%d] Failed to enable HDCP 1.4 stream enc\n", - connector->base.name, connector->base.base.id); + drm_err(&i915->drm, "[CONNECTOR:%d:%s] Failed to enable HDCP 1.4 stream enc\n", + connector->base.base.id, connector->base.name); return ret; } drm_dbg_kms(&i915->drm, "HDCP 1.4 transcoder: %s stream encrypted\n", @@ -878,14 +946,14 @@ static int _intel_hdcp_disable(struct intel_connector *connector) u32 repeater_ctl; int ret; - drm_dbg_kms(&i915->drm, "[%s:%d] HDCP is being disabled...\n", - connector->base.name, connector->base.base.id); + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] HDCP is being disabled...\n", + connector->base.base.id, connector->base.name); if (hdcp->shim->stream_encryption) { ret = hdcp->shim->stream_encryption(connector, false); if (ret) { - drm_err(&i915->drm, "[%s:%d] Failed to disable HDCP 1.4 stream enc\n", - connector->base.name, connector->base.base.id); + drm_err(&i915->drm, "[CONNECTOR:%d:%s] Failed to disable HDCP 1.4 stream enc\n", + connector->base.base.id, connector->base.name); return ret; } drm_dbg_kms(&i915->drm, "HDCP 1.4 transcoder: %s stream encryption disabled\n", @@ -929,8 +997,8 @@ static int intel_hdcp1_enable(struct intel_connector *connector) struct intel_hdcp *hdcp = &connector->hdcp; int i, ret, tries = 3; - drm_dbg_kms(&i915->drm, "[%s:%d] HDCP is being enabled...\n", - connector->base.name, connector->base.base.id); + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] HDCP is being enabled...\n", + connector->base.base.id, connector->base.name); if (!hdcp_key_loadable(i915)) { drm_err(&i915->drm, "HDCP key Load is not possible\n"); @@ -1027,8 +1095,8 @@ static int intel_hdcp_check_link(struct intel_connector *connector) if (drm_WARN_ON(&i915->drm, !intel_hdcp_in_use(i915, cpu_transcoder, port))) { drm_err(&i915->drm, - "%s:%d HDCP link stopped encryption,%x\n", - connector->base.name, connector->base.base.id, + "[CONNECTOR:%d:%s] HDCP link stopped encryption,%x\n", + connector->base.base.id, connector->base.name, intel_de_read(i915, HDCP_STATUS(i915, cpu_transcoder, port))); ret = -ENXIO; intel_hdcp_update_value(connector, @@ -1046,8 +1114,8 @@ static int intel_hdcp_check_link(struct intel_connector *connector) } drm_dbg_kms(&i915->drm, - "[%s:%d] HDCP link failed, retrying authentication\n", - connector->base.name, connector->base.base.id); + "[CONNECTOR:%d:%s] HDCP link failed, retrying authentication\n", + connector->base.base.id, connector->base.name); ret = _intel_hdcp_disable(connector); if (ret) { @@ -1058,15 +1126,9 @@ static int intel_hdcp_check_link(struct intel_connector *connector) goto out; } - ret = intel_hdcp1_enable(connector); - if (ret) { - drm_err(&i915->drm, "Failed to enable hdcp (%d)\n", ret); - intel_hdcp_update_value(connector, - DRM_MODE_CONTENT_PROTECTION_DESIRED, - true); - goto out; - } - + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_DESIRED, + true); out: mutex_unlock(&dig_port->hdcp_mutex); mutex_unlock(&hdcp->mutex); @@ -1633,6 +1695,12 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector) !HDCP_2_2_HDCP1_DEVICE_CONNECTED(rx_info[1]) && !HDCP_2_2_HDCP_2_0_REP_CONNECTED(rx_info[1]); + if (!dig_port->hdcp_mst_type1_capable && hdcp->content_type) { + drm_dbg_kms(&i915->drm, + "HDCP1.x or 2.0 Legacy Device Downstream\n"); + return -EINVAL; + } + /* Converting and Storing the seq_num_v to local variable as DWORD */ seq_num_v = drm_hdcp_be24_to_cpu((const u8 *)msgs.recvid_list.seq_num_v); @@ -1731,8 +1799,8 @@ static int hdcp2_enable_stream_encryption(struct intel_connector *connector) if (!(intel_de_read(i915, HDCP2_STATUS(i915, cpu_transcoder, port)) & LINK_ENCRYPTION_STATUS)) { - drm_err(&i915->drm, "[%s:%d] HDCP 2.2 Link is not encrypted\n", - connector->base.name, connector->base.base.id); + drm_err(&i915->drm, "[CONNECTOR:%d:%s] HDCP 2.2 Link is not encrypted\n", + connector->base.base.id, connector->base.name); ret = -EPERM; goto link_recover; } @@ -1740,8 +1808,8 @@ static int hdcp2_enable_stream_encryption(struct intel_connector *connector) if (hdcp->shim->stream_2_2_encryption) { ret = hdcp->shim->stream_2_2_encryption(connector, true); if (ret) { - drm_err(&i915->drm, "[%s:%d] Failed to enable HDCP 2.2 stream enc\n", - connector->base.name, connector->base.base.id); + drm_err(&i915->drm, "[CONNECTOR:%d:%s] Failed to enable HDCP 2.2 stream enc\n", + connector->base.base.id, connector->base.name); return ret; } drm_dbg_kms(&i915->drm, "HDCP 2.2 transcoder: %s stream encrypted\n", @@ -1865,7 +1933,8 @@ hdcp2_propagate_stream_management_info(struct intel_connector *connector) return ret; } -static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector) +static int hdcp2_authenticate_and_encrypt(struct intel_atomic_state *state, + struct intel_connector *connector) { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *i915 = to_i915(connector->base.dev); @@ -1874,7 +1943,13 @@ static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector) for (i = 0; i < tries && !dig_port->hdcp_auth_status; i++) { ret = hdcp2_authenticate_sink(connector); if (!ret) { - intel_hdcp_prepare_streams(connector); + ret = intel_hdcp_prepare_streams(state, connector); + if (ret) { + drm_dbg_kms(&i915->drm, + "Prepare stream failed.(%d)\n", + ret); + break; + } ret = hdcp2_propagate_stream_management_info(connector); if (ret) { @@ -1919,25 +1994,26 @@ static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector) return ret; } -static int _intel_hdcp2_enable(struct intel_connector *connector) +static int _intel_hdcp2_enable(struct intel_atomic_state *state, + struct intel_connector *connector) { struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; int ret; - drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is being enabled. Type: %d\n", - connector->base.name, connector->base.base.id, + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] HDCP2.2 is being enabled. Type: %d\n", + connector->base.base.id, connector->base.name, hdcp->content_type); - ret = hdcp2_authenticate_and_encrypt(connector); + ret = hdcp2_authenticate_and_encrypt(state, connector); if (ret) { drm_dbg_kms(&i915->drm, "HDCP2 Type%d Enabling Failed. (%d)\n", hdcp->content_type, ret); return ret; } - drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is enabled. Type %d\n", - connector->base.name, connector->base.base.id, + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] HDCP2.2 is enabled. Type %d\n", + connector->base.base.id, connector->base.name, hdcp->content_type); hdcp->hdcp2_encrypted = true; @@ -1953,14 +2029,14 @@ _intel_hdcp2_disable(struct intel_connector *connector, bool hdcp2_link_recovery struct intel_hdcp *hdcp = &connector->hdcp; int ret; - drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is being Disabled\n", - connector->base.name, connector->base.base.id); + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] HDCP2.2 is being Disabled\n", + connector->base.base.id, connector->base.name); if (hdcp->shim->stream_2_2_encryption) { ret = hdcp->shim->stream_2_2_encryption(connector, false); if (ret) { - drm_err(&i915->drm, "[%s:%d] Failed to disable HDCP 2.2 stream enc\n", - connector->base.name, connector->base.base.id); + drm_err(&i915->drm, "[CONNECTOR:%d:%s] Failed to disable HDCP 2.2 stream enc\n", + connector->base.base.id, connector->base.name); return ret; } drm_dbg_kms(&i915->drm, "HDCP 2.2 transcoder: %s stream encryption disabled\n", @@ -2032,45 +2108,24 @@ static int intel_hdcp2_check_link(struct intel_connector *connector) drm_dbg_kms(&i915->drm, "HDCP2.2 Downstream topology change\n"); - ret = hdcp2_authenticate_repeater_topology(connector); - if (!ret) { - intel_hdcp_update_value(connector, - DRM_MODE_CONTENT_PROTECTION_ENABLED, - true); - goto out; - } - drm_dbg_kms(&i915->drm, - "[%s:%d] Repeater topology auth failed.(%d)\n", - connector->base.name, connector->base.base.id, - ret); } else { drm_dbg_kms(&i915->drm, - "[%s:%d] HDCP2.2 link failed, retrying auth\n", - connector->base.name, connector->base.base.id); + "[CONNECTOR:%d:%s] HDCP2.2 link failed, retrying auth\n", + connector->base.base.id, connector->base.name); } ret = _intel_hdcp2_disable(connector, true); if (ret) { drm_err(&i915->drm, - "[%s:%d] Failed to disable hdcp2.2 (%d)\n", - connector->base.name, connector->base.base.id, ret); + "[CONNECTOR:%d:%s] Failed to disable hdcp2.2 (%d)\n", + connector->base.base.id, connector->base.name, ret); intel_hdcp_update_value(connector, DRM_MODE_CONTENT_PROTECTION_DESIRED, true); goto out; } - ret = _intel_hdcp2_enable(connector); - if (ret) { - drm_dbg_kms(&i915->drm, - "[%s:%d] Failed to enable hdcp2.2 (%d)\n", - connector->base.name, connector->base.base.id, - ret); - intel_hdcp_update_value(connector, - DRM_MODE_CONTENT_PROTECTION_DESIRED, - true); - goto out; - } - + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_DESIRED, true); out: mutex_unlock(&dig_port->hdcp_mutex); mutex_unlock(&hdcp->mutex); @@ -2278,52 +2333,6 @@ int intel_hdcp_init(struct intel_connector *connector, return 0; } -static int -intel_hdcp_set_streams(struct intel_digital_port *dig_port, - struct intel_atomic_state *state) -{ - struct drm_connector_list_iter conn_iter; - struct intel_digital_port *conn_dig_port; - struct intel_connector *connector; - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct hdcp_port_data *data = &dig_port->hdcp_port_data; - - if (!intel_encoder_is_mst(&dig_port->base)) { - data->k = 1; - data->streams[0].stream_id = 0; - return 0; - } - - data->k = 0; - - drm_connector_list_iter_begin(&i915->drm, &conn_iter); - for_each_intel_connector_iter(connector, &conn_iter) { - if (connector->base.status == connector_status_disconnected) - continue; - - if (!intel_encoder_is_mst(intel_attached_encoder(connector))) - continue; - - conn_dig_port = intel_attached_dig_port(connector); - if (conn_dig_port != dig_port) - continue; - - data->streams[data->k].stream_id = - intel_conn_to_vcpi(&state->base, connector); - data->k++; - - /* if there is only one active stream */ - if (dig_port->dp.active_mst_links <= 1) - break; - } - drm_connector_list_iter_end(&conn_iter); - - if (drm_WARN_ON(&i915->drm, data->k > INTEL_NUM_PIPES(i915) || data->k == 0)) - return -EINVAL; - - return 0; -} - static int _intel_hdcp_enable(struct intel_atomic_state *state, struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config, @@ -2341,8 +2350,8 @@ static int _intel_hdcp_enable(struct intel_atomic_state *state, return -ENOENT; if (!connector->encoder) { - drm_err(&i915->drm, "[%s:%d] encoder is not initialized\n", - connector->base.name, connector->base.base.id); + drm_err(&i915->drm, "[CONNECTOR:%d:%s] encoder is not initialized\n", + connector->base.base.id, connector->base.name); return -ENODEV; } @@ -2368,25 +2377,18 @@ static int _intel_hdcp_enable(struct intel_atomic_state *state, * 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_hdcp_set_streams(dig_port, state); - if (!ret) { - ret = _intel_hdcp2_enable(connector); - if (!ret) - check_link_interval = - DRM_HDCP2_CHECK_PERIOD_MS; - } else { - drm_dbg_kms(&i915->drm, - "Set content streams failed: (%d)\n", - ret); - } + if (intel_hdcp2_get_capability(connector)) { + ret = _intel_hdcp2_enable(state, connector); + if (!ret) + check_link_interval = + DRM_HDCP2_CHECK_PERIOD_MS; } /* * When HDCP2.2 fails and Content Type is not Type1, HDCP1.4 will * be attempted. */ - if (ret && intel_hdcp_capable(connector) && + if (ret && intel_hdcp_get_capability(connector) && hdcp->content_type != DRM_MODE_HDCP_CONTENT_TYPE1) { ret = intel_hdcp1_enable(connector); } |