[PATCH 24/43] drm/i915: wait for cp_irq

Ramalingam C
2018-02-14T14:20:43Z

DP HDCP asserts the CP_IRQ to indicate the msg availability and
auth state change at the panel.

Implements a completion structure to communicate the cp_irq
assertion and provides a function to wait for cp_irq with a timeout.

This can be used for implementation of both HDCP1.4 and HDCP2.2

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
drivers/gpu/drm/i915/intel_dp.c | 28 ++++++++++++++++++++++++++--
drivers/gpu/drm/i915/intel_drv.h | 3 +++
drivers/gpu/drm/i915/intel_hdcp.c | 1 +
3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 80476689754f..8847f1a36504 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -4402,6 +4402,7 @@ static bool
intel_dp_short_pulse(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
+ struct intel_connector *connector = intel_dp->attached_connector;
u8 sink_irq_vector = 0;
u8 old_sink_count = intel_dp->sink_count;
bool ret;
@@ -4436,8 +4437,13 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)

if (sink_irq_vector & DP_AUTOMATED_TEST_REQUEST)
intel_dp_handle_test_request(intel_dp);
- if (sink_irq_vector & (DP_CP_IRQ | DP_SINK_SPECIFIC_IRQ))
- DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
+ if (sink_irq_vector & DP_CP_IRQ) {
+ if (connector->hdcp)
+ complete(&connector->hdcp->cp_irq_recved);
+ }
+
+ if (sink_irq_vector & DP_SINK_SPECIFIC_IRQ)
+ DRM_DEBUG_DRIVER("Sink specific irq unhandled\n");
}

intel_dp_check_link_status(intel_dp);
@@ -5049,6 +5055,24 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
pps_unlock(intel_dp);
}

+static int wait_for_cp_irq(struct completion *cp_irq_recved, int timeout)
+{
+ long ret;
+
+ if (completion_done(cp_irq_recved))
+ reinit_completion(cp_irq_recved);
+
+ ret = wait_for_completion_interruptible_timeout(cp_irq_recved,
+ msecs_to_jiffies(
+ timeout));
+ reinit_completion(cp_irq_recved);
+ if (ret < 0)
+ return (int)ret;
+ else if (!ret)
+ return -ETIMEDOUT;
+ return 0;
+}
+
static
int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port,
u8 *an)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 5b170ff7ec14..1c0d324c1044 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -384,6 +384,9 @@ struct intel_hdcp {
struct delayed_work hdcp_check_work;
struct work_struct hdcp_prop_work;
struct work_struct hdcp_enable_work;
+
+ /* To indicate the assertion of CP_IRQ */
+ struct completion cp_irq_recved;
};

struct intel_connector {
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 9147fb17a9fc..31e1af5b43ec 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -695,6 +695,7 @@ int intel_hdcp_init(struct intel_connector *connector,
INIT_WORK(&hdcp->hdcp_prop_work, intel_hdcp_prop_work);
INIT_WORK(&hdcp->hdcp_enable_work, intel_hdcp_enable_work);

+ init_completion(&hdcp->cp_irq_recved);
connector->hdcp = hdcp;
return 0;