diff mbox

[35/43] drm/i915: Enable HDCP version that is best capable

Message ID 1518617638-21684-36-git-send-email-ramalingam.c@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Ramalingam C Feb. 14, 2018, 2:13 p.m. UTC
hdcp_enable_work is extended to choose the better hdcp version based
on the system and panel capability.

And intel_hdcp_disable will find the version that is inforce, if any.
And corresponding version specific disable function alone called.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_hdcp.c | 112 ++++++++++++++++++++++++++++++++++----
 1 file changed, 100 insertions(+), 12 deletions(-)

Comments

Chris Wilson Feb. 14, 2018, 2:42 p.m. UTC | #1
Quoting Ramalingam C (2018-02-14 14:13:50)
> hdcp_enable_work is extended to choose the better hdcp version based
> on the system and panel capability.
> 
> And intel_hdcp_disable will find the version that is inforce, if any.
> And corresponding version specific disable function alone called.
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_hdcp.c | 112 ++++++++++++++++++++++++++++++++++----
>  1 file changed, 100 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
> index 69ae47eaff49..2fe73f7eb6dd 100644
> --- a/drivers/gpu/drm/i915/intel_hdcp.c
> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
> @@ -27,6 +27,43 @@ static int _intel_hdcp2_disable(struct intel_hdcp *hdcp);
>  static void intel_hdcp2_check_work(struct work_struct *work);
>  static int intel_hdcp2_check_link(struct intel_hdcp *hdcp);
>  
> +static inline bool intel_hdcp1_supported(struct intel_hdcp *hdcp)
> +{
> +       return (hdcp->plat_cap & HDCP_CAPABILITY &&
> +               hdcp->panel_cap & HDCP_CAPABILITY);
> +}
> +
> +static inline bool intel_hdcp2_supported(struct intel_hdcp *hdcp)
> +{
> +       return (hdcp->plat_cap & HDCP2_CAPABILITY &&
> +               hdcp->panel_cap & HDCP2_CAPABILITY);
> +}
> +
> +static inline bool intel_hdcp_in_force(struct intel_hdcp *hdcp)
> +{
> +       struct drm_i915_private *dev_priv = to_i915(hdcp->connector->base.dev);
> +       enum port port = hdcp->connector->encoder->port;
> +       u32 reg;
> +
> +       reg = I915_READ(PORT_HDCP_STATUS(port));
> +       if (reg & HDCP_STATUS_AUTH || reg & HDCP_STATUS_ENC)
> +               return true;
> +       return false;

return reg & (HDCP_STATUS_AUTH | HDCP_STATUS_ENC);

> +
> +}
> +
> +static inline bool intel_hdcp2_in_force(struct intel_hdcp *hdcp)
> +{
> +       struct drm_i915_private *dev_priv = to_i915(hdcp->connector->base.dev);
> +       enum port port = hdcp->connector->encoder->port;
> +       u32 reg;
> +
> +       reg = I915_READ(HDCP2_STATUS_DDI(port));
> +       if (reg & LINK_ENCRYPTION_STATUS || reg & LINK_AUTH_STATUS)
> +               return true;
> +       return false;

return reg & (LINK_ENCRYPTION_STATUS | LINK_AUTH_STATUS);

> @@ -1437,7 +1525,7 @@ static int _intel_hdcp2_disable(struct intel_hdcp *hdcp)
>  {
>         int ret;
>  
> -       DRM_ERROR("[%s:%d] HDCP2.2 is being Disabled\n",
> +       DRM_INFO("[%s:%d] HDCP2.2 is being Disabled\n",
>                   hdcp->connector->base.name, hdcp->connector->base.base.id);

Will there be a third patch making this DEBUG_KMS?
-Chris
Ramalingam C Feb. 14, 2018, 2:51 p.m. UTC | #2
On Wednesday 14 February 2018 08:12 PM, Chris Wilson wrote:
> Quoting Ramalingam C (2018-02-14 14:13:50)
>> hdcp_enable_work is extended to choose the better hdcp version based
>> on the system and panel capability.
>>
>> And intel_hdcp_disable will find the version that is inforce, if any.
>> And corresponding version specific disable function alone called.
>>
>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>> ---
>>   drivers/gpu/drm/i915/intel_hdcp.c | 112 ++++++++++++++++++++++++++++++++++----
>>   1 file changed, 100 insertions(+), 12 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
>> index 69ae47eaff49..2fe73f7eb6dd 100644
>> --- a/drivers/gpu/drm/i915/intel_hdcp.c
>> +++ b/drivers/gpu/drm/i915/intel_hdcp.c
>> @@ -27,6 +27,43 @@ static int _intel_hdcp2_disable(struct intel_hdcp *hdcp);
>>   static void intel_hdcp2_check_work(struct work_struct *work);
>>   static int intel_hdcp2_check_link(struct intel_hdcp *hdcp);
>>   
>> +static inline bool intel_hdcp1_supported(struct intel_hdcp *hdcp)
>> +{
>> +       return (hdcp->plat_cap & HDCP_CAPABILITY &&
>> +               hdcp->panel_cap & HDCP_CAPABILITY);
>> +}
>> +
>> +static inline bool intel_hdcp2_supported(struct intel_hdcp *hdcp)
>> +{
>> +       return (hdcp->plat_cap & HDCP2_CAPABILITY &&
>> +               hdcp->panel_cap & HDCP2_CAPABILITY);
>> +}
>> +
>> +static inline bool intel_hdcp_in_force(struct intel_hdcp *hdcp)
>> +{
>> +       struct drm_i915_private *dev_priv = to_i915(hdcp->connector->base.dev);
>> +       enum port port = hdcp->connector->encoder->port;
>> +       u32 reg;
>> +
>> +       reg = I915_READ(PORT_HDCP_STATUS(port));
>> +       if (reg & HDCP_STATUS_AUTH || reg & HDCP_STATUS_ENC)
>> +               return true;
>> +       return false;
> return reg & (HDCP_STATUS_AUTH | HDCP_STATUS_ENC);
>
>> +
>> +}
>> +
>> +static inline bool intel_hdcp2_in_force(struct intel_hdcp *hdcp)
>> +{
>> +       struct drm_i915_private *dev_priv = to_i915(hdcp->connector->base.dev);
>> +       enum port port = hdcp->connector->encoder->port;
>> +       u32 reg;
>> +
>> +       reg = I915_READ(HDCP2_STATUS_DDI(port));
>> +       if (reg & LINK_ENCRYPTION_STATUS || reg & LINK_AUTH_STATUS)
>> +               return true;
>> +       return false;
> return reg & (LINK_ENCRYPTION_STATUS | LINK_AUTH_STATUS);
>
>> @@ -1437,7 +1525,7 @@ static int _intel_hdcp2_disable(struct intel_hdcp *hdcp)
>>   {
>>          int ret;
>>   
>> -       DRM_ERROR("[%s:%d] HDCP2.2 is being Disabled\n",
>> +       DRM_INFO("[%s:%d] HDCP2.2 is being Disabled\n",
>>                    hdcp->connector->base.name, hdcp->connector->base.base.id);
> Will there be a third patch making this DEBUG_KMS?
> -Chris
Thanks Chris!

Will address these comments. No, I feel its could to have DRM_INFO for 
state transition logs.
In practical HDCP logs will not be that frequent. If needed I will 
change them into DEBUG in upcoming versions :)

--Ram
Ramalingam C Feb. 14, 2018, 3 p.m. UTC | #3
On Wednesday 14 February 2018 08:30 PM, Chris Wilson wrote:
> Quoting Ramalingam C (2018-02-14 14:51:10)
>>
>> On Wednesday 14 February 2018 08:12 PM, Chris Wilson wrote:
>>> Quoting Ramalingam C (2018-02-14 14:13:50)
>>>> @@ -1437,7 +1525,7 @@ static int _intel_hdcp2_disable(struct intel_hdcp *hdcp)
>>>>    {
>>>>           int ret;
>>>>    
>>>> -       DRM_ERROR("[%s:%d] HDCP2.2 is being Disabled\n",
>>>> +       DRM_INFO("[%s:%d] HDCP2.2 is being Disabled\n",
>>>>                     hdcp->connector->base.name, hdcp->connector->base.base.id);
>>> Will there be a third patch making this DEBUG_KMS?
>>> -Chris
>> Thanks Chris!
>>
>> Will address these comments. No, I feel its could to have DRM_INFO for
>> state transition logs.
>> In practical HDCP logs will not be that frequent. If needed I will
>> change them into DEBUG in upcoming versions :)
> Treat everything above DEBUG as communicating with the user. For the
> user, this information is already available via the connector property.
> -Chris
In that case, I will convert them into DEBUG logs
Thanks,
--Ram
Chris Wilson Feb. 14, 2018, 3 p.m. UTC | #4
Quoting Ramalingam C (2018-02-14 14:51:10)
> 
> 
> On Wednesday 14 February 2018 08:12 PM, Chris Wilson wrote:
> > Quoting Ramalingam C (2018-02-14 14:13:50)
> >> @@ -1437,7 +1525,7 @@ static int _intel_hdcp2_disable(struct intel_hdcp *hdcp)
> >>   {
> >>          int ret;
> >>   
> >> -       DRM_ERROR("[%s:%d] HDCP2.2 is being Disabled\n",
> >> +       DRM_INFO("[%s:%d] HDCP2.2 is being Disabled\n",
> >>                    hdcp->connector->base.name, hdcp->connector->base.base.id);
> > Will there be a third patch making this DEBUG_KMS?
> > -Chris
> Thanks Chris!
> 
> Will address these comments. No, I feel its could to have DRM_INFO for 
> state transition logs.
> In practical HDCP logs will not be that frequent. If needed I will 
> change them into DEBUG in upcoming versions :)

Treat everything above DEBUG as communicating with the user. For the
user, this information is already available via the connector property.
-Chris
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 69ae47eaff49..2fe73f7eb6dd 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -27,6 +27,43 @@  static int _intel_hdcp2_disable(struct intel_hdcp *hdcp);
 static void intel_hdcp2_check_work(struct work_struct *work);
 static int intel_hdcp2_check_link(struct intel_hdcp *hdcp);
 
+static inline bool intel_hdcp1_supported(struct intel_hdcp *hdcp)
+{
+	return (hdcp->plat_cap & HDCP_CAPABILITY &&
+		hdcp->panel_cap & HDCP_CAPABILITY);
+}
+
+static inline bool intel_hdcp2_supported(struct intel_hdcp *hdcp)
+{
+	return (hdcp->plat_cap & HDCP2_CAPABILITY &&
+		hdcp->panel_cap & HDCP2_CAPABILITY);
+}
+
+static inline bool intel_hdcp_in_force(struct intel_hdcp *hdcp)
+{
+	struct drm_i915_private *dev_priv = to_i915(hdcp->connector->base.dev);
+	enum port port = hdcp->connector->encoder->port;
+	u32 reg;
+
+	reg = I915_READ(PORT_HDCP_STATUS(port));
+	if (reg & HDCP_STATUS_AUTH || reg & HDCP_STATUS_ENC)
+		return true;
+	return false;
+
+}
+
+static inline bool intel_hdcp2_in_force(struct intel_hdcp *hdcp)
+{
+	struct drm_i915_private *dev_priv = to_i915(hdcp->connector->base.dev);
+	enum port port = hdcp->connector->encoder->port;
+	u32 reg;
+
+	reg = I915_READ(HDCP2_STATUS_DDI(port));
+	if (reg & LINK_ENCRYPTION_STATUS || reg & LINK_AUTH_STATUS)
+		return true;
+	return false;
+}
+
 static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *intel_dig_port,
 				    const struct intel_hdcp_shim *shim)
 {
@@ -650,7 +687,11 @@  static void intel_hdcp_enable_work(struct work_struct *work)
 					       hdcp_enable_work);
 
 	mutex_lock(&hdcp->hdcp_mutex);
-	_intel_hdcp_enable(hdcp);
+	if (intel_hdcp2_supported(hdcp))
+		_intel_hdcp2_enable(hdcp);
+	else if (intel_hdcp1_supported(hdcp))
+		_intel_hdcp_enable(hdcp);
+
 	mutex_unlock(&hdcp->hdcp_mutex);
 }
 
@@ -727,13 +768,48 @@  int intel_hdcp_init(struct intel_connector *connector,
 	return ret;
 }
 
+static void intel_hdcp_probe_panel_cap(struct intel_hdcp *hdcp)
+{
+	struct intel_digital_port *intel_dig_port =
+					conn_to_dig_port(hdcp->connector);
+	bool capable = false;
+	u8 bksv[5];
+
+	hdcp->panel_cap = 0;
+
+	if (hdcp->plat_cap & HDCP_CAPABILITY) {
+		if (hdcp->hdcp_shim->hdcp_capable) {
+			hdcp->hdcp_shim->hdcp_capable(intel_dig_port, &capable);
+		} else {
+			if (!intel_hdcp_read_valid_bksv(intel_dig_port,
+							hdcp->hdcp_shim, bksv))
+				capable = true;
+		}
+		if (capable)
+			hdcp->panel_cap |= HDCP_CAPABILITY;
+	}
+
+	if (hdcp->plat_cap & HDCP2_CAPABILITY) {
+		hdcp->hdcp2_shim->hdcp_capable(intel_dig_port, &capable);
+		if (capable)
+			hdcp->panel_cap |= HDCP2_CAPABILITY;
+	}
+	DRM_DEBUG_KMS("plat_cap: 0x%X, panel_cap: 0x%X\n",
+		      hdcp->plat_cap, hdcp->panel_cap);
+}
+
 int intel_hdcp_enable(struct intel_connector *connector)
 {
 	struct intel_hdcp *hdcp = connector->hdcp;
 
-	if (!hdcp || !hdcp->hdcp_shim)
+	if (!hdcp)
 		return -ENOENT;
 
+	intel_hdcp_probe_panel_cap(hdcp);
+
+	if (!intel_hdcp1_supported(hdcp) && !intel_hdcp2_supported(hdcp))
+		return -EINVAL;
+
 	mutex_lock(&hdcp->hdcp_mutex);
 	schedule_work(&hdcp->hdcp_enable_work);
 	mutex_unlock(&hdcp->hdcp_mutex);
@@ -744,21 +820,33 @@  int intel_hdcp_enable(struct intel_connector *connector)
 int intel_hdcp_disable(struct intel_connector *connector)
 {
 	struct intel_hdcp *hdcp = connector->hdcp;
-	int ret = 0;
 
-	if (!hdcp || !hdcp->hdcp_shim)
+	if (!hdcp)
 		return -ENOENT;
 
-	mutex_lock(&hdcp->hdcp_mutex);
+	if (hdcp->hdcp_value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
+		return 0;
 
-	if (hdcp->hdcp_value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
-		hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
-		ret = _intel_hdcp_disable(hdcp);
-	}
+	/*
+	 * Setting it out of mutex, so that other on going process like check
+	 * link and auth can check for this state change and terminate themself.
+	 */
+	hdcp->hdcp_value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+	cancel_work_sync(&hdcp->hdcp_enable_work);
 
-	mutex_unlock(&hdcp->hdcp_mutex);
 	cancel_delayed_work_sync(&hdcp->hdcp_check_work);
-	return ret;
+	cancel_delayed_work_sync(&hdcp->hdcp2_check_work);
+
+	mutex_lock(&hdcp->hdcp_mutex);
+	if (hdcp->plat_cap & HDCP_CAPABILITY)
+		if (intel_hdcp_in_force(hdcp))
+			_intel_hdcp_disable(hdcp);
+	if (hdcp->plat_cap & HDCP2_CAPABILITY)
+		if (intel_hdcp2_in_force(hdcp))
+			_intel_hdcp2_disable(hdcp);
+	mutex_unlock(&hdcp->hdcp_mutex);
+
+	return 0;
 }
 
 void intel_hdcp_atomic_check(struct drm_connector *connector,
@@ -1437,7 +1525,7 @@  static int _intel_hdcp2_disable(struct intel_hdcp *hdcp)
 {
 	int ret;
 
-	DRM_ERROR("[%s:%d] HDCP2.2 is being Disabled\n",
+	DRM_INFO("[%s:%d] HDCP2.2 is being Disabled\n",
 		  hdcp->connector->base.name, hdcp->connector->base.base.id);
 
 	ret = hdcp2_disable_encryption(hdcp);