diff options
author | Ramalingam C <ramalingam.c@intel.com> | 2018-01-18 08:48:05 +0300 |
---|---|---|
committer | Sean Paul <seanpaul@chromium.org> | 2018-01-19 01:28:49 +0300 |
commit | fdddd08c4875db0799defd8cad318a68f564e7e5 (patch) | |
tree | 9aab7653509259ef312016392d4d2cff6803bc4b | |
parent | b7fc1a9b7e62dcae40d51e83390cbb678ae5c6c2 (diff) | |
download | linux-fdddd08c4875db0799defd8cad318a68f564e7e5.tar.xz |
drm/i915: Extending HDCP for HSW, BDW and BXT+
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
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdcp.c | 40 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 3 |
5 files changed, 37 insertions, 10 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e5f7ef636a8e..e3c6ca8ee6ad 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -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) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0f2290c7bede..9323b3541b1e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -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"); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 731dc36d7129..9461777d65b4 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -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, diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c index 827cab22f191..e49ca7fe893f 100644 --- a/drivers/gpu/drm/i915/intel_hdcp.c +++ b/drivers/gpu/drm/i915/intel_hdcp.c @@ -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) { diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 09b52d218fd4..b5a388208afa 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -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) |