Message ID | 20190709020927.15121-1-ramalingam.c@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v5] drm/i915: Enable HDCP 1.4 and 2.2 on Gen12+ | expand |
Regards Shashank On 7/9/2019 7:39 AM, Ramalingam C wrote: > From Gen12 onwards, HDCP HW block is implemented within transcoders. > Till Gen11 HDCP HW block was part of DDI. > > Hence required changes in HW programming is handled here. > > v2: > _MMIO_TRANS is used [Lucas and Daniel] > platform check is moved into the caller [Lucas] > v3: > platform check is moved into a macro [Shashank] > v4: > Few optimizations in the coding [Shashank] > v5: > Fixed alignment in macro definition in i915_reg.h [Shashank] > unused variables "reg" is removed. > > Signed-off-by: Ramalingam C <ramalingam.c@intel.com> > --- > drivers/gpu/drm/i915/display/intel_hdcp.c | 133 +++++++++++++--------- > drivers/gpu/drm/i915/display/intel_hdmi.c | 9 +- > drivers/gpu/drm/i915/i915_reg.h | 120 +++++++++++++++++-- > drivers/gpu/drm/i915/intel_drv.h | 8 ++ > 4 files changed, 207 insertions(+), 63 deletions(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c > index bc3a94d491c4..23dc3ad4ba4c 100644 > --- a/drivers/gpu/drm/i915/display/intel_hdcp.c > +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c > @@ -17,6 +17,7 @@ > #include "intel_drv.h" > #include "intel_hdcp.h" > #include "intel_sideband.h" > +#include "intel_connector.h" > > #define KEY_LOAD_TRIES 5 > #define ENCRYPT_STATUS_CHANGE_TIMEOUT_MS 50 > @@ -104,24 +105,17 @@ bool intel_hdcp2_capable(struct intel_connector *connector) > return capable; > } > > -static inline bool intel_hdcp_in_use(struct intel_connector *connector) > +static inline bool intel_hdcp_in_use(struct drm_i915_private *dev_priv, > + enum pipe pipe, enum port port) > { > - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); > - enum port port = connector->encoder->port; > - u32 reg; > - > - reg = I915_READ(PORT_HDCP_STATUS(port)); > - return reg & HDCP_STATUS_ENC; > + return I915_READ(HDCP_STATUS(dev_priv, pipe, port)) & HDCP_STATUS_ENC; > } > > -static inline bool intel_hdcp2_in_use(struct intel_connector *connector) > +static inline bool intel_hdcp2_in_use(struct drm_i915_private *dev_priv, > + enum pipe pipe, enum port port) > { > - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); > - enum port port = connector->encoder->port; > - u32 reg; > - > - reg = I915_READ(HDCP2_STATUS_DDI(port)); > - return reg & LINK_ENCRYPTION_STATUS; > + return I915_READ(HDCP2_STATUS(dev_priv, pipe, port)) & > + LINK_ENCRYPTION_STATUS; > } > > static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port, > @@ -253,9 +247,28 @@ static int intel_write_sha_text(struct drm_i915_private *dev_priv, u32 sha_text) > } > > static > -u32 intel_hdcp_get_repeater_ctl(struct intel_digital_port *intel_dig_port) > +u32 intel_hdcp_get_repeater_ctl(struct drm_i915_private *dev_priv, > + enum pipe pipe, enum port port) > { > - enum port port = intel_dig_port->base.port; > + if (INTEL_GEN(dev_priv) >= 12) { > + switch (pipe) { > + case PIPE_A: > + return HDCP_TRANSA_REP_PRESENT | > + HDCP_TRANSA_SHA1_M0; > + case PIPE_B: > + return HDCP_TRANSB_REP_PRESENT | > + HDCP_TRANSB_SHA1_M0; > + case PIPE_C: > + return HDCP_TRANSC_REP_PRESENT | > + HDCP_TRANSC_SHA1_M0; > + /* FIXME: Add a case for PIPE_D */ > + default: > + DRM_ERROR("Unknown pipe %d\n", pipe); > + break; > + } > + return -EINVAL; > + } > + > switch (port) { > case PORT_A: > return HDCP_DDIA_REP_PRESENT | HDCP_DDIA_SHA1_M0; > @@ -268,18 +281,21 @@ u32 intel_hdcp_get_repeater_ctl(struct intel_digital_port *intel_dig_port) > case PORT_E: > return HDCP_DDIE_REP_PRESENT | HDCP_DDIE_SHA1_M0; > default: > + DRM_ERROR("Unknown port %d\n", port); > break; > } > - DRM_ERROR("Unknown port %d\n", port); > return -EINVAL; > } > > static > -int intel_hdcp_validate_v_prime(struct intel_digital_port *intel_dig_port, > +int intel_hdcp_validate_v_prime(struct intel_connector *connector, > const struct intel_hdcp_shim *shim, > u8 *ksv_fifo, u8 num_downstream, u8 *bstatus) > { > + struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector); > struct drm_i915_private *dev_priv; > + enum pipe pipe = connector->hdcp.pipe; > + enum port port = intel_dig_port->base.port; > u32 vprime, sha_text, sha_leftovers, rep_ctl; > int ret, i, j, sha_idx; > > @@ -306,7 +322,7 @@ int intel_hdcp_validate_v_prime(struct intel_digital_port *intel_dig_port, > sha_idx = 0; > sha_text = 0; > sha_leftovers = 0; > - rep_ctl = intel_hdcp_get_repeater_ctl(intel_dig_port); > + rep_ctl = intel_hdcp_get_repeater_ctl(dev_priv, pipe, port); > I915_WRITE(HDCP_REP_CTL, rep_ctl | HDCP_SHA1_TEXT_32); > for (i = 0; i < num_downstream; i++) { > unsigned int sha_empty; > @@ -544,7 +560,7 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector) > * V prime atleast twice. > */ > for (i = 0; i < tries; i++) { > - ret = intel_hdcp_validate_v_prime(intel_dig_port, shim, > + ret = intel_hdcp_validate_v_prime(connector, shim, > ksv_fifo, num_downstream, > bstatus); > if (!ret) > @@ -572,6 +588,7 @@ static int intel_hdcp_auth(struct intel_connector *connector) > struct drm_device *dev = connector->base.dev; > const struct intel_hdcp_shim *shim = hdcp->shim; > struct drm_i915_private *dev_priv; > + enum pipe pipe = connector->hdcp.pipe; > enum port port; > unsigned long r0_prime_gen_start; > int ret, i, tries = 2; > @@ -611,19 +628,20 @@ static int intel_hdcp_auth(struct intel_connector *connector) > > /* Initialize An with 2 random values and acquire it */ > for (i = 0; i < 2; i++) > - I915_WRITE(PORT_HDCP_ANINIT(port), get_random_u32()); > - I915_WRITE(PORT_HDCP_CONF(port), HDCP_CONF_CAPTURE_AN); > + I915_WRITE(HDCP_ANINIT(dev_priv, pipe, port), get_random_u32()); > + I915_WRITE(HDCP_CONF(dev_priv, pipe, port), HDCP_CONF_CAPTURE_AN); > > /* Wait for An to be acquired */ > - if (intel_wait_for_register(&dev_priv->uncore, PORT_HDCP_STATUS(port), > + if (intel_wait_for_register(&dev_priv->uncore, > + HDCP_STATUS(dev_priv, pipe, port), > HDCP_STATUS_AN_READY, > HDCP_STATUS_AN_READY, 1)) { > DRM_ERROR("Timed out waiting for An\n"); > return -ETIMEDOUT; > } > > - an.reg[0] = I915_READ(PORT_HDCP_ANLO(port)); > - an.reg[1] = I915_READ(PORT_HDCP_ANHI(port)); > + an.reg[0] = I915_READ(HDCP_ANLO(dev_priv, pipe, port)); > + an.reg[1] = I915_READ(HDCP_ANHI(dev_priv, pipe, port)); > ret = shim->write_an_aksv(intel_dig_port, an.shim); > if (ret) > return ret; > @@ -641,24 +659,24 @@ static int intel_hdcp_auth(struct intel_connector *connector) > return -EPERM; > } > > - I915_WRITE(PORT_HDCP_BKSVLO(port), bksv.reg[0]); > - I915_WRITE(PORT_HDCP_BKSVHI(port), bksv.reg[1]); > + I915_WRITE(HDCP_BKSVLO(dev_priv, pipe, port), bksv.reg[0]); > + I915_WRITE(HDCP_BKSVHI(dev_priv, pipe, port), bksv.reg[1]); > > ret = shim->repeater_present(intel_dig_port, &repeater_present); > if (ret) > return ret; > if (repeater_present) > I915_WRITE(HDCP_REP_CTL, > - intel_hdcp_get_repeater_ctl(intel_dig_port)); > + intel_hdcp_get_repeater_ctl(dev_priv, pipe, port)); > > ret = shim->toggle_signalling(intel_dig_port, true); > if (ret) > return ret; > > - I915_WRITE(PORT_HDCP_CONF(port), HDCP_CONF_AUTH_AND_ENC); > + I915_WRITE(HDCP_CONF(dev_priv, pipe, port), HDCP_CONF_AUTH_AND_ENC); > > /* Wait for R0 ready */ > - if (wait_for(I915_READ(PORT_HDCP_STATUS(port)) & > + if (wait_for(I915_READ(HDCP_STATUS(dev_priv, pipe, port)) & > (HDCP_STATUS_R0_READY | HDCP_STATUS_ENC), 1)) { > DRM_ERROR("Timed out waiting for R0 ready\n"); > return -ETIMEDOUT; > @@ -686,22 +704,23 @@ static int intel_hdcp_auth(struct intel_connector *connector) > ret = shim->read_ri_prime(intel_dig_port, ri.shim); > if (ret) > return ret; > - I915_WRITE(PORT_HDCP_RPRIME(port), ri.reg); > + I915_WRITE(HDCP_RPRIME(dev_priv, pipe, port), ri.reg); > > /* Wait for Ri prime match */ > - if (!wait_for(I915_READ(PORT_HDCP_STATUS(port)) & > + if (!wait_for(I915_READ(HDCP_STATUS(dev_priv, pipe, port)) & > (HDCP_STATUS_RI_MATCH | HDCP_STATUS_ENC), 1)) > break; > } > > if (i == tries) { > DRM_DEBUG_KMS("Timed out waiting for Ri prime match (%x)\n", > - I915_READ(PORT_HDCP_STATUS(port))); > + I915_READ(HDCP_STATUS(dev_priv, pipe, port))); > return -ETIMEDOUT; > } > > /* Wait for encryption confirmation */ > - if (intel_wait_for_register(&dev_priv->uncore, PORT_HDCP_STATUS(port), > + if (intel_wait_for_register(&dev_priv->uncore, > + HDCP_STATUS(dev_priv, pipe, port), > HDCP_STATUS_ENC, HDCP_STATUS_ENC, > ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) { > DRM_ERROR("Timed out waiting for encryption\n"); > @@ -726,15 +745,16 @@ static int _intel_hdcp_disable(struct intel_connector *connector) > struct drm_i915_private *dev_priv = connector->base.dev->dev_private; > struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector); > enum port port = intel_dig_port->base.port; > + enum pipe pipe = hdcp->pipe; > int ret; > > DRM_DEBUG_KMS("[%s:%d] HDCP is being disabled...\n", > connector->base.name, connector->base.base.id); > > hdcp->hdcp_encrypted = false; > - I915_WRITE(PORT_HDCP_CONF(port), 0); > + I915_WRITE(HDCP_CONF(dev_priv, pipe, port), 0); > if (intel_wait_for_register(&dev_priv->uncore, > - PORT_HDCP_STATUS(port), ~0, 0, > + HDCP_STATUS(dev_priv, pipe, port), ~0, 0, > ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) { > DRM_ERROR("Failed to disable HDCP, timeout clearing status\n"); > return -ETIMEDOUT; > @@ -806,9 +826,11 @@ static int intel_hdcp_check_link(struct intel_connector *connector) > struct drm_i915_private *dev_priv = connector->base.dev->dev_private; > struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector); > enum port port = intel_dig_port->base.port; > + enum pipe pipe; > int ret = 0; > > mutex_lock(&hdcp->mutex); > + pipe = hdcp->pipe; > > /* Check_link valid only when HDCP1.4 is enabled */ > if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_ENABLED || > @@ -817,10 +839,10 @@ static int intel_hdcp_check_link(struct intel_connector *connector) > goto out; > } > > - if (WARN_ON(!intel_hdcp_in_use(connector))) { > + if (WARN_ON(!intel_hdcp_in_use(dev_priv, pipe, port))) { > DRM_ERROR("%s:%d HDCP link stopped encryption,%x\n", > connector->base.name, connector->base.base.id, > - I915_READ(PORT_HDCP_STATUS(port))); > + I915_READ(HDCP_STATUS(dev_priv, pipe, port))); > ret = -ENXIO; > hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED; > schedule_work(&hdcp->prop_work); > @@ -1491,10 +1513,11 @@ static int hdcp2_enable_encryption(struct intel_connector *connector) > struct drm_i915_private *dev_priv = to_i915(connector->base.dev); > struct intel_hdcp *hdcp = &connector->hdcp; > enum port port = connector->encoder->port; > + enum pipe pipe = hdcp->pipe; > int ret; > > - WARN_ON(I915_READ(HDCP2_STATUS_DDI(port)) & LINK_ENCRYPTION_STATUS); > - > + WARN_ON(I915_READ(HDCP2_STATUS(dev_priv, pipe, port)) & > + LINK_ENCRYPTION_STATUS); > if (hdcp->shim->toggle_signalling) { > ret = hdcp->shim->toggle_signalling(intel_dig_port, true); > if (ret) { > @@ -1504,14 +1527,15 @@ static int hdcp2_enable_encryption(struct intel_connector *connector) > } > } > > - if (I915_READ(HDCP2_STATUS_DDI(port)) & LINK_AUTH_STATUS) { > + if (I915_READ(HDCP2_STATUS(dev_priv, pipe, port)) & LINK_AUTH_STATUS) { > /* Link is Authenticated. Now set for Encryption */ > - I915_WRITE(HDCP2_CTL_DDI(port), > - I915_READ(HDCP2_CTL_DDI(port)) | > + I915_WRITE(HDCP2_CTL(dev_priv, pipe, port), > + I915_READ(HDCP2_CTL(dev_priv, pipe, port)) | > CTL_LINK_ENCRYPTION_REQ); > } > > - ret = intel_wait_for_register(&dev_priv->uncore, HDCP2_STATUS_DDI(port), > + ret = intel_wait_for_register(&dev_priv->uncore, > + HDCP2_STATUS(dev_priv, pipe, port), > LINK_ENCRYPTION_STATUS, > LINK_ENCRYPTION_STATUS, > ENCRYPT_STATUS_CHANGE_TIMEOUT_MS); > @@ -1525,14 +1549,17 @@ static int hdcp2_disable_encryption(struct intel_connector *connector) > struct drm_i915_private *dev_priv = to_i915(connector->base.dev); > struct intel_hdcp *hdcp = &connector->hdcp; > enum port port = connector->encoder->port; > + enum pipe pipe = hdcp->pipe; > int ret; > > - WARN_ON(!(I915_READ(HDCP2_STATUS_DDI(port)) & LINK_ENCRYPTION_STATUS)); > + WARN_ON(!(I915_READ(HDCP2_STATUS(dev_priv, pipe, port)) & > + LINK_ENCRYPTION_STATUS)); > + I915_WRITE(HDCP2_CTL(dev_priv, pipe, port), > + I915_READ(HDCP2_CTL(dev_priv, pipe, port)) & > + ~CTL_LINK_ENCRYPTION_REQ); > > - I915_WRITE(HDCP2_CTL_DDI(port), > - I915_READ(HDCP2_CTL_DDI(port)) & ~CTL_LINK_ENCRYPTION_REQ); > - > - ret = intel_wait_for_register(&dev_priv->uncore, HDCP2_STATUS_DDI(port), > + ret = intel_wait_for_register(&dev_priv->uncore, > + HDCP2_STATUS(dev_priv, pipe, port), > LINK_ENCRYPTION_STATUS, 0x0, > ENCRYPT_STATUS_CHANGE_TIMEOUT_MS); > if (ret == -ETIMEDOUT) > @@ -1631,9 +1658,11 @@ static int intel_hdcp2_check_link(struct intel_connector *connector) > struct drm_i915_private *dev_priv = to_i915(connector->base.dev); > struct intel_hdcp *hdcp = &connector->hdcp; > enum port port = connector->encoder->port; > + enum pipe pipe; > int ret = 0; > > mutex_lock(&hdcp->mutex); > + pipe = hdcp->pipe; > > /* hdcp2_check_link is expected only when HDCP2.2 is Enabled */ > if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_ENABLED || > @@ -1642,9 +1671,9 @@ static int intel_hdcp2_check_link(struct intel_connector *connector) > goto out; > } > > - if (WARN_ON(!intel_hdcp2_in_use(connector))) { > + if (WARN_ON(!intel_hdcp2_in_use(dev_priv, pipe, port))) { > DRM_ERROR("HDCP2.2 link stopped the encryption, %x\n", > - I915_READ(HDCP2_STATUS_DDI(port))); > + I915_READ(HDCP2_STATUS(dev_priv, pipe, port))); > ret = -ENXIO; > hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED; > schedule_work(&hdcp->prop_work); > @@ -1857,6 +1886,8 @@ int intel_hdcp_enable(struct intel_connector *connector) > mutex_lock(&hdcp->mutex); > WARN_ON(hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED); > > + hdcp->pipe = intel_connector_get_pipe(connector); > + > /* > * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup > * is capable of HDCP2.2, it is preferred to use HDCP2.2. > diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c > index 0ebec69bbbfc..2096aee174b2 100644 > --- a/drivers/gpu/drm/i915/display/intel_hdmi.c > +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c > @@ -1491,7 +1491,10 @@ bool intel_hdmi_hdcp_check_link(struct intel_digital_port *intel_dig_port) > { > struct drm_i915_private *dev_priv = > intel_dig_port->base.base.dev->dev_private; > + struct intel_connector *connector = > + intel_dig_port->hdmi.attached_connector; This line should be align as above one, with this comment fixed, please feel free to use: Reviewed-by: Shashank Sharma <shashank.sharma@intel.com> Regards Shashank > enum port port = intel_dig_port->base.port; > + enum pipe pipe = connector->hdcp.pipe; > int ret; > union { > u32 reg; > @@ -1502,13 +1505,13 @@ bool intel_hdmi_hdcp_check_link(struct intel_digital_port *intel_dig_port) > if (ret) > return false; > > - I915_WRITE(PORT_HDCP_RPRIME(port), ri.reg); > + I915_WRITE(HDCP_RPRIME(dev_priv, pipe, port), ri.reg); > > /* Wait for Ri prime match */ > - if (wait_for(I915_READ(PORT_HDCP_STATUS(port)) & > + if (wait_for(I915_READ(HDCP_STATUS(dev_priv, pipe, port)) & > (HDCP_STATUS_RI_MATCH | HDCP_STATUS_ENC), 1)) { > DRM_ERROR("Ri' mismatch detected, link check failed (%x)\n", > - I915_READ(PORT_HDCP_STATUS(port))); > + I915_READ(HDCP_STATUS(dev_priv, pipe, port))); > return false; > } > return true; > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index 5898f59e3dd7..3ea03433f4f4 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -9244,12 +9244,20 @@ enum skl_power_gate { > > /* HDCP Repeater Registers */ > #define HDCP_REP_CTL _MMIO(0x66d00) > +#define HDCP_TRANSA_REP_PRESENT BIT(31) > +#define HDCP_TRANSB_REP_PRESENT BIT(30) > +#define HDCP_TRANSC_REP_PRESENT BIT(29) > +#define HDCP_TRANSD_REP_PRESENT BIT(28) > #define HDCP_DDIB_REP_PRESENT BIT(30) > #define HDCP_DDIA_REP_PRESENT BIT(29) > #define HDCP_DDIC_REP_PRESENT BIT(28) > #define HDCP_DDID_REP_PRESENT BIT(27) > #define HDCP_DDIF_REP_PRESENT BIT(26) > #define HDCP_DDIE_REP_PRESENT BIT(25) > +#define HDCP_TRANSA_SHA1_M0 (1 << 20) > +#define HDCP_TRANSB_SHA1_M0 (2 << 20) > +#define HDCP_TRANSC_SHA1_M0 (3 << 20) > +#define HDCP_TRANSD_SHA1_M0 (4 << 20) > #define HDCP_DDIB_SHA1_M0 (1 << 20) > #define HDCP_DDIA_SHA1_M0 (2 << 20) > #define HDCP_DDIC_SHA1_M0 (3 << 20) > @@ -9289,15 +9297,89 @@ enum skl_power_gate { > _PORTE_HDCP_AUTHENC, \ > _PORTF_HDCP_AUTHENC) + (x)) > #define PORT_HDCP_CONF(port) _PORT_HDCP_AUTHENC(port, 0x0) > +#define _TRANSA_HDCP_CONF 0x66400 > +#define _TRANSB_HDCP_CONF 0x66500 > +#define TRANS_HDCP_CONF(trans) _MMIO_TRANS(trans, _TRANSA_HDCP_CONF, \ > + _TRANSB_HDCP_CONF) > +#define HDCP_CONF(dev_priv, pipe, port) (INTEL_GEN(dev_priv) >= 12 ? \ > + TRANS_HDCP_CONF(pipe) : \ > + PORT_HDCP_CONF(port)) > + > #define HDCP_CONF_CAPTURE_AN BIT(0) > #define HDCP_CONF_AUTH_AND_ENC (BIT(1) | BIT(0)) > #define PORT_HDCP_ANINIT(port) _PORT_HDCP_AUTHENC(port, 0x4) > +#define _TRANSA_HDCP_ANINIT 0x66404 > +#define _TRANSB_HDCP_ANINIT 0x66504 > +#define TRANS_HDCP_ANINIT(trans) _MMIO_TRANS(trans, \ > + _TRANSA_HDCP_ANINIT, \ > + _TRANSB_HDCP_ANINIT) > +#define HDCP_ANINIT(dev_priv, pipe, port) \ > + (INTEL_GEN(dev_priv) >= 12 ? \ > + TRANS_HDCP_ANINIT(pipe) : \ > + PORT_HDCP_ANINIT(port)) > + > #define PORT_HDCP_ANLO(port) _PORT_HDCP_AUTHENC(port, 0x8) > +#define _TRANSA_HDCP_ANLO 0x66408 > +#define _TRANSB_HDCP_ANLO 0x66508 > +#define TRANS_HDCP_ANLO(trans) _MMIO_TRANS(trans, _TRANSA_HDCP_ANLO, \ > + _TRANSB_HDCP_ANLO) > +#define HDCP_ANLO(dev_priv, pipe, port) (INTEL_GEN(dev_priv) >= 12 ? \ > + TRANS_HDCP_ANLO(pipe) : \ > + PORT_HDCP_ANLO(port)) > + > #define PORT_HDCP_ANHI(port) _PORT_HDCP_AUTHENC(port, 0xC) > +#define _TRANSA_HDCP_ANHI 0x6640C > +#define _TRANSB_HDCP_ANHI 0x6650C > +#define TRANS_HDCP_ANHI(trans) _MMIO_TRANS(trans, _TRANSA_HDCP_ANHI, \ > + _TRANSB_HDCP_ANHI) > +#define HDCP_ANHI(dev_priv, pipe, port) (INTEL_GEN(dev_priv) >= 12 ? \ > + TRANS_HDCP_ANHI(pipe) : \ > + PORT_HDCP_ANHI(port)) > + > #define PORT_HDCP_BKSVLO(port) _PORT_HDCP_AUTHENC(port, 0x10) > +#define _TRANSA_HDCP_BKSVLO 0x66410 > +#define _TRANSB_HDCP_BKSVLO 0x66510 > +#define TRANS_HDCP_BKSVLO(trans) _MMIO_TRANS(trans, \ > + _TRANSA_HDCP_BKSVLO, \ > + _TRANSB_HDCP_BKSVLO) > +#define HDCP_BKSVLO(dev_priv, pipe, port) \ > + (INTEL_GEN(dev_priv) >= 12 ? \ > + TRANS_HDCP_BKSVLO(pipe) : \ > + PORT_HDCP_BKSVLO(port)) > + > #define PORT_HDCP_BKSVHI(port) _PORT_HDCP_AUTHENC(port, 0x14) > +#define _TRANSA_HDCP_BKSVHI 0x66414 > +#define _TRANSB_HDCP_BKSVHI 0x66514 > +#define TRANS_HDCP_BKSVHI(trans) _MMIO_TRANS(trans, \ > + _TRANSA_HDCP_BKSVHI, \ > + _TRANSB_HDCP_BKSVHI) > +#define HDCP_BKSVHI(dev_priv, pipe, port) \ > + (INTEL_GEN(dev_priv) >= 12 ? \ > + TRANS_HDCP_BKSVHI(pipe) : \ > + PORT_HDCP_BKSVHI(port)) > + > #define PORT_HDCP_RPRIME(port) _PORT_HDCP_AUTHENC(port, 0x18) > +#define _TRANSA_HDCP_RPRIME 0x66418 > +#define _TRANSB_HDCP_RPRIME 0x66518 > +#define TRANS_HDCP_RPRIME(trans) _MMIO_TRANS(trans, \ > + _TRANSA_HDCP_RPRIME, \ > + _TRANSB_HDCP_RPRIME) > +#define HDCP_RPRIME(dev_priv, pipe, port) \ > + (INTEL_GEN(dev_priv) >= 12 ? \ > + TRANS_HDCP_RPRIME(pipe) : \ > + PORT_HDCP_RPRIME(port)) > + > #define PORT_HDCP_STATUS(port) _PORT_HDCP_AUTHENC(port, 0x1C) > +#define _TRANSA_HDCP_STATUS 0x6641C > +#define _TRANSB_HDCP_STATUS 0x6651C > +#define TRANS_HDCP_STATUS(trans) _MMIO_TRANS(trans, \ > + _TRANSA_HDCP_STATUS, \ > + _TRANSB_HDCP_STATUS) > +#define HDCP_STATUS(dev_priv, pipe, port) \ > + (INTEL_GEN(dev_priv) >= 12 ? \ > + TRANS_HDCP_STATUS(pipe) : \ > + PORT_HDCP_STATUS(port)) > + > #define HDCP_STATUS_STREAM_A_ENC BIT(31) > #define HDCP_STATUS_STREAM_B_ENC BIT(30) > #define HDCP_STATUS_STREAM_C_ENC BIT(29) > @@ -9324,23 +9406,43 @@ enum skl_power_gate { > _PORTD_HDCP2_BASE, \ > _PORTE_HDCP2_BASE, \ > _PORTF_HDCP2_BASE) + (x)) > - > -#define HDCP2_AUTH_DDI(port) _PORT_HDCP2_BASE(port, 0x98) > +#define PORT_HDCP2_AUTH(port) _PORT_HDCP2_BASE(port, 0x98) > +#define _TRANSA_HDCP2_AUTH 0x66498 > +#define _TRANSB_HDCP2_AUTH 0x66598 > +#define TRANS_HDCP2_AUTH(trans) _MMIO_TRANS(trans, _TRANSA_HDCP2_AUTH, \ > + _TRANSB_HDCP2_AUTH) > #define AUTH_LINK_AUTHENTICATED BIT(31) > #define AUTH_LINK_TYPE BIT(30) > #define AUTH_FORCE_CLR_INPUTCTR BIT(19) > #define AUTH_CLR_KEYS BIT(18) > - > -#define HDCP2_CTL_DDI(port) _PORT_HDCP2_BASE(port, 0xB0) > +#define HDCP2_AUTH(dev_priv, pipe, port) \ > + (INTEL_GEN(dev_priv) >= 12 ? \ > + TRANS_HDCP2_AUTH(pipe) : \ > + PORT_HDCP2_AUTH(port)) > + > +#define PORT_HDCP2_CTL(port) _PORT_HDCP2_BASE(port, 0xB0) > +#define _TRANSA_HDCP2_CTL 0x664B0 > +#define _TRANSB_HDCP2_CTL 0x665B0 > +#define TRANS_HDCP2_CTL(trans) _MMIO_TRANS(trans, _TRANSA_HDCP2_CTL, \ > + _TRANSB_HDCP2_CTL) > #define CTL_LINK_ENCRYPTION_REQ BIT(31) > - > -#define HDCP2_STATUS_DDI(port) _PORT_HDCP2_BASE(port, 0xB4) > -#define STREAM_ENCRYPTION_STATUS_A BIT(31) > -#define STREAM_ENCRYPTION_STATUS_B BIT(30) > -#define STREAM_ENCRYPTION_STATUS_C BIT(29) > +#define HDCP2_CTL(dev_priv, pipe, port) (INTEL_GEN(dev_priv) >= 12 ? \ > + TRANS_HDCP2_CTL(pipe) : \ > + PORT_HDCP2_CTL(port)) > + > +#define PORT_HDCP2_STATUS(port) _PORT_HDCP2_BASE(port, 0xB4) > +#define _TRANSA_HDCP2_STATUS 0x664B4 > +#define _TRANSB_HDCP2_STATUS 0x665B4 > +#define TRANS_HDCP2_STATUS(trans) _MMIO_TRANS(trans, \ > + _TRANSA_HDCP2_STATUS, \ > + _TRANSB_HDCP2_STATUS) > #define LINK_TYPE_STATUS BIT(22) > #define LINK_AUTH_STATUS BIT(21) > #define LINK_ENCRYPTION_STATUS BIT(20) > +#define HDCP2_STATUS(dev_priv, pipe, port) \ > + (INTEL_GEN(dev_priv) >= 12 ? \ > + TRANS_HDCP2_STATUS(pipe) : \ > + PORT_HDCP2_STATUS(port)) > > /* Per-pipe DDI Function Control */ > #define _TRANS_DDI_FUNC_CTL_A 0x60400 > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index 24c63ed45c6f..741fa21c3e57 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -365,6 +365,14 @@ struct intel_hdcp { > wait_queue_head_t cp_irq_queue; > atomic_t cp_irq_count; > int cp_irq_count_cached; > + > + /* > + * Gen 12 onwards, HDCP is part of transcoder(previously DDI). > + * So chacheing the pipe associated to connector at hdcp_enable > + * would help in subsequent functions to derive the right offsets > + * for HDCP registers. > + */ > + enum pipe pipe; > }; > > struct intel_connector {
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index bc3a94d491c4..23dc3ad4ba4c 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -17,6 +17,7 @@ #include "intel_drv.h" #include "intel_hdcp.h" #include "intel_sideband.h" +#include "intel_connector.h" #define KEY_LOAD_TRIES 5 #define ENCRYPT_STATUS_CHANGE_TIMEOUT_MS 50 @@ -104,24 +105,17 @@ bool intel_hdcp2_capable(struct intel_connector *connector) return capable; } -static inline bool intel_hdcp_in_use(struct intel_connector *connector) +static inline bool intel_hdcp_in_use(struct drm_i915_private *dev_priv, + enum pipe pipe, enum port port) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - enum port port = connector->encoder->port; - u32 reg; - - reg = I915_READ(PORT_HDCP_STATUS(port)); - return reg & HDCP_STATUS_ENC; + return I915_READ(HDCP_STATUS(dev_priv, pipe, port)) & HDCP_STATUS_ENC; } -static inline bool intel_hdcp2_in_use(struct intel_connector *connector) +static inline bool intel_hdcp2_in_use(struct drm_i915_private *dev_priv, + enum pipe pipe, enum port port) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - enum port port = connector->encoder->port; - u32 reg; - - reg = I915_READ(HDCP2_STATUS_DDI(port)); - return reg & LINK_ENCRYPTION_STATUS; + return I915_READ(HDCP2_STATUS(dev_priv, pipe, port)) & + LINK_ENCRYPTION_STATUS; } static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port, @@ -253,9 +247,28 @@ static int intel_write_sha_text(struct drm_i915_private *dev_priv, u32 sha_text) } static -u32 intel_hdcp_get_repeater_ctl(struct intel_digital_port *intel_dig_port) +u32 intel_hdcp_get_repeater_ctl(struct drm_i915_private *dev_priv, + enum pipe pipe, enum port port) { - enum port port = intel_dig_port->base.port; + if (INTEL_GEN(dev_priv) >= 12) { + switch (pipe) { + case PIPE_A: + return HDCP_TRANSA_REP_PRESENT | + HDCP_TRANSA_SHA1_M0; + case PIPE_B: + return HDCP_TRANSB_REP_PRESENT | + HDCP_TRANSB_SHA1_M0; + case PIPE_C: + return HDCP_TRANSC_REP_PRESENT | + HDCP_TRANSC_SHA1_M0; + /* FIXME: Add a case for PIPE_D */ + default: + DRM_ERROR("Unknown pipe %d\n", pipe); + break; + } + return -EINVAL; + } + switch (port) { case PORT_A: return HDCP_DDIA_REP_PRESENT | HDCP_DDIA_SHA1_M0; @@ -268,18 +281,21 @@ u32 intel_hdcp_get_repeater_ctl(struct intel_digital_port *intel_dig_port) case PORT_E: return HDCP_DDIE_REP_PRESENT | HDCP_DDIE_SHA1_M0; default: + DRM_ERROR("Unknown port %d\n", port); break; } - DRM_ERROR("Unknown port %d\n", port); return -EINVAL; } static -int intel_hdcp_validate_v_prime(struct intel_digital_port *intel_dig_port, +int intel_hdcp_validate_v_prime(struct intel_connector *connector, const struct intel_hdcp_shim *shim, u8 *ksv_fifo, u8 num_downstream, u8 *bstatus) { + struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector); struct drm_i915_private *dev_priv; + enum pipe pipe = connector->hdcp.pipe; + enum port port = intel_dig_port->base.port; u32 vprime, sha_text, sha_leftovers, rep_ctl; int ret, i, j, sha_idx; @@ -306,7 +322,7 @@ int intel_hdcp_validate_v_prime(struct intel_digital_port *intel_dig_port, sha_idx = 0; sha_text = 0; sha_leftovers = 0; - rep_ctl = intel_hdcp_get_repeater_ctl(intel_dig_port); + rep_ctl = intel_hdcp_get_repeater_ctl(dev_priv, pipe, port); I915_WRITE(HDCP_REP_CTL, rep_ctl | HDCP_SHA1_TEXT_32); for (i = 0; i < num_downstream; i++) { unsigned int sha_empty; @@ -544,7 +560,7 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector) * V prime atleast twice. */ for (i = 0; i < tries; i++) { - ret = intel_hdcp_validate_v_prime(intel_dig_port, shim, + ret = intel_hdcp_validate_v_prime(connector, shim, ksv_fifo, num_downstream, bstatus); if (!ret) @@ -572,6 +588,7 @@ static int intel_hdcp_auth(struct intel_connector *connector) struct drm_device *dev = connector->base.dev; const struct intel_hdcp_shim *shim = hdcp->shim; struct drm_i915_private *dev_priv; + enum pipe pipe = connector->hdcp.pipe; enum port port; unsigned long r0_prime_gen_start; int ret, i, tries = 2; @@ -611,19 +628,20 @@ static int intel_hdcp_auth(struct intel_connector *connector) /* Initialize An with 2 random values and acquire it */ for (i = 0; i < 2; i++) - I915_WRITE(PORT_HDCP_ANINIT(port), get_random_u32()); - I915_WRITE(PORT_HDCP_CONF(port), HDCP_CONF_CAPTURE_AN); + I915_WRITE(HDCP_ANINIT(dev_priv, pipe, port), get_random_u32()); + I915_WRITE(HDCP_CONF(dev_priv, pipe, port), HDCP_CONF_CAPTURE_AN); /* Wait for An to be acquired */ - if (intel_wait_for_register(&dev_priv->uncore, PORT_HDCP_STATUS(port), + if (intel_wait_for_register(&dev_priv->uncore, + HDCP_STATUS(dev_priv, pipe, port), HDCP_STATUS_AN_READY, HDCP_STATUS_AN_READY, 1)) { DRM_ERROR("Timed out waiting for An\n"); return -ETIMEDOUT; } - an.reg[0] = I915_READ(PORT_HDCP_ANLO(port)); - an.reg[1] = I915_READ(PORT_HDCP_ANHI(port)); + an.reg[0] = I915_READ(HDCP_ANLO(dev_priv, pipe, port)); + an.reg[1] = I915_READ(HDCP_ANHI(dev_priv, pipe, port)); ret = shim->write_an_aksv(intel_dig_port, an.shim); if (ret) return ret; @@ -641,24 +659,24 @@ static int intel_hdcp_auth(struct intel_connector *connector) return -EPERM; } - I915_WRITE(PORT_HDCP_BKSVLO(port), bksv.reg[0]); - I915_WRITE(PORT_HDCP_BKSVHI(port), bksv.reg[1]); + I915_WRITE(HDCP_BKSVLO(dev_priv, pipe, port), bksv.reg[0]); + I915_WRITE(HDCP_BKSVHI(dev_priv, pipe, port), bksv.reg[1]); ret = shim->repeater_present(intel_dig_port, &repeater_present); if (ret) return ret; if (repeater_present) I915_WRITE(HDCP_REP_CTL, - intel_hdcp_get_repeater_ctl(intel_dig_port)); + intel_hdcp_get_repeater_ctl(dev_priv, pipe, port)); ret = shim->toggle_signalling(intel_dig_port, true); if (ret) return ret; - I915_WRITE(PORT_HDCP_CONF(port), HDCP_CONF_AUTH_AND_ENC); + I915_WRITE(HDCP_CONF(dev_priv, pipe, port), HDCP_CONF_AUTH_AND_ENC); /* Wait for R0 ready */ - if (wait_for(I915_READ(PORT_HDCP_STATUS(port)) & + if (wait_for(I915_READ(HDCP_STATUS(dev_priv, pipe, port)) & (HDCP_STATUS_R0_READY | HDCP_STATUS_ENC), 1)) { DRM_ERROR("Timed out waiting for R0 ready\n"); return -ETIMEDOUT; @@ -686,22 +704,23 @@ static int intel_hdcp_auth(struct intel_connector *connector) ret = shim->read_ri_prime(intel_dig_port, ri.shim); if (ret) return ret; - I915_WRITE(PORT_HDCP_RPRIME(port), ri.reg); + I915_WRITE(HDCP_RPRIME(dev_priv, pipe, port), ri.reg); /* Wait for Ri prime match */ - if (!wait_for(I915_READ(PORT_HDCP_STATUS(port)) & + if (!wait_for(I915_READ(HDCP_STATUS(dev_priv, pipe, port)) & (HDCP_STATUS_RI_MATCH | HDCP_STATUS_ENC), 1)) break; } if (i == tries) { DRM_DEBUG_KMS("Timed out waiting for Ri prime match (%x)\n", - I915_READ(PORT_HDCP_STATUS(port))); + I915_READ(HDCP_STATUS(dev_priv, pipe, port))); return -ETIMEDOUT; } /* Wait for encryption confirmation */ - if (intel_wait_for_register(&dev_priv->uncore, PORT_HDCP_STATUS(port), + if (intel_wait_for_register(&dev_priv->uncore, + HDCP_STATUS(dev_priv, pipe, port), HDCP_STATUS_ENC, HDCP_STATUS_ENC, ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) { DRM_ERROR("Timed out waiting for encryption\n"); @@ -726,15 +745,16 @@ static int _intel_hdcp_disable(struct intel_connector *connector) struct drm_i915_private *dev_priv = connector->base.dev->dev_private; struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector); enum port port = intel_dig_port->base.port; + enum pipe pipe = hdcp->pipe; int ret; DRM_DEBUG_KMS("[%s:%d] HDCP is being disabled...\n", connector->base.name, connector->base.base.id); hdcp->hdcp_encrypted = false; - I915_WRITE(PORT_HDCP_CONF(port), 0); + I915_WRITE(HDCP_CONF(dev_priv, pipe, port), 0); if (intel_wait_for_register(&dev_priv->uncore, - PORT_HDCP_STATUS(port), ~0, 0, + HDCP_STATUS(dev_priv, pipe, port), ~0, 0, ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) { DRM_ERROR("Failed to disable HDCP, timeout clearing status\n"); return -ETIMEDOUT; @@ -806,9 +826,11 @@ static int intel_hdcp_check_link(struct intel_connector *connector) struct drm_i915_private *dev_priv = connector->base.dev->dev_private; struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector); enum port port = intel_dig_port->base.port; + enum pipe pipe; int ret = 0; mutex_lock(&hdcp->mutex); + pipe = hdcp->pipe; /* Check_link valid only when HDCP1.4 is enabled */ if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_ENABLED || @@ -817,10 +839,10 @@ static int intel_hdcp_check_link(struct intel_connector *connector) goto out; } - if (WARN_ON(!intel_hdcp_in_use(connector))) { + if (WARN_ON(!intel_hdcp_in_use(dev_priv, pipe, port))) { DRM_ERROR("%s:%d HDCP link stopped encryption,%x\n", connector->base.name, connector->base.base.id, - I915_READ(PORT_HDCP_STATUS(port))); + I915_READ(HDCP_STATUS(dev_priv, pipe, port))); ret = -ENXIO; hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED; schedule_work(&hdcp->prop_work); @@ -1491,10 +1513,11 @@ static int hdcp2_enable_encryption(struct intel_connector *connector) struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; enum port port = connector->encoder->port; + enum pipe pipe = hdcp->pipe; int ret; - WARN_ON(I915_READ(HDCP2_STATUS_DDI(port)) & LINK_ENCRYPTION_STATUS); - + WARN_ON(I915_READ(HDCP2_STATUS(dev_priv, pipe, port)) & + LINK_ENCRYPTION_STATUS); if (hdcp->shim->toggle_signalling) { ret = hdcp->shim->toggle_signalling(intel_dig_port, true); if (ret) { @@ -1504,14 +1527,15 @@ static int hdcp2_enable_encryption(struct intel_connector *connector) } } - if (I915_READ(HDCP2_STATUS_DDI(port)) & LINK_AUTH_STATUS) { + if (I915_READ(HDCP2_STATUS(dev_priv, pipe, port)) & LINK_AUTH_STATUS) { /* Link is Authenticated. Now set for Encryption */ - I915_WRITE(HDCP2_CTL_DDI(port), - I915_READ(HDCP2_CTL_DDI(port)) | + I915_WRITE(HDCP2_CTL(dev_priv, pipe, port), + I915_READ(HDCP2_CTL(dev_priv, pipe, port)) | CTL_LINK_ENCRYPTION_REQ); } - ret = intel_wait_for_register(&dev_priv->uncore, HDCP2_STATUS_DDI(port), + ret = intel_wait_for_register(&dev_priv->uncore, + HDCP2_STATUS(dev_priv, pipe, port), LINK_ENCRYPTION_STATUS, LINK_ENCRYPTION_STATUS, ENCRYPT_STATUS_CHANGE_TIMEOUT_MS); @@ -1525,14 +1549,17 @@ static int hdcp2_disable_encryption(struct intel_connector *connector) struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; enum port port = connector->encoder->port; + enum pipe pipe = hdcp->pipe; int ret; - WARN_ON(!(I915_READ(HDCP2_STATUS_DDI(port)) & LINK_ENCRYPTION_STATUS)); + WARN_ON(!(I915_READ(HDCP2_STATUS(dev_priv, pipe, port)) & + LINK_ENCRYPTION_STATUS)); + I915_WRITE(HDCP2_CTL(dev_priv, pipe, port), + I915_READ(HDCP2_CTL(dev_priv, pipe, port)) & + ~CTL_LINK_ENCRYPTION_REQ); - I915_WRITE(HDCP2_CTL_DDI(port), - I915_READ(HDCP2_CTL_DDI(port)) & ~CTL_LINK_ENCRYPTION_REQ); - - ret = intel_wait_for_register(&dev_priv->uncore, HDCP2_STATUS_DDI(port), + ret = intel_wait_for_register(&dev_priv->uncore, + HDCP2_STATUS(dev_priv, pipe, port), LINK_ENCRYPTION_STATUS, 0x0, ENCRYPT_STATUS_CHANGE_TIMEOUT_MS); if (ret == -ETIMEDOUT) @@ -1631,9 +1658,11 @@ static int intel_hdcp2_check_link(struct intel_connector *connector) struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; enum port port = connector->encoder->port; + enum pipe pipe; int ret = 0; mutex_lock(&hdcp->mutex); + pipe = hdcp->pipe; /* hdcp2_check_link is expected only when HDCP2.2 is Enabled */ if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_ENABLED || @@ -1642,9 +1671,9 @@ static int intel_hdcp2_check_link(struct intel_connector *connector) goto out; } - if (WARN_ON(!intel_hdcp2_in_use(connector))) { + if (WARN_ON(!intel_hdcp2_in_use(dev_priv, pipe, port))) { DRM_ERROR("HDCP2.2 link stopped the encryption, %x\n", - I915_READ(HDCP2_STATUS_DDI(port))); + I915_READ(HDCP2_STATUS(dev_priv, pipe, port))); ret = -ENXIO; hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED; schedule_work(&hdcp->prop_work); @@ -1857,6 +1886,8 @@ int intel_hdcp_enable(struct intel_connector *connector) mutex_lock(&hdcp->mutex); WARN_ON(hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED); + hdcp->pipe = intel_connector_get_pipe(connector); + /* * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup * is capable of HDCP2.2, it is preferred to use HDCP2.2. diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 0ebec69bbbfc..2096aee174b2 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -1491,7 +1491,10 @@ bool intel_hdmi_hdcp_check_link(struct intel_digital_port *intel_dig_port) { struct drm_i915_private *dev_priv = intel_dig_port->base.base.dev->dev_private; + struct intel_connector *connector = + intel_dig_port->hdmi.attached_connector; enum port port = intel_dig_port->base.port; + enum pipe pipe = connector->hdcp.pipe; int ret; union { u32 reg; @@ -1502,13 +1505,13 @@ bool intel_hdmi_hdcp_check_link(struct intel_digital_port *intel_dig_port) if (ret) return false; - I915_WRITE(PORT_HDCP_RPRIME(port), ri.reg); + I915_WRITE(HDCP_RPRIME(dev_priv, pipe, port), ri.reg); /* Wait for Ri prime match */ - if (wait_for(I915_READ(PORT_HDCP_STATUS(port)) & + if (wait_for(I915_READ(HDCP_STATUS(dev_priv, pipe, port)) & (HDCP_STATUS_RI_MATCH | HDCP_STATUS_ENC), 1)) { DRM_ERROR("Ri' mismatch detected, link check failed (%x)\n", - I915_READ(PORT_HDCP_STATUS(port))); + I915_READ(HDCP_STATUS(dev_priv, pipe, port))); return false; } return true; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5898f59e3dd7..3ea03433f4f4 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -9244,12 +9244,20 @@ enum skl_power_gate { /* HDCP Repeater Registers */ #define HDCP_REP_CTL _MMIO(0x66d00) +#define HDCP_TRANSA_REP_PRESENT BIT(31) +#define HDCP_TRANSB_REP_PRESENT BIT(30) +#define HDCP_TRANSC_REP_PRESENT BIT(29) +#define HDCP_TRANSD_REP_PRESENT BIT(28) #define HDCP_DDIB_REP_PRESENT BIT(30) #define HDCP_DDIA_REP_PRESENT BIT(29) #define HDCP_DDIC_REP_PRESENT BIT(28) #define HDCP_DDID_REP_PRESENT BIT(27) #define HDCP_DDIF_REP_PRESENT BIT(26) #define HDCP_DDIE_REP_PRESENT BIT(25) +#define HDCP_TRANSA_SHA1_M0 (1 << 20) +#define HDCP_TRANSB_SHA1_M0 (2 << 20) +#define HDCP_TRANSC_SHA1_M0 (3 << 20) +#define HDCP_TRANSD_SHA1_M0 (4 << 20) #define HDCP_DDIB_SHA1_M0 (1 << 20) #define HDCP_DDIA_SHA1_M0 (2 << 20) #define HDCP_DDIC_SHA1_M0 (3 << 20) @@ -9289,15 +9297,89 @@ enum skl_power_gate { _PORTE_HDCP_AUTHENC, \ _PORTF_HDCP_AUTHENC) + (x)) #define PORT_HDCP_CONF(port) _PORT_HDCP_AUTHENC(port, 0x0) +#define _TRANSA_HDCP_CONF 0x66400 +#define _TRANSB_HDCP_CONF 0x66500 +#define TRANS_HDCP_CONF(trans) _MMIO_TRANS(trans, _TRANSA_HDCP_CONF, \ + _TRANSB_HDCP_CONF) +#define HDCP_CONF(dev_priv, pipe, port) (INTEL_GEN(dev_priv) >= 12 ? \ + TRANS_HDCP_CONF(pipe) : \ + PORT_HDCP_CONF(port)) + #define HDCP_CONF_CAPTURE_AN BIT(0) #define HDCP_CONF_AUTH_AND_ENC (BIT(1) | BIT(0)) #define PORT_HDCP_ANINIT(port) _PORT_HDCP_AUTHENC(port, 0x4) +#define _TRANSA_HDCP_ANINIT 0x66404 +#define _TRANSB_HDCP_ANINIT 0x66504 +#define TRANS_HDCP_ANINIT(trans) _MMIO_TRANS(trans, \ + _TRANSA_HDCP_ANINIT, \ + _TRANSB_HDCP_ANINIT) +#define HDCP_ANINIT(dev_priv, pipe, port) \ + (INTEL_GEN(dev_priv) >= 12 ? \ + TRANS_HDCP_ANINIT(pipe) : \ + PORT_HDCP_ANINIT(port)) + #define PORT_HDCP_ANLO(port) _PORT_HDCP_AUTHENC(port, 0x8) +#define _TRANSA_HDCP_ANLO 0x66408 +#define _TRANSB_HDCP_ANLO 0x66508 +#define TRANS_HDCP_ANLO(trans) _MMIO_TRANS(trans, _TRANSA_HDCP_ANLO, \ + _TRANSB_HDCP_ANLO) +#define HDCP_ANLO(dev_priv, pipe, port) (INTEL_GEN(dev_priv) >= 12 ? \ + TRANS_HDCP_ANLO(pipe) : \ + PORT_HDCP_ANLO(port)) + #define PORT_HDCP_ANHI(port) _PORT_HDCP_AUTHENC(port, 0xC) +#define _TRANSA_HDCP_ANHI 0x6640C +#define _TRANSB_HDCP_ANHI 0x6650C +#define TRANS_HDCP_ANHI(trans) _MMIO_TRANS(trans, _TRANSA_HDCP_ANHI, \ + _TRANSB_HDCP_ANHI) +#define HDCP_ANHI(dev_priv, pipe, port) (INTEL_GEN(dev_priv) >= 12 ? \ + TRANS_HDCP_ANHI(pipe) : \ + PORT_HDCP_ANHI(port)) + #define PORT_HDCP_BKSVLO(port) _PORT_HDCP_AUTHENC(port, 0x10) +#define _TRANSA_HDCP_BKSVLO 0x66410 +#define _TRANSB_HDCP_BKSVLO 0x66510 +#define TRANS_HDCP_BKSVLO(trans) _MMIO_TRANS(trans, \ + _TRANSA_HDCP_BKSVLO, \ + _TRANSB_HDCP_BKSVLO) +#define HDCP_BKSVLO(dev_priv, pipe, port) \ + (INTEL_GEN(dev_priv) >= 12 ? \ + TRANS_HDCP_BKSVLO(pipe) : \ + PORT_HDCP_BKSVLO(port)) + #define PORT_HDCP_BKSVHI(port) _PORT_HDCP_AUTHENC(port, 0x14) +#define _TRANSA_HDCP_BKSVHI 0x66414 +#define _TRANSB_HDCP_BKSVHI 0x66514 +#define TRANS_HDCP_BKSVHI(trans) _MMIO_TRANS(trans, \ + _TRANSA_HDCP_BKSVHI, \ + _TRANSB_HDCP_BKSVHI) +#define HDCP_BKSVHI(dev_priv, pipe, port) \ + (INTEL_GEN(dev_priv) >= 12 ? \ + TRANS_HDCP_BKSVHI(pipe) : \ + PORT_HDCP_BKSVHI(port)) + #define PORT_HDCP_RPRIME(port) _PORT_HDCP_AUTHENC(port, 0x18) +#define _TRANSA_HDCP_RPRIME 0x66418 +#define _TRANSB_HDCP_RPRIME 0x66518 +#define TRANS_HDCP_RPRIME(trans) _MMIO_TRANS(trans, \ + _TRANSA_HDCP_RPRIME, \ + _TRANSB_HDCP_RPRIME) +#define HDCP_RPRIME(dev_priv, pipe, port) \ + (INTEL_GEN(dev_priv) >= 12 ? \ + TRANS_HDCP_RPRIME(pipe) : \ + PORT_HDCP_RPRIME(port)) + #define PORT_HDCP_STATUS(port) _PORT_HDCP_AUTHENC(port, 0x1C) +#define _TRANSA_HDCP_STATUS 0x6641C +#define _TRANSB_HDCP_STATUS 0x6651C +#define TRANS_HDCP_STATUS(trans) _MMIO_TRANS(trans, \ + _TRANSA_HDCP_STATUS, \ + _TRANSB_HDCP_STATUS) +#define HDCP_STATUS(dev_priv, pipe, port) \ + (INTEL_GEN(dev_priv) >= 12 ? \ + TRANS_HDCP_STATUS(pipe) : \ + PORT_HDCP_STATUS(port)) + #define HDCP_STATUS_STREAM_A_ENC BIT(31) #define HDCP_STATUS_STREAM_B_ENC BIT(30) #define HDCP_STATUS_STREAM_C_ENC BIT(29) @@ -9324,23 +9406,43 @@ enum skl_power_gate { _PORTD_HDCP2_BASE, \ _PORTE_HDCP2_BASE, \ _PORTF_HDCP2_BASE) + (x)) - -#define HDCP2_AUTH_DDI(port) _PORT_HDCP2_BASE(port, 0x98) +#define PORT_HDCP2_AUTH(port) _PORT_HDCP2_BASE(port, 0x98) +#define _TRANSA_HDCP2_AUTH 0x66498 +#define _TRANSB_HDCP2_AUTH 0x66598 +#define TRANS_HDCP2_AUTH(trans) _MMIO_TRANS(trans, _TRANSA_HDCP2_AUTH, \ + _TRANSB_HDCP2_AUTH) #define AUTH_LINK_AUTHENTICATED BIT(31) #define AUTH_LINK_TYPE BIT(30) #define AUTH_FORCE_CLR_INPUTCTR BIT(19) #define AUTH_CLR_KEYS BIT(18) - -#define HDCP2_CTL_DDI(port) _PORT_HDCP2_BASE(port, 0xB0) +#define HDCP2_AUTH(dev_priv, pipe, port) \ + (INTEL_GEN(dev_priv) >= 12 ? \ + TRANS_HDCP2_AUTH(pipe) : \ + PORT_HDCP2_AUTH(port)) + +#define PORT_HDCP2_CTL(port) _PORT_HDCP2_BASE(port, 0xB0) +#define _TRANSA_HDCP2_CTL 0x664B0 +#define _TRANSB_HDCP2_CTL 0x665B0 +#define TRANS_HDCP2_CTL(trans) _MMIO_TRANS(trans, _TRANSA_HDCP2_CTL, \ + _TRANSB_HDCP2_CTL) #define CTL_LINK_ENCRYPTION_REQ BIT(31) - -#define HDCP2_STATUS_DDI(port) _PORT_HDCP2_BASE(port, 0xB4) -#define STREAM_ENCRYPTION_STATUS_A BIT(31) -#define STREAM_ENCRYPTION_STATUS_B BIT(30) -#define STREAM_ENCRYPTION_STATUS_C BIT(29) +#define HDCP2_CTL(dev_priv, pipe, port) (INTEL_GEN(dev_priv) >= 12 ? \ + TRANS_HDCP2_CTL(pipe) : \ + PORT_HDCP2_CTL(port)) + +#define PORT_HDCP2_STATUS(port) _PORT_HDCP2_BASE(port, 0xB4) +#define _TRANSA_HDCP2_STATUS 0x664B4 +#define _TRANSB_HDCP2_STATUS 0x665B4 +#define TRANS_HDCP2_STATUS(trans) _MMIO_TRANS(trans, \ + _TRANSA_HDCP2_STATUS, \ + _TRANSB_HDCP2_STATUS) #define LINK_TYPE_STATUS BIT(22) #define LINK_AUTH_STATUS BIT(21) #define LINK_ENCRYPTION_STATUS BIT(20) +#define HDCP2_STATUS(dev_priv, pipe, port) \ + (INTEL_GEN(dev_priv) >= 12 ? \ + TRANS_HDCP2_STATUS(pipe) : \ + PORT_HDCP2_STATUS(port)) /* Per-pipe DDI Function Control */ #define _TRANS_DDI_FUNC_CTL_A 0x60400 diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 24c63ed45c6f..741fa21c3e57 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -365,6 +365,14 @@ struct intel_hdcp { wait_queue_head_t cp_irq_queue; atomic_t cp_irq_count; int cp_irq_count_cached; + + /* + * Gen 12 onwards, HDCP is part of transcoder(previously DDI). + * So chacheing the pipe associated to connector at hdcp_enable + * would help in subsequent functions to derive the right offsets + * for HDCP registers. + */ + enum pipe pipe; }; struct intel_connector {
From Gen12 onwards, HDCP HW block is implemented within transcoders. Till Gen11 HDCP HW block was part of DDI. Hence required changes in HW programming is handled here. v2: _MMIO_TRANS is used [Lucas and Daniel] platform check is moved into the caller [Lucas] v3: platform check is moved into a macro [Shashank] v4: Few optimizations in the coding [Shashank] v5: Fixed alignment in macro definition in i915_reg.h [Shashank] unused variables "reg" is removed. Signed-off-by: Ramalingam C <ramalingam.c@intel.com> --- drivers/gpu/drm/i915/display/intel_hdcp.c | 133 +++++++++++++--------- drivers/gpu/drm/i915/display/intel_hdmi.c | 9 +- drivers/gpu/drm/i915/i915_reg.h | 120 +++++++++++++++++-- drivers/gpu/drm/i915/intel_drv.h | 8 ++ 4 files changed, 207 insertions(+), 63 deletions(-)