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.
v5:
  Rebased.

Signed-off-by: Ramalingam C <ramalinga...@intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h  |  2 +
 drivers/gpu/drm/i915/intel_hdcp.c | 73 +++++++++++++++++++++++++++----
 include/drm/drm_hdcp.h            |  1 +
 3 files changed, 68 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a38b9cff5cd0..b998479d89e7 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -485,6 +485,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 84ac23ea75af..1c75df1ccaf5 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -496,6 +496,7 @@ int intel_hdcp_auth_downstream(struct intel_connector 
*connector)
 {
        struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
        const struct intel_hdcp_shim *shim = connector->hdcp.shim;
+       struct intel_hdcp *hdcp = &connector->hdcp;
        struct drm_device *dev = connector->base.dev;
        u8 bstatus[2], num_downstream, *ksv_fifo;
        int ret, i, tries = 3;
@@ -527,6 +528,9 @@ int intel_hdcp_auth_downstream(struct intel_connector 
*connector)
        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;
@@ -540,6 +544,8 @@ int intel_hdcp_auth_downstream(struct intel_connector 
*connector)
                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.
@@ -642,15 +648,20 @@ static int intel_hdcp_auth(struct intel_connector 
*connector)
                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)
@@ -747,13 +758,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;
 
@@ -780,7 +796,11 @@ static int _intel_hdcp_enable(struct intel_connector 
*connector)
        for (i = 0; i < tries; i++) {
                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;
                }
 
@@ -1216,6 +1236,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.
@@ -1408,6 +1434,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);
@@ -1594,6 +1625,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;
        }
 
@@ -1601,12 +1638,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",
@@ -1617,8 +1658,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;
 }
 
@@ -1835,10 +1879,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;
@@ -1848,6 +1899,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 011f35e121a5..34836d42675b 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

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to