hdcp_enable_work is extended to choose the better hdcp version based
on the system and panel capability.

And intel_hdcp_disable will find the version that is inforce, if any.
And corresponding version specific disable function alone called.

Signed-off-by: Ramalingam C <ramalinga...@intel.com>
---
 drivers/gpu/drm/i915/intel_hdcp.c | 112 ++++++++++++++++++++++++++++++++++----
 1 file changed, 100 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c 
b/drivers/gpu/drm/i915/intel_hdcp.c
index 69ae47eaff49..2fe73f7eb6dd 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -27,6 +27,43 @@ static int _intel_hdcp2_disable(struct intel_hdcp *hdcp);
 static void intel_hdcp2_check_work(struct work_struct *work);
 static int intel_hdcp2_check_link(struct intel_hdcp *hdcp);
 
+static inline bool intel_hdcp1_supported(struct intel_hdcp *hdcp)
+{
+       return (hdcp->plat_cap & HDCP_CAPABILITY &&
+               hdcp->panel_cap & HDCP_CAPABILITY);
+}
+
+static inline bool intel_hdcp2_supported(struct intel_hdcp *hdcp)
+{
+       return (hdcp->plat_cap & HDCP2_CAPABILITY &&
+               hdcp->panel_cap & HDCP2_CAPABILITY);
+}
+
+static inline bool intel_hdcp_in_force(struct intel_hdcp *hdcp)
+{
+       struct drm_i915_private *dev_priv = to_i915(hdcp->connector->base.dev);
+       enum port port = hdcp->connector->encoder->port;
+       u32 reg;
+
+       reg = I915_READ(PORT_HDCP_STATUS(port));
+       if (reg & HDCP_STATUS_AUTH || reg & HDCP_STATUS_ENC)
+               return true;
+       return false;
+
+}
+
+static inline bool intel_hdcp2_in_force(struct intel_hdcp *hdcp)
+{
+       struct drm_i915_private *dev_priv = to_i915(hdcp->connector->base.dev);
+       enum port port = hdcp->connector->encoder->port;
+       u32 reg;
+
+       reg = I915_READ(HDCP2_STATUS_DDI(port));
+       if (reg & LINK_ENCRYPTION_STATUS || reg & LINK_AUTH_STATUS)
+               return true;
+       return false;
+}
+
 static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
                                    const struct intel_hdcp_shim *shim)
 {
@@ -650,7 +687,11 @@ static void intel_hdcp_enable_work(struct work_struct 
*work)
                                               hdcp_enable_work);
 
        mutex_lock(&hdcp->hdcp_mutex);
-       _intel_hdcp_enable(hdcp);
+       if (intel_hdcp2_supported(hdcp))
+               _intel_hdcp2_enable(hdcp);
+       else if (intel_hdcp1_supported(hdcp))
+               _intel_hdcp_enable(hdcp);
+
        mutex_unlock(&hdcp->hdcp_mutex);
 }
 
@@ -727,13 +768,48 @@ int intel_hdcp_init(struct intel_connector *connector,
        return ret;
 }
 
+static void intel_hdcp_probe_panel_cap(struct intel_hdcp *hdcp)
+{
+       struct intel_digital_port *intel_dig_port =
+                                       conn_to_dig_port(hdcp->connector);
+       bool capable = false;
+       u8 bksv[5];
+
+       hdcp->panel_cap = 0;
+
+       if (hdcp->plat_cap & HDCP_CAPABILITY) {
+               if (hdcp->hdcp_shim->hdcp_capable) {
+                       hdcp->hdcp_shim->hdcp_capable(intel_dig_port, &capable);
+               } else {
+                       if (!intel_hdcp_read_valid_bksv(intel_dig_port,
+                                                       hdcp->hdcp_shim, bksv))
+                               capable = true;
+               }
+               if (capable)
+                       hdcp->panel_cap |= HDCP_CAPABILITY;
+       }
+
+       if (hdcp->plat_cap & HDCP2_CAPABILITY) {
+               hdcp->hdcp2_shim->hdcp_capable(intel_dig_port, &capable);
+               if (capable)
+                       hdcp->panel_cap |= HDCP2_CAPABILITY;
+       }
+       DRM_DEBUG_KMS("plat_cap: 0x%X, panel_cap: 0x%X\n",
+                     hdcp->plat_cap, hdcp->panel_cap);
+}
+
 int intel_hdcp_enable(struct intel_connector *connector)
 {
        struct intel_hdcp *hdcp = connector->hdcp;
 
-       if (!hdcp || !hdcp->hdcp_shim)
+       if (!hdcp)
                return -ENOENT;
 
+       intel_hdcp_probe_panel_cap(hdcp);
+
+       if (!intel_hdcp1_supported(hdcp) && !intel_hdcp2_supported(hdcp))
+               return -EINVAL;
+
        mutex_lock(&hdcp->hdcp_mutex);
        schedule_work(&hdcp->hdcp_enable_work);
        mutex_unlock(&hdcp->hdcp_mutex);
@@ -744,21 +820,33 @@ int intel_hdcp_enable(struct intel_connector *connector)
 int intel_hdcp_disable(struct intel_connector *connector)
 {
        struct intel_hdcp *hdcp = connector->hdcp;
-       int ret = 0;
 
-       if (!hdcp || !hdcp->hdcp_shim)
+       if (!hdcp)
                return -ENOENT;
 
-       mutex_lock(&hdcp->hdcp_mutex);
+       if (hdcp->hdcp_value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
+               return 0;
 
-       if (hdcp->hdcp_value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
-               hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
-               ret = _intel_hdcp_disable(hdcp);
-       }
+       /*
+        * Setting it out of mutex, so that other on going process like check
+        * link and auth can check for this state change and terminate themself.
+        */
+       hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+       cancel_work_sync(&hdcp->hdcp_enable_work);
 
-       mutex_unlock(&hdcp->hdcp_mutex);
        cancel_delayed_work_sync(&hdcp->hdcp_check_work);
-       return ret;
+       cancel_delayed_work_sync(&hdcp->hdcp2_check_work);
+
+       mutex_lock(&hdcp->hdcp_mutex);
+       if (hdcp->plat_cap & HDCP_CAPABILITY)
+               if (intel_hdcp_in_force(hdcp))
+                       _intel_hdcp_disable(hdcp);
+       if (hdcp->plat_cap & HDCP2_CAPABILITY)
+               if (intel_hdcp2_in_force(hdcp))
+                       _intel_hdcp2_disable(hdcp);
+       mutex_unlock(&hdcp->hdcp_mutex);
+
+       return 0;
 }
 
 void intel_hdcp_atomic_check(struct drm_connector *connector,
@@ -1437,7 +1525,7 @@ static int _intel_hdcp2_disable(struct intel_hdcp *hdcp)
 {
        int ret;
 
-       DRM_ERROR("[%s:%d] HDCP2.2 is being Disabled\n",
+       DRM_INFO("[%s:%d] HDCP2.2 is being Disabled\n",
                  hdcp->connector->base.name, hdcp->connector->base.base.id);
 
        ret = hdcp2_disable_encryption(hdcp);
-- 
2.7.4

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

Reply via email to