drivers/gpu/drm/i915/display/intel_hdmi.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/i915/display/intel_hdmi.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/display/intel_hdmi.c
Extension
.c
Size
101472 bytes
Lines
3400
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct hdcp2_hdmi_msg_timeout {
	u8 msg_id;
	u16 timeout;
};

static const struct hdcp2_hdmi_msg_timeout hdcp2_msg_timeout[] = {
	{ HDCP_2_2_AKE_SEND_CERT, HDCP_2_2_CERT_TIMEOUT_MS, },
	{ HDCP_2_2_AKE_SEND_PAIRING_INFO, HDCP_2_2_PAIRING_TIMEOUT_MS, },
	{ HDCP_2_2_LC_SEND_LPRIME, HDCP_2_2_HDMI_LPRIME_TIMEOUT_MS, },
	{ HDCP_2_2_REP_SEND_RECVID_LIST, HDCP_2_2_RECVID_LIST_TIMEOUT_MS, },
	{ HDCP_2_2_REP_STREAM_READY, HDCP_2_2_STREAM_READY_TIMEOUT_MS, },
};

static
int intel_hdmi_hdcp2_read_rx_status(struct intel_digital_port *dig_port,
				    u8 *rx_status)
{
	return intel_hdmi_hdcp_read(dig_port,
				    HDCP_2_2_HDMI_REG_RXSTATUS_OFFSET,
				    rx_status,
				    HDCP_2_2_HDMI_RXSTATUS_LEN);
}

static int get_hdcp2_msg_timeout(u8 msg_id, bool is_paired)
{
	int i;

	if (msg_id == HDCP_2_2_AKE_SEND_HPRIME) {
		if (is_paired)
			return HDCP_2_2_HPRIME_PAIRED_TIMEOUT_MS;
		else
			return HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT_MS;
	}

	for (i = 0; i < ARRAY_SIZE(hdcp2_msg_timeout); i++) {
		if (hdcp2_msg_timeout[i].msg_id == msg_id)
			return hdcp2_msg_timeout[i].timeout;
	}

	return -EINVAL;
}

static int
hdcp2_detect_msg_availability(struct intel_digital_port *dig_port,
			      u8 msg_id, bool *msg_ready,
			      ssize_t *msg_sz)
{
	struct intel_display *display = to_intel_display(dig_port);
	u8 rx_status[HDCP_2_2_HDMI_RXSTATUS_LEN];
	int ret;

	ret = intel_hdmi_hdcp2_read_rx_status(dig_port, rx_status);
	if (ret < 0) {
		drm_dbg_kms(display->drm, "rx_status read failed. Err %d\n",
			    ret);
		return ret;
	}

	*msg_sz = ((HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(rx_status[1]) << 8) |
		  rx_status[0]);

	if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST)
		*msg_ready = (HDCP_2_2_HDMI_RXSTATUS_READY(rx_status[1]) &&
			     *msg_sz);
	else
		*msg_ready = *msg_sz;

	return 0;
}

static ssize_t
intel_hdmi_hdcp2_wait_for_msg(struct intel_digital_port *dig_port,
			      u8 msg_id, bool paired)
{
	struct intel_display *display = to_intel_display(dig_port);
	bool msg_ready = false;
	int timeout, ret;
	ssize_t msg_sz = 0;

	timeout = get_hdcp2_msg_timeout(msg_id, paired);
	if (timeout < 0)
		return timeout;

	ret = poll_timeout_us(ret = hdcp2_detect_msg_availability(dig_port, msg_id,
								  &msg_ready, &msg_sz),
			      !ret && msg_ready && msg_sz,
			      4000, timeout * 1000, false);
	if (ret)
		drm_dbg_kms(display->drm,
			    "msg_id: %d, ret: %d, timeout: %d\n",

Annotation

Implementation Notes