1 /*
2  * Copyright 2019 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * 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 OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: AMD
23  *
24  */
25 
26 #include "hdcp.h"
27 
28 #define MIN(a, b) ((a) < (b) ? (a) : (b))
29 #define HDCP_I2C_ADDR 0x3a	/* 0x74 >> 1*/
30 #define KSV_READ_SIZE 0xf	/* 0x6803b - 0x6802c */
31 #define HDCP_MAX_AUX_TRANSACTION_SIZE 16
32 
33 enum mod_hdcp_ddc_message_id {
34 	MOD_HDCP_MESSAGE_ID_INVALID = -1,
35 
36 	/* HDCP 1.4 */
37 
38 	MOD_HDCP_MESSAGE_ID_READ_BKSV = 0,
39 	MOD_HDCP_MESSAGE_ID_READ_RI_R0,
40 	MOD_HDCP_MESSAGE_ID_WRITE_AKSV,
41 	MOD_HDCP_MESSAGE_ID_WRITE_AINFO,
42 	MOD_HDCP_MESSAGE_ID_WRITE_AN,
43 	MOD_HDCP_MESSAGE_ID_READ_VH_X,
44 	MOD_HDCP_MESSAGE_ID_READ_VH_0,
45 	MOD_HDCP_MESSAGE_ID_READ_VH_1,
46 	MOD_HDCP_MESSAGE_ID_READ_VH_2,
47 	MOD_HDCP_MESSAGE_ID_READ_VH_3,
48 	MOD_HDCP_MESSAGE_ID_READ_VH_4,
49 	MOD_HDCP_MESSAGE_ID_READ_BCAPS,
50 	MOD_HDCP_MESSAGE_ID_READ_BSTATUS,
51 	MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO,
52 	MOD_HDCP_MESSAGE_ID_READ_BINFO,
53 
54 	MOD_HDCP_MESSAGE_ID_MAX
55 };
56 
57 static const uint8_t hdcp_i2c_offsets[] = {
58 	[MOD_HDCP_MESSAGE_ID_READ_BKSV] = 0x0,
59 	[MOD_HDCP_MESSAGE_ID_READ_RI_R0] = 0x8,
60 	[MOD_HDCP_MESSAGE_ID_WRITE_AKSV] = 0x10,
61 	[MOD_HDCP_MESSAGE_ID_WRITE_AINFO] = 0x15,
62 	[MOD_HDCP_MESSAGE_ID_WRITE_AN] = 0x18,
63 	[MOD_HDCP_MESSAGE_ID_READ_VH_X] = 0x20,
64 	[MOD_HDCP_MESSAGE_ID_READ_VH_0] = 0x20,
65 	[MOD_HDCP_MESSAGE_ID_READ_VH_1] = 0x24,
66 	[MOD_HDCP_MESSAGE_ID_READ_VH_2] = 0x28,
67 	[MOD_HDCP_MESSAGE_ID_READ_VH_3] = 0x2C,
68 	[MOD_HDCP_MESSAGE_ID_READ_VH_4] = 0x30,
69 	[MOD_HDCP_MESSAGE_ID_READ_BCAPS] = 0x40,
70 	[MOD_HDCP_MESSAGE_ID_READ_BSTATUS] = 0x41,
71 	[MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x43,
72 	[MOD_HDCP_MESSAGE_ID_READ_BINFO] = 0xFF,
73 };
74 
75 static const uint32_t hdcp_dpcd_addrs[] = {
76 	[MOD_HDCP_MESSAGE_ID_READ_BKSV] = 0x68000,
77 	[MOD_HDCP_MESSAGE_ID_READ_RI_R0] = 0x68005,
78 	[MOD_HDCP_MESSAGE_ID_WRITE_AKSV] = 0x68007,
79 	[MOD_HDCP_MESSAGE_ID_WRITE_AINFO] = 0x6803B,
80 	[MOD_HDCP_MESSAGE_ID_WRITE_AN] = 0x6800c,
81 	[MOD_HDCP_MESSAGE_ID_READ_VH_X] = 0x68014,
82 	[MOD_HDCP_MESSAGE_ID_READ_VH_0] = 0x68014,
83 	[MOD_HDCP_MESSAGE_ID_READ_VH_1] = 0x68018,
84 	[MOD_HDCP_MESSAGE_ID_READ_VH_2] = 0x6801c,
85 	[MOD_HDCP_MESSAGE_ID_READ_VH_3] = 0x68020,
86 	[MOD_HDCP_MESSAGE_ID_READ_VH_4] = 0x68024,
87 	[MOD_HDCP_MESSAGE_ID_READ_BCAPS] = 0x68028,
88 	[MOD_HDCP_MESSAGE_ID_READ_BSTATUS] = 0x68029,
89 	[MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x6802c,
90 	[MOD_HDCP_MESSAGE_ID_READ_BINFO] = 0x6802a,
91 };
92 
93 static enum mod_hdcp_status read(struct mod_hdcp *hdcp,
94 		enum mod_hdcp_ddc_message_id msg_id,
95 		uint8_t *buf,
96 		uint32_t buf_len)
97 {
98 	bool success = true;
99 	uint32_t cur_size = 0;
100 	uint32_t data_offset = 0;
101 
102 	if (is_dp_hdcp(hdcp)) {
103 		while (buf_len > 0) {
104 			cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE);
105 			success = hdcp->config.ddc.funcs.read_dpcd(hdcp->config.ddc.handle,
106 					hdcp_dpcd_addrs[msg_id] + data_offset,
107 					buf + data_offset,
108 					cur_size);
109 
110 			if (!success)
111 				break;
112 
113 			buf_len -= cur_size;
114 			data_offset += cur_size;
115 		}
116 	} else {
117 		success = hdcp->config.ddc.funcs.read_i2c(
118 				hdcp->config.ddc.handle,
119 				HDCP_I2C_ADDR,
120 				hdcp_i2c_offsets[msg_id],
121 				buf,
122 				(uint32_t)buf_len);
123 	}
124 
125 	return success ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE;
126 }
127 
128 static enum mod_hdcp_status read_repeatedly(struct mod_hdcp *hdcp,
129 		enum mod_hdcp_ddc_message_id msg_id,
130 		uint8_t *buf,
131 		uint32_t buf_len,
132 		uint8_t read_size)
133 {
134 	enum mod_hdcp_status status = MOD_HDCP_STATUS_DDC_FAILURE;
135 	uint32_t cur_size = 0;
136 	uint32_t data_offset = 0;
137 
138 	while (buf_len > 0) {
139 		cur_size = MIN(buf_len, read_size);
140 		status = read(hdcp, msg_id, buf + data_offset, cur_size);
141 
142 		if (status != MOD_HDCP_STATUS_SUCCESS)
143 			break;
144 
145 		buf_len -= cur_size;
146 		data_offset += cur_size;
147 	}
148 
149 	return status;
150 }
151 
152 static enum mod_hdcp_status write(struct mod_hdcp *hdcp,
153 		enum mod_hdcp_ddc_message_id msg_id,
154 		uint8_t *buf,
155 		uint32_t buf_len)
156 {
157 	bool success = true;
158 	uint32_t cur_size = 0;
159 	uint32_t data_offset = 0;
160 
161 	if (is_dp_hdcp(hdcp)) {
162 		while (buf_len > 0) {
163 			cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE);
164 			success = hdcp->config.ddc.funcs.write_dpcd(
165 					hdcp->config.ddc.handle,
166 					hdcp_dpcd_addrs[msg_id] + data_offset,
167 					buf + data_offset,
168 					cur_size);
169 
170 			if (!success)
171 				break;
172 
173 			buf_len -= cur_size;
174 			data_offset += cur_size;
175 		}
176 	} else {
177 		hdcp->buf[0] = hdcp_i2c_offsets[msg_id];
178 		memmove(&hdcp->buf[1], buf, buf_len);
179 		success = hdcp->config.ddc.funcs.write_i2c(
180 				hdcp->config.ddc.handle,
181 				HDCP_I2C_ADDR,
182 				hdcp->buf,
183 				(uint32_t)(buf_len+1));
184 	}
185 
186 	return success ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE;
187 }
188 
189 enum mod_hdcp_status mod_hdcp_read_bksv(struct mod_hdcp *hdcp)
190 {
191 	return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BKSV,
192 			hdcp->auth.msg.hdcp1.bksv,
193 			sizeof(hdcp->auth.msg.hdcp1.bksv));
194 }
195 
196 enum mod_hdcp_status mod_hdcp_read_bcaps(struct mod_hdcp *hdcp)
197 {
198 	return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BCAPS,
199 			&hdcp->auth.msg.hdcp1.bcaps,
200 			sizeof(hdcp->auth.msg.hdcp1.bcaps));
201 }
202 
203 enum mod_hdcp_status mod_hdcp_read_bstatus(struct mod_hdcp *hdcp)
204 {
205 	enum mod_hdcp_status status;
206 
207 	if (is_dp_hdcp(hdcp))
208 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BSTATUS,
209 					(uint8_t *)&hdcp->auth.msg.hdcp1.bstatus,
210 					1);
211 	else
212 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BSTATUS,
213 				(uint8_t *)&hdcp->auth.msg.hdcp1.bstatus,
214 				sizeof(hdcp->auth.msg.hdcp1.bstatus));
215 	return status;
216 }
217 
218 enum mod_hdcp_status mod_hdcp_read_r0p(struct mod_hdcp *hdcp)
219 {
220 	return read(hdcp, MOD_HDCP_MESSAGE_ID_READ_RI_R0,
221 			(uint8_t *)&hdcp->auth.msg.hdcp1.r0p,
222 			sizeof(hdcp->auth.msg.hdcp1.r0p));
223 }
224 
225 /* special case, reading repeatedly at the same address, don't use read() */
226 enum mod_hdcp_status mod_hdcp_read_ksvlist(struct mod_hdcp *hdcp)
227 {
228 	enum mod_hdcp_status status;
229 
230 	if (is_dp_hdcp(hdcp))
231 		status = read_repeatedly(hdcp, MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO,
232 				hdcp->auth.msg.hdcp1.ksvlist,
233 				hdcp->auth.msg.hdcp1.ksvlist_size,
234 				KSV_READ_SIZE);
235 	else
236 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_KSV_FIFO,
237 				(uint8_t *)&hdcp->auth.msg.hdcp1.ksvlist,
238 				hdcp->auth.msg.hdcp1.ksvlist_size);
239 	return status;
240 }
241 
242 enum mod_hdcp_status mod_hdcp_read_vp(struct mod_hdcp *hdcp)
243 {
244 	enum mod_hdcp_status status;
245 
246 	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_0,
247 			&hdcp->auth.msg.hdcp1.vp[0], 4);
248 	if (status != MOD_HDCP_STATUS_SUCCESS)
249 		goto out;
250 
251 	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_1,
252 			&hdcp->auth.msg.hdcp1.vp[4], 4);
253 	if (status != MOD_HDCP_STATUS_SUCCESS)
254 		goto out;
255 
256 	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_2,
257 			&hdcp->auth.msg.hdcp1.vp[8], 4);
258 	if (status != MOD_HDCP_STATUS_SUCCESS)
259 		goto out;
260 
261 	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_3,
262 			&hdcp->auth.msg.hdcp1.vp[12], 4);
263 	if (status != MOD_HDCP_STATUS_SUCCESS)
264 		goto out;
265 
266 	status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_VH_4,
267 			&hdcp->auth.msg.hdcp1.vp[16], 4);
268 out:
269 	return status;
270 }
271 
272 enum mod_hdcp_status mod_hdcp_read_binfo(struct mod_hdcp *hdcp)
273 {
274 	enum mod_hdcp_status status;
275 
276 	if (is_dp_hdcp(hdcp))
277 		status = read(hdcp, MOD_HDCP_MESSAGE_ID_READ_BINFO,
278 				(uint8_t *)&hdcp->auth.msg.hdcp1.binfo_dp,
279 				sizeof(hdcp->auth.msg.hdcp1.binfo_dp));
280 	else
281 		status = MOD_HDCP_STATUS_INVALID_OPERATION;
282 
283 	return status;
284 }
285 
286 enum mod_hdcp_status mod_hdcp_write_aksv(struct mod_hdcp *hdcp)
287 {
288 	return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AKSV,
289 			hdcp->auth.msg.hdcp1.aksv,
290 			sizeof(hdcp->auth.msg.hdcp1.aksv));
291 }
292 
293 enum mod_hdcp_status mod_hdcp_write_ainfo(struct mod_hdcp *hdcp)
294 {
295 	return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AINFO,
296 			&hdcp->auth.msg.hdcp1.ainfo,
297 			sizeof(hdcp->auth.msg.hdcp1.ainfo));
298 }
299 
300 enum mod_hdcp_status mod_hdcp_write_an(struct mod_hdcp *hdcp)
301 {
302 	return write(hdcp, MOD_HDCP_MESSAGE_ID_WRITE_AN,
303 			hdcp->auth.msg.hdcp1.an,
304 			sizeof(hdcp->auth.msg.hdcp1.an));
305 }
306