diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_hdcp.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_hdcp.c | 154 |
1 files changed, 82 insertions, 72 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 650232c4892b..dd539106ee5a 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -30,7 +30,8 @@ #define KEY_LOAD_TRIES 5 #define HDCP2_LC_RETRY_CNT 3 -static int intel_conn_to_vcpi(struct intel_connector *connector) +static int intel_conn_to_vcpi(struct drm_atomic_state *state, + struct intel_connector *connector) { struct drm_dp_mst_topology_mgr *mgr; struct drm_dp_mst_atomic_payload *payload; @@ -42,7 +43,7 @@ static int intel_conn_to_vcpi(struct intel_connector *connector) return 0; mgr = connector->port->mgr; - drm_modeset_lock(&mgr->base.lock, NULL); + drm_modeset_lock(&mgr->base.lock, state->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)) @@ -54,7 +55,6 @@ static int intel_conn_to_vcpi(struct intel_connector *connector) goto out; } out: - drm_modeset_unlock(&mgr->base.lock); return vcpi; } @@ -68,48 +68,18 @@ out: * DP MST topology. Though it is not compulsory, security fw should change its * policy to mark different content_types for different streams. */ -static int +static void intel_hdcp_required_content_stream(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; - data->k = 0; - if (dig_port->hdcp_auth_status) - return 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; - - if (!enforce_type0 && !dig_port->hdcp_mst_type1_capable) - enforce_type0 = true; - - data->streams[data->k].stream_id = intel_conn_to_vcpi(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); + return; - if (drm_WARN_ON(&i915->drm, data->k > INTEL_NUM_PIPES(i915) || data->k == 0)) - return -EINVAL; + if (!dig_port->hdcp_mst_type1_capable) + enforce_type0 = true; /* * Apply common protection level across all streams in DP MST Topology. @@ -118,27 +88,19 @@ 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 int intel_hdcp_prepare_streams(struct intel_connector *connector) +static void intel_hdcp_prepare_streams(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; - int ret; if (!intel_encoder_is_mst(intel_attached_encoder(connector))) { - data->k = 1; data->streams[0].stream_type = hdcp->content_type; } else { - ret = intel_hdcp_required_content_stream(dig_port); - if (ret) - return ret; + intel_hdcp_required_content_stream(dig_port); } - - return 0; } static @@ -204,8 +166,6 @@ bool intel_hdcp2_capable(struct intel_connector *connector) struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; - struct intel_gt *gt = dev_priv->media_gt; - struct intel_gsc_uc *gsc = >->uc.gsc; bool capable = false; /* I915 support for HDCP2.2 */ @@ -213,9 +173,13 @@ bool intel_hdcp2_capable(struct intel_connector *connector) return false; /* If MTL+ make sure gsc is loaded and proxy is setup */ - if (intel_hdcp_gsc_cs_required(dev_priv)) - if (!intel_uc_fw_is_running(&gsc->fw)) + if (intel_hdcp_gsc_cs_required(dev_priv)) { + struct intel_gt *gt = dev_priv->media_gt; + struct intel_gsc_uc *gsc = gt ? >->uc.gsc : NULL; + + if (!gsc || !intel_uc_fw_is_running(&gsc->fw)) return false; + } /* MEI/GSC interface is solid depending on which is used */ mutex_lock(&dev_priv->display.hdcp.comp_mutex); @@ -1917,13 +1881,7 @@ 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) { - ret = intel_hdcp_prepare_streams(connector); - if (ret) { - drm_dbg_kms(&i915->drm, - "Prepare streams failed.(%d)\n", - ret); - break; - } + intel_hdcp_prepare_streams(connector); ret = hdcp2_propagate_stream_management_info(connector); if (ret) { @@ -2202,7 +2160,6 @@ static int initialize_hdcp_port_data(struct intel_connector *connector, { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct hdcp_port_data *data = &dig_port->hdcp_port_data; - struct intel_hdcp *hdcp = &connector->hdcp; enum port port = dig_port->base.port; if (DISPLAY_VER(dev_priv) < 12) @@ -2232,9 +2189,6 @@ static int initialize_hdcp_port_data(struct intel_connector *connector, drm_err(&dev_priv->drm, "Out of Memory\n"); return -ENOMEM; } - /* For SST */ - data->streams[0].stream_id = 0; - data->streams[0].stream_type = hdcp->content_type; return 0; } @@ -2330,10 +2284,60 @@ int intel_hdcp_init(struct intel_connector *connector, return 0; } -int intel_hdcp_enable(struct intel_connector *connector, - const struct intel_crtc_state *pipe_config, u8 content_type) +static int +intel_hdcp_set_streams(struct intel_digital_port *dig_port, + struct intel_atomic_state *state) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + 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; +} + +int intel_hdcp_enable(struct intel_atomic_state *state, + struct intel_encoder *encoder, + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_connector *connector = + to_intel_connector(conn_state->connector); struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct intel_hdcp *hdcp = &connector->hdcp; unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS; @@ -2352,7 +2356,7 @@ int intel_hdcp_enable(struct intel_connector *connector, mutex_lock(&dig_port->hdcp_mutex); drm_WARN_ON(&dev_priv->drm, hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED); - hdcp->content_type = content_type; + hdcp->content_type = (u8)conn_state->content_type; if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) { hdcp->cpu_transcoder = pipe_config->mst_master_transcoder; @@ -2371,9 +2375,17 @@ int intel_hdcp_enable(struct intel_connector *connector, * is capable of HDCP2.2, it is preferred to use HDCP2.2. */ if (intel_hdcp2_capable(connector)) { - ret = _intel_hdcp2_enable(connector); - if (!ret) - check_link_interval = DRM_HDCP2_CHECK_PERIOD_MS; + 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(&dev_priv->drm, + "Set content streams failed: (%d)\n", + ret); + } } /* @@ -2483,9 +2495,7 @@ void intel_hdcp_update_pipe(struct intel_atomic_state *state, } if (desired_and_not_enabled || content_protection_type_changed) - intel_hdcp_enable(connector, - crtc_state, - (u8)conn_state->hdcp_content_type); + intel_hdcp_enable(state, encoder, crtc_state, conn_state); } void intel_hdcp_component_fini(struct drm_i915_private *dev_priv) |