1 /* Copyright 2021 Advanced Micro Devices, Inc. All rights reserved. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a 4 * copy of this software and associated documentation files (the "Software"), 5 * to deal in the Software without restriction, including without limitation 6 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 * and/or sell copies of the Software, and to permit persons to whom the 8 * Software is furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 * OTHER DEALINGS IN THE SOFTWARE. 20 * 21 * Authors: AMD 22 * 23 */ 24 25 #include "link_enc_cfg.h" 26 #include "resource.h" 27 #include "dc_link_dp.h" 28 29 /* Check whether stream is supported by DIG link encoders. */ 30 static bool is_dig_link_enc_stream(struct dc_stream_state *stream) 31 { 32 bool is_dig_stream = false; 33 struct link_encoder *link_enc = NULL; 34 int i; 35 36 /* Loop over created link encoder objects. */ 37 if (stream) { 38 for (i = 0; i < stream->ctx->dc->res_pool->res_cap->num_dig_link_enc; i++) { 39 link_enc = stream->ctx->dc->res_pool->link_encoders[i]; 40 41 /* Need to check link signal type rather than stream signal type which may not 42 * yet match. 43 */ 44 if (link_enc && ((uint32_t)stream->link->connector_signal & link_enc->output_signals)) { 45 if (dc_is_dp_signal(stream->signal)) { 46 /* DIGs do not support DP2.0 streams with 128b/132b encoding. */ 47 struct dc_link_settings link_settings = {0}; 48 49 decide_link_settings(stream, &link_settings); 50 if ((link_settings.link_rate >= LINK_RATE_LOW) && 51 link_settings.link_rate <= LINK_RATE_HIGH3) { 52 is_dig_stream = true; 53 break; 54 } 55 } else { 56 is_dig_stream = true; 57 break; 58 } 59 } 60 } 61 } 62 return is_dig_stream; 63 } 64 65 static struct link_enc_assignment get_assignment(struct dc *dc, int i) 66 { 67 struct link_enc_assignment assignment; 68 69 if (dc->current_state->res_ctx.link_enc_cfg_ctx.mode == LINK_ENC_CFG_TRANSIENT) 70 assignment = dc->current_state->res_ctx.link_enc_cfg_ctx.transient_assignments[i]; 71 else /* LINK_ENC_CFG_STEADY */ 72 assignment = dc->current_state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; 73 74 return assignment; 75 } 76 77 /* Return stream using DIG link encoder resource. NULL if unused. */ 78 static struct dc_stream_state *get_stream_using_link_enc( 79 struct dc_state *state, 80 enum engine_id eng_id) 81 { 82 struct dc_stream_state *stream = NULL; 83 int i; 84 85 for (i = 0; i < state->stream_count; i++) { 86 struct link_enc_assignment assignment = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; 87 88 if ((assignment.valid == true) && (assignment.eng_id == eng_id)) { 89 stream = state->streams[i]; 90 break; 91 } 92 } 93 94 return stream; 95 } 96 97 static void remove_link_enc_assignment( 98 struct dc_state *state, 99 struct dc_stream_state *stream, 100 enum engine_id eng_id) 101 { 102 int eng_idx; 103 int i; 104 105 if (eng_id != ENGINE_ID_UNKNOWN) { 106 eng_idx = eng_id - ENGINE_ID_DIGA; 107 108 /* stream ptr of stream in dc_state used to update correct entry in 109 * link_enc_assignments table. 110 */ 111 for (i = 0; i < MAX_PIPES; i++) { 112 struct link_enc_assignment assignment = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; 113 114 if (assignment.valid && assignment.stream == stream) { 115 state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i].valid = false; 116 /* Only add link encoder back to availability pool if not being 117 * used by any other stream (i.e. removing SST stream or last MST stream). 118 */ 119 if (get_stream_using_link_enc(state, eng_id) == NULL) 120 state->res_ctx.link_enc_cfg_ctx.link_enc_avail[eng_idx] = eng_id; 121 122 stream->link_enc = NULL; 123 state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i].eng_id = ENGINE_ID_UNKNOWN; 124 state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i].stream = NULL; 125 dc_stream_release(stream); 126 break; 127 } 128 } 129 } 130 } 131 132 static void add_link_enc_assignment( 133 struct dc_state *state, 134 struct dc_stream_state *stream, 135 enum engine_id eng_id) 136 { 137 int eng_idx; 138 int i; 139 140 if (eng_id != ENGINE_ID_UNKNOWN) { 141 eng_idx = eng_id - ENGINE_ID_DIGA; 142 143 /* stream ptr of stream in dc_state used to update correct entry in 144 * link_enc_assignments table. 145 */ 146 for (i = 0; i < state->stream_count; i++) { 147 if (stream == state->streams[i]) { 148 state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i] = (struct link_enc_assignment){ 149 .valid = true, 150 .ep_id = (struct display_endpoint_id) { 151 .link_id = stream->link->link_id, 152 .ep_type = stream->link->ep_type}, 153 .eng_id = eng_id, 154 .stream = stream}; 155 dc_stream_retain(stream); 156 state->res_ctx.link_enc_cfg_ctx.link_enc_avail[eng_idx] = ENGINE_ID_UNKNOWN; 157 stream->link_enc = stream->ctx->dc->res_pool->link_encoders[eng_idx]; 158 break; 159 } 160 } 161 162 /* Attempted to add an encoder assignment for a stream not in dc_state. */ 163 ASSERT(i != state->stream_count); 164 } 165 } 166 167 /* Return first available DIG link encoder. */ 168 static enum engine_id find_first_avail_link_enc( 169 const struct dc_context *ctx, 170 const struct dc_state *state) 171 { 172 enum engine_id eng_id = ENGINE_ID_UNKNOWN; 173 int i; 174 175 for (i = 0; i < ctx->dc->res_pool->res_cap->num_dig_link_enc; i++) { 176 eng_id = state->res_ctx.link_enc_cfg_ctx.link_enc_avail[i]; 177 if (eng_id != ENGINE_ID_UNKNOWN) 178 break; 179 } 180 181 return eng_id; 182 } 183 184 /* Check for availability of link encoder eng_id. */ 185 static bool is_avail_link_enc(struct dc_state *state, enum engine_id eng_id, struct dc_stream_state *stream) 186 { 187 bool is_avail = false; 188 int eng_idx = eng_id - ENGINE_ID_DIGA; 189 190 /* An encoder is available if it is still in the availability pool. */ 191 if (eng_id != ENGINE_ID_UNKNOWN && state->res_ctx.link_enc_cfg_ctx.link_enc_avail[eng_idx] != ENGINE_ID_UNKNOWN) { 192 is_avail = true; 193 } else { 194 struct dc_stream_state *stream_assigned = NULL; 195 196 /* MST streams share the same link and should share the same encoder. 197 * If a stream that has already been assigned a link encoder uses as the 198 * same link as the stream checking for availability, it is an MST stream 199 * and should use the same link encoder. 200 */ 201 stream_assigned = get_stream_using_link_enc(state, eng_id); 202 if (stream_assigned && stream != stream_assigned && stream->link == stream_assigned->link) 203 is_avail = true; 204 } 205 206 return is_avail; 207 } 208 209 /* Test for display_endpoint_id equality. */ 210 static bool are_ep_ids_equal(struct display_endpoint_id *lhs, struct display_endpoint_id *rhs) 211 { 212 bool are_equal = false; 213 214 if (lhs->link_id.id == rhs->link_id.id && 215 lhs->link_id.enum_id == rhs->link_id.enum_id && 216 lhs->link_id.type == rhs->link_id.type && 217 lhs->ep_type == rhs->ep_type) 218 are_equal = true; 219 220 return are_equal; 221 } 222 223 static struct link_encoder *get_link_enc_used_by_link( 224 struct dc_state *state, 225 const struct dc_link *link) 226 { 227 struct link_encoder *link_enc = NULL; 228 struct display_endpoint_id ep_id; 229 int i; 230 231 ep_id = (struct display_endpoint_id) { 232 .link_id = link->link_id, 233 .ep_type = link->ep_type}; 234 235 for (i = 0; i < MAX_PIPES; i++) { 236 struct link_enc_assignment assignment = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; 237 238 if (assignment.valid == true && are_ep_ids_equal(&assignment.ep_id, &ep_id)) 239 link_enc = link->dc->res_pool->link_encoders[assignment.eng_id - ENGINE_ID_DIGA]; 240 } 241 242 return link_enc; 243 } 244 /* Clear all link encoder assignments. */ 245 static void clear_enc_assignments(const struct dc *dc, struct dc_state *state) 246 { 247 int i; 248 249 for (i = 0; i < MAX_PIPES; i++) { 250 state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i].valid = false; 251 state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i].eng_id = ENGINE_ID_UNKNOWN; 252 if (state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i].stream != NULL) { 253 dc_stream_release(state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i].stream); 254 state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i].stream = NULL; 255 } 256 } 257 258 for (i = 0; i < dc->res_pool->res_cap->num_dig_link_enc; i++) { 259 if (dc->res_pool->link_encoders[i]) 260 state->res_ctx.link_enc_cfg_ctx.link_enc_avail[i] = (enum engine_id) i; 261 else 262 state->res_ctx.link_enc_cfg_ctx.link_enc_avail[i] = ENGINE_ID_UNKNOWN; 263 } 264 } 265 266 void link_enc_cfg_init( 267 const struct dc *dc, 268 struct dc_state *state) 269 { 270 clear_enc_assignments(dc, state); 271 272 state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_STEADY; 273 } 274 275 void link_enc_cfg_copy(const struct dc_state *src_ctx, struct dc_state *dst_ctx) 276 { 277 memcpy(&dst_ctx->res_ctx.link_enc_cfg_ctx, 278 &src_ctx->res_ctx.link_enc_cfg_ctx, 279 sizeof(dst_ctx->res_ctx.link_enc_cfg_ctx)); 280 } 281 282 void link_enc_cfg_link_encs_assign( 283 struct dc *dc, 284 struct dc_state *state, 285 struct dc_stream_state *streams[], 286 uint8_t stream_count) 287 { 288 enum engine_id eng_id = ENGINE_ID_UNKNOWN; 289 int i; 290 int j; 291 292 ASSERT(state->stream_count == stream_count); 293 294 /* Release DIG link encoder resources before running assignment algorithm. */ 295 for (i = 0; i < dc->current_state->stream_count; i++) 296 dc->res_pool->funcs->link_enc_unassign(state, dc->current_state->streams[i]); 297 298 for (i = 0; i < MAX_PIPES; i++) 299 ASSERT(state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i].valid == false); 300 301 /* (a) Assign DIG link encoders to physical (unmappable) endpoints first. */ 302 for (i = 0; i < stream_count; i++) { 303 struct dc_stream_state *stream = streams[i]; 304 305 /* Skip stream if not supported by DIG link encoder. */ 306 if (!is_dig_link_enc_stream(stream)) 307 continue; 308 309 /* Physical endpoints have a fixed mapping to DIG link encoders. */ 310 if (!stream->link->is_dig_mapping_flexible) { 311 eng_id = stream->link->eng_id; 312 add_link_enc_assignment(state, stream, eng_id); 313 } 314 } 315 316 /* (b) Retain previous assignments for mappable endpoints if encoders still available. */ 317 eng_id = ENGINE_ID_UNKNOWN; 318 319 if (state != dc->current_state) { 320 struct dc_state *prev_state = dc->current_state; 321 322 for (i = 0; i < stream_count; i++) { 323 struct dc_stream_state *stream = state->streams[i]; 324 325 /* Skip stream if not supported by DIG link encoder. */ 326 if (!is_dig_link_enc_stream(stream)) 327 continue; 328 329 if (!stream->link->is_dig_mapping_flexible) 330 continue; 331 332 for (j = 0; j < prev_state->stream_count; j++) { 333 struct dc_stream_state *prev_stream = prev_state->streams[j]; 334 335 if (stream == prev_stream && stream->link == prev_stream->link && 336 prev_state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[j].valid) { 337 eng_id = prev_state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[j].eng_id; 338 if (is_avail_link_enc(state, eng_id, stream)) 339 add_link_enc_assignment(state, stream, eng_id); 340 } 341 } 342 } 343 } 344 345 /* (c) Then assign encoders to remaining mappable endpoints. */ 346 eng_id = ENGINE_ID_UNKNOWN; 347 348 for (i = 0; i < stream_count; i++) { 349 struct dc_stream_state *stream = streams[i]; 350 351 /* Skip stream if not supported by DIG link encoder. */ 352 if (!is_dig_link_enc_stream(stream)) { 353 ASSERT(stream->link->is_dig_mapping_flexible != true); 354 continue; 355 } 356 357 /* Mappable endpoints have a flexible mapping to DIG link encoders. */ 358 if (stream->link->is_dig_mapping_flexible) { 359 struct link_encoder *link_enc = NULL; 360 361 /* Skip if encoder assignment retained in step (b) above. */ 362 if (stream->link_enc) 363 continue; 364 365 /* For MST, multiple streams will share the same link / display 366 * endpoint. These streams should use the same link encoder 367 * assigned to that endpoint. 368 */ 369 link_enc = get_link_enc_used_by_link(state, stream->link); 370 if (link_enc == NULL) 371 eng_id = find_first_avail_link_enc(stream->ctx, state); 372 else 373 eng_id = link_enc->preferred_engine; 374 add_link_enc_assignment(state, stream, eng_id); 375 } 376 } 377 378 link_enc_cfg_validate(dc, state); 379 380 /* Update transient assignments. */ 381 for (i = 0; i < MAX_PIPES; i++) { 382 dc->current_state->res_ctx.link_enc_cfg_ctx.transient_assignments[i] = 383 state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; 384 } 385 386 /* Current state mode will be set to steady once this state committed. */ 387 state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_STEADY; 388 } 389 390 void link_enc_cfg_link_enc_unassign( 391 struct dc_state *state, 392 struct dc_stream_state *stream) 393 { 394 enum engine_id eng_id = ENGINE_ID_UNKNOWN; 395 396 /* Only DIG link encoders. */ 397 if (!is_dig_link_enc_stream(stream)) 398 return; 399 400 if (stream->link_enc) 401 eng_id = stream->link_enc->preferred_engine; 402 403 remove_link_enc_assignment(state, stream, eng_id); 404 } 405 406 bool link_enc_cfg_is_transmitter_mappable( 407 struct dc *dc, 408 struct link_encoder *link_enc) 409 { 410 bool is_mappable = false; 411 enum engine_id eng_id = link_enc->preferred_engine; 412 struct dc_stream_state *stream = link_enc_cfg_get_stream_using_link_enc(dc, eng_id); 413 414 if (stream) 415 is_mappable = stream->link->is_dig_mapping_flexible; 416 417 return is_mappable; 418 } 419 420 struct dc_stream_state *link_enc_cfg_get_stream_using_link_enc( 421 struct dc *dc, 422 enum engine_id eng_id) 423 { 424 struct dc_stream_state *stream = NULL; 425 int i; 426 427 for (i = 0; i < MAX_PIPES; i++) { 428 struct link_enc_assignment assignment = get_assignment(dc, i); 429 430 if ((assignment.valid == true) && (assignment.eng_id == eng_id)) { 431 stream = assignment.stream; 432 break; 433 } 434 } 435 436 return stream; 437 } 438 439 struct dc_link *link_enc_cfg_get_link_using_link_enc( 440 struct dc *dc, 441 enum engine_id eng_id) 442 { 443 struct dc_link *link = NULL; 444 struct dc_stream_state *stream = NULL; 445 446 stream = link_enc_cfg_get_stream_using_link_enc(dc, eng_id); 447 448 if (stream) 449 link = stream->link; 450 451 // dm_output_to_console("%s: No link using DIG(%d).\n", __func__, eng_id); 452 return link; 453 } 454 455 struct link_encoder *link_enc_cfg_get_link_enc_used_by_link( 456 struct dc *dc, 457 const struct dc_link *link) 458 { 459 struct link_encoder *link_enc = NULL; 460 struct display_endpoint_id ep_id; 461 int i; 462 463 ep_id = (struct display_endpoint_id) { 464 .link_id = link->link_id, 465 .ep_type = link->ep_type}; 466 467 for (i = 0; i < MAX_PIPES; i++) { 468 struct link_enc_assignment assignment = get_assignment(dc, i); 469 470 if (assignment.valid == true && are_ep_ids_equal(&assignment.ep_id, &ep_id)) { 471 link_enc = link->dc->res_pool->link_encoders[assignment.eng_id - ENGINE_ID_DIGA]; 472 break; 473 } 474 } 475 476 return link_enc; 477 } 478 479 struct link_encoder *link_enc_cfg_get_next_avail_link_enc(struct dc *dc) 480 { 481 struct link_encoder *link_enc = NULL; 482 enum engine_id encs_assigned[MAX_DIG_LINK_ENCODERS]; 483 int i; 484 485 for (i = 0; i < MAX_DIG_LINK_ENCODERS; i++) 486 encs_assigned[i] = ENGINE_ID_UNKNOWN; 487 488 /* Add assigned encoders to list. */ 489 for (i = 0; i < MAX_PIPES; i++) { 490 struct link_enc_assignment assignment = get_assignment(dc, i); 491 492 if (assignment.valid) 493 encs_assigned[assignment.eng_id - ENGINE_ID_DIGA] = assignment.eng_id; 494 } 495 496 for (i = 0; i < dc->res_pool->res_cap->num_dig_link_enc; i++) { 497 if (encs_assigned[i] == ENGINE_ID_UNKNOWN && 498 dc->res_pool->link_encoders[i] != NULL) { 499 link_enc = dc->res_pool->link_encoders[i]; 500 break; 501 } 502 } 503 504 return link_enc; 505 } 506 507 struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream( 508 struct dc *dc, 509 const struct dc_stream_state *stream) 510 { 511 struct link_encoder *link_enc; 512 513 link_enc = link_enc_cfg_get_link_enc_used_by_link(dc, stream->link); 514 515 return link_enc; 516 } 517 518 struct link_encoder *link_enc_cfg_get_link_enc( 519 const struct dc_link *link) 520 { 521 struct link_encoder *link_enc = NULL; 522 523 /* Links supporting dynamically assigned link encoder will be assigned next 524 * available encoder if one not already assigned. 525 */ 526 if (link->is_dig_mapping_flexible && 527 link->dc->res_pool->funcs->link_encs_assign) { 528 link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); 529 if (link_enc == NULL) 530 link_enc = link_enc_cfg_get_next_avail_link_enc( 531 link->ctx->dc); 532 } else 533 link_enc = link->link_enc; 534 535 return link_enc; 536 } 537 538 bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id, struct dc_link *link) 539 { 540 bool is_avail = true; 541 int i; 542 543 /* An encoder is not available if it has already been assigned to a different endpoint. */ 544 for (i = 0; i < MAX_PIPES; i++) { 545 struct link_enc_assignment assignment = get_assignment(dc, i); 546 struct display_endpoint_id ep_id = (struct display_endpoint_id) { 547 .link_id = link->link_id, 548 .ep_type = link->ep_type}; 549 550 if (assignment.valid && assignment.eng_id == eng_id && !are_ep_ids_equal(&ep_id, &assignment.ep_id)) { 551 is_avail = false; 552 break; 553 } 554 } 555 556 return is_avail; 557 } 558 559 bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state) 560 { 561 bool is_valid = false; 562 bool valid_entries = true; 563 bool valid_stream_ptrs = true; 564 bool valid_uniqueness = true; 565 bool valid_avail = true; 566 bool valid_streams = true; 567 int i, j; 568 uint8_t valid_count = 0; 569 uint8_t dig_stream_count = 0; 570 int matching_stream_ptrs = 0; 571 int eng_ids_per_ep_id[MAX_PIPES] = {0}; 572 int valid_bitmap = 0; 573 574 /* (1) No. valid entries same as stream count. */ 575 for (i = 0; i < MAX_PIPES; i++) { 576 struct link_enc_assignment assignment = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; 577 578 if (assignment.valid) 579 valid_count++; 580 581 if (is_dig_link_enc_stream(state->streams[i])) 582 dig_stream_count++; 583 } 584 if (valid_count != dig_stream_count) 585 valid_entries = false; 586 587 /* (2) Matching stream ptrs. */ 588 for (i = 0; i < MAX_PIPES; i++) { 589 struct link_enc_assignment assignment = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; 590 591 if (assignment.valid) { 592 if (assignment.stream == state->streams[i]) 593 matching_stream_ptrs++; 594 else 595 valid_stream_ptrs = false; 596 } 597 } 598 599 /* (3) Each endpoint assigned unique encoder. */ 600 for (i = 0; i < MAX_PIPES; i++) { 601 struct link_enc_assignment assignment_i = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; 602 603 if (assignment_i.valid) { 604 struct display_endpoint_id ep_id_i = assignment_i.ep_id; 605 606 eng_ids_per_ep_id[i]++; 607 for (j = 0; j < MAX_PIPES; j++) { 608 struct link_enc_assignment assignment_j = 609 state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[j]; 610 611 if (j == i) 612 continue; 613 614 if (assignment_j.valid) { 615 struct display_endpoint_id ep_id_j = assignment_j.ep_id; 616 617 if (are_ep_ids_equal(&ep_id_i, &ep_id_j) && 618 assignment_i.eng_id != assignment_j.eng_id) { 619 valid_uniqueness = false; 620 eng_ids_per_ep_id[i]++; 621 } 622 } 623 } 624 } 625 } 626 627 /* (4) Assigned encoders not in available pool. */ 628 for (i = 0; i < MAX_PIPES; i++) { 629 struct link_enc_assignment assignment = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; 630 631 if (assignment.valid) { 632 for (j = 0; j < dc->res_pool->res_cap->num_dig_link_enc; j++) { 633 if (state->res_ctx.link_enc_cfg_ctx.link_enc_avail[j] == assignment.eng_id) { 634 valid_avail = false; 635 break; 636 } 637 } 638 } 639 } 640 641 /* (5) All streams have valid link encoders. */ 642 for (i = 0; i < state->stream_count; i++) { 643 struct dc_stream_state *stream = state->streams[i]; 644 645 if (is_dig_link_enc_stream(stream) && stream->link_enc == NULL) { 646 valid_streams = false; 647 break; 648 } 649 } 650 651 is_valid = valid_entries && valid_stream_ptrs && valid_uniqueness && valid_avail && valid_streams; 652 ASSERT(is_valid); 653 654 if (is_valid == false) { 655 valid_bitmap = 656 (valid_entries & 0x1) | 657 ((valid_stream_ptrs & 0x1) << 1) | 658 ((valid_uniqueness & 0x1) << 2) | 659 ((valid_avail & 0x1) << 3) | 660 ((valid_streams & 0x1) << 4); 661 dm_error("Invalid link encoder assignments: 0x%x\n", valid_bitmap); 662 } 663 664 return is_valid; 665 } 666