drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c
Extension
.c
Size
12837 bytes
Lines
427
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 protection_properties {
	bool supported;
	bool (*process_transaction)(
		struct dc_link *link,
		struct hdcp_protection_message *message_info);
};

static const struct protection_properties non_supported_protection = {
	.supported = false
};

static bool hdmi_14_process_transaction(
	struct dc_link *link,
	struct hdcp_protection_message *message_info)
{
	uint8_t *buff = NULL;
	bool result;
	const uint8_t hdcp_i2c_addr_link_primary = 0x3a; /* 0x74 >> 1*/
	const uint8_t hdcp_i2c_addr_link_secondary = 0x3b; /* 0x76 >> 1*/
	struct i2c_command i2c_command;
	uint8_t offset;
	struct i2c_payload i2c_payloads[] = {
		{ true, 0, 1, 0 },
		/* actual hdcp payload, will be filled later, zeroed for now*/
		{ 0 }
	};

	if (message_info->msg_id == HDCP_MESSAGE_ID_INVALID) {
		DC_LOG_ERROR("%s: Invalid message_info msg_id - %d\n", __func__, message_info->msg_id);
		return false;
	}

	offset = hdcp_i2c_offsets[message_info->msg_id];
	i2c_payloads[0].data = &offset;

	switch (message_info->link) {
	case HDCP_LINK_SECONDARY:
		i2c_payloads[0].address = hdcp_i2c_addr_link_secondary;
		i2c_payloads[1].address = hdcp_i2c_addr_link_secondary;
		break;
	case HDCP_LINK_PRIMARY:
	default:
		i2c_payloads[0].address = hdcp_i2c_addr_link_primary;
		i2c_payloads[1].address = hdcp_i2c_addr_link_primary;
		break;
	}

	if (hdcp_cmd_is_read[message_info->msg_id]) {
		i2c_payloads[1].write = false;
		i2c_command.number_of_payloads = ARRAY_SIZE(i2c_payloads);
		i2c_payloads[1].length = message_info->length;
		i2c_payloads[1].data = message_info->data;
	} else {
		i2c_command.number_of_payloads = 1;
		buff = kzalloc(message_info->length + 1, GFP_KERNEL);

		if (!buff)
			return false;

		buff[0] = offset;
		memmove(&buff[1], message_info->data, message_info->length);
		i2c_payloads[0].length = message_info->length + 1;
		i2c_payloads[0].data = buff;
	}

	i2c_command.payloads = i2c_payloads;
	i2c_command.engine = I2C_COMMAND_ENGINE_HW;//only HW
	i2c_command.speed = link->ddc->ctx->dc->caps.i2c_speed_in_khz;

	result = dm_helpers_submit_i2c(
			link->ctx,
			link,
			&i2c_command);
	kfree(buff);

	return result;
}

static const struct protection_properties hdmi_14_protection = {
	.supported = true,
	.process_transaction = hdmi_14_process_transaction
};

static const uint32_t hdcp_dpcd_addrs[HDCP_MESSAGE_ID_MAX] = {
	[HDCP_MESSAGE_ID_READ_BKSV] = 0x68000,
	[HDCP_MESSAGE_ID_READ_RI_R0] = 0x68005,
	[HDCP_MESSAGE_ID_READ_PJ] = 0xFFFFFFFF,
	[HDCP_MESSAGE_ID_WRITE_AKSV] = 0x68007,
	[HDCP_MESSAGE_ID_WRITE_AINFO] = 0x6803B,
	[HDCP_MESSAGE_ID_WRITE_AN] = 0x6800c,

Annotation

Implementation Notes