1 /* 2 * Copyright 2015 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 <linux/string.h> 27 #include <linux/acpi.h> 28 #include <linux/i2c.h> 29 30 #include <drm/drm_atomic.h> 31 #include <drm/drm_probe_helper.h> 32 #include <drm/amdgpu_drm.h> 33 #include <drm/drm_edid.h> 34 35 #include "dm_services.h" 36 #include "amdgpu.h" 37 #include "dc.h" 38 #include "amdgpu_dm.h" 39 #include "amdgpu_dm_irq.h" 40 #include "amdgpu_dm_mst_types.h" 41 42 #include "dm_helpers.h" 43 #include "ddc_service_types.h" 44 45 /* dm_helpers_parse_edid_caps 46 * 47 * Parse edid caps 48 * 49 * @edid: [in] pointer to edid 50 * edid_caps: [in] pointer to edid caps 51 * @return 52 * void 53 * */ 54 enum dc_edid_status dm_helpers_parse_edid_caps( 55 struct dc_link *link, 56 const struct dc_edid *edid, 57 struct dc_edid_caps *edid_caps) 58 { 59 struct amdgpu_dm_connector *aconnector = link->priv; 60 struct drm_connector *connector = &aconnector->base; 61 struct edid *edid_buf = edid ? (struct edid *) edid->raw_edid : NULL; 62 struct cea_sad *sads; 63 int sad_count = -1; 64 int sadb_count = -1; 65 int i = 0; 66 uint8_t *sadb = NULL; 67 68 enum dc_edid_status result = EDID_OK; 69 70 if (!edid_caps || !edid) 71 return EDID_BAD_INPUT; 72 73 if (!drm_edid_is_valid(edid_buf)) 74 result = EDID_BAD_CHECKSUM; 75 76 edid_caps->manufacturer_id = (uint16_t) edid_buf->mfg_id[0] | 77 ((uint16_t) edid_buf->mfg_id[1])<<8; 78 edid_caps->product_id = (uint16_t) edid_buf->prod_code[0] | 79 ((uint16_t) edid_buf->prod_code[1])<<8; 80 edid_caps->serial_number = edid_buf->serial; 81 edid_caps->manufacture_week = edid_buf->mfg_week; 82 edid_caps->manufacture_year = edid_buf->mfg_year; 83 84 drm_edid_get_monitor_name(edid_buf, 85 edid_caps->display_name, 86 AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS); 87 88 edid_caps->edid_hdmi = connector->display_info.is_hdmi; 89 90 sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, &sads); 91 if (sad_count <= 0) 92 return result; 93 94 edid_caps->audio_mode_count = sad_count < DC_MAX_AUDIO_DESC_COUNT ? sad_count : DC_MAX_AUDIO_DESC_COUNT; 95 for (i = 0; i < edid_caps->audio_mode_count; ++i) { 96 struct cea_sad *sad = &sads[i]; 97 98 edid_caps->audio_modes[i].format_code = sad->format; 99 edid_caps->audio_modes[i].channel_count = sad->channels + 1; 100 edid_caps->audio_modes[i].sample_rate = sad->freq; 101 edid_caps->audio_modes[i].sample_size = sad->byte2; 102 } 103 104 sadb_count = drm_edid_to_speaker_allocation((struct edid *) edid->raw_edid, &sadb); 105 106 if (sadb_count < 0) { 107 DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sadb_count); 108 sadb_count = 0; 109 } 110 111 if (sadb_count) 112 edid_caps->speaker_flags = sadb[0]; 113 else 114 edid_caps->speaker_flags = DEFAULT_SPEAKER_LOCATION; 115 116 kfree(sads); 117 kfree(sadb); 118 119 return result; 120 } 121 122 static void 123 fill_dc_mst_payload_table_from_drm(struct dc_link *link, 124 bool enable, 125 struct drm_dp_mst_atomic_payload *target_payload, 126 struct dc_dp_mst_stream_allocation_table *table) 127 { 128 struct dc_dp_mst_stream_allocation_table new_table = { 0 }; 129 struct dc_dp_mst_stream_allocation *sa; 130 struct link_mst_stream_allocation_table copy_of_link_table = 131 link->mst_stream_alloc_table; 132 133 int i; 134 int current_hw_table_stream_cnt = copy_of_link_table.stream_count; 135 struct link_mst_stream_allocation *dc_alloc; 136 137 /* TODO: refactor to set link->mst_stream_alloc_table directly if possible.*/ 138 if (enable) { 139 dc_alloc = 140 ©_of_link_table.stream_allocations[current_hw_table_stream_cnt]; 141 dc_alloc->vcp_id = target_payload->vcpi; 142 dc_alloc->slot_count = target_payload->time_slots; 143 } else { 144 for (i = 0; i < copy_of_link_table.stream_count; i++) { 145 dc_alloc = 146 ©_of_link_table.stream_allocations[i]; 147 148 if (dc_alloc->vcp_id == target_payload->vcpi) { 149 dc_alloc->vcp_id = 0; 150 dc_alloc->slot_count = 0; 151 break; 152 } 153 } 154 ASSERT(i != copy_of_link_table.stream_count); 155 } 156 157 /* Fill payload info*/ 158 for (i = 0; i < MAX_CONTROLLER_NUM; i++) { 159 dc_alloc = 160 ©_of_link_table.stream_allocations[i]; 161 if (dc_alloc->vcp_id > 0 && dc_alloc->slot_count > 0) { 162 sa = &new_table.stream_allocations[new_table.stream_count]; 163 sa->slot_count = dc_alloc->slot_count; 164 sa->vcp_id = dc_alloc->vcp_id; 165 new_table.stream_count++; 166 } 167 } 168 169 /* Overwrite the old table */ 170 *table = new_table; 171 } 172 173 void dm_helpers_dp_update_branch_info( 174 struct dc_context *ctx, 175 const struct dc_link *link) 176 {} 177 178 /* 179 * Writes payload allocation table in immediate downstream device. 180 */ 181 bool dm_helpers_dp_mst_write_payload_allocation_table( 182 struct dc_context *ctx, 183 const struct dc_stream_state *stream, 184 struct dc_dp_mst_stream_allocation_table *proposed_table, 185 bool enable) 186 { 187 struct amdgpu_dm_connector *aconnector; 188 struct drm_dp_mst_topology_state *mst_state; 189 struct drm_dp_mst_atomic_payload *payload; 190 struct drm_dp_mst_topology_mgr *mst_mgr; 191 192 aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; 193 /* Accessing the connector state is required for vcpi_slots allocation 194 * and directly relies on behaviour in commit check 195 * that blocks before commit guaranteeing that the state 196 * is not gonna be swapped while still in use in commit tail */ 197 198 if (!aconnector || !aconnector->mst_port) 199 return false; 200 201 mst_mgr = &aconnector->mst_port->mst_mgr; 202 mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state); 203 204 /* It's OK for this to fail */ 205 payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->port); 206 if (enable) 207 drm_dp_add_payload_part1(mst_mgr, mst_state, payload); 208 else 209 drm_dp_remove_payload(mst_mgr, mst_state, payload); 210 211 /* mst_mgr->->payloads are VC payload notify MST branch using DPCD or 212 * AUX message. The sequence is slot 1-63 allocated sequence for each 213 * stream. AMD ASIC stream slot allocation should follow the same 214 * sequence. copy DRM MST allocation to dc */ 215 fill_dc_mst_payload_table_from_drm(stream->link, enable, payload, proposed_table); 216 217 return true; 218 } 219 220 /* 221 * poll pending down reply 222 */ 223 void dm_helpers_dp_mst_poll_pending_down_reply( 224 struct dc_context *ctx, 225 const struct dc_link *link) 226 {} 227 228 /* 229 * Clear payload allocation table before enable MST DP link. 230 */ 231 void dm_helpers_dp_mst_clear_payload_allocation_table( 232 struct dc_context *ctx, 233 const struct dc_link *link) 234 {} 235 236 /* 237 * Polls for ACT (allocation change trigger) handled and sends 238 * ALLOCATE_PAYLOAD message. 239 */ 240 enum act_return_status dm_helpers_dp_mst_poll_for_allocation_change_trigger( 241 struct dc_context *ctx, 242 const struct dc_stream_state *stream) 243 { 244 struct amdgpu_dm_connector *aconnector; 245 struct drm_dp_mst_topology_mgr *mst_mgr; 246 int ret; 247 248 aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; 249 250 if (!aconnector || !aconnector->mst_port) 251 return ACT_FAILED; 252 253 mst_mgr = &aconnector->mst_port->mst_mgr; 254 255 if (!mst_mgr->mst_state) 256 return ACT_FAILED; 257 258 ret = drm_dp_check_act_status(mst_mgr); 259 260 if (ret) 261 return ACT_FAILED; 262 263 return ACT_SUCCESS; 264 } 265 266 bool dm_helpers_dp_mst_send_payload_allocation( 267 struct dc_context *ctx, 268 const struct dc_stream_state *stream, 269 bool enable) 270 { 271 struct amdgpu_dm_connector *aconnector; 272 struct drm_dp_mst_topology_state *mst_state; 273 struct drm_dp_mst_topology_mgr *mst_mgr; 274 struct drm_dp_mst_atomic_payload *payload; 275 enum mst_progress_status set_flag = MST_ALLOCATE_NEW_PAYLOAD; 276 enum mst_progress_status clr_flag = MST_CLEAR_ALLOCATED_PAYLOAD; 277 278 aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; 279 280 if (!aconnector || !aconnector->mst_port) 281 return false; 282 283 mst_mgr = &aconnector->mst_port->mst_mgr; 284 mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state); 285 286 payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->port); 287 if (!enable) { 288 set_flag = MST_CLEAR_ALLOCATED_PAYLOAD; 289 clr_flag = MST_ALLOCATE_NEW_PAYLOAD; 290 } 291 292 if (enable && drm_dp_add_payload_part2(mst_mgr, mst_state->base.state, payload)) { 293 amdgpu_dm_set_mst_status(&aconnector->mst_status, 294 set_flag, false); 295 } else { 296 amdgpu_dm_set_mst_status(&aconnector->mst_status, 297 set_flag, true); 298 amdgpu_dm_set_mst_status(&aconnector->mst_status, 299 clr_flag, false); 300 } 301 302 return true; 303 } 304 305 void dm_dtn_log_begin(struct dc_context *ctx, 306 struct dc_log_buffer_ctx *log_ctx) 307 { 308 static const char msg[] = "[dtn begin]\n"; 309 310 if (!log_ctx) { 311 pr_info("%s", msg); 312 return; 313 } 314 315 dm_dtn_log_append_v(ctx, log_ctx, "%s", msg); 316 } 317 318 __printf(3, 4) 319 void dm_dtn_log_append_v(struct dc_context *ctx, 320 struct dc_log_buffer_ctx *log_ctx, 321 const char *msg, ...) 322 { 323 va_list args; 324 size_t total; 325 int n; 326 327 if (!log_ctx) { 328 /* No context, redirect to dmesg. */ 329 struct va_format vaf; 330 331 vaf.fmt = msg; 332 vaf.va = &args; 333 334 va_start(args, msg); 335 pr_info("%pV", &vaf); 336 va_end(args); 337 338 return; 339 } 340 341 /* Measure the output. */ 342 va_start(args, msg); 343 n = vsnprintf(NULL, 0, msg, args); 344 va_end(args); 345 346 if (n <= 0) 347 return; 348 349 /* Reallocate the string buffer as needed. */ 350 total = log_ctx->pos + n + 1; 351 352 if (total > log_ctx->size) { 353 char *buf = (char *)kvcalloc(total, sizeof(char), GFP_KERNEL); 354 355 if (buf) { 356 memcpy(buf, log_ctx->buf, log_ctx->pos); 357 kfree(log_ctx->buf); 358 359 log_ctx->buf = buf; 360 log_ctx->size = total; 361 } 362 } 363 364 if (!log_ctx->buf) 365 return; 366 367 /* Write the formatted string to the log buffer. */ 368 va_start(args, msg); 369 n = vscnprintf( 370 log_ctx->buf + log_ctx->pos, 371 log_ctx->size - log_ctx->pos, 372 msg, 373 args); 374 va_end(args); 375 376 if (n > 0) 377 log_ctx->pos += n; 378 } 379 380 void dm_dtn_log_end(struct dc_context *ctx, 381 struct dc_log_buffer_ctx *log_ctx) 382 { 383 static const char msg[] = "[dtn end]\n"; 384 385 if (!log_ctx) { 386 pr_info("%s", msg); 387 return; 388 } 389 390 dm_dtn_log_append_v(ctx, log_ctx, "%s", msg); 391 } 392 393 bool dm_helpers_dp_mst_start_top_mgr( 394 struct dc_context *ctx, 395 const struct dc_link *link, 396 bool boot) 397 { 398 struct amdgpu_dm_connector *aconnector = link->priv; 399 400 if (!aconnector) { 401 DRM_ERROR("Failed to find connector for link!"); 402 return false; 403 } 404 405 if (boot) { 406 DRM_INFO("DM_MST: Differing MST start on aconnector: %p [id: %d]\n", 407 aconnector, aconnector->base.base.id); 408 return true; 409 } 410 411 DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n", 412 aconnector, aconnector->base.base.id); 413 414 return (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) == 0); 415 } 416 417 bool dm_helpers_dp_mst_stop_top_mgr( 418 struct dc_context *ctx, 419 struct dc_link *link) 420 { 421 struct amdgpu_dm_connector *aconnector = link->priv; 422 423 if (!aconnector) { 424 DRM_ERROR("Failed to find connector for link!"); 425 return false; 426 } 427 428 DRM_INFO("DM_MST: stopping TM on aconnector: %p [id: %d]\n", 429 aconnector, aconnector->base.base.id); 430 431 if (aconnector->mst_mgr.mst_state == true) { 432 drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, false); 433 link->cur_link_settings.lane_count = 0; 434 } 435 436 return false; 437 } 438 439 bool dm_helpers_dp_read_dpcd( 440 struct dc_context *ctx, 441 const struct dc_link *link, 442 uint32_t address, 443 uint8_t *data, 444 uint32_t size) 445 { 446 447 struct amdgpu_dm_connector *aconnector = link->priv; 448 449 if (!aconnector) { 450 DC_LOG_DC("Failed to find connector for link!\n"); 451 return false; 452 } 453 454 return drm_dp_dpcd_read(&aconnector->dm_dp_aux.aux, address, 455 data, size) > 0; 456 } 457 458 bool dm_helpers_dp_write_dpcd( 459 struct dc_context *ctx, 460 const struct dc_link *link, 461 uint32_t address, 462 const uint8_t *data, 463 uint32_t size) 464 { 465 struct amdgpu_dm_connector *aconnector = link->priv; 466 467 if (!aconnector) { 468 DRM_ERROR("Failed to find connector for link!"); 469 return false; 470 } 471 472 return drm_dp_dpcd_write(&aconnector->dm_dp_aux.aux, 473 address, (uint8_t *)data, size) > 0; 474 } 475 476 bool dm_helpers_submit_i2c( 477 struct dc_context *ctx, 478 const struct dc_link *link, 479 struct i2c_command *cmd) 480 { 481 struct amdgpu_dm_connector *aconnector = link->priv; 482 struct i2c_msg *msgs; 483 int i = 0; 484 int num = cmd->number_of_payloads; 485 bool result; 486 487 if (!aconnector) { 488 DRM_ERROR("Failed to find connector for link!"); 489 return false; 490 } 491 492 msgs = kcalloc(num, sizeof(struct i2c_msg), GFP_KERNEL); 493 494 if (!msgs) 495 return false; 496 497 for (i = 0; i < num; i++) { 498 msgs[i].flags = cmd->payloads[i].write ? 0 : I2C_M_RD; 499 msgs[i].addr = cmd->payloads[i].address; 500 msgs[i].len = cmd->payloads[i].length; 501 msgs[i].buf = cmd->payloads[i].data; 502 } 503 504 result = i2c_transfer(&aconnector->i2c->base, msgs, num) == num; 505 506 kfree(msgs); 507 508 return result; 509 } 510 511 #if defined(CONFIG_DRM_AMD_DC_DCN) 512 static bool execute_synaptics_rc_command(struct drm_dp_aux *aux, 513 bool is_write_cmd, 514 unsigned char cmd, 515 unsigned int length, 516 unsigned int offset, 517 unsigned char *data) 518 { 519 bool success = false; 520 unsigned char rc_data[16] = {0}; 521 unsigned char rc_offset[4] = {0}; 522 unsigned char rc_length[2] = {0}; 523 unsigned char rc_cmd = 0; 524 unsigned char rc_result = 0xFF; 525 unsigned char i = 0; 526 int ret; 527 528 if (is_write_cmd) { 529 // write rc data 530 memmove(rc_data, data, length); 531 ret = drm_dp_dpcd_write(aux, SYNAPTICS_RC_DATA, rc_data, sizeof(rc_data)); 532 } 533 534 // write rc offset 535 rc_offset[0] = (unsigned char) offset & 0xFF; 536 rc_offset[1] = (unsigned char) (offset >> 8) & 0xFF; 537 rc_offset[2] = (unsigned char) (offset >> 16) & 0xFF; 538 rc_offset[3] = (unsigned char) (offset >> 24) & 0xFF; 539 ret = drm_dp_dpcd_write(aux, SYNAPTICS_RC_OFFSET, rc_offset, sizeof(rc_offset)); 540 541 // write rc length 542 rc_length[0] = (unsigned char) length & 0xFF; 543 rc_length[1] = (unsigned char) (length >> 8) & 0xFF; 544 ret = drm_dp_dpcd_write(aux, SYNAPTICS_RC_LENGTH, rc_length, sizeof(rc_length)); 545 546 // write rc cmd 547 rc_cmd = cmd | 0x80; 548 ret = drm_dp_dpcd_write(aux, SYNAPTICS_RC_COMMAND, &rc_cmd, sizeof(rc_cmd)); 549 550 if (ret < 0) { 551 DRM_ERROR(" execute_synaptics_rc_command - write cmd ..., err = %d\n", ret); 552 return false; 553 } 554 555 // poll until active is 0 556 for (i = 0; i < 10; i++) { 557 drm_dp_dpcd_read(aux, SYNAPTICS_RC_COMMAND, &rc_cmd, sizeof(rc_cmd)); 558 if (rc_cmd == cmd) 559 // active is 0 560 break; 561 msleep(10); 562 } 563 564 // read rc result 565 drm_dp_dpcd_read(aux, SYNAPTICS_RC_RESULT, &rc_result, sizeof(rc_result)); 566 success = (rc_result == 0); 567 568 if (success && !is_write_cmd) { 569 // read rc data 570 drm_dp_dpcd_read(aux, SYNAPTICS_RC_DATA, data, length); 571 } 572 573 DC_LOG_DC(" execute_synaptics_rc_command - success = %d\n", success); 574 575 return success; 576 } 577 578 static void apply_synaptics_fifo_reset_wa(struct drm_dp_aux *aux) 579 { 580 unsigned char data[16] = {0}; 581 582 DC_LOG_DC("Start apply_synaptics_fifo_reset_wa\n"); 583 584 // Step 2 585 data[0] = 'P'; 586 data[1] = 'R'; 587 data[2] = 'I'; 588 data[3] = 'U'; 589 data[4] = 'S'; 590 591 if (!execute_synaptics_rc_command(aux, true, 0x01, 5, 0, data)) 592 return; 593 594 // Step 3 and 4 595 if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x220998, data)) 596 return; 597 598 data[0] &= (~(1 << 1)); // set bit 1 to 0 599 if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x220998, data)) 600 return; 601 602 if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x220D98, data)) 603 return; 604 605 data[0] &= (~(1 << 1)); // set bit 1 to 0 606 if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x220D98, data)) 607 return; 608 609 if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x221198, data)) 610 return; 611 612 data[0] &= (~(1 << 1)); // set bit 1 to 0 613 if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x221198, data)) 614 return; 615 616 // Step 3 and 5 617 if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x220998, data)) 618 return; 619 620 data[0] |= (1 << 1); // set bit 1 to 1 621 if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x220998, data)) 622 return; 623 624 if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x220D98, data)) 625 return; 626 627 data[0] |= (1 << 1); // set bit 1 to 1 628 return; 629 630 if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x221198, data)) 631 return; 632 633 data[0] |= (1 << 1); // set bit 1 to 1 634 if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x221198, data)) 635 return; 636 637 // Step 6 638 if (!execute_synaptics_rc_command(aux, true, 0x02, 0, 0, NULL)) 639 return; 640 641 DC_LOG_DC("Done apply_synaptics_fifo_reset_wa\n"); 642 } 643 644 static uint8_t write_dsc_enable_synaptics_non_virtual_dpcd_mst( 645 struct drm_dp_aux *aux, 646 const struct dc_stream_state *stream, 647 bool enable) 648 { 649 uint8_t ret = 0; 650 651 DC_LOG_DC("Configure DSC to non-virtual dpcd synaptics\n"); 652 653 if (enable) { 654 /* When DSC is enabled on previous boot and reboot with the hub, 655 * there is a chance that Synaptics hub gets stuck during reboot sequence. 656 * Applying a workaround to reset Synaptics SDP fifo before enabling the first stream 657 */ 658 if (!stream->link->link_status.link_active && 659 memcmp(stream->link->dpcd_caps.branch_dev_name, 660 (int8_t *)SYNAPTICS_DEVICE_ID, 4) == 0) 661 apply_synaptics_fifo_reset_wa(aux); 662 663 ret = drm_dp_dpcd_write(aux, DP_DSC_ENABLE, &enable, 1); 664 DRM_INFO("Send DSC enable to synaptics\n"); 665 666 } else { 667 /* Synaptics hub not support virtual dpcd, 668 * external monitor occur garbage while disable DSC, 669 * Disable DSC only when entire link status turn to false, 670 */ 671 if (!stream->link->link_status.link_active) { 672 ret = drm_dp_dpcd_write(aux, DP_DSC_ENABLE, &enable, 1); 673 DRM_INFO("Send DSC disable to synaptics\n"); 674 } 675 } 676 677 return ret; 678 } 679 #endif 680 681 bool dm_helpers_dp_write_dsc_enable( 682 struct dc_context *ctx, 683 const struct dc_stream_state *stream, 684 bool enable) 685 { 686 static const uint8_t DSC_DISABLE; 687 static const uint8_t DSC_DECODING = 0x01; 688 static const uint8_t DSC_PASSTHROUGH = 0x02; 689 690 struct amdgpu_dm_connector *aconnector; 691 struct drm_dp_mst_port *port; 692 uint8_t enable_dsc = enable ? DSC_DECODING : DSC_DISABLE; 693 uint8_t enable_passthrough = enable ? DSC_PASSTHROUGH : DSC_DISABLE; 694 uint8_t ret = 0; 695 696 if (!stream) 697 return false; 698 699 if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { 700 aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; 701 702 if (!aconnector->dsc_aux) 703 return false; 704 705 #if defined(CONFIG_DRM_AMD_DC_DCN) 706 // apply w/a to synaptics 707 if (needs_dsc_aux_workaround(aconnector->dc_link) && 708 (aconnector->mst_downstream_port_present.byte & 0x7) != 0x3) 709 return write_dsc_enable_synaptics_non_virtual_dpcd_mst( 710 aconnector->dsc_aux, stream, enable_dsc); 711 #endif 712 713 port = aconnector->port; 714 715 if (enable) { 716 if (port->passthrough_aux) { 717 ret = drm_dp_dpcd_write(port->passthrough_aux, 718 DP_DSC_ENABLE, 719 &enable_passthrough, 1); 720 DC_LOG_DC("Sent DSC pass-through enable to virtual dpcd port, ret = %u\n", 721 ret); 722 } 723 724 ret = drm_dp_dpcd_write(aconnector->dsc_aux, 725 DP_DSC_ENABLE, &enable_dsc, 1); 726 DC_LOG_DC("Sent DSC decoding enable to %s port, ret = %u\n", 727 (port->passthrough_aux) ? "remote RX" : 728 "virtual dpcd", 729 ret); 730 } else { 731 ret = drm_dp_dpcd_write(aconnector->dsc_aux, 732 DP_DSC_ENABLE, &enable_dsc, 1); 733 DC_LOG_DC("Sent DSC decoding disable to %s port, ret = %u\n", 734 (port->passthrough_aux) ? "remote RX" : 735 "virtual dpcd", 736 ret); 737 738 if (port->passthrough_aux) { 739 ret = drm_dp_dpcd_write(port->passthrough_aux, 740 DP_DSC_ENABLE, 741 &enable_passthrough, 1); 742 DC_LOG_DC("Sent DSC pass-through disable to virtual dpcd port, ret = %u\n", 743 ret); 744 } 745 } 746 } 747 748 if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT || stream->signal == SIGNAL_TYPE_EDP) { 749 #if defined(CONFIG_DRM_AMD_DC_DCN) 750 if (stream->sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_NONE) { 751 #endif 752 ret = dm_helpers_dp_write_dpcd(ctx, stream->link, DP_DSC_ENABLE, &enable_dsc, 1); 753 DC_LOG_DC("Send DSC %s to SST RX\n", enable_dsc ? "enable" : "disable"); 754 #if defined(CONFIG_DRM_AMD_DC_DCN) 755 } else if (stream->sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER) { 756 ret = dm_helpers_dp_write_dpcd(ctx, stream->link, DP_DSC_ENABLE, &enable_dsc, 1); 757 DC_LOG_DC("Send DSC %s to DP-HDMI PCON\n", enable_dsc ? "enable" : "disable"); 758 } 759 #endif 760 } 761 762 return ret; 763 } 764 765 bool dm_helpers_is_dp_sink_present(struct dc_link *link) 766 { 767 bool dp_sink_present; 768 struct amdgpu_dm_connector *aconnector = link->priv; 769 770 if (!aconnector) { 771 BUG_ON("Failed to find connector for link!"); 772 return true; 773 } 774 775 mutex_lock(&aconnector->dm_dp_aux.aux.hw_mutex); 776 dp_sink_present = dc_link_is_dp_sink_present(link); 777 mutex_unlock(&aconnector->dm_dp_aux.aux.hw_mutex); 778 return dp_sink_present; 779 } 780 781 enum dc_edid_status dm_helpers_read_local_edid( 782 struct dc_context *ctx, 783 struct dc_link *link, 784 struct dc_sink *sink) 785 { 786 struct amdgpu_dm_connector *aconnector = link->priv; 787 struct drm_connector *connector = &aconnector->base; 788 struct i2c_adapter *ddc; 789 int retry = 3; 790 enum dc_edid_status edid_status; 791 struct edid *edid; 792 793 if (link->aux_mode) 794 ddc = &aconnector->dm_dp_aux.aux.ddc; 795 else 796 ddc = &aconnector->i2c->base; 797 798 /* some dongles read edid incorrectly the first time, 799 * do check sum and retry to make sure read correct edid. 800 */ 801 do { 802 803 edid = drm_get_edid(&aconnector->base, ddc); 804 805 /* DP Compliance Test 4.2.2.6 */ 806 if (link->aux_mode && connector->edid_corrupt) 807 drm_dp_send_real_edid_checksum(&aconnector->dm_dp_aux.aux, connector->real_edid_checksum); 808 809 if (!edid && connector->edid_corrupt) { 810 connector->edid_corrupt = false; 811 return EDID_BAD_CHECKSUM; 812 } 813 814 if (!edid) 815 return EDID_NO_RESPONSE; 816 817 sink->dc_edid.length = EDID_LENGTH * (edid->extensions + 1); 818 memmove(sink->dc_edid.raw_edid, (uint8_t *)edid, sink->dc_edid.length); 819 820 /* We don't need the original edid anymore */ 821 kfree(edid); 822 823 edid_status = dm_helpers_parse_edid_caps( 824 link, 825 &sink->dc_edid, 826 &sink->edid_caps); 827 828 } while (edid_status == EDID_BAD_CHECKSUM && --retry > 0); 829 830 if (edid_status != EDID_OK) 831 DRM_ERROR("EDID err: %d, on connector: %s", 832 edid_status, 833 aconnector->base.name); 834 835 /* DP Compliance Test 4.2.2.3 */ 836 if (link->aux_mode) 837 drm_dp_send_real_edid_checksum(&aconnector->dm_dp_aux.aux, sink->dc_edid.raw_edid[sink->dc_edid.length-1]); 838 839 return edid_status; 840 } 841 int dm_helper_dmub_aux_transfer_sync( 842 struct dc_context *ctx, 843 const struct dc_link *link, 844 struct aux_payload *payload, 845 enum aux_return_code_type *operation_result) 846 { 847 return amdgpu_dm_process_dmub_aux_transfer_sync(ctx, link->link_index, payload, 848 operation_result); 849 } 850 851 int dm_helpers_dmub_set_config_sync(struct dc_context *ctx, 852 const struct dc_link *link, 853 struct set_config_cmd_payload *payload, 854 enum set_config_status *operation_result) 855 { 856 return amdgpu_dm_process_dmub_set_config_sync(ctx, link->link_index, payload, 857 operation_result); 858 } 859 860 void dm_set_dcn_clocks(struct dc_context *ctx, struct dc_clocks *clks) 861 { 862 /* TODO: something */ 863 } 864 865 void dm_helpers_smu_timeout(struct dc_context *ctx, unsigned int msg_id, unsigned int param, unsigned int timeout_us) 866 { 867 // TODO: 868 //amdgpu_device_gpu_recover(dc_context->driver-context, NULL); 869 } 870 871 void dm_helpers_init_panel_settings( 872 struct dc_context *ctx, 873 struct dc_panel_config *panel_config, 874 struct dc_sink *sink) 875 { 876 // Extra Panel Power Sequence 877 panel_config->pps.extra_t3_ms = sink->edid_caps.panel_patch.extra_t3_ms; 878 panel_config->pps.extra_t7_ms = sink->edid_caps.panel_patch.extra_t7_ms; 879 panel_config->pps.extra_delay_backlight_off = sink->edid_caps.panel_patch.extra_delay_backlight_off; 880 panel_config->pps.extra_post_t7_ms = 0; 881 panel_config->pps.extra_pre_t11_ms = 0; 882 panel_config->pps.extra_t12_ms = sink->edid_caps.panel_patch.extra_t12_ms; 883 panel_config->pps.extra_post_OUI_ms = 0; 884 // Feature DSC 885 panel_config->dsc.disable_dsc_edp = false; 886 panel_config->dsc.force_dsc_edp_policy = 0; 887 } 888 889 void dm_helpers_override_panel_settings( 890 struct dc_context *ctx, 891 struct dc_panel_config *panel_config) 892 { 893 // Feature DSC 894 if (amdgpu_dc_debug_mask & DC_DISABLE_DSC) { 895 panel_config->dsc.disable_dsc_edp = true; 896 } 897 } 898 899 void *dm_helpers_allocate_gpu_mem( 900 struct dc_context *ctx, 901 enum dc_gpu_mem_alloc_type type, 902 size_t size, 903 long long *addr) 904 { 905 struct amdgpu_device *adev = ctx->driver_context; 906 struct dal_allocation *da; 907 u32 domain = (type == DC_MEM_ALLOC_TYPE_GART) ? 908 AMDGPU_GEM_DOMAIN_GTT : AMDGPU_GEM_DOMAIN_VRAM; 909 int ret; 910 911 da = kzalloc(sizeof(struct dal_allocation), GFP_KERNEL); 912 if (!da) 913 return NULL; 914 915 ret = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE, 916 domain, &da->bo, 917 &da->gpu_addr, &da->cpu_ptr); 918 919 *addr = da->gpu_addr; 920 921 if (ret) { 922 kfree(da); 923 return NULL; 924 } 925 926 /* add da to list in dm */ 927 list_add(&da->list, &adev->dm.da_list); 928 929 return da->cpu_ptr; 930 } 931 932 void dm_helpers_free_gpu_mem( 933 struct dc_context *ctx, 934 enum dc_gpu_mem_alloc_type type, 935 void *pvMem) 936 { 937 struct amdgpu_device *adev = ctx->driver_context; 938 struct dal_allocation *da; 939 940 /* walk the da list in DM */ 941 list_for_each_entry(da, &adev->dm.da_list, list) { 942 if (pvMem == da->cpu_ptr) { 943 amdgpu_bo_free_kernel(&da->bo, &da->gpu_addr, &da->cpu_ptr); 944 list_del(&da->list); 945 kfree(da); 946 break; 947 } 948 } 949 } 950 951 bool dm_helpers_dmub_outbox_interrupt_control(struct dc_context *ctx, bool enable) 952 { 953 enum dc_irq_source irq_source; 954 bool ret; 955 956 irq_source = DC_IRQ_SOURCE_DMCUB_OUTBOX; 957 958 ret = dc_interrupt_set(ctx->dc, irq_source, enable); 959 960 DRM_DEBUG_DRIVER("Dmub trace irq %sabling: r=%d\n", 961 enable ? "en" : "dis", ret); 962 return ret; 963 } 964 965 void dm_helpers_mst_enable_stream_features(const struct dc_stream_state *stream) 966 { 967 /* TODO: virtual DPCD */ 968 struct dc_link *link = stream->link; 969 union down_spread_ctrl old_downspread; 970 union down_spread_ctrl new_downspread; 971 972 if (link->aux_access_disabled) 973 return; 974 975 if (!dm_helpers_dp_read_dpcd(link->ctx, link, DP_DOWNSPREAD_CTRL, 976 &old_downspread.raw, 977 sizeof(old_downspread))) 978 return; 979 980 new_downspread.raw = old_downspread.raw; 981 new_downspread.bits.IGNORE_MSA_TIMING_PARAM = 982 (stream->ignore_msa_timing_param) ? 1 : 0; 983 984 if (new_downspread.raw != old_downspread.raw) 985 dm_helpers_dp_write_dpcd(link->ctx, link, DP_DOWNSPREAD_CTRL, 986 &new_downspread.raw, 987 sizeof(new_downspread)); 988 } 989 990 void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz) 991 { 992 // TODO 993 } 994 995 void dm_helpers_enable_periodic_detection(struct dc_context *ctx, bool enable) 996 { 997 /* TODO: add periodic detection implementation */ 998 } 999 1000 void dm_helpers_dp_mst_update_branch_bandwidth( 1001 struct dc_context *ctx, 1002 struct dc_link *link) 1003 { 1004 // TODO 1005 } 1006 1007