devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sean Paul <sean@poorly.run>
To: abhinavk@codeaurora.org
Cc: Sean Paul <sean@poorly.run>,
	dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org,
	freedreno@lists.freedesktop.org, swboyd@chromium.org,
	Sean Paul <seanpaul@chromium.org>, Andy Gross <agross@kernel.org>,
	Bjorn Andersson <bjorn.andersson@linaro.org>,
	Rob Herring <robh+dt@kernel.org>, Rob Clark <robdclark@gmail.com>,
	David Airlie <airlied@linux.ie>, Daniel Vetter <daniel@ffwll.ch>,
	linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org
Subject: Re: [Freedreno] [PATCH v2 13/13] drm/msm: Implement HDCP 1.x using the new drm HDCP helpers
Date: Tue, 28 Sep 2021 14:02:19 -0400	[thread overview]
Message-ID: <20210928180219.GT2515@art_vandelay> (raw)
In-Reply-To: <2486179cbd76c34a9c085dfff98448e5@codeaurora.org>

On Tue, Sep 21, 2021 at 07:25:41PM -0700, abhinavk@codeaurora.org wrote:
> On 2021-09-15 13:38, Sean Paul wrote:
> > From: Sean Paul <seanpaul@chromium.org>
> > 
> > This patch adds HDCP 1.x support to msm DP connectors using the new HDCP
> > helpers.
> > 
> > Cc: Stephen Boyd <swboyd@chromium.org>
> > Signed-off-by: Sean Paul <seanpaul@chromium.org>
> > Link:
> > https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-15-sean@poorly.run
> > #v1
> > 
> > Changes in v2:
> > -Squash [1] into this patch with the following changes (Stephen)
> >   -Update the sc7180 dtsi file
> >   -Remove resource names and just use index (Stephen)
> > 
> 
> 
> > [1]
> > https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-14-sean@poorly.run
> > ---

/snip

> > diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
> > index 904535eda0c4..98731fd262d6 100644
> > --- a/drivers/gpu/drm/msm/Makefile
> > +++ b/drivers/gpu/drm/msm/Makefile
> > @@ -109,6 +109,7 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \
> >  	dp/dp_ctrl.o \
> >  	dp/dp_display.o \
> >  	dp/dp_drm.o \
> > +	dp/dp_hdcp.o \
> >  	dp/dp_hpd.o \
> >  	dp/dp_link.o \
> >  	dp/dp_panel.o \
> > diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c
> > b/drivers/gpu/drm/msm/dp/dp_debug.c
> > index 2f6247e80e9d..de16fca8782a 100644
> > --- a/drivers/gpu/drm/msm/dp/dp_debug.c
> > +++ b/drivers/gpu/drm/msm/dp/dp_debug.c

/snip

> > +static ssize_t dp_hdcp_key_write(struct file *file, const char __user
> > *ubuf,
> > +				 size_t len, loff_t *offp)
> > +{
> > +	char *input_buffer;
> > +	int ret = 0;
> > +	struct dp_debug_private *debug = file->private_data;
> > +	struct drm_device *dev;
> > +
> > +	dev = debug->drm_dev;
> > +
> > +	if (len != (DRM_HDCP_KSV_LEN + DP_HDCP_NUM_KEYS * DP_HDCP_KEY_LEN))
> > +		return -EINVAL;
> > +
> > +	if (!debug->hdcp)
> > +		return -ENOENT;
> > +
> > +	input_buffer = memdup_user_nul(ubuf, len);
> > +	if (IS_ERR(input_buffer))
> > +		return PTR_ERR(input_buffer);
> > +
> > +	ret = dp_hdcp_ingest_key(debug->hdcp, input_buffer, len);
> > +
> > +	kfree(input_buffer);
> > +	if (ret < 0) {
> > +		DRM_ERROR("Could not ingest HDCP key, ret=%d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	*offp += len;
> > +	return len;
> > +}
> 
> It seems like the HDCP keys written using debugfs, just for my
> understanding,
> are you storing this in some secure partition and the usermode reads from it
> and writes them here?
> 

We have not sorted out the userspace side of HDCP enablement yet, so it remains
to be seen whether the keys will be injected via debugfs/firmware file/property.

/snip

> > +static int dp_connector_atomic_check(struct drm_connector *connector,
> > +				     struct drm_atomic_state *state)
> > +{
> > +	struct drm_connector_state *conn_state;
> > +	struct dp_connector_state *dp_state;
> > +
> > +	conn_state = drm_atomic_get_new_connector_state(state, connector);
> > +	dp_state = to_dp_connector_state(conn_state);
> > +
> > +	dp_state->hdcp_transition = drm_hdcp_atomic_check(connector, state);
> 
> I have a general question related to the transition flag and overall tying
> the HDCP
> enable and authentication to the commit.
> So lets say there is a case where the driver needs to disable HDCP. It could
> be due
> to link integrity failure OR some other error condition which usermode is
> not aware of.
> In that case, we will set this hdcp_transition to true but in the next
> commit we will
> actually do the authentication. What if usermode doesnt issue a new frame?
> This question arises because currently the link intergrity check is done
> using SW polling
> in the previous patchset. But as I had commented there, this occurs in HW
> for us.
> I dont see that isr itself in this patchset. So wanted to understand if
> thats part of this
> approach to still tie it with commit.
> 
> So if we go with the HW polling based approach which is the preferred
> method, we need to
> untie this from the commit.
> 

In the case of error, the worker will detect it and try to re-authenticate. If
the re-authentication is successful, userspace will continue to be unaware and
everything will keep working. If re-authentication is unsuccessful, the worker
will update the property value and issue a uevent to userspace. So HDCP
enablement is only tied to commits when the property value is changing as a
result of userspace.

Regarding SW vs HW link checks, I don't think there's any difference in efficacy
between them. If HW can be relied on to issue an interrupt in failure cases, a
follow-up set allowing for this seems like a great idea.

> > +
> > +	return 0;
> > +}

/snip

> > +static int dp_hdcp_load_keys(struct drm_connector *connector)
> > +{
> > +	struct dp_hdcp *hdcp = dp_display_connector_to_hdcp(connector);
> > +	struct dp_hdcp_key *key;
> > +	int i, ret = 0;
> > +
> > +	mutex_lock(&hdcp->key_lock);
> > +
> > +	key = hdcp->key;
> > +
> > +	if (!key->valid) {
> > +		ret = -ENOENT;
> > +		goto out;
> > +	}
> > +
> > +	dp_hdcp_write_dp(hdcp, DP_HDCP_SW_LOWER_AKSV, key->ksv.words[0]);
> > +	dp_hdcp_write_dp(hdcp, DP_HDCP_SW_UPPER_AKSV, key->ksv.words[1]);
> > +
> > +	for (i = 0; i < DP_HDCP_NUM_KEYS; i++) {
> > +		dp_hdcp_write_hdcp(hdcp, DP_HDCP_KEY_LSB(i),
> > +				   key->keys[i].words[0]);
> > +		dp_hdcp_write_hdcp(hdcp, DP_HDCP_KEY_MSB(i),
> > +				   key->keys[i].words[1]);
> > +	}
> > +
> > +	dp_hdcp_write_hdcp(hdcp, DP_HDCP_KEY_VALID, DP_HDCP_SW_KEY_VALID);
> 
> I think all of these are TZ_*** registers. So the separation of write_hdcp()
> Vs write_hdcp_tz()
> is not very clear to me.
> Maybe change the write APIs to something like dp_hdcp_write_hdcp_tz() for
> the first address space
> and dp_hdcp_write_hdcp_tz_hlos() for the other one?
> 

Will do in v3, thank you for the suggestion.

> > +	wmb();
> > +
> > +	dp_hdcp_write_dp(hdcp, DP_HDCP_ENTROPY_CTRL0, get_random_u32());
> > +	dp_hdcp_write_dp(hdcp, DP_HDCP_ENTROPY_CTRL1, get_random_u32());
> > +	wmb();
> > +
> > +out:
> > +	mutex_unlock(&hdcp->key_lock);
> > +	return ret;
> > +}
> > +
> > +static int dp_hdcp_hdcp2_capable(struct drm_connector *connector,
> > bool *capable)
> > +{
> > +	*capable = false;
> > +	return 0;
> > +}
> > +
> > +static int dp_hdcp_hdcp1_read_an_aksv(struct drm_connector *connector,
> > +				      u32 *an, u32 *aksv)
> > +{
> > +	struct dp_hdcp *hdcp = dp_display_connector_to_hdcp(connector);
> > +	bool keys_valid;
> > +	int ret;
> > +	u32 val;
> > +
> > +	dp_hdcp_write_dp(hdcp, DP_HDCP_CTRL, 1);
> > +
> > +	ret = read_poll_timeout(dp_hdcp_are_keys_valid, keys_valid,
> > keys_valid,
> > +				20 * 1000, 10 * 1000, false, connector);
> > +	if (ret) {
> > +		drm_err(hdcp->dev, "HDCP keys invalid %d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	/* Clear AInfo */
> > +	dp_hdcp_write_dp(hdcp, DP_HDCP_RCVPORT_DATA4, 0);
> > +
> > +	aksv[0] = dp_hdcp_read_dp(hdcp, DP_HDCP_RCVPORT_DATA3);
> > +	aksv[1] = GENMASK(7, 0) & dp_hdcp_read_dp(hdcp,
> > DP_HDCP_RCVPORT_DATA4);
> > +
> > +	ret = read_poll_timeout(dp_hdcp_read_dp, val,
> > +				(val & DP_HDCP_AN_READY_MASK) == DP_HDCP_AN_READY_MASK,
> > +				100, 10 * 1000, false, hdcp, DP_HDCP_STATUS);
> > +	if (ret) {
> > +		drm_err(hdcp->dev, "AN failed to become ready %x/%d\n", val, ret);
> > +		return ret;
> > +	}
> > +
> > +	/*
> > +	 * Get An from hardware, for unknown reasons we need to read the reg
> > +	 * twice to get valid data.
> > +	 */
> > +	dp_hdcp_read_dp(hdcp, DP_HDCP_RCVPORT_DATA5);
> > +	an[0] = dp_hdcp_read_dp(hdcp, DP_HDCP_RCVPORT_DATA5);
> > +
> > +	dp_hdcp_read_dp(hdcp, DP_HDCP_RCVPORT_DATA6);
> > +	an[1] = dp_hdcp_read_dp(hdcp, DP_HDCP_RCVPORT_DATA6);
> 
> Yes its true, but we also have a 1 microsec delay between the first and
> second one.
> So I would certainly preserve that.

Will do in v3, thank you for the suggestion.

> 
> > +
> > +	return 0;
> > +}
> > +
> > +static int dp_hdcp_hdcp1_store_receiver_info(struct drm_connector
> > *connector,
> > +					     u32 *ksv, u32 status, u8 bcaps,
> > +					     bool is_repeater)
> > +{
> > +	struct dp_hdcp *hdcp = dp_display_connector_to_hdcp(connector);
> > +	u32 val;
> > +
> > +	dp_hdcp_write_tz(hdcp, HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA0,
> > +			 ksv[0]);
> > +	dp_hdcp_write_tz(hdcp, HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA1,
> > +			 ksv[1]);
> > +
> > +	val = ((status & GENMASK(15, 0)) << 8) | (bcaps & GENMASK(7, 0));
> > +
> > +	dp_hdcp_write_tz(hdcp, HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12,
> > val);
> > +
> 
> Cant this entire API be skipped for non-repeater cases from the hdcp lib
> layer?
> You can write the bcaps to this earlier and write the bstatus only if its a
> repeater.

Could you expand on the benefits of this?

> 
> > +	return 0;
> > +}

/snip

-- 
Sean Paul, Software Engineer, Google / Chromium OS

  reply	other threads:[~2021-09-28 18:02 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20210915203834.1439-1-sean@poorly.run>
2021-09-15 20:38 ` [PATCH v2 12/13] dt-bindings: msm/dp: Add bindings for HDCP registers Sean Paul
2021-09-16 12:21   ` Rob Herring
2021-09-16 12:58   ` Rob Herring
2021-09-15 20:38 ` [PATCH v2 13/13] drm/msm: Implement HDCP 1.x using the new drm HDCP helpers Sean Paul
2021-09-17  6:00   ` Stephen Boyd
2021-09-17 21:05     ` Sean Paul
2021-09-22  2:25   ` [Freedreno] " abhinavk
2021-09-28 18:02     ` Sean Paul [this message]
2021-09-28 21:35       ` abhinavk
2021-09-29 14:52         ` Sean Paul

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210928180219.GT2515@art_vandelay \
    --to=sean@poorly.run \
    --cc=abhinavk@codeaurora.org \
    --cc=agross@kernel.org \
    --cc=airlied@linux.ie \
    --cc=bjorn.andersson@linaro.org \
    --cc=daniel@ffwll.ch \
    --cc=devicetree@vger.kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=freedreno@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=robdclark@gmail.com \
    --cc=robh+dt@kernel.org \
    --cc=seanpaul@chromium.org \
    --cc=swboyd@chromium.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).