drm/i915: Extending HDCP for HSW, BDW and BXT+
authorRamalingam C <ramalingam.c@intel.com>
Thu, 18 Jan 2018 05:48:05 +0000 (11:18 +0530)
committerSean Paul <seanpaul@chromium.org>
Thu, 18 Jan 2018 22:28:49 +0000 (17:28 -0500)
This patch extends the Key load process and hdcp initialization for
few more capable intel platforms i.e. HSW, BDW and BXT+.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
[seanpaul fixed checkpatch issues]
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Link: https://patchwork.freedesktop.org/patch/msgid/1516254488-4971-2-git-send-email-ramalingam.c@intel.com
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_hdcp.c
drivers/gpu/drm/i915/intel_hdmi.c

index e5f7ef6..e3c6ca8 100644 (file)
@@ -8352,6 +8352,7 @@ enum skl_power_gate {
 #define HDCP_KEY_CONF          _MMIO(0x66c00)
 #define  HDCP_AKSV_SEND_TRIGGER                BIT(31)
 #define  HDCP_CLEAR_KEYS_TRIGGER       BIT(30)
+#define  HDCP_KEY_LOAD_TRIGGER         BIT(8)
 #define HDCP_KEY_STATUS                _MMIO(0x66c04)
 #define  HDCP_FUSE_IN_PROGRESS BIT(7)
 #define  HDCP_FUSE_ERROR               BIT(6)
index 0f2290c..9323b35 100644 (file)
@@ -6354,7 +6354,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 
        intel_dp_add_properties(intel_dp, connector);
 
-       if (INTEL_GEN(dev_priv) >= 9 && !intel_dp_is_edp(intel_dp)) {
+       if (is_hdcp_supported(dev_priv, port) && !intel_dp_is_edp(intel_dp)) {
                int ret = intel_hdcp_init(intel_connector, &intel_dp_hdcp_shim);
                if (ret)
                        DRM_DEBUG_KMS("HDCP init failed, skipping.\n");
index 731dc36..9461777 100644 (file)
@@ -1848,6 +1848,7 @@ int intel_hdcp_init(struct intel_connector *connector,
 int intel_hdcp_enable(struct intel_connector *connector);
 int intel_hdcp_disable(struct intel_connector *connector);
 int intel_hdcp_check_link(struct intel_connector *connector);
+bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
 
 /* intel_psr.c */
 void intel_psr_enable(struct intel_dp *intel_dp,
index 827cab2..e49ca7f 100644 (file)
@@ -49,13 +49,32 @@ static int intel_hdcp_load_keys(struct drm_i915_private *dev_priv)
        int ret;
        u32 val;
 
-       /* Initiate loading the HDCP key from fuses */
-       mutex_lock(&dev_priv->pcu_lock);
-       ret = sandybridge_pcode_write(dev_priv, SKL_PCODE_LOAD_HDCP_KEYS, 1);
-       mutex_unlock(&dev_priv->pcu_lock);
-       if (ret) {
-               DRM_ERROR("Failed to initiate HDCP key load (%d)\n", ret);
-               return ret;
+       /*
+        * On HSW and BDW HW loads the HDCP1.4 Key when Display comes
+        * out of reset. So if Key is not already loaded, its an error state.
+        */
+       if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
+               if (!(I915_READ(HDCP_KEY_STATUS) & HDCP_KEY_LOAD_DONE))
+                       return -ENXIO;
+
+       /*
+        * Initiate loading the HDCP key from fuses.
+        *
+        * BXT+ platforms, HDCP key needs to be loaded by SW. Only SKL and KBL
+        * differ in the key load trigger process from other platforms.
+        */
+       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+               mutex_lock(&dev_priv->pcu_lock);
+               ret = sandybridge_pcode_write(dev_priv,
+                                             SKL_PCODE_LOAD_HDCP_KEYS, 1);
+               mutex_unlock(&dev_priv->pcu_lock);
+               if (ret) {
+                       DRM_ERROR("Failed to initiate HDCP key load (%d)\n",
+                                 ret);
+                       return ret;
+               }
+       } else {
+               I915_WRITE(HDCP_KEY_CONF, HDCP_KEY_LOAD_TRIGGER);
        }
 
        /* Wait for the keys to load (500us) */
@@ -575,6 +594,13 @@ static void intel_hdcp_prop_work(struct work_struct *work)
        drm_modeset_unlock(&dev->mode_config.connection_mutex);
 }
 
+bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port)
+{
+       /* PORT E doesn't have HDCP, and PORT F is disabled */
+       return ((INTEL_GEN(dev_priv) >= 8 || IS_HASWELL(dev_priv)) &&
+               !IS_CHERRYVIEW(dev_priv) && port < PORT_E);
+}
+
 int intel_hdcp_init(struct intel_connector *connector,
                    const struct intel_hdcp_shim *hdcp_shim)
 {
index 09b52d2..b5a3882 100644 (file)
@@ -2296,8 +2296,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 
        intel_hdmi_add_properties(intel_hdmi, connector);
 
-       /* PORT E doesn't have HDCP, and PORT F is disabled */
-       if (INTEL_GEN(dev_priv) >= 9 && port < PORT_E) {
+       if (is_hdcp_supported(dev_priv, port)) {
                int ret = intel_hdcp_init(intel_connector,
                                          &intel_hdmi_hdcp_shim);
                if (ret)