1c349dbc7Sjsg /*
2c349dbc7Sjsg * Copyright 2018 Advanced Micro Devices, Inc.
3c349dbc7Sjsg *
4c349dbc7Sjsg * Permission is hereby granted, free of charge, to any person obtaining a
5c349dbc7Sjsg * copy of this software and associated documentation files (the "Software"),
6c349dbc7Sjsg * to deal in the Software without restriction, including without limitation
7c349dbc7Sjsg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8c349dbc7Sjsg * and/or sell copies of the Software, and to permit persons to whom the
9c349dbc7Sjsg * Software is furnished to do so, subject to the following conditions:
10c349dbc7Sjsg *
11c349dbc7Sjsg * The above copyright notice and this permission notice shall be included in
12c349dbc7Sjsg * all copies or substantial portions of the Software.
13c349dbc7Sjsg *
14c349dbc7Sjsg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15c349dbc7Sjsg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16c349dbc7Sjsg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17c349dbc7Sjsg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18c349dbc7Sjsg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19c349dbc7Sjsg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20c349dbc7Sjsg * OTHER DEALINGS IN THE SOFTWARE.
21c349dbc7Sjsg *
22c349dbc7Sjsg * Authors: AMD
23c349dbc7Sjsg *
24c349dbc7Sjsg */
25c349dbc7Sjsg
26c349dbc7Sjsg #include <linux/delay.h>
27c349dbc7Sjsg
28c349dbc7Sjsg #include "hdcp.h"
29c349dbc7Sjsg
check_receiver_id_list_ready(struct mod_hdcp * hdcp)30c349dbc7Sjsg static inline enum mod_hdcp_status check_receiver_id_list_ready(struct mod_hdcp *hdcp)
31c349dbc7Sjsg {
32c349dbc7Sjsg uint8_t is_ready = 0;
33c349dbc7Sjsg
34c349dbc7Sjsg if (is_dp_hdcp(hdcp))
35c349dbc7Sjsg is_ready = HDCP_2_2_DP_RXSTATUS_READY(hdcp->auth.msg.hdcp2.rxstatus_dp) ? 1 : 0;
36c349dbc7Sjsg else
37c349dbc7Sjsg is_ready = (HDCP_2_2_HDMI_RXSTATUS_READY(hdcp->auth.msg.hdcp2.rxstatus[1]) &&
38c349dbc7Sjsg (HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
39c349dbc7Sjsg hdcp->auth.msg.hdcp2.rxstatus[0])) ? 1 : 0;
40c349dbc7Sjsg return is_ready ? MOD_HDCP_STATUS_SUCCESS :
41c349dbc7Sjsg MOD_HDCP_STATUS_HDCP2_RX_ID_LIST_NOT_READY;
42c349dbc7Sjsg }
43c349dbc7Sjsg
check_hdcp2_capable(struct mod_hdcp * hdcp)44c349dbc7Sjsg static inline enum mod_hdcp_status check_hdcp2_capable(struct mod_hdcp *hdcp)
45c349dbc7Sjsg {
46c349dbc7Sjsg enum mod_hdcp_status status;
47c349dbc7Sjsg
48c349dbc7Sjsg if (is_dp_hdcp(hdcp))
49c349dbc7Sjsg status = (hdcp->auth.msg.hdcp2.rxcaps_dp[0] == HDCP_2_2_RX_CAPS_VERSION_VAL) &&
50c349dbc7Sjsg HDCP_2_2_DP_HDCP_CAPABLE(hdcp->auth.msg.hdcp2.rxcaps_dp[2]) ?
51c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS :
52c349dbc7Sjsg MOD_HDCP_STATUS_HDCP2_NOT_CAPABLE;
53c349dbc7Sjsg else
54c349dbc7Sjsg status = (hdcp->auth.msg.hdcp2.hdcp2version_hdmi & HDCP_2_2_HDMI_SUPPORT_MASK) ?
55c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS :
56c349dbc7Sjsg MOD_HDCP_STATUS_HDCP2_NOT_CAPABLE;
57c349dbc7Sjsg return status;
58c349dbc7Sjsg }
59c349dbc7Sjsg
check_reauthentication_request(struct mod_hdcp * hdcp)60c349dbc7Sjsg static inline enum mod_hdcp_status check_reauthentication_request(
61c349dbc7Sjsg struct mod_hdcp *hdcp)
62c349dbc7Sjsg {
63c349dbc7Sjsg uint8_t ret = 0;
64c349dbc7Sjsg
65c349dbc7Sjsg if (is_dp_hdcp(hdcp))
66c349dbc7Sjsg ret = HDCP_2_2_DP_RXSTATUS_REAUTH_REQ(hdcp->auth.msg.hdcp2.rxstatus_dp) ?
67c349dbc7Sjsg MOD_HDCP_STATUS_HDCP2_REAUTH_REQUEST :
68c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS;
69c349dbc7Sjsg else
70c349dbc7Sjsg ret = HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(hdcp->auth.msg.hdcp2.rxstatus[1]) ?
71c349dbc7Sjsg MOD_HDCP_STATUS_HDCP2_REAUTH_REQUEST :
72c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS;
73c349dbc7Sjsg return ret;
74c349dbc7Sjsg }
75c349dbc7Sjsg
check_link_integrity_failure_dp(struct mod_hdcp * hdcp)76c349dbc7Sjsg static inline enum mod_hdcp_status check_link_integrity_failure_dp(
77c349dbc7Sjsg struct mod_hdcp *hdcp)
78c349dbc7Sjsg {
79c349dbc7Sjsg return HDCP_2_2_DP_RXSTATUS_LINK_FAILED(hdcp->auth.msg.hdcp2.rxstatus_dp) ?
80c349dbc7Sjsg MOD_HDCP_STATUS_HDCP2_REAUTH_LINK_INTEGRITY_FAILURE :
81c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS;
82c349dbc7Sjsg }
83c349dbc7Sjsg
check_ake_cert_available(struct mod_hdcp * hdcp)84c349dbc7Sjsg static enum mod_hdcp_status check_ake_cert_available(struct mod_hdcp *hdcp)
85c349dbc7Sjsg {
86c349dbc7Sjsg enum mod_hdcp_status status;
87c349dbc7Sjsg uint16_t size;
88c349dbc7Sjsg
89c349dbc7Sjsg if (is_dp_hdcp(hdcp)) {
90c349dbc7Sjsg status = MOD_HDCP_STATUS_SUCCESS;
91c349dbc7Sjsg } else {
92c349dbc7Sjsg status = mod_hdcp_read_rxstatus(hdcp);
93c349dbc7Sjsg if (status == MOD_HDCP_STATUS_SUCCESS) {
94c349dbc7Sjsg size = HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
95c349dbc7Sjsg hdcp->auth.msg.hdcp2.rxstatus[0];
96c349dbc7Sjsg status = (size == sizeof(hdcp->auth.msg.hdcp2.ake_cert)) ?
97c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS :
98c349dbc7Sjsg MOD_HDCP_STATUS_HDCP2_AKE_CERT_PENDING;
99c349dbc7Sjsg }
100c349dbc7Sjsg }
101c349dbc7Sjsg return status;
102c349dbc7Sjsg }
103c349dbc7Sjsg
check_h_prime_available(struct mod_hdcp * hdcp)104c349dbc7Sjsg static enum mod_hdcp_status check_h_prime_available(struct mod_hdcp *hdcp)
105c349dbc7Sjsg {
106c349dbc7Sjsg enum mod_hdcp_status status;
107c349dbc7Sjsg uint8_t size;
108c349dbc7Sjsg
109c349dbc7Sjsg status = mod_hdcp_read_rxstatus(hdcp);
110c349dbc7Sjsg if (status != MOD_HDCP_STATUS_SUCCESS)
111c349dbc7Sjsg goto out;
112c349dbc7Sjsg
113c349dbc7Sjsg if (is_dp_hdcp(hdcp)) {
114c349dbc7Sjsg status = HDCP_2_2_DP_RXSTATUS_H_PRIME(hdcp->auth.msg.hdcp2.rxstatus_dp) ?
115c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS :
116c349dbc7Sjsg MOD_HDCP_STATUS_HDCP2_H_PRIME_PENDING;
117c349dbc7Sjsg } else {
118c349dbc7Sjsg size = HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
119c349dbc7Sjsg hdcp->auth.msg.hdcp2.rxstatus[0];
120c349dbc7Sjsg status = (size == sizeof(hdcp->auth.msg.hdcp2.ake_h_prime)) ?
121c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS :
122c349dbc7Sjsg MOD_HDCP_STATUS_HDCP2_H_PRIME_PENDING;
123c349dbc7Sjsg }
124c349dbc7Sjsg out:
125c349dbc7Sjsg return status;
126c349dbc7Sjsg }
127c349dbc7Sjsg
check_pairing_info_available(struct mod_hdcp * hdcp)128c349dbc7Sjsg static enum mod_hdcp_status check_pairing_info_available(struct mod_hdcp *hdcp)
129c349dbc7Sjsg {
130c349dbc7Sjsg enum mod_hdcp_status status;
131c349dbc7Sjsg uint8_t size;
132c349dbc7Sjsg
133c349dbc7Sjsg status = mod_hdcp_read_rxstatus(hdcp);
134c349dbc7Sjsg if (status != MOD_HDCP_STATUS_SUCCESS)
135c349dbc7Sjsg goto out;
136c349dbc7Sjsg
137c349dbc7Sjsg if (is_dp_hdcp(hdcp)) {
138c349dbc7Sjsg status = HDCP_2_2_DP_RXSTATUS_PAIRING(hdcp->auth.msg.hdcp2.rxstatus_dp) ?
139c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS :
140c349dbc7Sjsg MOD_HDCP_STATUS_HDCP2_PAIRING_INFO_PENDING;
141c349dbc7Sjsg } else {
142c349dbc7Sjsg size = HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
143c349dbc7Sjsg hdcp->auth.msg.hdcp2.rxstatus[0];
144c349dbc7Sjsg status = (size == sizeof(hdcp->auth.msg.hdcp2.ake_pairing_info)) ?
145c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS :
146c349dbc7Sjsg MOD_HDCP_STATUS_HDCP2_PAIRING_INFO_PENDING;
147c349dbc7Sjsg }
148c349dbc7Sjsg out:
149c349dbc7Sjsg return status;
150c349dbc7Sjsg }
151c349dbc7Sjsg
poll_l_prime_available(struct mod_hdcp * hdcp)152c349dbc7Sjsg static enum mod_hdcp_status poll_l_prime_available(struct mod_hdcp *hdcp)
153c349dbc7Sjsg {
154c349dbc7Sjsg enum mod_hdcp_status status;
155c349dbc7Sjsg uint8_t size;
156c349dbc7Sjsg uint16_t max_wait = 20; // units of ms
157c349dbc7Sjsg uint16_t num_polls = 5;
158c349dbc7Sjsg uint16_t wait_time = max_wait / num_polls;
159c349dbc7Sjsg
160c349dbc7Sjsg if (is_dp_hdcp(hdcp))
161c349dbc7Sjsg status = MOD_HDCP_STATUS_INVALID_OPERATION;
162c349dbc7Sjsg else
163c349dbc7Sjsg for (; num_polls; num_polls--) {
164c349dbc7Sjsg drm_msleep(wait_time);
165c349dbc7Sjsg
166c349dbc7Sjsg status = mod_hdcp_read_rxstatus(hdcp);
167c349dbc7Sjsg if (status != MOD_HDCP_STATUS_SUCCESS)
168c349dbc7Sjsg break;
169c349dbc7Sjsg
170c349dbc7Sjsg size = HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
171c349dbc7Sjsg hdcp->auth.msg.hdcp2.rxstatus[0];
172c349dbc7Sjsg status = (size == sizeof(hdcp->auth.msg.hdcp2.lc_l_prime)) ?
173c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS :
174c349dbc7Sjsg MOD_HDCP_STATUS_HDCP2_L_PRIME_PENDING;
175c349dbc7Sjsg if (status == MOD_HDCP_STATUS_SUCCESS)
176c349dbc7Sjsg break;
177c349dbc7Sjsg }
178c349dbc7Sjsg return status;
179c349dbc7Sjsg }
180c349dbc7Sjsg
check_stream_ready_available(struct mod_hdcp * hdcp)181c349dbc7Sjsg static enum mod_hdcp_status check_stream_ready_available(struct mod_hdcp *hdcp)
182c349dbc7Sjsg {
183c349dbc7Sjsg enum mod_hdcp_status status;
184c349dbc7Sjsg uint8_t size;
185c349dbc7Sjsg
186c349dbc7Sjsg if (is_dp_hdcp(hdcp)) {
187c349dbc7Sjsg status = MOD_HDCP_STATUS_INVALID_OPERATION;
188c349dbc7Sjsg } else {
189c349dbc7Sjsg status = mod_hdcp_read_rxstatus(hdcp);
190c349dbc7Sjsg if (status != MOD_HDCP_STATUS_SUCCESS)
191c349dbc7Sjsg goto out;
192c349dbc7Sjsg size = HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
193c349dbc7Sjsg hdcp->auth.msg.hdcp2.rxstatus[0];
194c349dbc7Sjsg status = (size == sizeof(hdcp->auth.msg.hdcp2.repeater_auth_stream_ready)) ?
195c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS :
196c349dbc7Sjsg MOD_HDCP_STATUS_HDCP2_STREAM_READY_PENDING;
197c349dbc7Sjsg }
198c349dbc7Sjsg out:
199c349dbc7Sjsg return status;
200c349dbc7Sjsg }
201c349dbc7Sjsg
get_device_count(struct mod_hdcp * hdcp)202c349dbc7Sjsg static inline uint8_t get_device_count(struct mod_hdcp *hdcp)
203c349dbc7Sjsg {
204c349dbc7Sjsg return HDCP_2_2_DEV_COUNT_LO(hdcp->auth.msg.hdcp2.rx_id_list[2]) +
205c349dbc7Sjsg (HDCP_2_2_DEV_COUNT_HI(hdcp->auth.msg.hdcp2.rx_id_list[1]) << 4);
206c349dbc7Sjsg }
207c349dbc7Sjsg
check_device_count(struct mod_hdcp * hdcp)208c349dbc7Sjsg static enum mod_hdcp_status check_device_count(struct mod_hdcp *hdcp)
209c349dbc7Sjsg {
210*5ca02815Sjsg /* Avoid device count == 0 to do authentication */
211*5ca02815Sjsg if (0 == get_device_count(hdcp)) {
212*5ca02815Sjsg return MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE;
213*5ca02815Sjsg }
214*5ca02815Sjsg
215*5ca02815Sjsg /* Some MST display may choose to report the internal panel as an HDCP RX. */
216*5ca02815Sjsg /* To update this condition with 1(because the immediate repeater's internal */
217*5ca02815Sjsg /* panel is possibly not included in DEVICE_COUNT) + get_device_count(hdcp). */
218*5ca02815Sjsg /* Device count must be greater than or equal to tracked hdcp displays. */
219*5ca02815Sjsg return ((1 + get_device_count(hdcp)) < get_active_display_count(hdcp)) ?
220c349dbc7Sjsg MOD_HDCP_STATUS_HDCP2_DEVICE_COUNT_MISMATCH_FAILURE :
221c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS;
222c349dbc7Sjsg }
223c349dbc7Sjsg
process_rxstatus(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input,enum mod_hdcp_status * status)224c349dbc7Sjsg static uint8_t process_rxstatus(struct mod_hdcp *hdcp,
225c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
226c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input,
227c349dbc7Sjsg enum mod_hdcp_status *status)
228c349dbc7Sjsg {
229c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_rxstatus,
230c349dbc7Sjsg &input->rxstatus_read, status,
231c349dbc7Sjsg hdcp, "rxstatus_read"))
232c349dbc7Sjsg goto out;
233c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_reauthentication_request,
234c349dbc7Sjsg &input->reauth_request_check, status,
235c349dbc7Sjsg hdcp, "reauth_request_check"))
236c349dbc7Sjsg goto out;
237c349dbc7Sjsg if (is_dp_hdcp(hdcp)) {
238c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_link_integrity_failure_dp,
239c349dbc7Sjsg &input->link_integrity_check_dp, status,
240c349dbc7Sjsg hdcp, "link_integrity_check_dp"))
241c349dbc7Sjsg goto out;
242c349dbc7Sjsg }
243c349dbc7Sjsg if (hdcp->connection.is_repeater)
244c349dbc7Sjsg if (check_receiver_id_list_ready(hdcp) ==
245c349dbc7Sjsg MOD_HDCP_STATUS_SUCCESS) {
246c349dbc7Sjsg HDCP_INPUT_PASS_TRACE(hdcp, "rx_id_list_ready");
247c349dbc7Sjsg event_ctx->rx_id_list_ready = 1;
248c349dbc7Sjsg if (is_dp_hdcp(hdcp))
249c349dbc7Sjsg hdcp->auth.msg.hdcp2.rx_id_list_size =
250c349dbc7Sjsg sizeof(hdcp->auth.msg.hdcp2.rx_id_list);
251c349dbc7Sjsg else
252c349dbc7Sjsg hdcp->auth.msg.hdcp2.rx_id_list_size =
253c349dbc7Sjsg HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
254c349dbc7Sjsg hdcp->auth.msg.hdcp2.rxstatus[0];
255c349dbc7Sjsg }
256c349dbc7Sjsg out:
257c349dbc7Sjsg return (*status == MOD_HDCP_STATUS_SUCCESS);
258c349dbc7Sjsg }
259c349dbc7Sjsg
known_hdcp2_capable_rx(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)260c349dbc7Sjsg static enum mod_hdcp_status known_hdcp2_capable_rx(struct mod_hdcp *hdcp,
261c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
262c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
263c349dbc7Sjsg {
264c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
265c349dbc7Sjsg
266c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
267c349dbc7Sjsg event_ctx->unexpected_event = 1;
268c349dbc7Sjsg goto out;
269c349dbc7Sjsg }
270c349dbc7Sjsg
271c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_hdcp2version,
272c349dbc7Sjsg &input->hdcp2version_read, &status,
273c349dbc7Sjsg hdcp, "hdcp2version_read"))
274c349dbc7Sjsg goto out;
275c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_hdcp2_capable,
276c349dbc7Sjsg &input->hdcp2_capable_check, &status,
277c349dbc7Sjsg hdcp, "hdcp2_capable"))
278c349dbc7Sjsg goto out;
279c349dbc7Sjsg out:
280c349dbc7Sjsg return status;
281c349dbc7Sjsg }
282c349dbc7Sjsg
send_ake_init(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)283c349dbc7Sjsg static enum mod_hdcp_status send_ake_init(struct mod_hdcp *hdcp,
284c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
285c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
286c349dbc7Sjsg {
287c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
288c349dbc7Sjsg
289c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
290c349dbc7Sjsg event_ctx->unexpected_event = 1;
291c349dbc7Sjsg goto out;
292c349dbc7Sjsg }
293c349dbc7Sjsg
294c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_create_session,
295c349dbc7Sjsg &input->create_session, &status,
296c349dbc7Sjsg hdcp, "create_session"))
297c349dbc7Sjsg goto out;
298c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_prepare_ake_init,
299c349dbc7Sjsg &input->ake_init_prepare, &status,
300c349dbc7Sjsg hdcp, "ake_init_prepare"))
301c349dbc7Sjsg goto out;
302c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_write_ake_init,
303c349dbc7Sjsg &input->ake_init_write, &status,
304c349dbc7Sjsg hdcp, "ake_init_write"))
305c349dbc7Sjsg goto out;
306c349dbc7Sjsg out:
307c349dbc7Sjsg return status;
308c349dbc7Sjsg }
309c349dbc7Sjsg
validate_ake_cert(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)310c349dbc7Sjsg static enum mod_hdcp_status validate_ake_cert(struct mod_hdcp *hdcp,
311c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
312c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
313c349dbc7Sjsg {
314c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
315c349dbc7Sjsg
316c349dbc7Sjsg
317c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
318c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
319c349dbc7Sjsg event_ctx->unexpected_event = 1;
320c349dbc7Sjsg goto out;
321c349dbc7Sjsg }
322c349dbc7Sjsg
323c349dbc7Sjsg if (is_hdmi_dvi_sl_hdcp(hdcp))
324c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_ake_cert_available,
325c349dbc7Sjsg &input->ake_cert_available, &status,
326c349dbc7Sjsg hdcp, "ake_cert_available"))
327c349dbc7Sjsg goto out;
328c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_ake_cert,
329c349dbc7Sjsg &input->ake_cert_read, &status,
330c349dbc7Sjsg hdcp, "ake_cert_read"))
331c349dbc7Sjsg goto out;
332c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_validate_ake_cert,
333c349dbc7Sjsg &input->ake_cert_validation, &status,
334c349dbc7Sjsg hdcp, "ake_cert_validation"))
335c349dbc7Sjsg goto out;
336c349dbc7Sjsg out:
337c349dbc7Sjsg return status;
338c349dbc7Sjsg }
339c349dbc7Sjsg
send_no_stored_km(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)340c349dbc7Sjsg static enum mod_hdcp_status send_no_stored_km(struct mod_hdcp *hdcp,
341c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
342c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
343c349dbc7Sjsg {
344c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
345c349dbc7Sjsg
346c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
347c349dbc7Sjsg event_ctx->unexpected_event = 1;
348c349dbc7Sjsg goto out;
349c349dbc7Sjsg }
350c349dbc7Sjsg
351c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_write_no_stored_km,
352c349dbc7Sjsg &input->no_stored_km_write, &status,
353c349dbc7Sjsg hdcp, "no_stored_km_write"))
354c349dbc7Sjsg goto out;
355c349dbc7Sjsg out:
356c349dbc7Sjsg return status;
357c349dbc7Sjsg }
358c349dbc7Sjsg
read_h_prime(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)359c349dbc7Sjsg static enum mod_hdcp_status read_h_prime(struct mod_hdcp *hdcp,
360c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
361c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
362c349dbc7Sjsg {
363c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
364c349dbc7Sjsg
365c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
366c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_CPIRQ &&
367c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
368c349dbc7Sjsg event_ctx->unexpected_event = 1;
369c349dbc7Sjsg goto out;
370c349dbc7Sjsg }
371c349dbc7Sjsg
372c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_h_prime_available,
373c349dbc7Sjsg &input->h_prime_available, &status,
374c349dbc7Sjsg hdcp, "h_prime_available"))
375c349dbc7Sjsg goto out;
376c349dbc7Sjsg
377c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_h_prime,
378c349dbc7Sjsg &input->h_prime_read, &status,
379c349dbc7Sjsg hdcp, "h_prime_read"))
380c349dbc7Sjsg goto out;
381c349dbc7Sjsg out:
382c349dbc7Sjsg return status;
383c349dbc7Sjsg }
384c349dbc7Sjsg
read_pairing_info_and_validate_h_prime(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)385c349dbc7Sjsg static enum mod_hdcp_status read_pairing_info_and_validate_h_prime(
386c349dbc7Sjsg struct mod_hdcp *hdcp,
387c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
388c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
389c349dbc7Sjsg {
390c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
391c349dbc7Sjsg
392c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
393c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_CPIRQ &&
394c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
395c349dbc7Sjsg event_ctx->unexpected_event = 1;
396c349dbc7Sjsg goto out;
397c349dbc7Sjsg }
398c349dbc7Sjsg
399c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_pairing_info_available,
400c349dbc7Sjsg &input->pairing_available, &status,
401c349dbc7Sjsg hdcp, "pairing_available"))
402c349dbc7Sjsg goto out;
403c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_pairing_info,
404c349dbc7Sjsg &input->pairing_info_read, &status,
405c349dbc7Sjsg hdcp, "pairing_info_read"))
406c349dbc7Sjsg goto out;
407c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_validate_h_prime,
408c349dbc7Sjsg &input->h_prime_validation, &status,
409c349dbc7Sjsg hdcp, "h_prime_validation"))
410c349dbc7Sjsg goto out;
411c349dbc7Sjsg out:
412c349dbc7Sjsg return status;
413c349dbc7Sjsg }
414c349dbc7Sjsg
send_stored_km(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)415c349dbc7Sjsg static enum mod_hdcp_status send_stored_km(struct mod_hdcp *hdcp,
416c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
417c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
418c349dbc7Sjsg {
419c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
420c349dbc7Sjsg
421c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
422c349dbc7Sjsg event_ctx->unexpected_event = 1;
423c349dbc7Sjsg goto out;
424c349dbc7Sjsg }
425c349dbc7Sjsg
426c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_write_stored_km,
427c349dbc7Sjsg &input->stored_km_write, &status,
428c349dbc7Sjsg hdcp, "stored_km_write"))
429c349dbc7Sjsg goto out;
430c349dbc7Sjsg out:
431c349dbc7Sjsg return status;
432c349dbc7Sjsg }
433c349dbc7Sjsg
validate_h_prime(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)434c349dbc7Sjsg static enum mod_hdcp_status validate_h_prime(struct mod_hdcp *hdcp,
435c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
436c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
437c349dbc7Sjsg {
438c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
439c349dbc7Sjsg
440c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
441c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_CPIRQ &&
442c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
443c349dbc7Sjsg event_ctx->unexpected_event = 1;
444c349dbc7Sjsg goto out;
445c349dbc7Sjsg }
446c349dbc7Sjsg
447c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_h_prime_available,
448c349dbc7Sjsg &input->h_prime_available, &status,
449c349dbc7Sjsg hdcp, "h_prime_available"))
450c349dbc7Sjsg goto out;
451c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_h_prime,
452c349dbc7Sjsg &input->h_prime_read, &status,
453c349dbc7Sjsg hdcp, "h_prime_read"))
454c349dbc7Sjsg goto out;
455c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_validate_h_prime,
456c349dbc7Sjsg &input->h_prime_validation, &status,
457c349dbc7Sjsg hdcp, "h_prime_validation"))
458c349dbc7Sjsg goto out;
459c349dbc7Sjsg out:
460c349dbc7Sjsg return status;
461c349dbc7Sjsg }
462c349dbc7Sjsg
locality_check(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)463c349dbc7Sjsg static enum mod_hdcp_status locality_check(struct mod_hdcp *hdcp,
464c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
465c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
466c349dbc7Sjsg {
467c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
468c349dbc7Sjsg
469c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
470c349dbc7Sjsg event_ctx->unexpected_event = 1;
471c349dbc7Sjsg goto out;
472c349dbc7Sjsg }
473c349dbc7Sjsg
474c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_prepare_lc_init,
475c349dbc7Sjsg &input->lc_init_prepare, &status,
476c349dbc7Sjsg hdcp, "lc_init_prepare"))
477c349dbc7Sjsg goto out;
478c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_write_lc_init,
479c349dbc7Sjsg &input->lc_init_write, &status,
480c349dbc7Sjsg hdcp, "lc_init_write"))
481c349dbc7Sjsg goto out;
482c349dbc7Sjsg if (is_dp_hdcp(hdcp))
483c349dbc7Sjsg drm_msleep(16);
484c349dbc7Sjsg else
485c349dbc7Sjsg if (!mod_hdcp_execute_and_set(poll_l_prime_available,
486c349dbc7Sjsg &input->l_prime_available_poll, &status,
487c349dbc7Sjsg hdcp, "l_prime_available_poll"))
488c349dbc7Sjsg goto out;
489c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_l_prime,
490c349dbc7Sjsg &input->l_prime_read, &status,
491c349dbc7Sjsg hdcp, "l_prime_read"))
492c349dbc7Sjsg goto out;
493c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_validate_l_prime,
494c349dbc7Sjsg &input->l_prime_validation, &status,
495c349dbc7Sjsg hdcp, "l_prime_validation"))
496c349dbc7Sjsg goto out;
497c349dbc7Sjsg out:
498c349dbc7Sjsg return status;
499c349dbc7Sjsg }
500c349dbc7Sjsg
exchange_ks_and_test_for_repeater(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)501c349dbc7Sjsg static enum mod_hdcp_status exchange_ks_and_test_for_repeater(struct mod_hdcp *hdcp,
502c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
503c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
504c349dbc7Sjsg {
505c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
506c349dbc7Sjsg
507c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
508c349dbc7Sjsg event_ctx->unexpected_event = 1;
509c349dbc7Sjsg goto out;
510c349dbc7Sjsg }
511c349dbc7Sjsg
512c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_prepare_eks,
513c349dbc7Sjsg &input->eks_prepare, &status,
514c349dbc7Sjsg hdcp, "eks_prepare"))
515c349dbc7Sjsg goto out;
516c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_write_eks,
517c349dbc7Sjsg &input->eks_write, &status,
518c349dbc7Sjsg hdcp, "eks_write"))
519c349dbc7Sjsg goto out;
520c349dbc7Sjsg out:
521c349dbc7Sjsg return status;
522c349dbc7Sjsg }
523c349dbc7Sjsg
enable_encryption(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)524c349dbc7Sjsg static enum mod_hdcp_status enable_encryption(struct mod_hdcp *hdcp,
525c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
526c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
527c349dbc7Sjsg {
528c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
529c349dbc7Sjsg
530c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
531c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_CPIRQ) {
532c349dbc7Sjsg event_ctx->unexpected_event = 1;
533c349dbc7Sjsg goto out;
534c349dbc7Sjsg }
535c349dbc7Sjsg if (event_ctx->event == MOD_HDCP_EVENT_CPIRQ) {
536c349dbc7Sjsg process_rxstatus(hdcp, event_ctx, input, &status);
537c349dbc7Sjsg goto out;
538c349dbc7Sjsg }
539c349dbc7Sjsg
540c349dbc7Sjsg if (is_hdmi_dvi_sl_hdcp(hdcp)) {
541c349dbc7Sjsg if (!process_rxstatus(hdcp, event_ctx, input, &status))
542c349dbc7Sjsg goto out;
543c349dbc7Sjsg if (event_ctx->rx_id_list_ready)
544c349dbc7Sjsg goto out;
545c349dbc7Sjsg }
546c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_enable_encryption,
547c349dbc7Sjsg &input->enable_encryption, &status,
548c349dbc7Sjsg hdcp, "enable_encryption"))
549c349dbc7Sjsg goto out;
550c349dbc7Sjsg if (is_dp_mst_hdcp(hdcp)) {
551c349dbc7Sjsg if (!mod_hdcp_execute_and_set(
552c349dbc7Sjsg mod_hdcp_hdcp2_enable_dp_stream_encryption,
553c349dbc7Sjsg &input->stream_encryption_dp, &status,
554c349dbc7Sjsg hdcp, "stream_encryption_dp"))
555c349dbc7Sjsg goto out;
556c349dbc7Sjsg }
557c349dbc7Sjsg out:
558c349dbc7Sjsg return status;
559c349dbc7Sjsg }
560c349dbc7Sjsg
authenticated(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)561c349dbc7Sjsg static enum mod_hdcp_status authenticated(struct mod_hdcp *hdcp,
562c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
563c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
564c349dbc7Sjsg {
565c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
566c349dbc7Sjsg
567c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
568c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_CPIRQ) {
569c349dbc7Sjsg event_ctx->unexpected_event = 1;
570c349dbc7Sjsg goto out;
571c349dbc7Sjsg }
572c349dbc7Sjsg
573*5ca02815Sjsg process_rxstatus(hdcp, event_ctx, input, &status);
574c349dbc7Sjsg out:
575c349dbc7Sjsg return status;
576c349dbc7Sjsg }
577c349dbc7Sjsg
wait_for_rx_id_list(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)578c349dbc7Sjsg static enum mod_hdcp_status wait_for_rx_id_list(struct mod_hdcp *hdcp,
579c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
580c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
581c349dbc7Sjsg {
582c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
583c349dbc7Sjsg
584c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
585c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_CPIRQ &&
586c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
587c349dbc7Sjsg event_ctx->unexpected_event = 1;
588c349dbc7Sjsg goto out;
589c349dbc7Sjsg }
590c349dbc7Sjsg
591c349dbc7Sjsg if (!process_rxstatus(hdcp, event_ctx, input, &status))
592c349dbc7Sjsg goto out;
593c349dbc7Sjsg if (!event_ctx->rx_id_list_ready) {
594c349dbc7Sjsg status = MOD_HDCP_STATUS_HDCP2_RX_ID_LIST_NOT_READY;
595c349dbc7Sjsg goto out;
596c349dbc7Sjsg }
597c349dbc7Sjsg out:
598c349dbc7Sjsg return status;
599c349dbc7Sjsg }
600c349dbc7Sjsg
verify_rx_id_list_and_send_ack(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)601c349dbc7Sjsg static enum mod_hdcp_status verify_rx_id_list_and_send_ack(struct mod_hdcp *hdcp,
602c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
603c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
604c349dbc7Sjsg {
605c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
606c349dbc7Sjsg
607c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
608c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_CPIRQ) {
609c349dbc7Sjsg event_ctx->unexpected_event = 1;
610c349dbc7Sjsg goto out;
611c349dbc7Sjsg }
612c349dbc7Sjsg if (event_ctx->event == MOD_HDCP_EVENT_CPIRQ) {
613c349dbc7Sjsg process_rxstatus(hdcp, event_ctx, input, &status);
614c349dbc7Sjsg goto out;
615c349dbc7Sjsg }
616c349dbc7Sjsg
617c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_rx_id_list,
618c349dbc7Sjsg &input->rx_id_list_read,
619c349dbc7Sjsg &status, hdcp, "receiver_id_list_read"))
620c349dbc7Sjsg goto out;
621c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_device_count,
622c349dbc7Sjsg &input->device_count_check,
623c349dbc7Sjsg &status, hdcp, "device_count_check"))
624c349dbc7Sjsg goto out;
625c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_validate_rx_id_list,
626c349dbc7Sjsg &input->rx_id_list_validation,
627c349dbc7Sjsg &status, hdcp, "rx_id_list_validation"))
628c349dbc7Sjsg goto out;
629c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_write_repeater_auth_ack,
630c349dbc7Sjsg &input->repeater_auth_ack_write,
631c349dbc7Sjsg &status, hdcp, "repeater_auth_ack_write"))
632c349dbc7Sjsg goto out;
633c349dbc7Sjsg out:
634c349dbc7Sjsg return status;
635c349dbc7Sjsg }
636c349dbc7Sjsg
send_stream_management(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)637c349dbc7Sjsg static enum mod_hdcp_status send_stream_management(struct mod_hdcp *hdcp,
638c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
639c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
640c349dbc7Sjsg {
641c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
642c349dbc7Sjsg
643c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
644c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_CPIRQ) {
645c349dbc7Sjsg event_ctx->unexpected_event = 1;
646c349dbc7Sjsg goto out;
647c349dbc7Sjsg }
648c349dbc7Sjsg if (event_ctx->event == MOD_HDCP_EVENT_CPIRQ) {
649c349dbc7Sjsg process_rxstatus(hdcp, event_ctx, input, &status);
650c349dbc7Sjsg goto out;
651c349dbc7Sjsg }
652c349dbc7Sjsg
653c349dbc7Sjsg if (is_hdmi_dvi_sl_hdcp(hdcp)) {
654c349dbc7Sjsg if (!process_rxstatus(hdcp, event_ctx, input, &status))
655c349dbc7Sjsg goto out;
656c349dbc7Sjsg if (event_ctx->rx_id_list_ready)
657c349dbc7Sjsg goto out;
658c349dbc7Sjsg }
659c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_prepare_stream_management,
660c349dbc7Sjsg &input->prepare_stream_manage,
661c349dbc7Sjsg &status, hdcp, "prepare_stream_manage"))
662c349dbc7Sjsg goto out;
663c349dbc7Sjsg
664c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_write_stream_manage,
665c349dbc7Sjsg &input->stream_manage_write,
666c349dbc7Sjsg &status, hdcp, "stream_manage_write"))
667c349dbc7Sjsg goto out;
668c349dbc7Sjsg out:
669c349dbc7Sjsg return status;
670c349dbc7Sjsg }
671c349dbc7Sjsg
validate_stream_ready(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)672c349dbc7Sjsg static enum mod_hdcp_status validate_stream_ready(struct mod_hdcp *hdcp,
673c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
674c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
675c349dbc7Sjsg {
676c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
677c349dbc7Sjsg
678c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
679c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_CPIRQ &&
680c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
681c349dbc7Sjsg event_ctx->unexpected_event = 1;
682c349dbc7Sjsg goto out;
683c349dbc7Sjsg }
684c349dbc7Sjsg if (event_ctx->event == MOD_HDCP_EVENT_CPIRQ) {
685c349dbc7Sjsg process_rxstatus(hdcp, event_ctx, input, &status);
686c349dbc7Sjsg goto out;
687c349dbc7Sjsg }
688c349dbc7Sjsg
689c349dbc7Sjsg if (is_hdmi_dvi_sl_hdcp(hdcp)) {
690c349dbc7Sjsg if (!process_rxstatus(hdcp, event_ctx, input, &status))
691c349dbc7Sjsg goto out;
692c349dbc7Sjsg if (event_ctx->rx_id_list_ready) {
693c349dbc7Sjsg goto out;
694c349dbc7Sjsg }
695c349dbc7Sjsg }
696c349dbc7Sjsg if (is_hdmi_dvi_sl_hdcp(hdcp))
697c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_stream_ready_available,
698c349dbc7Sjsg &input->stream_ready_available,
699c349dbc7Sjsg &status, hdcp, "stream_ready_available"))
700c349dbc7Sjsg goto out;
701c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_stream_ready,
702c349dbc7Sjsg &input->stream_ready_read,
703c349dbc7Sjsg &status, hdcp, "stream_ready_read"))
704c349dbc7Sjsg goto out;
705c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_validate_stream_ready,
706c349dbc7Sjsg &input->stream_ready_validation,
707c349dbc7Sjsg &status, hdcp, "stream_ready_validation"))
708c349dbc7Sjsg goto out;
709c349dbc7Sjsg
710c349dbc7Sjsg out:
711c349dbc7Sjsg return status;
712c349dbc7Sjsg }
713c349dbc7Sjsg
determine_rx_hdcp_capable_dp(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)714c349dbc7Sjsg static enum mod_hdcp_status determine_rx_hdcp_capable_dp(struct mod_hdcp *hdcp,
715c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
716c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
717c349dbc7Sjsg {
718c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
719c349dbc7Sjsg
720c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
721c349dbc7Sjsg event_ctx->unexpected_event = 1;
722c349dbc7Sjsg goto out;
723c349dbc7Sjsg }
724c349dbc7Sjsg
725c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_read_rxcaps,
726c349dbc7Sjsg &input->rx_caps_read_dp,
727c349dbc7Sjsg &status, hdcp, "rx_caps_read_dp"))
728c349dbc7Sjsg goto out;
729c349dbc7Sjsg if (!mod_hdcp_execute_and_set(check_hdcp2_capable,
730c349dbc7Sjsg &input->hdcp2_capable_check, &status,
731c349dbc7Sjsg hdcp, "hdcp2_capable_check"))
732c349dbc7Sjsg goto out;
733c349dbc7Sjsg out:
734c349dbc7Sjsg return status;
735c349dbc7Sjsg }
736c349dbc7Sjsg
send_content_stream_type_dp(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)737c349dbc7Sjsg static enum mod_hdcp_status send_content_stream_type_dp(struct mod_hdcp *hdcp,
738c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
739c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
740c349dbc7Sjsg {
741c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
742c349dbc7Sjsg
743c349dbc7Sjsg if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
744c349dbc7Sjsg event_ctx->event != MOD_HDCP_EVENT_CPIRQ) {
745c349dbc7Sjsg event_ctx->unexpected_event = 1;
746c349dbc7Sjsg goto out;
747c349dbc7Sjsg }
748c349dbc7Sjsg
749c349dbc7Sjsg if (!process_rxstatus(hdcp, event_ctx, input, &status))
750c349dbc7Sjsg goto out;
751c349dbc7Sjsg if (!mod_hdcp_execute_and_set(mod_hdcp_write_content_type,
752c349dbc7Sjsg &input->content_stream_type_write, &status,
753c349dbc7Sjsg hdcp, "content_stream_type_write"))
754c349dbc7Sjsg goto out;
755c349dbc7Sjsg out:
756c349dbc7Sjsg return status;
757c349dbc7Sjsg }
758c349dbc7Sjsg
mod_hdcp_hdcp2_execution(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)759c349dbc7Sjsg enum mod_hdcp_status mod_hdcp_hdcp2_execution(struct mod_hdcp *hdcp,
760c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
761c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
762c349dbc7Sjsg {
763c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
764c349dbc7Sjsg
765c349dbc7Sjsg switch (current_state(hdcp)) {
766c349dbc7Sjsg case H2_A0_KNOWN_HDCP2_CAPABLE_RX:
767c349dbc7Sjsg status = known_hdcp2_capable_rx(hdcp, event_ctx, input);
768c349dbc7Sjsg break;
769c349dbc7Sjsg case H2_A1_SEND_AKE_INIT:
770c349dbc7Sjsg status = send_ake_init(hdcp, event_ctx, input);
771c349dbc7Sjsg break;
772c349dbc7Sjsg case H2_A1_VALIDATE_AKE_CERT:
773c349dbc7Sjsg status = validate_ake_cert(hdcp, event_ctx, input);
774c349dbc7Sjsg break;
775c349dbc7Sjsg case H2_A1_SEND_NO_STORED_KM:
776c349dbc7Sjsg status = send_no_stored_km(hdcp, event_ctx, input);
777c349dbc7Sjsg break;
778c349dbc7Sjsg case H2_A1_READ_H_PRIME:
779c349dbc7Sjsg status = read_h_prime(hdcp, event_ctx, input);
780c349dbc7Sjsg break;
781c349dbc7Sjsg case H2_A1_READ_PAIRING_INFO_AND_VALIDATE_H_PRIME:
782c349dbc7Sjsg status = read_pairing_info_and_validate_h_prime(hdcp,
783c349dbc7Sjsg event_ctx, input);
784c349dbc7Sjsg break;
785c349dbc7Sjsg case H2_A1_SEND_STORED_KM:
786c349dbc7Sjsg status = send_stored_km(hdcp, event_ctx, input);
787c349dbc7Sjsg break;
788c349dbc7Sjsg case H2_A1_VALIDATE_H_PRIME:
789c349dbc7Sjsg status = validate_h_prime(hdcp, event_ctx, input);
790c349dbc7Sjsg break;
791c349dbc7Sjsg case H2_A2_LOCALITY_CHECK:
792c349dbc7Sjsg status = locality_check(hdcp, event_ctx, input);
793c349dbc7Sjsg break;
794c349dbc7Sjsg case H2_A3_EXCHANGE_KS_AND_TEST_FOR_REPEATER:
795c349dbc7Sjsg status = exchange_ks_and_test_for_repeater(hdcp, event_ctx, input);
796c349dbc7Sjsg break;
797c349dbc7Sjsg case H2_ENABLE_ENCRYPTION:
798c349dbc7Sjsg status = enable_encryption(hdcp, event_ctx, input);
799c349dbc7Sjsg break;
800c349dbc7Sjsg case H2_A5_AUTHENTICATED:
801c349dbc7Sjsg status = authenticated(hdcp, event_ctx, input);
802c349dbc7Sjsg break;
803c349dbc7Sjsg case H2_A6_WAIT_FOR_RX_ID_LIST:
804c349dbc7Sjsg status = wait_for_rx_id_list(hdcp, event_ctx, input);
805c349dbc7Sjsg break;
806c349dbc7Sjsg case H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK:
807c349dbc7Sjsg status = verify_rx_id_list_and_send_ack(hdcp, event_ctx, input);
808c349dbc7Sjsg break;
809c349dbc7Sjsg case H2_A9_SEND_STREAM_MANAGEMENT:
810c349dbc7Sjsg status = send_stream_management(hdcp, event_ctx, input);
811c349dbc7Sjsg break;
812c349dbc7Sjsg case H2_A9_VALIDATE_STREAM_READY:
813c349dbc7Sjsg status = validate_stream_ready(hdcp, event_ctx, input);
814c349dbc7Sjsg break;
815c349dbc7Sjsg default:
816c349dbc7Sjsg status = MOD_HDCP_STATUS_INVALID_STATE;
817c349dbc7Sjsg break;
818c349dbc7Sjsg }
819c349dbc7Sjsg
820c349dbc7Sjsg return status;
821c349dbc7Sjsg }
822c349dbc7Sjsg
mod_hdcp_hdcp2_dp_execution(struct mod_hdcp * hdcp,struct mod_hdcp_event_context * event_ctx,struct mod_hdcp_transition_input_hdcp2 * input)823c349dbc7Sjsg enum mod_hdcp_status mod_hdcp_hdcp2_dp_execution(struct mod_hdcp *hdcp,
824c349dbc7Sjsg struct mod_hdcp_event_context *event_ctx,
825c349dbc7Sjsg struct mod_hdcp_transition_input_hdcp2 *input)
826c349dbc7Sjsg {
827c349dbc7Sjsg enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
828c349dbc7Sjsg
829c349dbc7Sjsg switch (current_state(hdcp)) {
830c349dbc7Sjsg case D2_A0_DETERMINE_RX_HDCP_CAPABLE:
831c349dbc7Sjsg status = determine_rx_hdcp_capable_dp(hdcp, event_ctx, input);
832c349dbc7Sjsg break;
833c349dbc7Sjsg case D2_A1_SEND_AKE_INIT:
834c349dbc7Sjsg status = send_ake_init(hdcp, event_ctx, input);
835c349dbc7Sjsg break;
836c349dbc7Sjsg case D2_A1_VALIDATE_AKE_CERT:
837c349dbc7Sjsg status = validate_ake_cert(hdcp, event_ctx, input);
838c349dbc7Sjsg break;
839c349dbc7Sjsg case D2_A1_SEND_NO_STORED_KM:
840c349dbc7Sjsg status = send_no_stored_km(hdcp, event_ctx, input);
841c349dbc7Sjsg break;
842c349dbc7Sjsg case D2_A1_READ_H_PRIME:
843c349dbc7Sjsg status = read_h_prime(hdcp, event_ctx, input);
844c349dbc7Sjsg break;
845c349dbc7Sjsg case D2_A1_READ_PAIRING_INFO_AND_VALIDATE_H_PRIME:
846c349dbc7Sjsg status = read_pairing_info_and_validate_h_prime(hdcp,
847c349dbc7Sjsg event_ctx, input);
848c349dbc7Sjsg break;
849c349dbc7Sjsg case D2_A1_SEND_STORED_KM:
850c349dbc7Sjsg status = send_stored_km(hdcp, event_ctx, input);
851c349dbc7Sjsg break;
852c349dbc7Sjsg case D2_A1_VALIDATE_H_PRIME:
853c349dbc7Sjsg status = validate_h_prime(hdcp, event_ctx, input);
854c349dbc7Sjsg break;
855c349dbc7Sjsg case D2_A2_LOCALITY_CHECK:
856c349dbc7Sjsg status = locality_check(hdcp, event_ctx, input);
857c349dbc7Sjsg break;
858c349dbc7Sjsg case D2_A34_EXCHANGE_KS_AND_TEST_FOR_REPEATER:
859c349dbc7Sjsg status = exchange_ks_and_test_for_repeater(hdcp,
860c349dbc7Sjsg event_ctx, input);
861c349dbc7Sjsg break;
862c349dbc7Sjsg case D2_SEND_CONTENT_STREAM_TYPE:
863c349dbc7Sjsg status = send_content_stream_type_dp(hdcp, event_ctx, input);
864c349dbc7Sjsg break;
865c349dbc7Sjsg case D2_ENABLE_ENCRYPTION:
866c349dbc7Sjsg status = enable_encryption(hdcp, event_ctx, input);
867c349dbc7Sjsg break;
868c349dbc7Sjsg case D2_A5_AUTHENTICATED:
869c349dbc7Sjsg status = authenticated(hdcp, event_ctx, input);
870c349dbc7Sjsg break;
871c349dbc7Sjsg case D2_A6_WAIT_FOR_RX_ID_LIST:
872c349dbc7Sjsg status = wait_for_rx_id_list(hdcp, event_ctx, input);
873c349dbc7Sjsg break;
874c349dbc7Sjsg case D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK:
875c349dbc7Sjsg status = verify_rx_id_list_and_send_ack(hdcp, event_ctx, input);
876c349dbc7Sjsg break;
877c349dbc7Sjsg case D2_A9_SEND_STREAM_MANAGEMENT:
878c349dbc7Sjsg status = send_stream_management(hdcp, event_ctx, input);
879c349dbc7Sjsg break;
880c349dbc7Sjsg case D2_A9_VALIDATE_STREAM_READY:
881c349dbc7Sjsg status = validate_stream_ready(hdcp, event_ctx, input);
882c349dbc7Sjsg break;
883c349dbc7Sjsg default:
884c349dbc7Sjsg status = MOD_HDCP_STATUS_INVALID_STATE;
885c349dbc7Sjsg break;
886c349dbc7Sjsg }
887c349dbc7Sjsg
888c349dbc7Sjsg return status;
889c349dbc7Sjsg }
890