Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c
26552 views
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
static void push_error_status(struct mod_hdcp *hdcp,
29
enum mod_hdcp_status status)
30
{
31
struct mod_hdcp_trace *trace = &hdcp->connection.trace;
32
33
if (trace->error_count < MAX_NUM_OF_ERROR_TRACE) {
34
trace->errors[trace->error_count].status = status;
35
trace->errors[trace->error_count].state_id = hdcp->state.id;
36
trace->error_count++;
37
HDCP_ERROR_TRACE(hdcp, status);
38
}
39
40
if (is_hdcp1(hdcp)) {
41
hdcp->connection.hdcp1_retry_count++;
42
if (hdcp->connection.hdcp1_retry_count == MAX_NUM_OF_ATTEMPTS)
43
hdcp->connection.link.adjust.hdcp1.disable = 1;
44
} else if (is_hdcp2(hdcp)) {
45
hdcp->connection.hdcp2_retry_count++;
46
if (hdcp->connection.hdcp2_retry_count == MAX_NUM_OF_ATTEMPTS)
47
hdcp->connection.link.adjust.hdcp2.disable = 1;
48
}
49
}
50
51
static uint8_t is_cp_desired_hdcp1(struct mod_hdcp *hdcp)
52
{
53
int i, is_auth_needed = 0;
54
55
/* if all displays on the link don't need authentication,
56
* hdcp is not desired
57
*/
58
for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) {
59
if (hdcp->displays[i].state != MOD_HDCP_DISPLAY_INACTIVE &&
60
hdcp->displays[i].adjust.disable != MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION) {
61
is_auth_needed = 1;
62
break;
63
}
64
}
65
66
return is_auth_needed &&
67
!hdcp->connection.link.adjust.hdcp1.disable &&
68
!hdcp->connection.is_hdcp1_revoked;
69
}
70
71
static uint8_t is_cp_desired_hdcp2(struct mod_hdcp *hdcp)
72
{
73
int i, is_auth_needed = 0;
74
75
/* if all displays on the link don't need authentication,
76
* hdcp is not desired
77
*/
78
for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) {
79
if (hdcp->displays[i].state != MOD_HDCP_DISPLAY_INACTIVE &&
80
hdcp->displays[i].adjust.disable != MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION) {
81
is_auth_needed = 1;
82
break;
83
}
84
}
85
86
return is_auth_needed &&
87
!hdcp->connection.link.adjust.hdcp2.disable &&
88
!hdcp->connection.is_hdcp2_revoked;
89
}
90
91
static enum mod_hdcp_status execution(struct mod_hdcp *hdcp,
92
struct mod_hdcp_event_context *event_ctx,
93
union mod_hdcp_transition_input *input)
94
{
95
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
96
97
if (is_in_initialized_state(hdcp)) {
98
if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
99
event_ctx->unexpected_event = 1;
100
goto out;
101
}
102
/* initialize transition input */
103
memset(input, 0, sizeof(union mod_hdcp_transition_input));
104
} else if (is_in_cp_not_desired_state(hdcp)) {
105
if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
106
event_ctx->unexpected_event = 1;
107
goto out;
108
}
109
} else if (is_in_hdcp1_states(hdcp)) {
110
status = mod_hdcp_hdcp1_execution(hdcp, event_ctx, &input->hdcp1);
111
} else if (is_in_hdcp1_dp_states(hdcp)) {
112
status = mod_hdcp_hdcp1_dp_execution(hdcp,
113
event_ctx, &input->hdcp1);
114
} else if (is_in_hdcp2_states(hdcp)) {
115
status = mod_hdcp_hdcp2_execution(hdcp, event_ctx, &input->hdcp2);
116
} else if (is_in_hdcp2_dp_states(hdcp)) {
117
status = mod_hdcp_hdcp2_dp_execution(hdcp,
118
event_ctx, &input->hdcp2);
119
} else {
120
event_ctx->unexpected_event = 1;
121
goto out;
122
}
123
out:
124
return status;
125
}
126
127
static enum mod_hdcp_status transition(struct mod_hdcp *hdcp,
128
struct mod_hdcp_event_context *event_ctx,
129
union mod_hdcp_transition_input *input,
130
struct mod_hdcp_output *output)
131
{
132
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
133
134
if (event_ctx->unexpected_event)
135
goto out;
136
137
if (is_in_initialized_state(hdcp)) {
138
if (is_dp_hdcp(hdcp))
139
if (is_cp_desired_hdcp2(hdcp)) {
140
callback_in_ms(0, output);
141
set_state_id(hdcp, output, D2_A0_DETERMINE_RX_HDCP_CAPABLE);
142
} else if (is_cp_desired_hdcp1(hdcp)) {
143
callback_in_ms(0, output);
144
set_state_id(hdcp, output, D1_A0_DETERMINE_RX_HDCP_CAPABLE);
145
} else {
146
callback_in_ms(0, output);
147
set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED);
148
set_auth_complete(hdcp, output);
149
}
150
else if (is_hdmi_dvi_sl_hdcp(hdcp))
151
if (is_cp_desired_hdcp2(hdcp)) {
152
callback_in_ms(0, output);
153
set_state_id(hdcp, output, H2_A0_KNOWN_HDCP2_CAPABLE_RX);
154
} else if (is_cp_desired_hdcp1(hdcp)) {
155
callback_in_ms(0, output);
156
set_state_id(hdcp, output, H1_A0_WAIT_FOR_ACTIVE_RX);
157
} else {
158
callback_in_ms(0, output);
159
set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED);
160
set_auth_complete(hdcp, output);
161
}
162
else {
163
callback_in_ms(0, output);
164
set_state_id(hdcp, output, HDCP_CP_NOT_DESIRED);
165
set_auth_complete(hdcp, output);
166
}
167
} else if (is_in_cp_not_desired_state(hdcp)) {
168
increment_stay_counter(hdcp);
169
} else if (is_in_hdcp1_states(hdcp)) {
170
status = mod_hdcp_hdcp1_transition(hdcp,
171
event_ctx, &input->hdcp1, output);
172
} else if (is_in_hdcp1_dp_states(hdcp)) {
173
status = mod_hdcp_hdcp1_dp_transition(hdcp,
174
event_ctx, &input->hdcp1, output);
175
} else if (is_in_hdcp2_states(hdcp)) {
176
status = mod_hdcp_hdcp2_transition(hdcp,
177
event_ctx, &input->hdcp2, output);
178
} else if (is_in_hdcp2_dp_states(hdcp)) {
179
status = mod_hdcp_hdcp2_dp_transition(hdcp,
180
event_ctx, &input->hdcp2, output);
181
} else {
182
status = MOD_HDCP_STATUS_INVALID_STATE;
183
}
184
out:
185
return status;
186
}
187
188
static enum mod_hdcp_status reset_authentication(struct mod_hdcp *hdcp,
189
struct mod_hdcp_output *output)
190
{
191
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
192
193
if (is_hdcp1(hdcp)) {
194
if (hdcp->auth.trans_input.hdcp1.create_session != UNKNOWN) {
195
/* TODO - update psp to unify create session failure
196
* recovery between hdcp1 and 2.
197
*/
198
mod_hdcp_hdcp1_destroy_session(hdcp);
199
200
}
201
202
HDCP_TOP_RESET_AUTH_TRACE(hdcp);
203
memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication));
204
memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state));
205
set_state_id(hdcp, output, HDCP_INITIALIZED);
206
} else if (is_hdcp2(hdcp)) {
207
if (hdcp->auth.trans_input.hdcp2.create_session == PASS) {
208
status = mod_hdcp_hdcp2_destroy_session(hdcp);
209
if (status != MOD_HDCP_STATUS_SUCCESS) {
210
output->callback_needed = 0;
211
output->watchdog_timer_needed = 0;
212
goto out;
213
}
214
}
215
216
HDCP_TOP_RESET_AUTH_TRACE(hdcp);
217
memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication));
218
memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state));
219
set_state_id(hdcp, output, HDCP_INITIALIZED);
220
} else if (is_in_cp_not_desired_state(hdcp)) {
221
HDCP_TOP_RESET_AUTH_TRACE(hdcp);
222
memset(&hdcp->auth, 0, sizeof(struct mod_hdcp_authentication));
223
memset(&hdcp->state, 0, sizeof(struct mod_hdcp_state));
224
set_state_id(hdcp, output, HDCP_INITIALIZED);
225
}
226
227
out:
228
/* stop callback and watchdog requests from previous authentication*/
229
output->watchdog_timer_stop = 1;
230
output->callback_stop = 1;
231
return status;
232
}
233
234
static enum mod_hdcp_status reset_connection(struct mod_hdcp *hdcp,
235
struct mod_hdcp_output *output)
236
{
237
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
238
239
memset(output, 0, sizeof(struct mod_hdcp_output));
240
241
status = reset_authentication(hdcp, output);
242
if (status != MOD_HDCP_STATUS_SUCCESS)
243
goto out;
244
245
if (current_state(hdcp) != HDCP_UNINITIALIZED) {
246
HDCP_TOP_RESET_CONN_TRACE(hdcp);
247
set_state_id(hdcp, output, HDCP_UNINITIALIZED);
248
}
249
memset(&hdcp->connection, 0, sizeof(hdcp->connection));
250
out:
251
return status;
252
}
253
254
static enum mod_hdcp_status update_display_adjustments(struct mod_hdcp *hdcp,
255
struct mod_hdcp_display *display,
256
struct mod_hdcp_display_adjustment *adj)
257
{
258
enum mod_hdcp_status status = MOD_HDCP_STATUS_NOT_IMPLEMENTED;
259
260
if (is_in_authenticated_states(hdcp) &&
261
is_dp_mst_hdcp(hdcp) &&
262
display->adjust.disable == true &&
263
adj->disable == false) {
264
display->adjust.disable = false;
265
if (is_hdcp1(hdcp))
266
status = mod_hdcp_hdcp1_enable_dp_stream_encryption(hdcp);
267
else if (is_hdcp2(hdcp))
268
status = mod_hdcp_hdcp2_enable_dp_stream_encryption(hdcp);
269
270
if (status != MOD_HDCP_STATUS_SUCCESS)
271
display->adjust.disable = true;
272
}
273
274
if (status == MOD_HDCP_STATUS_SUCCESS &&
275
memcmp(adj, &display->adjust,
276
sizeof(struct mod_hdcp_display_adjustment)) != 0)
277
status = MOD_HDCP_STATUS_NOT_IMPLEMENTED;
278
279
return status;
280
}
281
/*
282
* Implementation of functions in mod_hdcp.h
283
*/
284
size_t mod_hdcp_get_memory_size(void)
285
{
286
return sizeof(struct mod_hdcp);
287
}
288
289
enum mod_hdcp_status mod_hdcp_setup(struct mod_hdcp *hdcp,
290
struct mod_hdcp_config *config)
291
{
292
struct mod_hdcp_output output;
293
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
294
295
memset(&output, 0, sizeof(output));
296
hdcp->config = *config;
297
HDCP_TOP_INTERFACE_TRACE(hdcp);
298
status = reset_connection(hdcp, &output);
299
if (status != MOD_HDCP_STATUS_SUCCESS)
300
push_error_status(hdcp, status);
301
return status;
302
}
303
304
enum mod_hdcp_status mod_hdcp_teardown(struct mod_hdcp *hdcp)
305
{
306
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
307
struct mod_hdcp_output output;
308
309
HDCP_TOP_INTERFACE_TRACE(hdcp);
310
memset(&output, 0, sizeof(output));
311
status = reset_connection(hdcp, &output);
312
if (status == MOD_HDCP_STATUS_SUCCESS)
313
memset(hdcp, 0, sizeof(struct mod_hdcp));
314
else
315
push_error_status(hdcp, status);
316
return status;
317
}
318
319
enum mod_hdcp_status mod_hdcp_add_display(struct mod_hdcp *hdcp,
320
struct mod_hdcp_link *link, struct mod_hdcp_display *display,
321
struct mod_hdcp_output *output)
322
{
323
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
324
struct mod_hdcp_display *display_container = NULL;
325
326
HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, display->index);
327
memset(output, 0, sizeof(struct mod_hdcp_output));
328
329
/* skip inactive display */
330
if (display->state != MOD_HDCP_DISPLAY_ACTIVE) {
331
status = MOD_HDCP_STATUS_SUCCESS;
332
goto out;
333
}
334
335
/* check existing display container */
336
if (get_active_display_at_index(hdcp, display->index)) {
337
status = MOD_HDCP_STATUS_SUCCESS;
338
goto out;
339
}
340
341
/* find an empty display container */
342
display_container = get_empty_display_container(hdcp);
343
if (!display_container) {
344
status = MOD_HDCP_STATUS_DISPLAY_OUT_OF_BOUND;
345
goto out;
346
}
347
348
/* reset existing authentication status */
349
status = reset_authentication(hdcp, output);
350
if (status != MOD_HDCP_STATUS_SUCCESS)
351
goto out;
352
353
/* reset retry counters */
354
reset_retry_counts(hdcp);
355
356
/* reset error trace */
357
memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace));
358
359
/* add display to connection */
360
hdcp->connection.link = *link;
361
*display_container = *display;
362
status = mod_hdcp_add_display_to_topology(hdcp, display_container);
363
364
if (status != MOD_HDCP_STATUS_SUCCESS)
365
goto out;
366
367
/* request authentication */
368
if (current_state(hdcp) != HDCP_INITIALIZED)
369
set_state_id(hdcp, output, HDCP_INITIALIZED);
370
callback_in_ms(hdcp->connection.link.adjust.auth_delay * 1000, output);
371
out:
372
if (status != MOD_HDCP_STATUS_SUCCESS)
373
push_error_status(hdcp, status);
374
375
return status;
376
}
377
378
enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp,
379
uint8_t index, struct mod_hdcp_output *output)
380
{
381
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
382
struct mod_hdcp_display *display = NULL;
383
384
HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, index);
385
memset(output, 0, sizeof(struct mod_hdcp_output));
386
387
/* find display in connection */
388
display = get_active_display_at_index(hdcp, index);
389
if (!display) {
390
status = MOD_HDCP_STATUS_SUCCESS;
391
goto out;
392
}
393
394
/* stop current authentication */
395
status = reset_authentication(hdcp, output);
396
if (status != MOD_HDCP_STATUS_SUCCESS)
397
goto out;
398
399
/* clear retry counters */
400
reset_retry_counts(hdcp);
401
402
/* reset error trace */
403
memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace));
404
405
/* remove display */
406
status = mod_hdcp_remove_display_from_topology(hdcp, index);
407
if (status != MOD_HDCP_STATUS_SUCCESS)
408
goto out;
409
memset(display, 0, sizeof(struct mod_hdcp_display));
410
411
/* request authentication when connection is not reset */
412
if (current_state(hdcp) != HDCP_UNINITIALIZED)
413
callback_in_ms(hdcp->connection.link.adjust.auth_delay * 1000,
414
output);
415
out:
416
if (status != MOD_HDCP_STATUS_SUCCESS)
417
push_error_status(hdcp, status);
418
return status;
419
}
420
421
enum mod_hdcp_status mod_hdcp_update_display(struct mod_hdcp *hdcp,
422
uint8_t index,
423
struct mod_hdcp_link_adjustment *link_adjust,
424
struct mod_hdcp_display_adjustment *display_adjust,
425
struct mod_hdcp_output *output)
426
{
427
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
428
struct mod_hdcp_display *display = NULL;
429
430
HDCP_TOP_INTERFACE_TRACE_WITH_INDEX(hdcp, index);
431
memset(output, 0, sizeof(struct mod_hdcp_output));
432
433
/* find display in connection */
434
display = get_active_display_at_index(hdcp, index);
435
if (!display) {
436
status = MOD_HDCP_STATUS_DISPLAY_NOT_FOUND;
437
goto out;
438
}
439
440
/* skip if no changes */
441
if (memcmp(link_adjust, &hdcp->connection.link.adjust,
442
sizeof(struct mod_hdcp_link_adjustment)) == 0 &&
443
memcmp(display_adjust, &display->adjust,
444
sizeof(struct mod_hdcp_display_adjustment)) == 0) {
445
status = MOD_HDCP_STATUS_SUCCESS;
446
goto out;
447
}
448
449
if (memcmp(link_adjust, &hdcp->connection.link.adjust,
450
sizeof(struct mod_hdcp_link_adjustment)) == 0 &&
451
memcmp(display_adjust, &display->adjust,
452
sizeof(struct mod_hdcp_display_adjustment)) != 0) {
453
status = update_display_adjustments(hdcp, display, display_adjust);
454
if (status != MOD_HDCP_STATUS_NOT_IMPLEMENTED)
455
goto out;
456
}
457
458
/* stop current authentication */
459
status = reset_authentication(hdcp, output);
460
if (status != MOD_HDCP_STATUS_SUCCESS)
461
goto out;
462
463
/* clear retry counters */
464
reset_retry_counts(hdcp);
465
466
/* reset error trace */
467
memset(&hdcp->connection.trace, 0, sizeof(hdcp->connection.trace));
468
469
/* set new adjustment */
470
hdcp->connection.link.adjust = *link_adjust;
471
display->adjust = *display_adjust;
472
473
/* request authentication when connection is not reset */
474
if (current_state(hdcp) != HDCP_UNINITIALIZED)
475
/* wait 100ms to debounce simultaneous updates for different indices */
476
callback_in_ms(100, output);
477
478
out:
479
if (status != MOD_HDCP_STATUS_SUCCESS)
480
push_error_status(hdcp, status);
481
return status;
482
}
483
484
enum mod_hdcp_status mod_hdcp_query_display(struct mod_hdcp *hdcp,
485
uint8_t index, struct mod_hdcp_display_query *query)
486
{
487
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
488
struct mod_hdcp_display *display = NULL;
489
490
/* find display in connection */
491
display = get_active_display_at_index(hdcp, index);
492
if (!display) {
493
status = MOD_HDCP_STATUS_DISPLAY_NOT_FOUND;
494
goto out;
495
}
496
497
/* populate query */
498
query->link = &hdcp->connection.link;
499
query->display = display;
500
query->trace = &hdcp->connection.trace;
501
query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
502
503
if (is_display_encryption_enabled(display)) {
504
if (is_hdcp1(hdcp)) {
505
query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP1_ON;
506
} else if (is_hdcp2(hdcp)) {
507
if (query->link->adjust.hdcp2.force_type == MOD_HDCP_FORCE_TYPE_0)
508
query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE0_ON;
509
else if (query->link->adjust.hdcp2.force_type == MOD_HDCP_FORCE_TYPE_1)
510
query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP2_TYPE1_ON;
511
else
512
query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP2_ON;
513
}
514
} else {
515
query->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
516
}
517
518
out:
519
return status;
520
}
521
522
enum mod_hdcp_status mod_hdcp_reset_connection(struct mod_hdcp *hdcp,
523
struct mod_hdcp_output *output)
524
{
525
enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
526
527
HDCP_TOP_INTERFACE_TRACE(hdcp);
528
status = reset_connection(hdcp, output);
529
if (status != MOD_HDCP_STATUS_SUCCESS)
530
push_error_status(hdcp, status);
531
532
return status;
533
}
534
535
enum mod_hdcp_status mod_hdcp_process_event(struct mod_hdcp *hdcp,
536
enum mod_hdcp_event event, struct mod_hdcp_output *output)
537
{
538
enum mod_hdcp_status exec_status, trans_status, reset_status, status;
539
struct mod_hdcp_event_context event_ctx;
540
541
HDCP_EVENT_TRACE(hdcp, event);
542
memset(output, 0, sizeof(struct mod_hdcp_output));
543
memset(&event_ctx, 0, sizeof(struct mod_hdcp_event_context));
544
event_ctx.event = event;
545
546
/* execute and transition */
547
exec_status = execution(hdcp, &event_ctx, &hdcp->auth.trans_input);
548
trans_status = transition(
549
hdcp, &event_ctx, &hdcp->auth.trans_input, output);
550
if (trans_status == MOD_HDCP_STATUS_SUCCESS) {
551
status = MOD_HDCP_STATUS_SUCCESS;
552
} else if (exec_status == MOD_HDCP_STATUS_SUCCESS) {
553
status = MOD_HDCP_STATUS_INTERNAL_POLICY_FAILURE;
554
push_error_status(hdcp, status);
555
} else {
556
status = exec_status;
557
push_error_status(hdcp, status);
558
}
559
560
/* reset authentication if needed */
561
if (trans_status == MOD_HDCP_STATUS_RESET_NEEDED) {
562
mod_hdcp_log_ddc_trace(hdcp);
563
reset_status = reset_authentication(hdcp, output);
564
if (reset_status != MOD_HDCP_STATUS_SUCCESS)
565
push_error_status(hdcp, reset_status);
566
}
567
568
/* Clear CP_IRQ status if needed */
569
if (event_ctx.event == MOD_HDCP_EVENT_CPIRQ) {
570
status = mod_hdcp_clear_cp_irq_status(hdcp);
571
if (status != MOD_HDCP_STATUS_SUCCESS)
572
push_error_status(hdcp, status);
573
}
574
575
return status;
576
}
577
578
enum mod_hdcp_operation_mode mod_hdcp_signal_type_to_operation_mode(
579
enum signal_type signal)
580
{
581
enum mod_hdcp_operation_mode mode = MOD_HDCP_MODE_OFF;
582
583
switch (signal) {
584
case SIGNAL_TYPE_DVI_SINGLE_LINK:
585
case SIGNAL_TYPE_HDMI_TYPE_A:
586
mode = MOD_HDCP_MODE_DEFAULT;
587
break;
588
case SIGNAL_TYPE_EDP:
589
case SIGNAL_TYPE_DISPLAY_PORT:
590
case SIGNAL_TYPE_DISPLAY_PORT_MST:
591
mode = MOD_HDCP_MODE_DP;
592
break;
593
default:
594
break;
595
}
596
597
return mode;
598
}
599
600