Skip to content

Commit cf9cb35

Browse files
ramalingamcdanvet
authored andcommitted
drm/i915: CP_IRQ handling for DP HDCP2.2 msgs
Implements the Waitqueue is created to wait for CP_IRQ Signaling the CP_IRQ arrival through atomic variable. For applicable DP HDCP2.2 msgs read wait for CP_IRQ. As per HDCP2.2 spec "HDCP Transmitters must process CP_IRQ interrupts when they are received from HDCP Receivers" Without CP_IRQ processing, DP HDCP2.2 H_Prime msg was getting corrupted while reading it based on corresponding status bit. This creates the random failures in reading the DP HDCP2.2 msgs. v2: CP_IRQ arrival is tracked based on the atomic val inc [daniel] Recording the reviewed-by Daniel from IRC. Signed-off-by: Ramalingam C <[email protected]> Reviewed-by: Daniel Vetter <[email protected]> Signed-off-by: Daniel Vetter <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 2d4254e commit cf9cb35

File tree

3 files changed

+35
-15
lines changed

3 files changed

+35
-15
lines changed

drivers/gpu/drm/i915/intel_dp.c

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5623,6 +5623,18 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
56235623
edp_panel_vdd_off_sync(intel_dp);
56245624
}
56255625

5626+
static void intel_dp_hdcp_wait_for_cp_irq(struct intel_hdcp *hdcp, int timeout)
5627+
{
5628+
long ret;
5629+
5630+
#define C (hdcp->cp_irq_count_cached != atomic_read(&hdcp->cp_irq_count))
5631+
ret = wait_event_interruptible_timeout(hdcp->cp_irq_queue, C,
5632+
msecs_to_jiffies(timeout));
5633+
5634+
if (!ret)
5635+
DRM_DEBUG_KMS("Timedout at waiting for CP_IRQ\n");
5636+
}
5637+
56265638
static
56275639
int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port,
56285640
u8 *an)
@@ -5967,14 +5979,13 @@ intel_dp_hdcp2_wait_for_msg(struct intel_digital_port *intel_dig_port,
59675979
mdelay(timeout);
59685980
ret = 0;
59695981
} else {
5970-
/* TODO: In case if you need to wait on CP_IRQ, do it here */
5971-
ret = __wait_for(ret =
5972-
hdcp2_detect_msg_availability(intel_dig_port,
5973-
msg_id,
5974-
&msg_ready),
5975-
!ret && msg_ready, timeout * 1000,
5976-
1000, 5 * 1000);
5977-
5982+
/*
5983+
* As we want to check the msg availability at timeout, Ignoring
5984+
* the timeout at wait for CP_IRQ.
5985+
*/
5986+
intel_dp_hdcp_wait_for_cp_irq(hdcp, timeout);
5987+
ret = hdcp2_detect_msg_availability(intel_dig_port,
5988+
msg_id, &msg_ready);
59785989
if (!msg_ready)
59795990
ret = -ETIMEDOUT;
59805991
}
@@ -6001,6 +6012,8 @@ static
60016012
int intel_dp_hdcp2_write_msg(struct intel_digital_port *intel_dig_port,
60026013
void *buf, size_t size)
60036014
{
6015+
struct intel_dp *dp = &intel_dig_port->dp;
6016+
struct intel_hdcp *hdcp = &dp->attached_connector->hdcp;
60046017
unsigned int offset;
60056018
u8 *byte = buf;
60066019
ssize_t ret, bytes_to_write, len;
@@ -6016,6 +6029,8 @@ int intel_dp_hdcp2_write_msg(struct intel_digital_port *intel_dig_port,
60166029
bytes_to_write = size - 1;
60176030
byte++;
60186031

6032+
hdcp->cp_irq_count_cached = atomic_read(&hdcp->cp_irq_count);
6033+
60196034
while (bytes_to_write) {
60206035
len = bytes_to_write > DP_AUX_MAX_PAYLOAD_BYTES ?
60216036
DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_write;

drivers/gpu/drm/i915/intel_drv.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,14 @@ struct intel_hdcp {
474474
* over re-Auth has to be triggered.
475475
*/
476476
u32 seq_num_m;
477+
478+
/*
479+
* Work queue to signal the CP_IRQ. Used for the waiters to read the
480+
* available information from HDCP DP sink.
481+
*/
482+
wait_queue_head_t cp_irq_queue;
483+
atomic_t cp_irq_count;
484+
int cp_irq_count_cached;
477485
};
478486

479487
struct intel_connector {

drivers/gpu/drm/i915/intel_hdcp.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1806,6 +1806,7 @@ int intel_hdcp_init(struct intel_connector *connector,
18061806

18071807
if (is_hdcp2_supported(dev_priv))
18081808
intel_hdcp2_init(connector);
1809+
init_waitqueue_head(&hdcp->cp_irq_queue);
18091810

18101811
return 0;
18111812
}
@@ -1935,12 +1936,8 @@ void intel_hdcp_handle_cp_irq(struct intel_connector *connector)
19351936
if (!hdcp->shim)
19361937
return;
19371938

1938-
/*
1939-
* CP_IRQ could be triggered due to 1. HDCP2.2 auth msgs availability,
1940-
* 2. link failure and 3. repeater reauth request. At present we dont
1941-
* handle the CP_IRQ for the HDCP2.2 auth msg availability for read.
1942-
* To handle other two causes for CP_IRQ we have the work_fn which is
1943-
* scheduled here.
1944-
*/
1939+
atomic_inc(&connector->hdcp.cp_irq_count);
1940+
wake_up_all(&connector->hdcp.cp_irq_queue);
1941+
19451942
schedule_delayed_work(&hdcp->check_work, 0);
19461943
}

0 commit comments

Comments
 (0)