On 2019-12-12 at 14:02:22 -0500, Sean Paul wrote: > From: Sean Paul <seanpaul@xxxxxxxxxxxx> > > Instead of hand rolling the transfer ourselves in the hdcp hook, inspect > aux messages and add the aksv flag in the aux transfer hook. > > IIRC, this was the original implementation and folks wanted this hack to > be isolated to the hdcp code, which makes sense. > > However in testing an LG monitor on my desk, I noticed it was passing > back a DEFER reply. This wasn't handled in our hand-rolled code and HDCP > auth was failing as a result. Instead of copy/pasting all of the retry > logic and delays from drm dp helpers, let's just use the helpers and hide > the aksv select as best as we can. > > Reviewed-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > Signed-off-by: Sean Paul <seanpaul@xxxxxxxxxxxx> > Link: https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-3-sean@xxxxxxxxxx #v1 > > Changes in v2: > -Remove 'generate' in intel_dp_aux_generate_xfer_flags, make arg const (Ville) > -Bundle Aksv if statement together (Ville) > -Rename 'txbuf' to 'aksv' (Ville) LGTM Reviewed-by: Ramalingam C <ramalingam.c@xxxxxxxxx> > --- > drivers/gpu/drm/i915/display/intel_dp.c | 62 ++++++++++++------------- > 1 file changed, 29 insertions(+), 33 deletions(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c > index fe31bbfd6c62..5576193b4fed 100644 > --- a/drivers/gpu/drm/i915/display/intel_dp.c > +++ b/drivers/gpu/drm/i915/display/intel_dp.c > @@ -1515,12 +1515,27 @@ intel_dp_aux_header(u8 txbuf[HEADER_SIZE], > txbuf[3] = msg->size - 1; > } > > +static u32 intel_dp_aux_xfer_flags(const struct drm_dp_aux_msg *msg) > +{ > + /* > + * If we're trying to send the HDCP Aksv, we need to set a the Aksv > + * select bit to inform the hardware to send the Aksv after our header > + * since we can't access that data from software. > + */ > + if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_WRITE && > + msg->address == DP_AUX_HDCP_AKSV) > + return DP_AUX_CH_CTL_AUX_AKSV_SELECT; > + > + return 0; > +} > + > static ssize_t > intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) > { > struct intel_dp *intel_dp = container_of(aux, struct intel_dp, aux); > u8 txbuf[20], rxbuf[20]; > size_t txsize, rxsize; > + u32 flags = intel_dp_aux_xfer_flags(msg); > int ret; > > intel_dp_aux_header(txbuf, msg); > @@ -1541,7 +1556,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) > memcpy(txbuf + HEADER_SIZE, msg->buffer, msg->size); > > ret = intel_dp_aux_xfer(intel_dp, txbuf, txsize, > - rxbuf, rxsize, 0); > + rxbuf, rxsize, flags); > if (ret > 0) { > msg->reply = rxbuf[0] >> 4; > > @@ -1564,7 +1579,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) > return -E2BIG; > > ret = intel_dp_aux_xfer(intel_dp, txbuf, txsize, > - rxbuf, rxsize, 0); > + rxbuf, rxsize, flags); > if (ret > 0) { > msg->reply = rxbuf[0] >> 4; > /* > @@ -5904,17 +5919,9 @@ static > int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port, > u8 *an) > { > - struct intel_dp *intel_dp = enc_to_intel_dp(&intel_dig_port->base.base); > - static const struct drm_dp_aux_msg msg = { > - .request = DP_AUX_NATIVE_WRITE, > - .address = DP_AUX_HDCP_AKSV, > - .size = DRM_HDCP_KSV_LEN, > - }; > - u8 txbuf[HEADER_SIZE + DRM_HDCP_KSV_LEN] = {}, rxbuf[2], reply = 0; > + u8 aksv[DRM_HDCP_KSV_LEN] = {}; > ssize_t dpcd_ret; > - int ret; > > - /* Output An first, that's easy */ > dpcd_ret = drm_dp_dpcd_write(&intel_dig_port->dp.aux, DP_AUX_HDCP_AN, > an, DRM_HDCP_AN_LEN); > if (dpcd_ret != DRM_HDCP_AN_LEN) { > @@ -5924,29 +5931,18 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port, > } > > /* > - * Since Aksv is Oh-So-Secret, we can't access it in software. So in > - * order to get it on the wire, we need to create the AUX header as if > - * we were writing the data, and then tickle the hardware to output the > - * data once the header is sent out. > + * Since Aksv is Oh-So-Secret, we can't access it in software. So we > + * send an empty buffer of the correct length through the DP helpers. On > + * the other side, in the transfer hook, we'll generate a flag based on > + * the destination address which will tickle the hardware to output the > + * Aksv on our behalf after the header is sent. > */ > - intel_dp_aux_header(txbuf, &msg); > - > - ret = intel_dp_aux_xfer(intel_dp, txbuf, HEADER_SIZE + msg.size, > - rxbuf, sizeof(rxbuf), > - DP_AUX_CH_CTL_AUX_AKSV_SELECT); > - if (ret < 0) { > - DRM_DEBUG_KMS("Write Aksv over DP/AUX failed (%d)\n", ret); > - return ret; > - } else if (ret == 0) { > - DRM_DEBUG_KMS("Aksv write over DP/AUX was empty\n"); > - return -EIO; > - } > - > - reply = (rxbuf[0] >> 4) & DP_AUX_NATIVE_REPLY_MASK; > - if (reply != DP_AUX_NATIVE_REPLY_ACK) { > - DRM_DEBUG_KMS("Aksv write: no DP_AUX_NATIVE_REPLY_ACK %x\n", > - reply); > - return -EIO; > + dpcd_ret = drm_dp_dpcd_write(&intel_dig_port->dp.aux, DP_AUX_HDCP_AKSV, > + aksv, DRM_HDCP_KSV_LEN); > + if (dpcd_ret != DRM_HDCP_KSV_LEN) { > + DRM_DEBUG_KMS("Failed to write Aksv over DP/AUX (%zd)\n", > + dpcd_ret); > + return dpcd_ret >= 0 ? -EIO : dpcd_ret; > } > return 0; > } > -- > Sean Paul, Software Engineer, Google / Chromium OS > _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx