[PATCH v4 13/13] drm/i915: Populate downstream info for HDCP
Ramalingam C
ramalingam.c at intel.com
Fri Apr 5 12:03:19 UTC 2019
On 2019-04-05 at 14:13:02 +0530, Ramalingam C wrote:
> Implements drm blob property content_protection_downstream_info
> property on HDCP capable connectors.
>
> Downstream topology info is gathered across authentication stages
> and stored in intel_hdcp. When HDCP authentication is complete,
> new blob with latest downstream topology information is updated to
> content_protection_downstream_info property.
>
> v2:
> %s/cp_downstream/content_protection_downstream [daniel]
> v3:
> %s/content_protection_downstream/hdcp_topology [daniel]
> v4:
> Rebased.
Daniel,
Hope I have done enough explicit padding struct hdcp_topology_info.
Please correct me if i am still missing something.
For populating the structure for the blob, as you sugegsted this patch
is not using the separate functions. IMHO I feel usage is very minimal,
separate functions might not be justified here. Hope you are fine with
that.
-Ram
>
> Signed-off-by: Ramalingam C <ramalingam.c at intel.com>
> ---
> drivers/gpu/drm/i915/intel_drv.h | 2 +
> drivers/gpu/drm/i915/intel_hdcp.c | 87 ++++++++++++++++++++++++++-----
> include/drm/drm_hdcp.h | 1 +
> 3 files changed, 76 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index e387e842f414..6a321a56ce42 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -482,6 +482,8 @@ struct intel_hdcp {
> wait_queue_head_t cp_irq_queue;
> atomic_t cp_irq_count;
> int cp_irq_count_cached;
> +
> + struct hdcp_topology_info *topology_info;
> };
>
> struct intel_connector {
> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
> index f70f1e98e4ae..6993bb9ecd0b 100644
> --- a/drivers/gpu/drm/i915/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> @@ -490,9 +490,10 @@ int intel_hdcp_validate_v_prime(struct intel_digital_port *intel_dig_port,
>
> /* Implements Part 2 of the HDCP authorization procedure */
> static
> -int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port,
> - const struct intel_hdcp_shim *shim)
> +int intel_hdcp_auth_downstream(struct intel_hdcp *hdcp,
> + struct intel_digital_port *intel_dig_port)
> {
> + const struct intel_hdcp_shim *shim = hdcp->shim;
> u8 bstatus[2], num_downstream, *ksv_fifo;
> int ret, i, tries = 3;
>
> @@ -523,6 +524,9 @@ int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port,
> if (num_downstream == 0)
> return -EINVAL;
>
> + hdcp->topology_info->device_count = num_downstream;
> + hdcp->topology_info->depth = DRM_HDCP_DEPTH(bstatus[1]);
> +
> ksv_fifo = kcalloc(DRM_HDCP_KSV_LEN, num_downstream, GFP_KERNEL);
> if (!ksv_fifo)
> return -ENOMEM;
> @@ -536,6 +540,8 @@ int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port,
> return -EPERM;
> }
>
> + memcpy(hdcp->topology_info->ksv_list, ksv_fifo,
> + num_downstream * DRM_HDCP_KSV_LEN);
> /*
> * When V prime mismatches, DP Spec mandates re-read of
> * V prime atleast twice.
> @@ -562,9 +568,11 @@ int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port,
> }
>
> /* Implements Part 1 of the HDCP authorization procedure */
> -static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port,
> - const struct intel_hdcp_shim *shim)
> +static int intel_hdcp_auth(struct intel_connector *connector)
> {
> + struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
> + struct intel_hdcp *hdcp = &connector->hdcp;
> + const struct intel_hdcp_shim *shim = hdcp->shim;
> struct drm_i915_private *dev_priv;
> enum port port;
> unsigned long r0_prime_gen_start;
> @@ -635,15 +643,20 @@ static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port,
> return -EPERM;
> }
>
> + hdcp->topology_info->ver_in_force = DRM_MODE_HDCP14_IN_FORCE;
> + memcpy(hdcp->topology_info->bksv, bksv.shim, DRM_MODE_HDCP_KSV_LEN);
> +
> I915_WRITE(PORT_HDCP_BKSVLO(port), bksv.reg[0]);
> I915_WRITE(PORT_HDCP_BKSVHI(port), bksv.reg[1]);
>
> ret = shim->repeater_present(intel_dig_port, &repeater_present);
> if (ret)
> return ret;
> - if (repeater_present)
> + if (repeater_present) {
> I915_WRITE(HDCP_REP_CTL,
> intel_hdcp_get_repeater_ctl(intel_dig_port));
> + hdcp->topology_info->is_repeater = true;
> + }
>
> ret = shim->toggle_signalling(intel_dig_port, true);
> if (ret)
> @@ -708,7 +721,7 @@ static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port,
> */
>
> if (repeater_present)
> - return intel_hdcp_auth_downstream(intel_dig_port, shim);
> + return intel_hdcp_auth_downstream(hdcp, intel_dig_port);
>
> DRM_DEBUG_KMS("HDCP is enabled (no repeater present)\n");
> return 0;
> @@ -739,13 +752,18 @@ static int _intel_hdcp_disable(struct intel_connector *connector)
> return ret;
> }
>
> + memset(hdcp->topology_info, 0, sizeof(struct hdcp_topology_info));
> +
> + if (drm_connector_update_hdcp_topology_property(&connector->base,
> + connector->hdcp.topology_info))
> + DRM_ERROR("Downstream_info update failed.\n");
> +
> DRM_DEBUG_KMS("HDCP is disabled\n");
> return 0;
> }
>
> static int _intel_hdcp_enable(struct intel_connector *connector)
> {
> - struct intel_hdcp *hdcp = &connector->hdcp;
> struct drm_i915_private *dev_priv = connector->base.dev->dev_private;
> int i, ret, tries = 3;
>
> @@ -770,9 +788,13 @@ static int _intel_hdcp_enable(struct intel_connector *connector)
>
> /* Incase of authentication failures, HDCP spec expects reauth. */
> for (i = 0; i < tries; i++) {
> - ret = intel_hdcp_auth(conn_to_dig_port(connector), hdcp->shim);
> + ret = intel_hdcp_auth(connector);
> if (!ret) {
> - hdcp->hdcp_encrypted = true;
> + connector->hdcp.hdcp_encrypted = true;
> + if (drm_connector_update_hdcp_topology_property(
> + &connector->base,
> + connector->hdcp.topology_info))
> + DRM_ERROR("Downstream_info update failed.\n");
> return 0;
> }
>
> @@ -1206,6 +1228,12 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
> return -EPERM;
> }
>
> + hdcp->topology_info->ver_in_force = DRM_MODE_HDCP22_IN_FORCE;
> + hdcp->topology_info->content_type = hdcp->content_type;
> + memcpy(hdcp->topology_info->bksv, msgs.send_cert.cert_rx.receiver_id,
> + HDCP_2_2_RECEIVER_ID_LEN);
> + hdcp->topology_info->is_repeater = hdcp->is_repeater;
> +
> /*
> * Here msgs.no_stored_km will hold msgs corresponding to the km
> * stored also.
> @@ -1397,6 +1425,11 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
> return -EPERM;
> }
>
> + hdcp->topology_info->device_count = device_cnt;
> + hdcp->topology_info->depth = HDCP_2_2_DEPTH(rx_info[0]);
> + memcpy(hdcp->topology_info->ksv_list, msgs.recvid_list.receiver_ids,
> + device_cnt * HDCP_2_2_RECEIVER_ID_LEN);
> +
> ret = hdcp2_verify_rep_topology_prepare_ack(connector,
> &msgs.recvid_list,
> &msgs.rep_ack);
> @@ -1583,6 +1616,12 @@ static int _intel_hdcp2_enable(struct intel_connector *connector)
> if (ret) {
> DRM_DEBUG_KMS("HDCP2 Type%d Enabling Failed. (%d)\n",
> hdcp->content_type, ret);
> +
> + memset(hdcp->topology_info, 0,
> + sizeof(struct hdcp_topology_info));
> + drm_connector_update_hdcp_topology_property(&connector->base,
> + hdcp->topology_info);
> +
> return ret;
> }
>
> @@ -1590,12 +1629,16 @@ static int _intel_hdcp2_enable(struct intel_connector *connector)
> connector->base.name, connector->base.base.id,
> hdcp->content_type);
>
> + drm_connector_update_hdcp_topology_property(&connector->base,
> + hdcp->topology_info);
> hdcp->hdcp2_encrypted = true;
> +
> return 0;
> }
>
> static int _intel_hdcp2_disable(struct intel_connector *connector)
> {
> + struct intel_hdcp *hdcp = &connector->hdcp;
> int ret;
>
> DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is being Disabled\n",
> @@ -1606,8 +1649,11 @@ static int _intel_hdcp2_disable(struct intel_connector *connector)
> if (hdcp2_deauthenticate_port(connector) < 0)
> DRM_DEBUG_KMS("Port deauth failed.\n");
>
> - connector->hdcp.hdcp2_encrypted = false;
> + hdcp->hdcp2_encrypted = false;
>
> + memset(hdcp->topology_info, 0, sizeof(struct hdcp_topology_info));
> + drm_connector_update_hdcp_topology_property(&connector->base,
> + hdcp->topology_info);
> return ret;
> }
>
> @@ -1824,10 +1870,17 @@ int intel_hdcp_init(struct intel_connector *connector,
> ret =
> drm_connector_attach_content_protection_property(&connector->base,
> hdcp->hdcp2_supported);
> - if (ret) {
> - hdcp->hdcp2_supported = false;
> - kfree(hdcp->port_data.streams);
> - return ret;
> + if (ret)
> + goto err_exit;
> +
> + ret = drm_connector_attach_hdcp_topology_property(&connector->base);
> + if (ret)
> + goto err_exit;
> +
> + hdcp->topology_info = kzalloc(sizeof(*hdcp->topology_info), GFP_KERNEL);
> + if (!hdcp->topology_info) {
> + ret = -ENOMEM;
> + goto err_exit;
> }
>
> hdcp->shim = shim;
> @@ -1837,6 +1890,12 @@ int intel_hdcp_init(struct intel_connector *connector,
> init_waitqueue_head(&hdcp->cp_irq_queue);
>
> return 0;
> +
> +err_exit:
> + hdcp->hdcp2_supported = false;
> + kfree(hdcp->port_data.streams);
> +
> + return ret;
> }
>
> int intel_hdcp_enable(struct intel_connector *connector, u8 content_type)
> diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h
> index fdd65a14f4db..330e34715aa4 100644
> --- a/include/drm/drm_hdcp.h
> +++ b/include/drm/drm_hdcp.h
> @@ -23,6 +23,7 @@
> #define DRM_HDCP_V_PRIME_PART_LEN 4
> #define DRM_HDCP_V_PRIME_NUM_PARTS 5
> #define DRM_HDCP_NUM_DOWNSTREAM(x) (x & 0x7f)
> +#define DRM_HDCP_DEPTH(x) ((x) & 0x7)
> #define DRM_HDCP_MAX_CASCADE_EXCEEDED(x) (x & BIT(3))
> #define DRM_HDCP_MAX_DEVICE_EXCEEDED(x) (x & BIT(7))
>
> --
> 2.19.1
>
More information about the dri-devel
mailing list