1 /* $NetBSD: amdgpu_hdcp_msg.c,v 1.3 2021/12/19 12:02:39 riastradh Exp $ */
2
3 /*
4 * Copyright 2019 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: AMD
25 *
26 */
27
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: amdgpu_hdcp_msg.c,v 1.3 2021/12/19 12:02:39 riastradh Exp $");
30
31 #include <linux/slab.h>
32
33 #include "dm_services.h"
34 #include "dm_helpers.h"
35 #include "include/hdcp_types.h"
36 #include "include/i2caux_interface.h"
37 #include "include/signal_types.h"
38 #include "core_types.h"
39 #include "dc_link_ddc.h"
40 #include "link_hwss.h"
41
42 #define DC_LOGGER \
43 link->ctx->logger
44 #define HDCP14_KSV_SIZE 5
45 #define HDCP14_MAX_KSV_FIFO_SIZE 127*HDCP14_KSV_SIZE
46
47 static const bool hdcp_cmd_is_read[] = {
48 [HDCP_MESSAGE_ID_READ_BKSV] = true,
49 [HDCP_MESSAGE_ID_READ_RI_R0] = true,
50 [HDCP_MESSAGE_ID_READ_PJ] = true,
51 [HDCP_MESSAGE_ID_WRITE_AKSV] = false,
52 [HDCP_MESSAGE_ID_WRITE_AINFO] = false,
53 [HDCP_MESSAGE_ID_WRITE_AN] = false,
54 [HDCP_MESSAGE_ID_READ_VH_X] = true,
55 [HDCP_MESSAGE_ID_READ_VH_0] = true,
56 [HDCP_MESSAGE_ID_READ_VH_1] = true,
57 [HDCP_MESSAGE_ID_READ_VH_2] = true,
58 [HDCP_MESSAGE_ID_READ_VH_3] = true,
59 [HDCP_MESSAGE_ID_READ_VH_4] = true,
60 [HDCP_MESSAGE_ID_READ_BCAPS] = true,
61 [HDCP_MESSAGE_ID_READ_BSTATUS] = true,
62 [HDCP_MESSAGE_ID_READ_KSV_FIFO] = true,
63 [HDCP_MESSAGE_ID_READ_BINFO] = true,
64 [HDCP_MESSAGE_ID_HDCP2VERSION] = true,
65 [HDCP_MESSAGE_ID_RX_CAPS] = true,
66 [HDCP_MESSAGE_ID_WRITE_AKE_INIT] = false,
67 [HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = true,
68 [HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = false,
69 [HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = false,
70 [HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = true,
71 [HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = true,
72 [HDCP_MESSAGE_ID_WRITE_LC_INIT] = false,
73 [HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = true,
74 [HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = false,
75 [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = true,
76 [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = false,
77 [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = false,
78 [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = true,
79 [HDCP_MESSAGE_ID_READ_RXSTATUS] = true,
80 [HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = false
81 };
82
83 static const uint8_t hdcp_i2c_offsets[] = {
84 [HDCP_MESSAGE_ID_READ_BKSV] = 0x0,
85 [HDCP_MESSAGE_ID_READ_RI_R0] = 0x8,
86 [HDCP_MESSAGE_ID_READ_PJ] = 0xA,
87 [HDCP_MESSAGE_ID_WRITE_AKSV] = 0x10,
88 [HDCP_MESSAGE_ID_WRITE_AINFO] = 0x15,
89 [HDCP_MESSAGE_ID_WRITE_AN] = 0x18,
90 [HDCP_MESSAGE_ID_READ_VH_X] = 0x20,
91 [HDCP_MESSAGE_ID_READ_VH_0] = 0x20,
92 [HDCP_MESSAGE_ID_READ_VH_1] = 0x24,
93 [HDCP_MESSAGE_ID_READ_VH_2] = 0x28,
94 [HDCP_MESSAGE_ID_READ_VH_3] = 0x2C,
95 [HDCP_MESSAGE_ID_READ_VH_4] = 0x30,
96 [HDCP_MESSAGE_ID_READ_BCAPS] = 0x40,
97 [HDCP_MESSAGE_ID_READ_BSTATUS] = 0x41,
98 [HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x43,
99 [HDCP_MESSAGE_ID_READ_BINFO] = 0xFF,
100 [HDCP_MESSAGE_ID_HDCP2VERSION] = 0x50,
101 [HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x60,
102 [HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x80,
103 [HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x60,
104 [HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x60,
105 [HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x80,
106 [HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x80,
107 [HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x60,
108 [HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x80,
109 [HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x60,
110 [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x80,
111 [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x60,
112 [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x60,
113 [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x80,
114 [HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x70
115 };
116
117 struct protection_properties {
118 bool supported;
119 bool (*process_transaction)(
120 struct dc_link *link,
121 struct hdcp_protection_message *message_info);
122 };
123
124 static const struct protection_properties non_supported_protection __unused = {
125 .supported = false
126 };
127
hdmi_14_process_transaction(struct dc_link * link,struct hdcp_protection_message * message_info)128 static bool hdmi_14_process_transaction(
129 struct dc_link *link,
130 struct hdcp_protection_message *message_info)
131 {
132 uint8_t *buff = NULL;
133 bool result;
134 const uint8_t hdcp_i2c_addr_link_primary = 0x3a; /* 0x74 >> 1*/
135 const uint8_t hdcp_i2c_addr_link_secondary = 0x3b; /* 0x76 >> 1*/
136 struct i2c_command i2c_command;
137 uint8_t offset = hdcp_i2c_offsets[message_info->msg_id];
138 struct i2c_payload i2c_payloads[] = {
139 { true, 0, 1, &offset },
140 /* actual hdcp payload, will be filled later, zeroed for now*/
141 { 0 }
142 };
143
144 switch (message_info->link) {
145 case HDCP_LINK_SECONDARY:
146 i2c_payloads[0].address = hdcp_i2c_addr_link_secondary;
147 i2c_payloads[1].address = hdcp_i2c_addr_link_secondary;
148 break;
149 case HDCP_LINK_PRIMARY:
150 default:
151 i2c_payloads[0].address = hdcp_i2c_addr_link_primary;
152 i2c_payloads[1].address = hdcp_i2c_addr_link_primary;
153 break;
154 }
155
156 if (hdcp_cmd_is_read[message_info->msg_id]) {
157 i2c_payloads[1].write = false;
158 i2c_command.number_of_payloads = ARRAY_SIZE(i2c_payloads);
159 i2c_payloads[1].length = message_info->length;
160 i2c_payloads[1].data = message_info->data;
161 } else {
162 i2c_command.number_of_payloads = 1;
163 buff = kzalloc(message_info->length + 1, GFP_KERNEL);
164
165 if (!buff)
166 return false;
167
168 buff[0] = offset;
169 memmove(&buff[1], message_info->data, message_info->length);
170 i2c_payloads[0].length = message_info->length + 1;
171 i2c_payloads[0].data = buff;
172 }
173
174 i2c_command.payloads = i2c_payloads;
175 i2c_command.engine = I2C_COMMAND_ENGINE_HW;//only HW
176 i2c_command.speed = link->ddc->ctx->dc->caps.i2c_speed_in_khz;
177
178 result = dm_helpers_submit_i2c(
179 link->ctx,
180 link,
181 &i2c_command);
182 kfree(buff);
183
184 return result;
185 }
186
187 static const struct protection_properties hdmi_14_protection __unused = {
188 .supported = true,
189 .process_transaction = hdmi_14_process_transaction
190 };
191
192 static const uint32_t hdcp_dpcd_addrs[] = {
193 [HDCP_MESSAGE_ID_READ_BKSV] = 0x68000,
194 [HDCP_MESSAGE_ID_READ_RI_R0] = 0x68005,
195 [HDCP_MESSAGE_ID_READ_PJ] = 0xFFFFFFFF,
196 [HDCP_MESSAGE_ID_WRITE_AKSV] = 0x68007,
197 [HDCP_MESSAGE_ID_WRITE_AINFO] = 0x6803B,
198 [HDCP_MESSAGE_ID_WRITE_AN] = 0x6800c,
199 [HDCP_MESSAGE_ID_READ_VH_X] = 0x68014,
200 [HDCP_MESSAGE_ID_READ_VH_0] = 0x68014,
201 [HDCP_MESSAGE_ID_READ_VH_1] = 0x68018,
202 [HDCP_MESSAGE_ID_READ_VH_2] = 0x6801c,
203 [HDCP_MESSAGE_ID_READ_VH_3] = 0x68020,
204 [HDCP_MESSAGE_ID_READ_VH_4] = 0x68024,
205 [HDCP_MESSAGE_ID_READ_BCAPS] = 0x68028,
206 [HDCP_MESSAGE_ID_READ_BSTATUS] = 0x68029,
207 [HDCP_MESSAGE_ID_READ_KSV_FIFO] = 0x6802c,
208 [HDCP_MESSAGE_ID_READ_BINFO] = 0x6802a,
209 [HDCP_MESSAGE_ID_RX_CAPS] = 0x6921d,
210 [HDCP_MESSAGE_ID_WRITE_AKE_INIT] = 0x69000,
211 [HDCP_MESSAGE_ID_READ_AKE_SEND_CERT] = 0x6900b,
212 [HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM] = 0x69220,
213 [HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM] = 0x692a0,
214 [HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME] = 0x692c0,
215 [HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO] = 0x692e0,
216 [HDCP_MESSAGE_ID_WRITE_LC_INIT] = 0x692f0,
217 [HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME] = 0x692f8,
218 [HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS] = 0x69318,
219 [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST] = 0x69330,
220 [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK] = 0x693e0,
221 [HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE] = 0x693f0,
222 [HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY] = 0x69473,
223 [HDCP_MESSAGE_ID_READ_RXSTATUS] = 0x69493,
224 [HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE] = 0x69494
225 };
226
dpcd_access_helper(struct dc_link * link,uint32_t length,uint8_t * data,uint32_t dpcd_addr,bool is_read)227 static bool dpcd_access_helper(
228 struct dc_link *link,
229 uint32_t length,
230 uint8_t *data,
231 uint32_t dpcd_addr,
232 bool is_read)
233 {
234 enum dc_status status;
235 uint32_t cur_length = 0;
236 uint32_t offset = 0;
237 uint32_t ksv_read_size = 0x6803b - 0x6802c;
238
239 /* Read KSV, need repeatedly handle */
240 if (dpcd_addr == 0x6802c) {
241 if (length % HDCP14_KSV_SIZE) {
242 DC_LOG_ERROR("%s: KsvFifo Size(%d) is not a multiple of HDCP14_KSV_SIZE(%d)\n",
243 __func__,
244 length,
245 HDCP14_KSV_SIZE);
246 }
247 if (length > HDCP14_MAX_KSV_FIFO_SIZE) {
248 DC_LOG_ERROR("%s: KsvFifo Size(%d) is greater than HDCP14_MAX_KSV_FIFO_SIZE(%d)\n",
249 __func__,
250 length,
251 HDCP14_MAX_KSV_FIFO_SIZE);
252 }
253
254 DC_LOG_ERROR("%s: Reading %d Ksv(s) from KsvFifo\n",
255 __func__,
256 length / HDCP14_KSV_SIZE);
257
258 while (length > 0) {
259 if (length > ksv_read_size) {
260 status = core_link_read_dpcd(
261 link,
262 dpcd_addr + offset,
263 data + offset,
264 ksv_read_size);
265
266 data += ksv_read_size;
267 length -= ksv_read_size;
268 } else {
269 status = core_link_read_dpcd(
270 link,
271 dpcd_addr + offset,
272 data + offset,
273 length);
274
275 data += length;
276 length = 0;
277 }
278
279 if (status != DC_OK)
280 return false;
281 }
282 } else {
283 while (length > 0) {
284 if (length > DEFAULT_AUX_MAX_DATA_SIZE)
285 cur_length = DEFAULT_AUX_MAX_DATA_SIZE;
286 else
287 cur_length = length;
288
289 if (is_read) {
290 status = core_link_read_dpcd(
291 link,
292 dpcd_addr + offset,
293 data + offset,
294 cur_length);
295 } else {
296 status = core_link_write_dpcd(
297 link,
298 dpcd_addr + offset,
299 data + offset,
300 cur_length);
301 }
302
303 if (status != DC_OK)
304 return false;
305
306 length -= cur_length;
307 offset += cur_length;
308 }
309 }
310 return true;
311 }
312
dp_11_process_transaction(struct dc_link * link,struct hdcp_protection_message * message_info)313 static bool dp_11_process_transaction(
314 struct dc_link *link,
315 struct hdcp_protection_message *message_info)
316 {
317 return dpcd_access_helper(
318 link,
319 message_info->length,
320 message_info->data,
321 hdcp_dpcd_addrs[message_info->msg_id],
322 hdcp_cmd_is_read[message_info->msg_id]);
323 }
324
325 static const struct protection_properties dp_11_protection __unused = {
326 .supported = true,
327 .process_transaction = dp_11_process_transaction
328 };
329
330