brintos

brintos / linux-shallow public Read only

0
0
Text · 12.5 KiB · 1313a7c Raw
426 lines · c
1/*2 * Copyright 2019 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26#include "dm_services.h"27#include "dm_helpers.h"28#include "include/hdcp_msg_types.h"29#include "include/signal_types.h"30#include "core_types.h"31#include "link.h"32#include "link_hwss.h"33#include "link/protocols/link_dpcd.h"34 35#define DC_LOGGER \36	link->ctx->logger37#define HDCP14_KSV_SIZE 538#define HDCP14_MAX_KSV_FIFO_SIZE 127*HDCP14_KSV_SIZE39 40static const bool hdcp_cmd_is_read[HDCP_MESSAGE_ID_MAX] = {41	[HDCP_MESSAGE_ID_READ_BKSV] = true,42	[HDCP_MESSAGE_ID_READ_RI_R0] = true,43	[HDCP_MESSAGE_ID_READ_PJ] = true,44	[HDCP_MESSAGE_ID_WRITE_AKSV] = false,45	[HDCP_MESSAGE_ID_WRITE_AINFO] = false,46	[HDCP_MESSAGE_ID_WRITE_AN] = false,47	[HDCP_MESSAGE_ID_READ_VH_X] = true,48	[HDCP_MESSAGE_ID_READ_VH_0] = true,49	[HDCP_MESSAGE_ID_READ_VH_1] = true,50	[HDCP_MESSAGE_ID_READ_VH_2] = true,51	[HDCP_MESSAGE_ID_READ_VH_3] = true,52	[HDCP_MESSAGE_ID_READ_VH_4] = true,53	[HDCP_MESSAGE_ID_READ_BCAPS] = true,54	[HDCP_MESSAGE_ID_READ_BSTATUS] = true,55	[HDCP_MESSAGE_ID_READ_KSV_FIFO] = true,56	[HDCP_MESSAGE_ID_READ_BINFO] = true,57	[HDCP_MESSAGE_ID_HDCP2VERSION] = true,58	[HDCP_MESSAGE_ID_RX_CAPS] = true,59	[HDCP_MESSAGE_ID_WRITE_AKE_INIT] = false,60	[HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = true,61	[HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = false,62	[HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = false,63	[HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = true,64	[HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = true,65	[HDCP_MESSAGE_ID_WRITE_LC_INIT] = false,66	[HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = true,67	[HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = false,68	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = true,69	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = false,70	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = false,71	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = true,72	[HDCP_MESSAGE_ID_READ_RXSTATUS] = true,73	[HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = false,74};75 76static const uint8_t hdcp_i2c_offsets[HDCP_MESSAGE_ID_MAX] = {77	[HDCP_MESSAGE_ID_READ_BKSV] = 0x0,78	[HDCP_MESSAGE_ID_READ_RI_R0] = 0x8,79	[HDCP_MESSAGE_ID_READ_PJ] = 0xA,80	[HDCP_MESSAGE_ID_WRITE_AKSV] = 0x10,81	[HDCP_MESSAGE_ID_WRITE_AINFO] = 0x15,82	[HDCP_MESSAGE_ID_WRITE_AN] = 0x18,83	[HDCP_MESSAGE_ID_READ_VH_X] = 0x20,84	[HDCP_MESSAGE_ID_READ_VH_0] = 0x20,85	[HDCP_MESSAGE_ID_READ_VH_1] = 0x24,86	[HDCP_MESSAGE_ID_READ_VH_2] = 0x28,87	[HDCP_MESSAGE_ID_READ_VH_3] = 0x2C,88	[HDCP_MESSAGE_ID_READ_VH_4] = 0x30,89	[HDCP_MESSAGE_ID_READ_BCAPS] = 0x40,90	[HDCP_MESSAGE_ID_READ_BSTATUS] = 0x41,91	[HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x43,92	[HDCP_MESSAGE_ID_READ_BINFO] = 0xFF,93	[HDCP_MESSAGE_ID_HDCP2VERSION] = 0x50,94	[HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x60,95	[HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x80,96	[HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x60,97	[HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x60,98	[HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x80,99	[HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x80,100	[HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x60,101	[HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x80,102	[HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x60,103	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x80,104	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x60,105	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x60,106	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x80,107	[HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x70,108	[HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x0,109};110 111struct protection_properties {112	bool supported;113	bool (*process_transaction)(114		struct dc_link *link,115		struct hdcp_protection_message *message_info);116};117 118static const struct protection_properties non_supported_protection = {119	.supported = false120};121 122static bool hdmi_14_process_transaction(123	struct dc_link *link,124	struct hdcp_protection_message *message_info)125{126	uint8_t *buff = NULL;127	bool result;128	const uint8_t hdcp_i2c_addr_link_primary = 0x3a; /* 0x74 >> 1*/129	const uint8_t hdcp_i2c_addr_link_secondary = 0x3b; /* 0x76 >> 1*/130	struct i2c_command i2c_command;131	uint8_t offset;132	struct i2c_payload i2c_payloads[] = {133		{ true, 0, 1, 0 },134		/* actual hdcp payload, will be filled later, zeroed for now*/135		{ 0 }136	};137 138	if (message_info->msg_id == HDCP_MESSAGE_ID_INVALID) {139		DC_LOG_ERROR("%s: Invalid message_info msg_id - %d\n", __func__, message_info->msg_id);140		return false;141	}142 143	offset = hdcp_i2c_offsets[message_info->msg_id];144	i2c_payloads[0].data = &offset;145 146	switch (message_info->link) {147	case HDCP_LINK_SECONDARY:148		i2c_payloads[0].address = hdcp_i2c_addr_link_secondary;149		i2c_payloads[1].address = hdcp_i2c_addr_link_secondary;150		break;151	case HDCP_LINK_PRIMARY:152	default:153		i2c_payloads[0].address = hdcp_i2c_addr_link_primary;154		i2c_payloads[1].address = hdcp_i2c_addr_link_primary;155		break;156	}157 158	if (hdcp_cmd_is_read[message_info->msg_id]) {159		i2c_payloads[1].write = false;160		i2c_command.number_of_payloads = ARRAY_SIZE(i2c_payloads);161		i2c_payloads[1].length = message_info->length;162		i2c_payloads[1].data = message_info->data;163	} else {164		i2c_command.number_of_payloads = 1;165		buff = kzalloc(message_info->length + 1, GFP_KERNEL);166 167		if (!buff)168			return false;169 170		buff[0] = offset;171		memmove(&buff[1], message_info->data, message_info->length);172		i2c_payloads[0].length = message_info->length + 1;173		i2c_payloads[0].data = buff;174	}175 176	i2c_command.payloads = i2c_payloads;177	i2c_command.engine = I2C_COMMAND_ENGINE_HW;//only HW178	i2c_command.speed = link->ddc->ctx->dc->caps.i2c_speed_in_khz;179 180	result = dm_helpers_submit_i2c(181			link->ctx,182			link,183			&i2c_command);184	kfree(buff);185 186	return result;187}188 189static const struct protection_properties hdmi_14_protection = {190	.supported = true,191	.process_transaction = hdmi_14_process_transaction192};193 194static const uint32_t hdcp_dpcd_addrs[HDCP_MESSAGE_ID_MAX] = {195	[HDCP_MESSAGE_ID_READ_BKSV] = 0x68000,196	[HDCP_MESSAGE_ID_READ_RI_R0] = 0x68005,197	[HDCP_MESSAGE_ID_READ_PJ] = 0xFFFFFFFF,198	[HDCP_MESSAGE_ID_WRITE_AKSV] = 0x68007,199	[HDCP_MESSAGE_ID_WRITE_AINFO] = 0x6803B,200	[HDCP_MESSAGE_ID_WRITE_AN] = 0x6800c,201	[HDCP_MESSAGE_ID_READ_VH_X] = 0x68014,202	[HDCP_MESSAGE_ID_READ_VH_0] = 0x68014,203	[HDCP_MESSAGE_ID_READ_VH_1] = 0x68018,204	[HDCP_MESSAGE_ID_READ_VH_2] = 0x6801c,205	[HDCP_MESSAGE_ID_READ_VH_3] = 0x68020,206	[HDCP_MESSAGE_ID_READ_VH_4] = 0x68024,207	[HDCP_MESSAGE_ID_READ_BCAPS] = 0x68028,208	[HDCP_MESSAGE_ID_READ_BSTATUS] = 0x68029,209	[HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x6802c,210	[HDCP_MESSAGE_ID_READ_BINFO] = 0x6802a,211	[HDCP_MESSAGE_ID_RX_CAPS] = 0x6921d,212	[HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x69000,213	[HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x6900b,214	[HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x69220,215	[HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x692a0,216	[HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x692c0,217	[HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x692e0,218	[HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x692f0,219	[HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x692f8,220	[HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x69318,221	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x69330,222	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x693e0,223	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x693f0,224	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x69473,225	[HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x69493,226	[HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x69494227};228 229static bool dpcd_access_helper(230	struct dc_link *link,231	uint32_t length,232	uint8_t *data,233	uint32_t dpcd_addr,234	bool is_read)235{236	enum dc_status status;237	uint32_t cur_length = 0;238	uint32_t offset = 0;239	uint32_t ksv_read_size = 0x6803b - 0x6802c;240 241	/* Read KSV, need repeatedly handle */242	if (dpcd_addr == 0x6802c) {243		if (length % HDCP14_KSV_SIZE) {244			DC_LOG_ERROR("%s: KsvFifo Size(%d) is not a multiple of HDCP14_KSV_SIZE(%d)\n",245				__func__,246				length,247				HDCP14_KSV_SIZE);248		}249		if (length > HDCP14_MAX_KSV_FIFO_SIZE) {250			DC_LOG_ERROR("%s: KsvFifo Size(%d) is greater than HDCP14_MAX_KSV_FIFO_SIZE(%d)\n",251				__func__,252				length,253				HDCP14_MAX_KSV_FIFO_SIZE);254		}255 256		DC_LOG_ERROR("%s: Reading %d Ksv(s) from KsvFifo\n",257			__func__,258			length / HDCP14_KSV_SIZE);259 260		while (length > 0) {261			if (length > ksv_read_size) {262				status = core_link_read_dpcd(263					link,264					dpcd_addr + offset,265					data + offset,266					ksv_read_size);267 268				data += ksv_read_size;269				length -= ksv_read_size;270			} else {271				status = core_link_read_dpcd(272					link,273					dpcd_addr + offset,274					data + offset,275					length);276 277				data += length;278				length = 0;279			}280 281			if (status != DC_OK)282				return false;283		}284	} else {285		while (length > 0) {286			if (length > DEFAULT_AUX_MAX_DATA_SIZE)287				cur_length = DEFAULT_AUX_MAX_DATA_SIZE;288			else289				cur_length = length;290 291			if (is_read) {292				status = core_link_read_dpcd(293					link,294					dpcd_addr + offset,295					data + offset,296					cur_length);297			} else {298				status = core_link_write_dpcd(299					link,300					dpcd_addr + offset,301					data + offset,302					cur_length);303			}304 305			if (status != DC_OK)306				return false;307 308			length -= cur_length;309			offset += cur_length;310		}311	}312	return true;313}314 315static bool dp_11_process_transaction(316	struct dc_link *link,317	struct hdcp_protection_message *message_info)318{319	if (message_info->msg_id == HDCP_MESSAGE_ID_INVALID) {320		DC_LOG_ERROR("%s: Invalid message_info msg_id - %d\n", __func__, message_info->msg_id);321		return false;322	}323 324	return dpcd_access_helper(325		link,326		message_info->length,327		message_info->data,328		hdcp_dpcd_addrs[message_info->msg_id],329		hdcp_cmd_is_read[message_info->msg_id]);330}331 332static const struct protection_properties dp_11_protection = {333	.supported = true,334	.process_transaction = dp_11_process_transaction335};336 337static const struct protection_properties *get_protection_properties_by_signal(338	struct dc_link *link,339	enum signal_type st,340	enum hdcp_version version)341{342	switch (version) {343	case HDCP_VERSION_14:344		switch (st) {345		case SIGNAL_TYPE_DVI_SINGLE_LINK:346		case SIGNAL_TYPE_DVI_DUAL_LINK:347		case SIGNAL_TYPE_HDMI_TYPE_A:348			return &hdmi_14_protection;349		case SIGNAL_TYPE_DISPLAY_PORT:350			if (link &&351				(link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER ||352				link->dpcd_caps.dongle_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER)) {353				return &non_supported_protection;354			}355			return &dp_11_protection;356		case SIGNAL_TYPE_DISPLAY_PORT_MST:357		case SIGNAL_TYPE_EDP:358			return &dp_11_protection;359		default:360			return &non_supported_protection;361		}362		break;363	case HDCP_VERSION_22:364		switch (st) {365		case SIGNAL_TYPE_DVI_SINGLE_LINK:366		case SIGNAL_TYPE_DVI_DUAL_LINK:367		case SIGNAL_TYPE_HDMI_TYPE_A:368			return &hdmi_14_protection; //todo version2.2369		case SIGNAL_TYPE_DISPLAY_PORT:370		case SIGNAL_TYPE_DISPLAY_PORT_MST:371		case SIGNAL_TYPE_EDP:372			return &dp_11_protection;  //todo version2.2373		default:374			return &non_supported_protection;375		}376		break;377	default:378		return &non_supported_protection;379	}380}381 382enum hdcp_message_status dc_process_hdcp_msg(383	enum signal_type signal,384	struct dc_link *link,385	struct hdcp_protection_message *message_info)386{387	enum hdcp_message_status status = HDCP_MESSAGE_FAILURE;388	uint32_t i = 0;389 390	const struct protection_properties *protection_props;391 392	if (!message_info)393		return HDCP_MESSAGE_UNSUPPORTED;394 395	if (message_info->msg_id < HDCP_MESSAGE_ID_READ_BKSV ||396		message_info->msg_id >= HDCP_MESSAGE_ID_MAX)397		return HDCP_MESSAGE_UNSUPPORTED;398 399	protection_props =400		get_protection_properties_by_signal(401			link,402			signal,403			message_info->version);404 405	if (!protection_props->supported)406		return HDCP_MESSAGE_UNSUPPORTED;407 408	if (protection_props->process_transaction(409		link,410		message_info)) {411		status = HDCP_MESSAGE_SUCCESS;412	} else {413		for (i = 0; i < message_info->max_retries; i++) {414			if (protection_props->process_transaction(415						link,416						message_info)) {417				status = HDCP_MESSAGE_SUCCESS;418				break;419			}420		}421	}422 423	return status;424}425 426