Skip to content

Commit

Permalink
drm/i915/hdcp: Allocate stream id after HDCP AKE stage
Browse files Browse the repository at this point in the history
Allocate stream id after HDCP AKE stage and not before so that it
can also be done during link integrity check.
Right now for MST scenarios LIC fails after hdcp enablement for this
reason.

--v2
-no need for else block in prepare_streams function [Ankit]

--v3
-remove intel_hdcp argument from required_content_stream function
[Ankit]

Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
Reviewed-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240226063051.1685326-6-suraj.kandpal@intel.com
  • Loading branch information
Suraj Kandpal authored and Ankit Nautiyal committed Feb 27, 2024
1 parent 483f7d9 commit 66bd692
Showing 1 changed file with 65 additions and 72 deletions.
137 changes: 65 additions & 72 deletions drivers/gpu/drm/i915/display/intel_hdcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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))
Expand All @@ -68,39 +68,77 @@ static int intel_conn_to_vcpi(struct drm_atomic_state *state,
* 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.
*/
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
Expand Down Expand Up @@ -1895,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);
Expand All @@ -1904,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) {
Expand Down Expand Up @@ -1949,7 +1994,8 @@ 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;
Expand All @@ -1959,7 +2005,7 @@ static int _intel_hdcp2_enable(struct intel_connector *connector)
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);
Expand Down Expand Up @@ -2287,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,
Expand Down Expand Up @@ -2378,17 +2378,10 @@ static int _intel_hdcp_enable(struct intel_atomic_state *state,
* is capable of HDCP2.2, it is preferred to use HDCP2.2.
*/
if (intel_hdcp2_get_capability(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);
}
ret = _intel_hdcp2_enable(state, connector);
if (!ret)
check_link_interval =
DRM_HDCP2_CHECK_PERIOD_MS;
}

/*
Expand Down

0 comments on commit 66bd692

Please sign in to comment.