14c283fdaSBhawanpreet Lakha/*
24c283fdaSBhawanpreet Lakha * Copyright 2019 Advanced Micro Devices, Inc.
34c283fdaSBhawanpreet Lakha *
44c283fdaSBhawanpreet Lakha * Permission is hereby granted, free of charge, to any person obtaining a
54c283fdaSBhawanpreet Lakha * copy of this software and associated documentation files (the "Software"),
64c283fdaSBhawanpreet Lakha * to deal in the Software without restriction, including without limitation
74c283fdaSBhawanpreet Lakha * the rights to use, copy, modify, merge, publish, distribute, sublicense,
84c283fdaSBhawanpreet Lakha * and/or sell copies of the Software, and to permit persons to whom the
94c283fdaSBhawanpreet Lakha * Software is furnished to do so, subject to the following conditions:
104c283fdaSBhawanpreet Lakha *
114c283fdaSBhawanpreet Lakha * The above copyright notice and this permission notice shall be included in
124c283fdaSBhawanpreet Lakha * all copies or substantial portions of the Software.
134c283fdaSBhawanpreet Lakha *
144c283fdaSBhawanpreet Lakha * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
154c283fdaSBhawanpreet Lakha * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
164c283fdaSBhawanpreet Lakha * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
174c283fdaSBhawanpreet Lakha * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
184c283fdaSBhawanpreet Lakha * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
194c283fdaSBhawanpreet Lakha * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
204c283fdaSBhawanpreet Lakha * OTHER DEALINGS IN THE SOFTWARE.
214c283fdaSBhawanpreet Lakha *
224c283fdaSBhawanpreet Lakha * Authors: AMD
234c283fdaSBhawanpreet Lakha *
244c283fdaSBhawanpreet Lakha */
254c283fdaSBhawanpreet Lakha
264c283fdaSBhawanpreet Lakha#include <linux/slab.h>
274c283fdaSBhawanpreet Lakha
284c283fdaSBhawanpreet Lakha#include "dm_services.h"
294c283fdaSBhawanpreet Lakha#include "dm_helpers.h"
304c283fdaSBhawanpreet Lakha#include "include/hdcp_types.h"
314c283fdaSBhawanpreet Lakha#include "include/i2caux_interface.h"
324c283fdaSBhawanpreet Lakha#include "include/signal_types.h"
334c283fdaSBhawanpreet Lakha#include "core_types.h"
344c283fdaSBhawanpreet Lakha#include "dc_link_ddc.h"
354c283fdaSBhawanpreet Lakha#include "link_hwss.h"
3630adeee5SWesley Chalmers#include "inc/link_dpcd.h"
374c283fdaSBhawanpreet Lakha
384c283fdaSBhawanpreet Lakha#define DC_LOGGER \
394c283fdaSBhawanpreet Lakha	link->ctx->logger
404c283fdaSBhawanpreet Lakha#define HDCP14_KSV_SIZE 5
414c283fdaSBhawanpreet Lakha#define HDCP14_MAX_KSV_FIFO_SIZE 127*HDCP14_KSV_SIZE
424c283fdaSBhawanpreet Lakha
438e6fafd5SDan Carpenterstatic const bool hdcp_cmd_is_read[HDCP_MESSAGE_ID_MAX] = {
444c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_BKSV] = true,
454c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_RI_R0] = true,
464c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_PJ] = true,
474c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AKSV] = false,
484c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AINFO] = false,
494c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AN] = false,
504c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_X] = true,
514c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_0] = true,
524c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_1] = true,
534c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_2] = true,
544c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_3] = true,
554c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_4] = true,
564c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_BCAPS] = true,
574c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_BSTATUS] = true,
584c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_KSV_FIFO] = true,
594c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_BINFO] = true,
604c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_HDCP2VERSION] = true,
614c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_RX_CAPS] = true,
624c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AKE_INIT] = false,
634c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = true,
644c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = false,
654c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = false,
664c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = true,
674c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = true,
684c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_LC_INIT] = false,
694c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = true,
704c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = false,
714c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = true,
724c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = false,
734c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = false,
744c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = true,
754c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_RXSTATUS] = true,
764c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = false
774c283fdaSBhawanpreet Lakha};
784c283fdaSBhawanpreet Lakha
798e6fafd5SDan Carpenterstatic const uint8_t hdcp_i2c_offsets[HDCP_MESSAGE_ID_MAX] = {
804c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_BKSV] = 0x0,
814c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_RI_R0] = 0x8,
824c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_PJ] = 0xA,
834c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AKSV] = 0x10,
844c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AINFO] = 0x15,
854c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AN] = 0x18,
864c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_X] = 0x20,
874c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_0] = 0x20,
884c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_1] = 0x24,
894c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_2] = 0x28,
904c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_3] = 0x2C,
914c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_4] = 0x30,
924c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_BCAPS] = 0x40,
934c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_BSTATUS] = 0x41,
944c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x43,
954c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_BINFO] = 0xFF,
964c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_HDCP2VERSION] = 0x50,
974c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x60,
984c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x80,
994c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x60,
1004c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x60,
1014c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x80,
1024c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x80,
1034c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x60,
1044c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x80,
1054c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x60,
1064c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x80,
1074c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x60,
1084c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x60,
1094c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x80,
1108e6fafd5SDan Carpenter	[HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x70,
1118e6fafd5SDan Carpenter	[HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x0,
1124c283fdaSBhawanpreet Lakha};
1134c283fdaSBhawanpreet Lakha
1144c283fdaSBhawanpreet Lakhastruct protection_properties {
1154c283fdaSBhawanpreet Lakha	bool supported;
1164c283fdaSBhawanpreet Lakha	bool (*process_transaction)(
1174c283fdaSBhawanpreet Lakha		struct dc_link *link,
1184c283fdaSBhawanpreet Lakha		struct hdcp_protection_message *message_info);
1194c283fdaSBhawanpreet Lakha};
1204c283fdaSBhawanpreet Lakha
1214c283fdaSBhawanpreet Lakhastatic const struct protection_properties non_supported_protection = {
1224c283fdaSBhawanpreet Lakha	.supported = false
1234c283fdaSBhawanpreet Lakha};
1244c283fdaSBhawanpreet Lakha
1254c283fdaSBhawanpreet Lakhastatic bool hdmi_14_process_transaction(
1264c283fdaSBhawanpreet Lakha	struct dc_link *link,
1274c283fdaSBhawanpreet Lakha	struct hdcp_protection_message *message_info)
1284c283fdaSBhawanpreet Lakha{
1294c283fdaSBhawanpreet Lakha	uint8_t *buff = NULL;
1304c283fdaSBhawanpreet Lakha	bool result;
1314c283fdaSBhawanpreet Lakha	const uint8_t hdcp_i2c_addr_link_primary = 0x3a; /* 0x74 >> 1*/
1324c283fdaSBhawanpreet Lakha	const uint8_t hdcp_i2c_addr_link_secondary = 0x3b; /* 0x76 >> 1*/
1334c283fdaSBhawanpreet Lakha	struct i2c_command i2c_command;
1344c283fdaSBhawanpreet Lakha	uint8_t offset = hdcp_i2c_offsets[message_info->msg_id];
1354c283fdaSBhawanpreet Lakha	struct i2c_payload i2c_payloads[] = {
1364c283fdaSBhawanpreet Lakha		{ true, 0, 1, &offset },
1374c283fdaSBhawanpreet Lakha		/* actual hdcp payload, will be filled later, zeroed for now*/
1384c283fdaSBhawanpreet Lakha		{ 0 }
1394c283fdaSBhawanpreet Lakha	};
1404c283fdaSBhawanpreet Lakha
1414c283fdaSBhawanpreet Lakha	switch (message_info->link) {
1424c283fdaSBhawanpreet Lakha	case HDCP_LINK_SECONDARY:
1434c283fdaSBhawanpreet Lakha		i2c_payloads[0].address = hdcp_i2c_addr_link_secondary;
1444c283fdaSBhawanpreet Lakha		i2c_payloads[1].address = hdcp_i2c_addr_link_secondary;
1454c283fdaSBhawanpreet Lakha		break;
1464c283fdaSBhawanpreet Lakha	case HDCP_LINK_PRIMARY:
1474c283fdaSBhawanpreet Lakha	default:
1484c283fdaSBhawanpreet Lakha		i2c_payloads[0].address = hdcp_i2c_addr_link_primary;
1494c283fdaSBhawanpreet Lakha		i2c_payloads[1].address = hdcp_i2c_addr_link_primary;
1504c283fdaSBhawanpreet Lakha		break;
1514c283fdaSBhawanpreet Lakha	}
1524c283fdaSBhawanpreet Lakha
1534c283fdaSBhawanpreet Lakha	if (hdcp_cmd_is_read[message_info->msg_id]) {
1544c283fdaSBhawanpreet Lakha		i2c_payloads[1].write = false;
1554c283fdaSBhawanpreet Lakha		i2c_command.number_of_payloads = ARRAY_SIZE(i2c_payloads);
1564c283fdaSBhawanpreet Lakha		i2c_payloads[1].length = message_info->length;
1574c283fdaSBhawanpreet Lakha		i2c_payloads[1].data = message_info->data;
1584c283fdaSBhawanpreet Lakha	} else {
1594c283fdaSBhawanpreet Lakha		i2c_command.number_of_payloads = 1;
1604c283fdaSBhawanpreet Lakha		buff = kzalloc(message_info->length + 1, GFP_KERNEL);
1614c283fdaSBhawanpreet Lakha
1624c283fdaSBhawanpreet Lakha		if (!buff)
1634c283fdaSBhawanpreet Lakha			return false;
1644c283fdaSBhawanpreet Lakha
1654c283fdaSBhawanpreet Lakha		buff[0] = offset;
1664c283fdaSBhawanpreet Lakha		memmove(&buff[1], message_info->data, message_info->length);
1674c283fdaSBhawanpreet Lakha		i2c_payloads[0].length = message_info->length + 1;
1684c283fdaSBhawanpreet Lakha		i2c_payloads[0].data = buff;
1694c283fdaSBhawanpreet Lakha	}
1704c283fdaSBhawanpreet Lakha
1714c283fdaSBhawanpreet Lakha	i2c_command.payloads = i2c_payloads;
1724c283fdaSBhawanpreet Lakha	i2c_command.engine = I2C_COMMAND_ENGINE_HW;//only HW
1734c283fdaSBhawanpreet Lakha	i2c_command.speed = link->ddc->ctx->dc->caps.i2c_speed_in_khz;
1744c283fdaSBhawanpreet Lakha
1754c283fdaSBhawanpreet Lakha	result = dm_helpers_submit_i2c(
1764c283fdaSBhawanpreet Lakha			link->ctx,
1774c283fdaSBhawanpreet Lakha			link,
1784c283fdaSBhawanpreet Lakha			&i2c_command);
1795e8f5477Szhong jiang	kfree(buff);
1804c283fdaSBhawanpreet Lakha
1814c283fdaSBhawanpreet Lakha	return result;
1824c283fdaSBhawanpreet Lakha}
1834c283fdaSBhawanpreet Lakha
1844c283fdaSBhawanpreet Lakhastatic const struct protection_properties hdmi_14_protection = {
1854c283fdaSBhawanpreet Lakha	.supported = true,
1864c283fdaSBhawanpreet Lakha	.process_transaction = hdmi_14_process_transaction
1874c283fdaSBhawanpreet Lakha};
1884c283fdaSBhawanpreet Lakha
1898e6fafd5SDan Carpenterstatic const uint32_t hdcp_dpcd_addrs[HDCP_MESSAGE_ID_MAX] = {
1904c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_BKSV] = 0x68000,
1914c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_RI_R0] = 0x68005,
1924c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_PJ] = 0xFFFFFFFF,
1934c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AKSV] = 0x68007,
1944c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AINFO] = 0x6803B,
1954c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AN] = 0x6800c,
1964c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_X] = 0x68014,
1974c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_0] = 0x68014,
1984c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_1] = 0x68018,
1994c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_2] = 0x6801c,
2004c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_3] = 0x68020,
2014c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_VH_4] = 0x68024,
2024c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_BCAPS] = 0x68028,
2034c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_BSTATUS] = 0x68029,
2044c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x6802c,
2054c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_BINFO] = 0x6802a,
2064c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_RX_CAPS] = 0x6921d,
2074c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x69000,
2084c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x6900b,
2094c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x69220,
2104c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x692a0,
2114c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x692c0,
2124c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x692e0,
2134c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x692f0,
2144c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x692f8,
2154c283fdaSBhawanpreet Lakha	[HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x69318,
216