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