2614 lines · c
1/*2 * Copyright 2023 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26/* FILE POLICY AND INTENDED USAGE:27 * This file owns the programming sequence of stream's dpms state associated28 * with the link and link's enable/disable sequences as result of the stream's29 * dpms state change.30 *31 * TODO - The reason link owns stream's dpms programming sequence is32 * because dpms programming sequence is highly dependent on underlying signal33 * specific link protocols. This unfortunately causes link to own a portion of34 * stream state programming sequence. This creates a gray area where the35 * boundary between link and stream is not clearly defined.36 */37 38#include "link_dpms.h"39#include "link_hwss.h"40#include "link_validation.h"41#include "accessories/link_dp_trace.h"42#include "protocols/link_dpcd.h"43#include "protocols/link_ddc.h"44#include "protocols/link_hpd.h"45#include "protocols/link_dp_phy.h"46#include "protocols/link_dp_capability.h"47#include "protocols/link_dp_training.h"48#include "protocols/link_edp_panel_control.h"49#include "protocols/link_dp_dpia_bw.h"50 51#include "dm_helpers.h"52#include "link_enc_cfg.h"53#include "resource.h"54#include "dsc.h"55#include "dccg.h"56#include "clk_mgr.h"57#include "atomfirmware.h"58#include "vpg.h"59 60#define DC_LOGGER \61 dc_logger62#define DC_LOGGER_INIT(logger) \63 struct dal_logger *dc_logger = logger64 65#define LINK_INFO(...) \66 DC_LOG_HW_HOTPLUG( \67 __VA_ARGS__)68 69#define RETIMER_REDRIVER_INFO(...) \70 DC_LOG_RETIMER_REDRIVER( \71 __VA_ARGS__)72 73#define MAX_MTP_SLOT_COUNT 6474#define LINK_TRAINING_ATTEMPTS 475#define PEAK_FACTOR_X1000 100676 77void link_blank_all_dp_displays(struct dc *dc)78{79 unsigned int i;80 uint8_t dpcd_power_state = '\0';81 enum dc_status status = DC_ERROR_UNEXPECTED;82 83 for (i = 0; i < dc->link_count; i++) {84 if ((dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) ||85 (dc->links[i]->priv == NULL) || (dc->links[i]->local_sink == NULL))86 continue;87 88 /* DP 2.0 spec requires that we read LTTPR caps first */89 dp_retrieve_lttpr_cap(dc->links[i]);90 /* if any of the displays are lit up turn them off */91 status = core_link_read_dpcd(dc->links[i], DP_SET_POWER,92 &dpcd_power_state, sizeof(dpcd_power_state));93 94 if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0)95 link_blank_dp_stream(dc->links[i], true);96 }97 98}99 100void link_blank_all_edp_displays(struct dc *dc)101{102 unsigned int i;103 uint8_t dpcd_power_state = '\0';104 enum dc_status status = DC_ERROR_UNEXPECTED;105 106 for (i = 0; i < dc->link_count; i++) {107 if ((dc->links[i]->connector_signal != SIGNAL_TYPE_EDP) ||108 (!dc->links[i]->edp_sink_present))109 continue;110 111 /* if any of the displays are lit up turn them off */112 status = core_link_read_dpcd(dc->links[i], DP_SET_POWER,113 &dpcd_power_state, sizeof(dpcd_power_state));114 115 if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0)116 link_blank_dp_stream(dc->links[i], true);117 }118}119 120void link_blank_dp_stream(struct dc_link *link, bool hw_init)121{122 unsigned int j;123 struct dc *dc = link->ctx->dc;124 enum signal_type signal = link->connector_signal;125 126 if ((signal == SIGNAL_TYPE_EDP) ||127 (signal == SIGNAL_TYPE_DISPLAY_PORT)) {128 if (link->ep_type == DISPLAY_ENDPOINT_PHY &&129 link->link_enc->funcs->get_dig_frontend &&130 link->link_enc->funcs->is_dig_enabled(link->link_enc)) {131 int fe = link->link_enc->funcs->get_dig_frontend(link->link_enc);132 133 if (fe != ENGINE_ID_UNKNOWN)134 for (j = 0; j < dc->res_pool->stream_enc_count; j++) {135 if (fe == dc->res_pool->stream_enc[j]->id) {136 dc->res_pool->stream_enc[j]->funcs->dp_blank(link,137 dc->res_pool->stream_enc[j]);138 break;139 }140 }141 }142 143 if ((!link->wa_flags.dp_keep_receiver_powered) || hw_init)144 dpcd_write_rx_power_ctrl(link, false);145 }146}147 148void link_set_all_streams_dpms_off_for_link(struct dc_link *link)149{150 struct pipe_ctx *pipes[MAX_PIPES];151 struct dc_state *state = link->dc->current_state;152 uint8_t count;153 int i;154 struct dc_stream_update stream_update;155 bool dpms_off = true;156 struct link_resource link_res = {0};157 158 memset(&stream_update, 0, sizeof(stream_update));159 stream_update.dpms_off = &dpms_off;160 161 link_get_master_pipes_with_dpms_on(link, state, &count, pipes);162 163 for (i = 0; i < count; i++) {164 stream_update.stream = pipes[i]->stream;165 dc_commit_updates_for_stream(link->ctx->dc, NULL, 0,166 pipes[i]->stream, &stream_update,167 state);168 }169 170 /* link can be also enabled by vbios. In this case it is not recorded171 * in pipe_ctx. Disable link phy here to make sure it is completely off172 */173 dp_disable_link_phy(link, &link_res, link->connector_signal);174}175 176void link_resume(struct dc_link *link)177{178 if (link->connector_signal != SIGNAL_TYPE_VIRTUAL)179 program_hpd_filter(link);180}181 182/* This function returns true if the pipe is used to feed video signal directly183 * to the link.184 */185static bool is_master_pipe_for_link(const struct dc_link *link,186 const struct pipe_ctx *pipe)187{188 return resource_is_pipe_type(pipe, OTG_MASTER) &&189 pipe->stream->link == link;190}191 192/*193 * This function finds all master pipes feeding to a given link with dpms set to194 * on in given dc state.195 */196void link_get_master_pipes_with_dpms_on(const struct dc_link *link,197 struct dc_state *state,198 uint8_t *count,199 struct pipe_ctx *pipes[MAX_PIPES])200{201 int i;202 struct pipe_ctx *pipe = NULL;203 204 *count = 0;205 for (i = 0; i < MAX_PIPES; i++) {206 pipe = &state->res_ctx.pipe_ctx[i];207 208 if (is_master_pipe_for_link(link, pipe) &&209 pipe->stream->dpms_off == false) {210 pipes[(*count)++] = pipe;211 }212 }213}214 215static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx,216 enum engine_id eng_id,217 struct ext_hdmi_settings *settings)218{219 bool result = false;220 int i = 0;221 struct integrated_info *integrated_info =222 pipe_ctx->stream->ctx->dc_bios->integrated_info;223 224 if (integrated_info == NULL)225 return false;226 227 /*228 * Get retimer settings from sbios for passing SI eye test for DCE11229 * The setting values are varied based on board revision and port id230 * Therefore the setting values of each ports is passed by sbios.231 */232 233 // Check if current bios contains ext Hdmi settings234 if (integrated_info->gpu_cap_info & 0x20) {235 switch (eng_id) {236 case ENGINE_ID_DIGA:237 settings->slv_addr = integrated_info->dp0_ext_hdmi_slv_addr;238 settings->reg_num = integrated_info->dp0_ext_hdmi_6g_reg_num;239 settings->reg_num_6g = integrated_info->dp0_ext_hdmi_6g_reg_num;240 memmove(settings->reg_settings,241 integrated_info->dp0_ext_hdmi_reg_settings,242 sizeof(integrated_info->dp0_ext_hdmi_reg_settings));243 memmove(settings->reg_settings_6g,244 integrated_info->dp0_ext_hdmi_6g_reg_settings,245 sizeof(integrated_info->dp0_ext_hdmi_6g_reg_settings));246 result = true;247 break;248 case ENGINE_ID_DIGB:249 settings->slv_addr = integrated_info->dp1_ext_hdmi_slv_addr;250 settings->reg_num = integrated_info->dp1_ext_hdmi_6g_reg_num;251 settings->reg_num_6g = integrated_info->dp1_ext_hdmi_6g_reg_num;252 memmove(settings->reg_settings,253 integrated_info->dp1_ext_hdmi_reg_settings,254 sizeof(integrated_info->dp1_ext_hdmi_reg_settings));255 memmove(settings->reg_settings_6g,256 integrated_info->dp1_ext_hdmi_6g_reg_settings,257 sizeof(integrated_info->dp1_ext_hdmi_6g_reg_settings));258 result = true;259 break;260 case ENGINE_ID_DIGC:261 settings->slv_addr = integrated_info->dp2_ext_hdmi_slv_addr;262 settings->reg_num = integrated_info->dp2_ext_hdmi_6g_reg_num;263 settings->reg_num_6g = integrated_info->dp2_ext_hdmi_6g_reg_num;264 memmove(settings->reg_settings,265 integrated_info->dp2_ext_hdmi_reg_settings,266 sizeof(integrated_info->dp2_ext_hdmi_reg_settings));267 memmove(settings->reg_settings_6g,268 integrated_info->dp2_ext_hdmi_6g_reg_settings,269 sizeof(integrated_info->dp2_ext_hdmi_6g_reg_settings));270 result = true;271 break;272 case ENGINE_ID_DIGD:273 settings->slv_addr = integrated_info->dp3_ext_hdmi_slv_addr;274 settings->reg_num = integrated_info->dp3_ext_hdmi_6g_reg_num;275 settings->reg_num_6g = integrated_info->dp3_ext_hdmi_6g_reg_num;276 memmove(settings->reg_settings,277 integrated_info->dp3_ext_hdmi_reg_settings,278 sizeof(integrated_info->dp3_ext_hdmi_reg_settings));279 memmove(settings->reg_settings_6g,280 integrated_info->dp3_ext_hdmi_6g_reg_settings,281 sizeof(integrated_info->dp3_ext_hdmi_6g_reg_settings));282 result = true;283 break;284 default:285 break;286 }287 288 if (result == true) {289 // Validate settings from bios integrated info table290 if (settings->slv_addr == 0)291 return false;292 if (settings->reg_num > 9)293 return false;294 if (settings->reg_num_6g > 3)295 return false;296 297 for (i = 0; i < settings->reg_num; i++) {298 if (settings->reg_settings[i].i2c_reg_index > 0x20)299 return false;300 }301 302 for (i = 0; i < settings->reg_num_6g; i++) {303 if (settings->reg_settings_6g[i].i2c_reg_index > 0x20)304 return false;305 }306 }307 }308 309 return result;310}311 312static bool write_i2c(struct pipe_ctx *pipe_ctx,313 uint8_t address, uint8_t *buffer, uint32_t length)314{315 struct i2c_command cmd = {0};316 struct i2c_payload payload = {0};317 318 memset(&payload, 0, sizeof(payload));319 memset(&cmd, 0, sizeof(cmd));320 321 cmd.number_of_payloads = 1;322 cmd.engine = I2C_COMMAND_ENGINE_DEFAULT;323 cmd.speed = pipe_ctx->stream->ctx->dc->caps.i2c_speed_in_khz;324 325 payload.address = address;326 payload.data = buffer;327 payload.length = length;328 payload.write = true;329 cmd.payloads = &payload;330 331 if (dm_helpers_submit_i2c(pipe_ctx->stream->ctx,332 pipe_ctx->stream->link, &cmd))333 return true;334 335 return false;336}337 338static void write_i2c_retimer_setting(339 struct pipe_ctx *pipe_ctx,340 bool is_vga_mode,341 bool is_over_340mhz,342 struct ext_hdmi_settings *settings)343{344 uint8_t slave_address = (settings->slv_addr >> 1);345 uint8_t buffer[2];346 const uint8_t apply_rx_tx_change = 0x4;347 uint8_t offset = 0xA;348 uint8_t value = 0;349 int i = 0;350 bool i2c_success = false;351 DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);352 353 memset(&buffer, 0, sizeof(buffer));354 355 /* Start Ext-Hdmi programming*/356 357 for (i = 0; i < settings->reg_num; i++) {358 /* Apply 3G settings */359 if (settings->reg_settings[i].i2c_reg_index <= 0x20) {360 361 buffer[0] = settings->reg_settings[i].i2c_reg_index;362 buffer[1] = settings->reg_settings[i].i2c_reg_val;363 i2c_success = write_i2c(pipe_ctx, slave_address,364 buffer, sizeof(buffer));365 RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\366 offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n",367 slave_address, buffer[0], buffer[1], i2c_success?1:0);368 369 if (!i2c_success)370 goto i2c_write_fail;371 372 /* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A373 * needs to be set to 1 on every 0xA-0xC write.374 */375 if (settings->reg_settings[i].i2c_reg_index == 0xA ||376 settings->reg_settings[i].i2c_reg_index == 0xB ||377 settings->reg_settings[i].i2c_reg_index == 0xC) {378 379 /* Query current value from offset 0xA */380 if (settings->reg_settings[i].i2c_reg_index == 0xA)381 value = settings->reg_settings[i].i2c_reg_val;382 else {383 i2c_success =384 link_query_ddc_data(385 pipe_ctx->stream->link->ddc,386 slave_address, &offset, 1, &value, 1);387 if (!i2c_success)388 goto i2c_write_fail;389 }390 391 buffer[0] = offset;392 /* Set APPLY_RX_TX_CHANGE bit to 1 */393 buffer[1] = value | apply_rx_tx_change;394 i2c_success = write_i2c(pipe_ctx, slave_address,395 buffer, sizeof(buffer));396 RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\397 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",398 slave_address, buffer[0], buffer[1], i2c_success?1:0);399 if (!i2c_success)400 goto i2c_write_fail;401 }402 }403 }404 405 /* Apply 3G settings */406 if (is_over_340mhz) {407 for (i = 0; i < settings->reg_num_6g; i++) {408 /* Apply 3G settings */409 if (settings->reg_settings[i].i2c_reg_index <= 0x20) {410 411 buffer[0] = settings->reg_settings_6g[i].i2c_reg_index;412 buffer[1] = settings->reg_settings_6g[i].i2c_reg_val;413 i2c_success = write_i2c(pipe_ctx, slave_address,414 buffer, sizeof(buffer));415 RETIMER_REDRIVER_INFO("above 340Mhz: retimer write to slave_address = 0x%x,\416 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",417 slave_address, buffer[0], buffer[1], i2c_success?1:0);418 419 if (!i2c_success)420 goto i2c_write_fail;421 422 /* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A423 * needs to be set to 1 on every 0xA-0xC write.424 */425 if (settings->reg_settings_6g[i].i2c_reg_index == 0xA ||426 settings->reg_settings_6g[i].i2c_reg_index == 0xB ||427 settings->reg_settings_6g[i].i2c_reg_index == 0xC) {428 429 /* Query current value from offset 0xA */430 if (settings->reg_settings_6g[i].i2c_reg_index == 0xA)431 value = settings->reg_settings_6g[i].i2c_reg_val;432 else {433 i2c_success =434 link_query_ddc_data(435 pipe_ctx->stream->link->ddc,436 slave_address, &offset, 1, &value, 1);437 if (!i2c_success)438 goto i2c_write_fail;439 }440 441 buffer[0] = offset;442 /* Set APPLY_RX_TX_CHANGE bit to 1 */443 buffer[1] = value | apply_rx_tx_change;444 i2c_success = write_i2c(pipe_ctx, slave_address,445 buffer, sizeof(buffer));446 RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\447 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",448 slave_address, buffer[0], buffer[1], i2c_success?1:0);449 if (!i2c_success)450 goto i2c_write_fail;451 }452 }453 }454 }455 456 if (is_vga_mode) {457 /* Program additional settings if using 640x480 resolution */458 459 /* Write offset 0xFF to 0x01 */460 buffer[0] = 0xff;461 buffer[1] = 0x01;462 i2c_success = write_i2c(pipe_ctx, slave_address,463 buffer, sizeof(buffer));464 RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\465 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",466 slave_address, buffer[0], buffer[1], i2c_success?1:0);467 if (!i2c_success)468 goto i2c_write_fail;469 470 /* Write offset 0x00 to 0x23 */471 buffer[0] = 0x00;472 buffer[1] = 0x23;473 i2c_success = write_i2c(pipe_ctx, slave_address,474 buffer, sizeof(buffer));475 RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\476 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",477 slave_address, buffer[0], buffer[1], i2c_success?1:0);478 if (!i2c_success)479 goto i2c_write_fail;480 481 /* Write offset 0xff to 0x00 */482 buffer[0] = 0xff;483 buffer[1] = 0x00;484 i2c_success = write_i2c(pipe_ctx, slave_address,485 buffer, sizeof(buffer));486 RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\487 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",488 slave_address, buffer[0], buffer[1], i2c_success?1:0);489 if (!i2c_success)490 goto i2c_write_fail;491 492 }493 494 return;495 496i2c_write_fail:497 DC_LOG_DEBUG("Set retimer failed");498}499 500static void write_i2c_default_retimer_setting(501 struct pipe_ctx *pipe_ctx,502 bool is_vga_mode,503 bool is_over_340mhz)504{505 uint8_t slave_address = (0xBA >> 1);506 uint8_t buffer[2];507 bool i2c_success = false;508 DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);509 510 memset(&buffer, 0, sizeof(buffer));511 512 /* Program Slave Address for tuning single integrity */513 /* Write offset 0x0A to 0x13 */514 buffer[0] = 0x0A;515 buffer[1] = 0x13;516 i2c_success = write_i2c(pipe_ctx, slave_address,517 buffer, sizeof(buffer));518 RETIMER_REDRIVER_INFO("retimer writes default setting to slave_address = 0x%x,\519 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",520 slave_address, buffer[0], buffer[1], i2c_success?1:0);521 if (!i2c_success)522 goto i2c_write_fail;523 524 /* Write offset 0x0A to 0x17 */525 buffer[0] = 0x0A;526 buffer[1] = 0x17;527 i2c_success = write_i2c(pipe_ctx, slave_address,528 buffer, sizeof(buffer));529 RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\530 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",531 slave_address, buffer[0], buffer[1], i2c_success?1:0);532 if (!i2c_success)533 goto i2c_write_fail;534 535 /* Write offset 0x0B to 0xDA or 0xD8 */536 buffer[0] = 0x0B;537 buffer[1] = is_over_340mhz ? 0xDA : 0xD8;538 i2c_success = write_i2c(pipe_ctx, slave_address,539 buffer, sizeof(buffer));540 RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\541 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",542 slave_address, buffer[0], buffer[1], i2c_success?1:0);543 if (!i2c_success)544 goto i2c_write_fail;545 546 /* Write offset 0x0A to 0x17 */547 buffer[0] = 0x0A;548 buffer[1] = 0x17;549 i2c_success = write_i2c(pipe_ctx, slave_address,550 buffer, sizeof(buffer));551 RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\552 offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n",553 slave_address, buffer[0], buffer[1], i2c_success?1:0);554 if (!i2c_success)555 goto i2c_write_fail;556 557 /* Write offset 0x0C to 0x1D or 0x91 */558 buffer[0] = 0x0C;559 buffer[1] = is_over_340mhz ? 0x1D : 0x91;560 i2c_success = write_i2c(pipe_ctx, slave_address,561 buffer, sizeof(buffer));562 RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\563 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",564 slave_address, buffer[0], buffer[1], i2c_success?1:0);565 if (!i2c_success)566 goto i2c_write_fail;567 568 /* Write offset 0x0A to 0x17 */569 buffer[0] = 0x0A;570 buffer[1] = 0x17;571 i2c_success = write_i2c(pipe_ctx, slave_address,572 buffer, sizeof(buffer));573 RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\574 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",575 slave_address, buffer[0], buffer[1], i2c_success?1:0);576 if (!i2c_success)577 goto i2c_write_fail;578 579 580 if (is_vga_mode) {581 /* Program additional settings if using 640x480 resolution */582 583 /* Write offset 0xFF to 0x01 */584 buffer[0] = 0xff;585 buffer[1] = 0x01;586 i2c_success = write_i2c(pipe_ctx, slave_address,587 buffer, sizeof(buffer));588 RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\589 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",590 slave_address, buffer[0], buffer[1], i2c_success?1:0);591 if (!i2c_success)592 goto i2c_write_fail;593 594 /* Write offset 0x00 to 0x23 */595 buffer[0] = 0x00;596 buffer[1] = 0x23;597 i2c_success = write_i2c(pipe_ctx, slave_address,598 buffer, sizeof(buffer));599 RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\600 offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n",601 slave_address, buffer[0], buffer[1], i2c_success?1:0);602 if (!i2c_success)603 goto i2c_write_fail;604 605 /* Write offset 0xff to 0x00 */606 buffer[0] = 0xff;607 buffer[1] = 0x00;608 i2c_success = write_i2c(pipe_ctx, slave_address,609 buffer, sizeof(buffer));610 RETIMER_REDRIVER_INFO("retimer write default setting to slave_addr = 0x%x,\611 offset = 0x%x, reg_val= 0x%x, i2c_success = %d end here\n",612 slave_address, buffer[0], buffer[1], i2c_success?1:0);613 if (!i2c_success)614 goto i2c_write_fail;615 }616 617 return;618 619i2c_write_fail:620 DC_LOG_DEBUG("Set default retimer failed");621}622 623static void write_i2c_redriver_setting(624 struct pipe_ctx *pipe_ctx,625 bool is_over_340mhz)626{627 uint8_t slave_address = (0xF0 >> 1);628 uint8_t buffer[16];629 bool i2c_success = false;630 DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);631 632 memset(&buffer, 0, sizeof(buffer));633 634 // Program Slave Address for tuning single integrity635 buffer[3] = 0x4E;636 buffer[4] = 0x4E;637 buffer[5] = 0x4E;638 buffer[6] = is_over_340mhz ? 0x4E : 0x4A;639 640 i2c_success = write_i2c(pipe_ctx, slave_address,641 buffer, sizeof(buffer));642 RETIMER_REDRIVER_INFO("redriver write 0 to all 16 reg offset expect following:\n\643 \t slave_addr = 0x%x, offset[3] = 0x%x, offset[4] = 0x%x,\644 offset[5] = 0x%x,offset[6] is_over_340mhz = 0x%x,\645 i2c_success = %d\n",646 slave_address, buffer[3], buffer[4], buffer[5], buffer[6], i2c_success?1:0);647 648 if (!i2c_success)649 DC_LOG_DEBUG("Set redriver failed");650}651 652static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)653{654 struct cp_psp *cp_psp = &pipe_ctx->stream->ctx->cp_psp;655 struct link_encoder *link_enc = NULL;656 struct cp_psp_stream_config config = {0};657 enum dp_panel_mode panel_mode =658 dp_get_panel_mode(pipe_ctx->stream->link);659 660 if (cp_psp == NULL || cp_psp->funcs.update_stream_config == NULL)661 return;662 663 link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link);664 ASSERT(link_enc);665 if (link_enc == NULL)666 return;667 668 /* otg instance */669 config.otg_inst = (uint8_t) pipe_ctx->stream_res.tg->inst;670 671 /* dig front end */672 config.dig_fe = (uint8_t) pipe_ctx->stream_res.stream_enc->stream_enc_inst;673 674 /* stream encoder index */675 config.stream_enc_idx = pipe_ctx->stream_res.stream_enc->id - ENGINE_ID_DIGA;676 if (dp_is_128b_132b_signal(pipe_ctx))677 config.stream_enc_idx =678 pipe_ctx->stream_res.hpo_dp_stream_enc->id - ENGINE_ID_HPO_DP_0;679 680 /* dig back end */681 config.dig_be = pipe_ctx->stream->link->link_enc_hw_inst;682 683 /* link encoder index */684 config.link_enc_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;685 if (dp_is_128b_132b_signal(pipe_ctx))686 config.link_enc_idx = pipe_ctx->link_res.hpo_dp_link_enc->inst;687 688 /* dio output index is dpia index for DPIA endpoint & dcio index by default */689 if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)690 config.dio_output_idx = pipe_ctx->stream->link->link_id.enum_id - ENUM_ID_1;691 else692 config.dio_output_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;693 694 695 /* phy index */696 config.phy_idx = resource_transmitter_to_phy_idx(697 pipe_ctx->stream->link->dc, link_enc->transmitter);698 if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)699 /* USB4 DPIA doesn't use PHY in our soc, initialize it to 0 */700 config.phy_idx = 0;701 702 /* stream properties */703 config.assr_enabled = (panel_mode == DP_PANEL_MODE_EDP) ? 1 : 0;704 config.mst_enabled = (pipe_ctx->stream->signal ==705 SIGNAL_TYPE_DISPLAY_PORT_MST) ? 1 : 0;706 config.dp2_enabled = dp_is_128b_132b_signal(pipe_ctx) ? 1 : 0;707 config.usb4_enabled = (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) ?708 1 : 0;709 config.dpms_off = dpms_off;710 711 /* dm stream context */712 config.dm_stream_ctx = pipe_ctx->stream->dm_stream_context;713 714 cp_psp->funcs.update_stream_config(cp_psp->handle, &config);715}716 717static void set_avmute(struct pipe_ctx *pipe_ctx, bool enable)718{719 struct dc *dc = pipe_ctx->stream->ctx->dc;720 721 if (!dc_is_hdmi_signal(pipe_ctx->stream->signal))722 return;723 724 dc->hwss.set_avmute(pipe_ctx, enable);725}726 727static void enable_mst_on_sink(struct dc_link *link, bool enable)728{729 unsigned char mstmCntl = 0;730 731 core_link_read_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);732 if (enable)733 mstmCntl |= DP_MST_EN;734 else735 mstmCntl &= (~DP_MST_EN);736 737 core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);738}739 740static void dsc_optc_config_log(struct display_stream_compressor *dsc,741 struct dsc_optc_config *config)742{743 uint32_t precision = 1 << 28;744 uint32_t bytes_per_pixel_int = config->bytes_per_pixel / precision;745 uint32_t bytes_per_pixel_mod = config->bytes_per_pixel % precision;746 uint64_t ll_bytes_per_pix_fraq = bytes_per_pixel_mod;747 DC_LOGGER_INIT(dsc->ctx->logger);748 749 /* 7 fractional digits decimal precision for bytes per pixel is enough because DSC750 * bits per pixel precision is 1/16th of a pixel, which means bytes per pixel precision is751 * 1/16/8 = 1/128 of a byte, or 0.0078125 decimal752 */753 ll_bytes_per_pix_fraq *= 10000000;754 ll_bytes_per_pix_fraq /= precision;755 756 DC_LOG_DSC("\tbytes_per_pixel 0x%08x (%d.%07d)",757 config->bytes_per_pixel, bytes_per_pixel_int, (uint32_t)ll_bytes_per_pix_fraq);758 DC_LOG_DSC("\tis_pixel_format_444 %d", config->is_pixel_format_444);759 DC_LOG_DSC("\tslice_width %d", config->slice_width);760}761 762static bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)763{764 struct dc *dc = pipe_ctx->stream->ctx->dc;765 struct dc_stream_state *stream = pipe_ctx->stream;766 bool result = false;767 768 if (dc_is_virtual_signal(stream->signal))769 result = true;770 else771 result = dm_helpers_dp_write_dsc_enable(dc->ctx, stream, enable);772 return result;773}774 775/* The stream with these settings can be sent (unblanked) only after DSC was enabled on RX first,776 * i.e. after dp_enable_dsc_on_rx() had been called777 */778void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)779{780 /* TODO: Move this to HWSS as this is hardware programming sequence not a781 * link layer sequence782 */783 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;784 struct dc *dc = pipe_ctx->stream->ctx->dc;785 struct dc_stream_state *stream = pipe_ctx->stream;786 struct pipe_ctx *odm_pipe;787 int opp_cnt = 1;788 struct dccg *dccg = dc->res_pool->dccg;789 /* It has been found that when DSCCLK is lower than 16Mhz, we will get DCN790 * register access hung. When DSCCLk is based on refclk, DSCCLk is always a791 * fixed value higher than 16Mhz so the issue doesn't occur. When DSCCLK is792 * generated by DTO, DSCCLK would be based on 1/3 dispclk. For small timings793 * with DSC such as 480p60Hz, the dispclk could be low enough to trigger794 * this problem. We are implementing a workaround here to keep using dscclk795 * based on fixed value refclk when timing is smaller than 3x16Mhz (i.e796 * 48Mhz) pixel clock to avoid hitting this problem.797 */798 bool should_use_dto_dscclk = (dccg->funcs->set_dto_dscclk != NULL) &&799 stream->timing.pix_clk_100hz > 480000;800 DC_LOGGER_INIT(dsc->ctx->logger);801 802 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)803 opp_cnt++;804 805 if (enable) {806 struct dsc_config dsc_cfg;807 struct dsc_optc_config dsc_optc_cfg = {0};808 enum optc_dsc_mode optc_dsc_mode;809 810 /* Enable DSC hw block */811 dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;812 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;813 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;814 dsc_cfg.color_depth = stream->timing.display_color_depth;815 dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;816 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;817 ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);818 dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;819 820 if (should_use_dto_dscclk)821 dccg->funcs->set_dto_dscclk(dccg, dsc->inst);822 dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);823 dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);824 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {825 struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;826 827 if (should_use_dto_dscclk)828 dccg->funcs->set_dto_dscclk(dccg, odm_dsc->inst);829 odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);830 odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);831 }832 dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;833 dsc_cfg.pic_width *= opp_cnt;834 835 optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;836 837 /* Enable DSC in encoder */838 if (dc_is_dp_signal(stream->signal) && !dp_is_128b_132b_signal(pipe_ctx)) {839 DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id);840 dsc_optc_config_log(dsc, &dsc_optc_cfg);841 if (pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config)842 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,843 optc_dsc_mode,844 dsc_optc_cfg.bytes_per_pixel,845 dsc_optc_cfg.slice_width);846 847 /* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */848 }849 850 /* Enable DSC in OPTC */851 DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst);852 dsc_optc_config_log(dsc, &dsc_optc_cfg);853 pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg,854 optc_dsc_mode,855 dsc_optc_cfg.bytes_per_pixel,856 dsc_optc_cfg.slice_width);857 } else {858 /* disable DSC in OPTC */859 pipe_ctx->stream_res.tg->funcs->set_dsc_config(860 pipe_ctx->stream_res.tg,861 OPTC_DSC_DISABLED, 0, 0);862 863 /* disable DSC in stream encoder */864 if (dc_is_dp_signal(stream->signal)) {865 if (dp_is_128b_132b_signal(pipe_ctx))866 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(867 pipe_ctx->stream_res.hpo_dp_stream_enc,868 false,869 NULL,870 true);871 else {872 if (pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config)873 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(874 pipe_ctx->stream_res.stream_enc,875 OPTC_DSC_DISABLED, 0, 0);876 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(877 pipe_ctx->stream_res.stream_enc, false, NULL, true);878 }879 }880 881 /* disable DSC block */882 for (odm_pipe = pipe_ctx; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {883 odm_pipe->stream_res.dsc->funcs->dsc_disconnect(odm_pipe->stream_res.dsc);884 /*885 * TODO - dsc_disconnect is a double buffered register.886 * by the time we call dsc_disable, dsc may still remain887 * connected to OPP. In this case OPTC will no longer888 * get correct pixel data because DSCC is off. However889 * we also can't wait for the disconnect pending890 * complete, because this function can be called891 * with/without OTG master lock acquired. When the lock892 * is acquired we will never get pending complete until893 * we release the lock later. So there is no easy way to894 * solve this problem especially when the lock is895 * acquired. DSC is a front end hw block it should be896 * programmed as part of front end sequence, where the897 * commit sequence without lock and update sequence898 * with lock are completely separated. However because899 * we are programming dsc as part of back end link900 * programming sequence, we don't know if front end OPTC901 * master lock is acquired. The back end should be902 * agnostic to front end lock. DSC programming shouldn't903 * belong to this sequence.904 */905 odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);906 if (dccg->funcs->set_ref_dscclk)907 dccg->funcs->set_ref_dscclk(dccg, odm_pipe->stream_res.dsc->inst);908 }909 }910}911 912/*913 * For dynamic bpp change case, dsc is programmed with MASTER_UPDATE_LOCK enabled;914 * hence PPS info packet update need to use frame update instead of immediate update.915 * Added parameter immediate_update for this purpose.916 * The decision to use frame update is hard-coded in function dp_update_dsc_config(),917 * which is the only place where a "false" would be passed in for param immediate_update.918 *919 * immediate_update is only applicable when DSC is enabled.920 */921bool link_set_dsc_pps_packet(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update)922{923 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;924 struct dc_stream_state *stream = pipe_ctx->stream;925 926 if (!pipe_ctx->stream->timing.flags.DSC)927 return false;928 929 if (!dsc)930 return false;931 932 DC_LOGGER_INIT(dsc->ctx->logger);933 934 if (enable) {935 struct dsc_config dsc_cfg;936 uint8_t dsc_packed_pps[128];937 938 memset(&dsc_cfg, 0, sizeof(dsc_cfg));939 memset(dsc_packed_pps, 0, 128);940 941 /* Enable DSC hw block */942 dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;943 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;944 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;945 dsc_cfg.color_depth = stream->timing.display_color_depth;946 dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;947 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;948 949 dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]);950 memcpy(&stream->dsc_packed_pps[0], &dsc_packed_pps[0], sizeof(stream->dsc_packed_pps));951 if (dc_is_dp_signal(stream->signal)) {952 DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id);953 if (dp_is_128b_132b_signal(pipe_ctx))954 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(955 pipe_ctx->stream_res.hpo_dp_stream_enc,956 true,957 &dsc_packed_pps[0],958 immediate_update);959 else960 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(961 pipe_ctx->stream_res.stream_enc,962 true,963 &dsc_packed_pps[0],964 immediate_update);965 }966 } else {967 /* disable DSC PPS in stream encoder */968 memset(&stream->dsc_packed_pps[0], 0, sizeof(stream->dsc_packed_pps));969 if (dc_is_dp_signal(stream->signal)) {970 if (dp_is_128b_132b_signal(pipe_ctx))971 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet(972 pipe_ctx->stream_res.hpo_dp_stream_enc,973 false,974 NULL,975 true);976 else977 pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(978 pipe_ctx->stream_res.stream_enc, false, NULL, true);979 }980 }981 982 return true;983}984 985bool link_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable)986{987 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;988 bool result = false;989 990 if (!pipe_ctx->stream->timing.flags.DSC)991 goto out;992 if (!dsc)993 goto out;994 995 if (enable) {996 {997 link_set_dsc_on_stream(pipe_ctx, true);998 result = true;999 }1000 } else {1001 dp_set_dsc_on_rx(pipe_ctx, false);1002 link_set_dsc_on_stream(pipe_ctx, false);1003 result = true;1004 }1005out:1006 return result;1007}1008 1009bool link_update_dsc_config(struct pipe_ctx *pipe_ctx)1010{1011 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;1012 1013 if (!pipe_ctx->stream->timing.flags.DSC)1014 return false;1015 if (!dsc)1016 return false;1017 1018 link_set_dsc_on_stream(pipe_ctx, true);1019 link_set_dsc_pps_packet(pipe_ctx, true, false);1020 return true;1021}1022 1023static void enable_stream_features(struct pipe_ctx *pipe_ctx)1024{1025 struct dc_stream_state *stream = pipe_ctx->stream;1026 1027 if (pipe_ctx->stream->signal != SIGNAL_TYPE_DISPLAY_PORT_MST) {1028 struct dc_link *link = stream->link;1029 union down_spread_ctrl old_downspread;1030 union down_spread_ctrl new_downspread;1031 1032 memset(&old_downspread, 0, sizeof(old_downspread));1033 1034 core_link_read_dpcd(link, DP_DOWNSPREAD_CTRL,1035 &old_downspread.raw, sizeof(old_downspread));1036 1037 new_downspread.raw = old_downspread.raw;1038 1039 new_downspread.bits.IGNORE_MSA_TIMING_PARAM =1040 (stream->ignore_msa_timing_param) ? 1 : 0;1041 1042 if (new_downspread.raw != old_downspread.raw) {1043 core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,1044 &new_downspread.raw, sizeof(new_downspread));1045 }1046 1047 } else {1048 dm_helpers_mst_enable_stream_features(stream);1049 }1050}1051 1052static void log_vcp_x_y(const struct dc_link *link, struct fixed31_32 avg_time_slots_per_mtp)1053{1054 const uint32_t VCP_Y_PRECISION = 1000;1055 uint64_t vcp_x, vcp_y;1056 DC_LOGGER_INIT(link->ctx->logger);1057 1058 // Add 0.5*(1/VCP_Y_PRECISION) to round up to decimal precision1059 avg_time_slots_per_mtp = dc_fixpt_add(1060 avg_time_slots_per_mtp,1061 dc_fixpt_from_fraction(1062 1,1063 2*VCP_Y_PRECISION));1064 1065 vcp_x = dc_fixpt_floor(1066 avg_time_slots_per_mtp);1067 vcp_y = dc_fixpt_floor(1068 dc_fixpt_mul_int(1069 dc_fixpt_sub_int(1070 avg_time_slots_per_mtp,1071 dc_fixpt_floor(1072 avg_time_slots_per_mtp)),1073 VCP_Y_PRECISION));1074 1075 1076 if (link->type == dc_connection_mst_branch)1077 DC_LOG_DP2("MST Update Payload: set_throttled_vcp_size slot X.Y for MST stream "1078 "X: %llu "1079 "Y: %llu/%d",1080 vcp_x,1081 vcp_y,1082 VCP_Y_PRECISION);1083 else1084 DC_LOG_DP2("SST Update Payload: set_throttled_vcp_size slot X.Y for SST stream "1085 "X: %llu "1086 "Y: %llu/%d",1087 vcp_x,1088 vcp_y,1089 VCP_Y_PRECISION);1090}1091 1092static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream)1093{1094 struct fixed31_32 mbytes_per_sec;1095 uint32_t link_rate_in_mbytes_per_sec = dp_link_bandwidth_kbps(stream->link,1096 &stream->link->cur_link_settings);1097 link_rate_in_mbytes_per_sec /= 8000; /* Kbits to MBytes */1098 1099 mbytes_per_sec = dc_fixpt_from_int(link_rate_in_mbytes_per_sec);1100 1101 return dc_fixpt_div_int(mbytes_per_sec, 54);1102}1103 1104static struct fixed31_32 get_pbn_from_bw_in_kbps(uint64_t kbps)1105{1106 struct fixed31_32 peak_kbps;1107 uint32_t numerator = 0;1108 uint32_t denominator = 1;1109 1110 /*1111 * The 1.006 factor (margin 5300ppm + 300ppm ~ 0.6% as per spec) is not1112 * required when determining PBN/time slot utilization on the link between1113 * us and the branch, since that overhead is already accounted for in1114 * the get_pbn_per_slot function.1115 *1116 * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on1117 * common multiplier to render an integer PBN for all link rate/lane1118 * counts combinations1119 * calculate1120 * peak_kbps *= (64/54)1121 * peak_kbps /= (8 * 1000) convert to bytes1122 */1123 1124 numerator = 64;1125 denominator = 54 * 8 * 1000;1126 kbps *= numerator;1127 peak_kbps = dc_fixpt_from_fraction(kbps, denominator);1128 1129 return peak_kbps;1130}1131 1132static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx)1133{1134 uint64_t kbps;1135 enum dc_link_encoding_format link_encoding;1136 1137 if (dp_is_128b_132b_signal(pipe_ctx))1138 link_encoding = DC_LINK_ENCODING_DP_128b_132b;1139 else1140 link_encoding = DC_LINK_ENCODING_DP_8b_10b;1141 1142 kbps = dc_bandwidth_in_kbps_from_timing(&pipe_ctx->stream->timing, link_encoding);1143 return get_pbn_from_bw_in_kbps(kbps);1144}1145 1146 1147// TODO - DP2.0 Link: Fix get_lane_status to handle LTTPR offset (SST and MST)1148static void get_lane_status(1149 struct dc_link *link,1150 uint32_t lane_count,1151 union lane_status *status,1152 union lane_align_status_updated *status_updated)1153{1154 unsigned int lane;1155 uint8_t dpcd_buf[3] = {0};1156 1157 if (status == NULL || status_updated == NULL) {1158 return;1159 }1160 1161 core_link_read_dpcd(1162 link,1163 DP_LANE0_1_STATUS,1164 dpcd_buf,1165 sizeof(dpcd_buf));1166 1167 for (lane = 0; lane < lane_count; lane++) {1168 status[lane].raw = dp_get_nibble_at_index(&dpcd_buf[0], lane);1169 }1170 1171 status_updated->raw = dpcd_buf[2];1172}1173 1174static bool poll_for_allocation_change_trigger(struct dc_link *link)1175{1176 /*1177 * wait for ACT handled1178 */1179 int i;1180 const int act_retries = 30;1181 enum act_return_status result = ACT_FAILED;1182 enum dc_connection_type display_connected = (link->type != dc_connection_none);1183 union payload_table_update_status update_status = {0};1184 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];1185 union lane_align_status_updated lane_status_updated;1186 DC_LOGGER_INIT(link->ctx->logger);1187 1188 if (!display_connected || link->aux_access_disabled)1189 return true;1190 for (i = 0; i < act_retries; i++) {1191 get_lane_status(link, link->cur_link_settings.lane_count, dpcd_lane_status, &lane_status_updated);1192 1193 if (!dp_is_cr_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||1194 !dp_is_ch_eq_done(link->cur_link_settings.lane_count, dpcd_lane_status) ||1195 !dp_is_symbol_locked(link->cur_link_settings.lane_count, dpcd_lane_status) ||1196 !dp_is_interlane_aligned(lane_status_updated)) {1197 DC_LOG_ERROR("SST Update Payload: Link loss occurred while "1198 "polling for ACT handled.");1199 result = ACT_LINK_LOST;1200 break;1201 }1202 core_link_read_dpcd(1203 link,1204 DP_PAYLOAD_TABLE_UPDATE_STATUS,1205 &update_status.raw,1206 1);1207 1208 if (update_status.bits.ACT_HANDLED == 1) {1209 DC_LOG_DP2("SST Update Payload: ACT handled by downstream.");1210 result = ACT_SUCCESS;1211 break;1212 }1213 1214 fsleep(5000);1215 }1216 1217 if (result == ACT_FAILED) {1218 DC_LOG_ERROR("SST Update Payload: ACT still not handled after retries, "1219 "continue on. Something is wrong with the branch.");1220 }1221 1222 return (result == ACT_SUCCESS);1223}1224 1225static void update_mst_stream_alloc_table(1226 struct dc_link *link,1227 struct stream_encoder *stream_enc,1228 struct hpo_dp_stream_encoder *hpo_dp_stream_enc, // TODO: Rename stream_enc to dio_stream_enc?1229 const struct dc_dp_mst_stream_allocation_table *proposed_table)1230{1231 struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = { 0 };1232 struct link_mst_stream_allocation *dc_alloc;1233 1234 int i;1235 int j;1236 1237 /* if DRM proposed_table has more than one new payload */1238 ASSERT(proposed_table->stream_count -1239 link->mst_stream_alloc_table.stream_count < 2);1240 1241 /* copy proposed_table to link, add stream encoder */1242 for (i = 0; i < proposed_table->stream_count; i++) {1243 1244 for (j = 0; j < link->mst_stream_alloc_table.stream_count; j++) {1245 dc_alloc =1246 &link->mst_stream_alloc_table.stream_allocations[j];1247 1248 if (dc_alloc->vcp_id ==1249 proposed_table->stream_allocations[i].vcp_id) {1250 1251 work_table[i] = *dc_alloc;1252 work_table[i].slot_count = proposed_table->stream_allocations[i].slot_count;1253 break; /* exit j loop */1254 }1255 }1256 1257 /* new vcp_id */1258 if (j == link->mst_stream_alloc_table.stream_count) {1259 work_table[i].vcp_id =1260 proposed_table->stream_allocations[i].vcp_id;1261 work_table[i].slot_count =1262 proposed_table->stream_allocations[i].slot_count;1263 work_table[i].stream_enc = stream_enc;1264 work_table[i].hpo_dp_stream_enc = hpo_dp_stream_enc;1265 }1266 }1267 1268 /* update link->mst_stream_alloc_table with work_table */1269 link->mst_stream_alloc_table.stream_count =1270 proposed_table->stream_count;1271 for (i = 0; i < MAX_CONTROLLER_NUM; i++)1272 link->mst_stream_alloc_table.stream_allocations[i] =1273 work_table[i];1274}1275 1276static void remove_stream_from_alloc_table(1277 struct dc_link *link,1278 struct stream_encoder *dio_stream_enc,1279 struct hpo_dp_stream_encoder *hpo_dp_stream_enc)1280{1281 int i = 0;1282 struct link_mst_stream_allocation_table *table =1283 &link->mst_stream_alloc_table;1284 1285 if (hpo_dp_stream_enc) {1286 for (; i < table->stream_count; i++)1287 if (hpo_dp_stream_enc == table->stream_allocations[i].hpo_dp_stream_enc)1288 break;1289 } else {1290 for (; i < table->stream_count; i++)1291 if (dio_stream_enc == table->stream_allocations[i].stream_enc)1292 break;1293 }1294 1295 if (i < table->stream_count) {1296 i++;1297 for (; i < table->stream_count; i++)1298 table->stream_allocations[i-1] = table->stream_allocations[i];1299 memset(&table->stream_allocations[table->stream_count-1], 0,1300 sizeof(struct link_mst_stream_allocation));1301 table->stream_count--;1302 }1303}1304 1305static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)1306{1307 struct dc_stream_state *stream = pipe_ctx->stream;1308 struct dc_link *link = stream->link;1309 struct dc_dp_mst_stream_allocation_table proposed_table = {0};1310 struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0);1311 int i;1312 bool mst_mode = (link->type == dc_connection_mst_branch);1313 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);1314 const struct dc_link_settings empty_link_settings = {0};1315 DC_LOGGER_INIT(link->ctx->logger);1316 1317 /* deallocate_mst_payload is called before disable link. When mode or1318 * disable/enable monitor, new stream is created which is not in link1319 * stream[] yet. For this, payload is not allocated yet, so de-alloc1320 * should not done. For new mode set, map_resources will get engine1321 * for new stream, so stream_enc->id should be validated until here.1322 */1323 1324 /* slot X.Y */1325 if (link_hwss->ext.set_throttled_vcp_size)1326 link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp);1327 if (link_hwss->ext.set_hblank_min_symbol_width)1328 link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,1329 &empty_link_settings,1330 avg_time_slots_per_mtp);1331 1332 if (mst_mode) {1333 /* when link is in mst mode, reply on mst manager to remove1334 * payload1335 */1336 if (dm_helpers_dp_mst_write_payload_allocation_table(1337 stream->ctx,1338 stream,1339 &proposed_table,1340 false))1341 update_mst_stream_alloc_table(1342 link,1343 pipe_ctx->stream_res.stream_enc,1344 pipe_ctx->stream_res.hpo_dp_stream_enc,1345 &proposed_table);1346 else1347 DC_LOG_WARNING("Failed to update"1348 "MST allocation table for"1349 "pipe idx:%d\n",1350 pipe_ctx->pipe_idx);1351 } else {1352 /* when link is no longer in mst mode (mst hub unplugged),1353 * remove payload with default dc logic1354 */1355 remove_stream_from_alloc_table(link, pipe_ctx->stream_res.stream_enc,1356 pipe_ctx->stream_res.hpo_dp_stream_enc);1357 }1358 1359 DC_LOG_MST("%s"1360 "stream_count: %d: ",1361 __func__,1362 link->mst_stream_alloc_table.stream_count);1363 1364 for (i = 0; i < MAX_CONTROLLER_NUM; i++) {1365 DC_LOG_MST("stream_enc[%d]: %p "1366 "stream[%d].hpo_dp_stream_enc: %p "1367 "stream[%d].vcp_id: %d "1368 "stream[%d].slot_count: %d\n",1369 i,1370 (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,1371 i,1372 (void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,1373 i,1374 link->mst_stream_alloc_table.stream_allocations[i].vcp_id,1375 i,1376 link->mst_stream_alloc_table.stream_allocations[i].slot_count);1377 }1378 1379 /* update mst stream allocation table hardware state */1380 if (link_hwss->ext.update_stream_allocation_table == NULL ||1381 link_dp_get_encoding_format(&link->cur_link_settings) == DP_UNKNOWN_ENCODING) {1382 DC_LOG_DEBUG("Unknown encoding format\n");1383 return DC_ERROR_UNEXPECTED;1384 }1385 1386 link_hwss->ext.update_stream_allocation_table(link, &pipe_ctx->link_res,1387 &link->mst_stream_alloc_table);1388 1389 if (mst_mode)1390 dm_helpers_dp_mst_poll_for_allocation_change_trigger(1391 stream->ctx,1392 stream);1393 1394 dm_helpers_dp_mst_update_mst_mgr_for_deallocation(1395 stream->ctx,1396 stream);1397 1398 return DC_OK;1399}1400 1401/* convert link_mst_stream_alloc_table to dm dp_mst_stream_alloc_table1402 * because stream_encoder is not exposed to dm1403 */1404static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)1405{1406 struct dc_stream_state *stream = pipe_ctx->stream;1407 struct dc_link *link = stream->link;1408 struct dc_dp_mst_stream_allocation_table proposed_table = {0};1409 struct fixed31_32 avg_time_slots_per_mtp;1410 struct fixed31_32 pbn;1411 struct fixed31_32 pbn_per_slot;1412 int i;1413 enum act_return_status ret;1414 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);1415 DC_LOGGER_INIT(link->ctx->logger);1416 1417 /* enable_link_dp_mst already check link->enabled_stream_count1418 * and stream is in link->stream[]. This is called during set mode,1419 * stream_enc is available.1420 */1421 1422 /* get calculate VC payload for stream: stream_alloc */1423 if (dm_helpers_dp_mst_write_payload_allocation_table(1424 stream->ctx,1425 stream,1426 &proposed_table,1427 true))1428 update_mst_stream_alloc_table(1429 link,1430 pipe_ctx->stream_res.stream_enc,1431 pipe_ctx->stream_res.hpo_dp_stream_enc,1432 &proposed_table);1433 else1434 DC_LOG_WARNING("Failed to update"1435 "MST allocation table for"1436 "pipe idx:%d\n",1437 pipe_ctx->pipe_idx);1438 1439 DC_LOG_MST("%s "1440 "stream_count: %d: \n ",1441 __func__,1442 link->mst_stream_alloc_table.stream_count);1443 1444 for (i = 0; i < MAX_CONTROLLER_NUM; i++) {1445 DC_LOG_MST("stream_enc[%d]: %p "1446 "stream[%d].hpo_dp_stream_enc: %p "1447 "stream[%d].vcp_id: %d "1448 "stream[%d].slot_count: %d\n",1449 i,1450 (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,1451 i,1452 (void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,1453 i,1454 link->mst_stream_alloc_table.stream_allocations[i].vcp_id,1455 i,1456 link->mst_stream_alloc_table.stream_allocations[i].slot_count);1457 }1458 1459 ASSERT(proposed_table.stream_count > 0);1460 1461 /* program DP source TX for payload */1462 if (link_hwss->ext.update_stream_allocation_table == NULL ||1463 link_dp_get_encoding_format(&link->cur_link_settings) == DP_UNKNOWN_ENCODING) {1464 DC_LOG_ERROR("Failure: unknown encoding format\n");1465 return DC_ERROR_UNEXPECTED;1466 }1467 1468 link_hwss->ext.update_stream_allocation_table(link,1469 &pipe_ctx->link_res,1470 &link->mst_stream_alloc_table);1471 1472 /* send down message */1473 ret = dm_helpers_dp_mst_poll_for_allocation_change_trigger(1474 stream->ctx,1475 stream);1476 1477 if (ret != ACT_LINK_LOST)1478 dm_helpers_dp_mst_send_payload_allocation(1479 stream->ctx,1480 stream);1481 1482 /* slot X.Y for only current stream */1483 pbn_per_slot = get_pbn_per_slot(stream);1484 if (pbn_per_slot.value == 0) {1485 DC_LOG_ERROR("Failure: pbn_per_slot==0 not allowed. Cannot continue, returning DC_UNSUPPORTED_VALUE.\n");1486 return DC_UNSUPPORTED_VALUE;1487 }1488 pbn = get_pbn_from_timing(pipe_ctx);1489 avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);1490 1491 log_vcp_x_y(link, avg_time_slots_per_mtp);1492 1493 if (link_hwss->ext.set_throttled_vcp_size)1494 link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp);1495 if (link_hwss->ext.set_hblank_min_symbol_width)1496 link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,1497 &link->cur_link_settings,1498 avg_time_slots_per_mtp);1499 1500 return DC_OK;1501}1502 1503struct fixed31_32 link_calculate_sst_avg_time_slots_per_mtp(1504 const struct dc_stream_state *stream,1505 const struct dc_link *link)1506{1507 struct fixed31_32 link_bw_effective =1508 dc_fixpt_from_int(1509 dp_link_bandwidth_kbps(link, &link->cur_link_settings));1510 struct fixed31_32 timeslot_bw_effective =1511 dc_fixpt_div_int(link_bw_effective, MAX_MTP_SLOT_COUNT);1512 struct fixed31_32 timing_bw =1513 dc_fixpt_from_int(1514 dc_bandwidth_in_kbps_from_timing(&stream->timing,1515 dc_link_get_highest_encoding_format(link)));1516 struct fixed31_32 avg_time_slots_per_mtp =1517 dc_fixpt_div(timing_bw, timeslot_bw_effective);1518 1519 return avg_time_slots_per_mtp;1520}1521 1522 1523static bool write_128b_132b_sst_payload_allocation_table(1524 const struct dc_stream_state *stream,1525 struct dc_link *link,1526 struct link_mst_stream_allocation_table *proposed_table,1527 bool allocate)1528{1529 const uint8_t vc_id = 1; /// VC ID always 1 for SST1530 const uint8_t start_time_slot = 0; /// Always start at time slot 0 for SST1531 bool result = false;1532 uint8_t req_slot_count = 0;1533 struct fixed31_32 avg_time_slots_per_mtp = { 0 };1534 union payload_table_update_status update_status = { 0 };1535 const uint32_t max_retries = 30;1536 uint32_t retries = 0;1537 enum dc_connection_type display_connected = (link->type != dc_connection_none);1538 DC_LOGGER_INIT(link->ctx->logger);1539 1540 if (allocate) {1541 avg_time_slots_per_mtp = link_calculate_sst_avg_time_slots_per_mtp(stream, link);1542 req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp);1543 /// Validation should filter out modes that exceed link BW1544 ASSERT(req_slot_count <= MAX_MTP_SLOT_COUNT);1545 if (req_slot_count > MAX_MTP_SLOT_COUNT)1546 return false;1547 } else {1548 /// Leave req_slot_count = 0 if allocate is false.1549 }1550 1551 proposed_table->stream_count = 1; /// Always 1 stream for SST1552 proposed_table->stream_allocations[0].slot_count = req_slot_count;1553 proposed_table->stream_allocations[0].vcp_id = vc_id;1554 1555 if (!display_connected || link->aux_access_disabled)1556 return true;1557 1558 /// Write DPCD 2C0 = 1 to start updating1559 update_status.bits.VC_PAYLOAD_TABLE_UPDATED = 1;1560 core_link_write_dpcd(1561 link,1562 DP_PAYLOAD_TABLE_UPDATE_STATUS,1563 &update_status.raw,1564 1);1565 1566 /// Program the changes in DPCD 1C0 - 1C21567 ASSERT(vc_id == 1);1568 core_link_write_dpcd(1569 link,1570 DP_PAYLOAD_ALLOCATE_SET,1571 &vc_id,1572 1);1573 1574 ASSERT(start_time_slot == 0);1575 core_link_write_dpcd(1576 link,1577 DP_PAYLOAD_ALLOCATE_START_TIME_SLOT,1578 &start_time_slot,1579 1);1580 1581 core_link_write_dpcd(1582 link,1583 DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT,1584 &req_slot_count,1585 1);1586 1587 /// Poll till DPCD 2C0 read 11588 /// Try for at least 150ms (30 retries, with 5ms delay after each attempt)1589 1590 while (retries < max_retries) {1591 if (core_link_read_dpcd(1592 link,1593 DP_PAYLOAD_TABLE_UPDATE_STATUS,1594 &update_status.raw,1595 1) == DC_OK) {1596 if (update_status.bits.VC_PAYLOAD_TABLE_UPDATED == 1) {1597 DC_LOG_DP2("SST Update Payload: downstream payload table updated.");1598 result = true;1599 break;1600 }1601 } else {1602 union dpcd_rev dpcdRev = {0};1603 1604 if (core_link_read_dpcd(1605 link,1606 DP_DPCD_REV,1607 &dpcdRev.raw,1608 1) != DC_OK) {1609 DC_LOG_ERROR("SST Update Payload: Unable to read DPCD revision "1610 "of sink while polling payload table "1611 "updated status bit.");1612 break;1613 }1614 }1615 retries++;1616 fsleep(5000);1617 }1618 1619 if (!result && retries == max_retries) {1620 DC_LOG_ERROR("SST Update Payload: Payload table not updated after retries, "1621 "continue on. Something is wrong with the branch.");1622 // TODO - DP2.0 Payload: Read and log the payload table from downstream branch1623 }1624 1625 return result;1626}1627 1628/*1629 * Payload allocation/deallocation for SST introduced in DP2.01630 */1631static enum dc_status update_sst_payload(struct pipe_ctx *pipe_ctx,1632 bool allocate)1633{1634 struct dc_stream_state *stream = pipe_ctx->stream;1635 struct dc_link *link = stream->link;1636 struct link_mst_stream_allocation_table proposed_table = {0};1637 struct fixed31_32 avg_time_slots_per_mtp;1638 const struct dc_link_settings empty_link_settings = {0};1639 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);1640 DC_LOGGER_INIT(link->ctx->logger);1641 1642 /* slot X.Y for SST payload deallocate */1643 if (!allocate) {1644 avg_time_slots_per_mtp = dc_fixpt_from_int(0);1645 1646 log_vcp_x_y(link, avg_time_slots_per_mtp);1647 1648 if (link_hwss->ext.set_throttled_vcp_size)1649 link_hwss->ext.set_throttled_vcp_size(pipe_ctx,1650 avg_time_slots_per_mtp);1651 if (link_hwss->ext.set_hblank_min_symbol_width)1652 link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,1653 &empty_link_settings,1654 avg_time_slots_per_mtp);1655 }1656 1657 /* calculate VC payload and update branch with new payload allocation table*/1658 if (!write_128b_132b_sst_payload_allocation_table(1659 stream,1660 link,1661 &proposed_table,1662 allocate)) {1663 DC_LOG_ERROR("SST Update Payload: Failed to update "1664 "allocation table for "1665 "pipe idx: %d\n",1666 pipe_ctx->pipe_idx);1667 return DC_FAIL_DP_PAYLOAD_ALLOCATION;1668 }1669 1670 proposed_table.stream_allocations[0].hpo_dp_stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc;1671 1672 ASSERT(proposed_table.stream_count == 1);1673 1674 //TODO - DP2.0 Logging: Instead of hpo_dp_stream_enc pointer, log instance id1675 DC_LOG_DP2("SST Update Payload: hpo_dp_stream_enc: %p "1676 "vcp_id: %d "1677 "slot_count: %d\n",1678 (void *) proposed_table.stream_allocations[0].hpo_dp_stream_enc,1679 proposed_table.stream_allocations[0].vcp_id,1680 proposed_table.stream_allocations[0].slot_count);1681 1682 /* program DP source TX for payload */1683 link_hwss->ext.update_stream_allocation_table(link, &pipe_ctx->link_res,1684 &proposed_table);1685 1686 /* poll for ACT handled */1687 if (!poll_for_allocation_change_trigger(link)) {1688 // Failures will result in blackscreen and errors logged1689 BREAK_TO_DEBUGGER();1690 }1691 1692 /* slot X.Y for SST payload allocate */1693 if (allocate && link_dp_get_encoding_format(&link->cur_link_settings) ==1694 DP_128b_132b_ENCODING) {1695 avg_time_slots_per_mtp = link_calculate_sst_avg_time_slots_per_mtp(stream, link);1696 1697 log_vcp_x_y(link, avg_time_slots_per_mtp);1698 1699 if (link_hwss->ext.set_throttled_vcp_size)1700 link_hwss->ext.set_throttled_vcp_size(pipe_ctx,1701 avg_time_slots_per_mtp);1702 if (link_hwss->ext.set_hblank_min_symbol_width)1703 link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,1704 &link->cur_link_settings,1705 avg_time_slots_per_mtp);1706 }1707 1708 /* Always return DC_OK.1709 * If part of sequence fails, log failure(s) and show blackscreen1710 */1711 return DC_OK;1712}1713 1714enum dc_status link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw_in_kbps)1715{1716 struct dc_stream_state *stream = pipe_ctx->stream;1717 struct dc_link *link = stream->link;1718 struct fixed31_32 avg_time_slots_per_mtp;1719 struct fixed31_32 pbn;1720 struct fixed31_32 pbn_per_slot;1721 struct dc_dp_mst_stream_allocation_table proposed_table = {0};1722 uint8_t i;1723 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);1724 DC_LOGGER_INIT(link->ctx->logger);1725 1726 /* decrease throttled vcp size */1727 pbn_per_slot = get_pbn_per_slot(stream);1728 pbn = get_pbn_from_bw_in_kbps(bw_in_kbps);1729 avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);1730 1731 if (link_hwss->ext.set_throttled_vcp_size)1732 link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp);1733 if (link_hwss->ext.set_hblank_min_symbol_width)1734 link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,1735 &link->cur_link_settings,1736 avg_time_slots_per_mtp);1737 1738 /* send ALLOCATE_PAYLOAD sideband message with updated pbn */1739 dm_helpers_dp_mst_send_payload_allocation(1740 stream->ctx,1741 stream);1742 1743 /* notify immediate branch device table update */1744 if (dm_helpers_dp_mst_write_payload_allocation_table(1745 stream->ctx,1746 stream,1747 &proposed_table,1748 true)) {1749 /* update mst stream allocation table software state */1750 update_mst_stream_alloc_table(1751 link,1752 pipe_ctx->stream_res.stream_enc,1753 pipe_ctx->stream_res.hpo_dp_stream_enc,1754 &proposed_table);1755 } else {1756 DC_LOG_WARNING("Failed to update"1757 "MST allocation table for"1758 "pipe idx:%d\n",1759 pipe_ctx->pipe_idx);1760 }1761 1762 DC_LOG_MST("%s "1763 "stream_count: %d: \n ",1764 __func__,1765 link->mst_stream_alloc_table.stream_count);1766 1767 for (i = 0; i < MAX_CONTROLLER_NUM; i++) {1768 DC_LOG_MST("stream_enc[%d]: %p "1769 "stream[%d].hpo_dp_stream_enc: %p "1770 "stream[%d].vcp_id: %d "1771 "stream[%d].slot_count: %d\n",1772 i,1773 (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,1774 i,1775 (void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,1776 i,1777 link->mst_stream_alloc_table.stream_allocations[i].vcp_id,1778 i,1779 link->mst_stream_alloc_table.stream_allocations[i].slot_count);1780 }1781 1782 ASSERT(proposed_table.stream_count > 0);1783 1784 /* update mst stream allocation table hardware state */1785 if (link_hwss->ext.update_stream_allocation_table == NULL ||1786 link_dp_get_encoding_format(&link->cur_link_settings) == DP_UNKNOWN_ENCODING) {1787 DC_LOG_ERROR("Failure: unknown encoding format\n");1788 return DC_ERROR_UNEXPECTED;1789 }1790 1791 link_hwss->ext.update_stream_allocation_table(link, &pipe_ctx->link_res,1792 &link->mst_stream_alloc_table);1793 1794 /* poll for immediate branch device ACT handled */1795 dm_helpers_dp_mst_poll_for_allocation_change_trigger(1796 stream->ctx,1797 stream);1798 1799 return DC_OK;1800}1801 1802enum dc_status link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw_in_kbps)1803{1804 struct dc_stream_state *stream = pipe_ctx->stream;1805 struct dc_link *link = stream->link;1806 struct fixed31_32 avg_time_slots_per_mtp;1807 struct fixed31_32 pbn;1808 struct fixed31_32 pbn_per_slot;1809 struct dc_dp_mst_stream_allocation_table proposed_table = {0};1810 uint8_t i;1811 enum act_return_status ret;1812 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);1813 DC_LOGGER_INIT(link->ctx->logger);1814 1815 /* notify immediate branch device table update */1816 if (dm_helpers_dp_mst_write_payload_allocation_table(1817 stream->ctx,1818 stream,1819 &proposed_table,1820 true)) {1821 /* update mst stream allocation table software state */1822 update_mst_stream_alloc_table(1823 link,1824 pipe_ctx->stream_res.stream_enc,1825 pipe_ctx->stream_res.hpo_dp_stream_enc,1826 &proposed_table);1827 }1828 1829 DC_LOG_MST("%s "1830 "stream_count: %d: \n ",1831 __func__,1832 link->mst_stream_alloc_table.stream_count);1833 1834 for (i = 0; i < MAX_CONTROLLER_NUM; i++) {1835 DC_LOG_MST("stream_enc[%d]: %p "1836 "stream[%d].hpo_dp_stream_enc: %p "1837 "stream[%d].vcp_id: %d "1838 "stream[%d].slot_count: %d\n",1839 i,1840 (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,1841 i,1842 (void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,1843 i,1844 link->mst_stream_alloc_table.stream_allocations[i].vcp_id,1845 i,1846 link->mst_stream_alloc_table.stream_allocations[i].slot_count);1847 }1848 1849 ASSERT(proposed_table.stream_count > 0);1850 1851 /* update mst stream allocation table hardware state */1852 if (link_hwss->ext.update_stream_allocation_table == NULL ||1853 link_dp_get_encoding_format(&link->cur_link_settings) == DP_UNKNOWN_ENCODING) {1854 DC_LOG_ERROR("Failure: unknown encoding format\n");1855 return DC_ERROR_UNEXPECTED;1856 }1857 1858 link_hwss->ext.update_stream_allocation_table(link, &pipe_ctx->link_res,1859 &link->mst_stream_alloc_table);1860 1861 /* poll for immediate branch device ACT handled */1862 ret = dm_helpers_dp_mst_poll_for_allocation_change_trigger(1863 stream->ctx,1864 stream);1865 1866 if (ret != ACT_LINK_LOST) {1867 /* send ALLOCATE_PAYLOAD sideband message with updated pbn */1868 dm_helpers_dp_mst_send_payload_allocation(1869 stream->ctx,1870 stream);1871 }1872 1873 /* increase throttled vcp size */1874 pbn = get_pbn_from_bw_in_kbps(bw_in_kbps);1875 pbn_per_slot = get_pbn_per_slot(stream);1876 avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);1877 1878 if (link_hwss->ext.set_throttled_vcp_size)1879 link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp);1880 if (link_hwss->ext.set_hblank_min_symbol_width)1881 link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,1882 &link->cur_link_settings,1883 avg_time_slots_per_mtp);1884 1885 return DC_OK;1886}1887 1888static void disable_link_dp(struct dc_link *link,1889 const struct link_resource *link_res,1890 enum signal_type signal)1891{1892 struct dc_link_settings link_settings = link->cur_link_settings;1893 1894 if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST &&1895 link->mst_stream_alloc_table.stream_count > 0)1896 /* disable MST link only when last vc payload is deallocated */1897 return;1898 1899 dp_disable_link_phy(link, link_res, signal);1900 1901 if (link->connector_signal == SIGNAL_TYPE_EDP) {1902 if (!link->skip_implict_edp_power_control)1903 link->dc->hwss.edp_power_control(link, false);1904 }1905 1906 if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST)1907 /* set the sink to SST mode after disabling the link */1908 enable_mst_on_sink(link, false);1909 1910 if (link_dp_get_encoding_format(&link_settings) ==1911 DP_8b_10b_ENCODING) {1912 dp_set_fec_enable(link, false);1913 dp_set_fec_ready(link, link_res, false);1914 }1915}1916 1917static void disable_link(struct dc_link *link,1918 const struct link_resource *link_res,1919 enum signal_type signal)1920{1921 if (dc_is_dp_signal(signal)) {1922 disable_link_dp(link, link_res, signal);1923 } else if (signal == SIGNAL_TYPE_VIRTUAL) {1924 link->dc->hwss.disable_link_output(link, link_res, SIGNAL_TYPE_DISPLAY_PORT);1925 } else {1926 link->dc->hwss.disable_link_output(link, link_res, signal);1927 }1928 1929 if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {1930 /* MST disable link only when no stream use the link */1931 if (link->mst_stream_alloc_table.stream_count <= 0)1932 link->link_status.link_active = false;1933 } else {1934 link->link_status.link_active = false;1935 }1936}1937 1938static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)1939{1940 struct dc_stream_state *stream = pipe_ctx->stream;1941 struct dc_link *link = stream->link;1942 enum dc_color_depth display_color_depth;1943 enum engine_id eng_id;1944 struct ext_hdmi_settings settings = {0};1945 bool is_over_340mhz = false;1946 bool is_vga_mode = (stream->timing.h_addressable == 640)1947 && (stream->timing.v_addressable == 480);1948 struct dc *dc = pipe_ctx->stream->ctx->dc;1949 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);1950 1951 if (stream->phy_pix_clk == 0)1952 stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10;1953 if (stream->phy_pix_clk > 340000)1954 is_over_340mhz = true;1955 1956 if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {1957 unsigned short masked_chip_caps = pipe_ctx->stream->link->chip_caps &1958 EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK;1959 if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) {1960 /* DP159, Retimer settings */1961 eng_id = pipe_ctx->stream_res.stream_enc->id;1962 1963 if (get_ext_hdmi_settings(pipe_ctx, eng_id, &settings)) {1964 write_i2c_retimer_setting(pipe_ctx,1965 is_vga_mode, is_over_340mhz, &settings);1966 } else {1967 write_i2c_default_retimer_setting(pipe_ctx,1968 is_vga_mode, is_over_340mhz);1969 }1970 } else if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_PI3EQX1204) {1971 /* PI3EQX1204, Redriver settings */1972 write_i2c_redriver_setting(pipe_ctx, is_over_340mhz);1973 }1974 }1975 1976 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))1977 write_scdc_data(1978 stream->link->ddc,1979 stream->phy_pix_clk,1980 stream->timing.flags.LTE_340MCSC_SCRAMBLE);1981 1982 memset(&stream->link->cur_link_settings, 0,1983 sizeof(struct dc_link_settings));1984 1985 display_color_depth = stream->timing.display_color_depth;1986 if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)1987 display_color_depth = COLOR_DEPTH_888;1988 1989 /* We need to enable stream encoder for TMDS first to apply 1/4 TMDS1990 * character clock in case that beyond 340MHz.1991 */1992 if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) || dc_is_dvi_signal(pipe_ctx->stream->signal))1993 link_hwss->setup_stream_encoder(pipe_ctx);1994 1995 dc->hwss.enable_tmds_link_output(1996 link,1997 &pipe_ctx->link_res,1998 pipe_ctx->stream->signal,1999 pipe_ctx->clock_source->id,2000 display_color_depth,2001 stream->phy_pix_clk);2002 2003 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))2004 read_scdc_data(link->ddc);2005}2006 2007static enum dc_status enable_link_dp(struct dc_state *state,2008 struct pipe_ctx *pipe_ctx)2009{2010 struct dc_stream_state *stream = pipe_ctx->stream;2011 enum dc_status status;2012 bool skip_video_pattern;2013 struct dc_link *link = stream->link;2014 const struct dc_link_settings *link_settings =2015 &pipe_ctx->link_config.dp_link_settings;2016 bool fec_enable;2017 int i;2018 bool apply_seamless_boot_optimization = false;2019 uint32_t bl_oled_enable_delay = 50; // in ms2020 uint32_t post_oui_delay = 30; // 30ms2021 /* Reduce link bandwidth between failed link training attempts. */2022 bool do_fallback = false;2023 int lt_attempts = LINK_TRAINING_ATTEMPTS;2024 2025 // Increase retry count if attempting DP1.x on FIXED_VS link2026 if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&2027 link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING)2028 lt_attempts = 10;2029 2030 // check for seamless boot2031 for (i = 0; i < state->stream_count; i++) {2032 if (state->streams[i]->apply_seamless_boot_optimization) {2033 apply_seamless_boot_optimization = true;2034 break;2035 }2036 }2037 2038 /* Train with fallback when enabling DPIA link. Conventional links are2039 * trained with fallback during sink detection.2040 */2041 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)2042 do_fallback = true;2043 2044 /*2045 * Temporary w/a to get DP2.0 link rates to work with SST.2046 * TODO DP2.0 - Workaround: Remove w/a if and when the issue is resolved.2047 */2048 if (link_dp_get_encoding_format(link_settings) == DP_128b_132b_ENCODING &&2049 pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&2050 link->dc->debug.set_mst_en_for_sst) {2051 enable_mst_on_sink(link, true);2052 }2053 if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP) {2054 /*in case it is not on*/2055 if (!link->dc->config.edp_no_power_sequencing)2056 link->dc->hwss.edp_power_control(link, true);2057 link->dc->hwss.edp_wait_for_hpd_ready(link, true);2058 }2059 2060 if (link_dp_get_encoding_format(link_settings) == DP_128b_132b_ENCODING) {2061 /* TODO - DP2.0 HW: calculate 32 symbol clock for HPO encoder */2062 } else {2063 pipe_ctx->stream_res.pix_clk_params.requested_sym_clk =2064 link_settings->link_rate * LINK_RATE_REF_FREQ_IN_KHZ;2065 if (state->clk_mgr && !apply_seamless_boot_optimization)2066 state->clk_mgr->funcs->update_clocks(state->clk_mgr,2067 state, false);2068 }2069 2070 // during mode switch we do DP_SET_POWER off then on, and OUI is lost2071 dpcd_set_source_specific_data(link);2072 if (link->dpcd_sink_ext_caps.raw != 0) {2073 post_oui_delay += link->panel_config.pps.extra_post_OUI_ms;2074 msleep(post_oui_delay);2075 }2076 2077 // similarly, mode switch can cause loss of cable ID2078 dpcd_write_cable_id_to_dprx(link);2079 2080 skip_video_pattern = true;2081 2082 if (link_settings->link_rate == LINK_RATE_LOW)2083 skip_video_pattern = false;2084 2085 if (perform_link_training_with_retries(link_settings,2086 skip_video_pattern,2087 lt_attempts,2088 pipe_ctx,2089 pipe_ctx->stream->signal,2090 do_fallback)) {2091 status = DC_OK;2092 } else {2093 status = DC_FAIL_DP_LINK_TRAINING;2094 }2095 2096 if (link->preferred_training_settings.fec_enable)2097 fec_enable = *link->preferred_training_settings.fec_enable;2098 else2099 fec_enable = true;2100 2101 if (link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING)2102 dp_set_fec_enable(link, fec_enable);2103 2104 // during mode set we do DP_SET_POWER off then on, aux writes are lost2105 if (link->dpcd_sink_ext_caps.bits.oled == 1 ||2106 link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1 ||2107 link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1) {2108 set_default_brightness_aux(link);2109 if (link->dpcd_sink_ext_caps.bits.oled == 1)2110 msleep(bl_oled_enable_delay);2111 edp_backlight_enable_aux(link, true);2112 }2113 2114 return status;2115}2116 2117static enum dc_status enable_link_edp(2118 struct dc_state *state,2119 struct pipe_ctx *pipe_ctx)2120{2121 return enable_link_dp(state, pipe_ctx);2122}2123 2124static void enable_link_lvds(struct pipe_ctx *pipe_ctx)2125{2126 struct dc_stream_state *stream = pipe_ctx->stream;2127 struct dc_link *link = stream->link;2128 struct dc *dc = stream->ctx->dc;2129 2130 if (stream->phy_pix_clk == 0)2131 stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10;2132 2133 memset(&stream->link->cur_link_settings, 0,2134 sizeof(struct dc_link_settings));2135 dc->hwss.enable_lvds_link_output(2136 link,2137 &pipe_ctx->link_res,2138 pipe_ctx->clock_source->id,2139 stream->phy_pix_clk);2140 2141}2142 2143static enum dc_status enable_link_dp_mst(2144 struct dc_state *state,2145 struct pipe_ctx *pipe_ctx)2146{2147 struct dc_link *link = pipe_ctx->stream->link;2148 unsigned char mstm_cntl = 0;2149 2150 /* sink signal type after MST branch is MST. Multiple MST sinks2151 * share one link. Link DP PHY is enable or training only once.2152 */2153 if (link->link_status.link_active)2154 return DC_OK;2155 2156 /* clear payload table */2157 core_link_read_dpcd(link, DP_MSTM_CTRL, &mstm_cntl, 1);2158 if (mstm_cntl & DP_MST_EN)2159 dm_helpers_dp_mst_clear_payload_allocation_table(link->ctx, link);2160 2161 /* to make sure the pending down rep can be processed2162 * before enabling the link2163 */2164 dm_helpers_dp_mst_poll_pending_down_reply(link->ctx, link);2165 2166 /* set the sink to MST mode before enabling the link */2167 enable_mst_on_sink(link, true);2168 2169 return enable_link_dp(state, pipe_ctx);2170}2171 2172static enum dc_status enable_link_virtual(struct pipe_ctx *pipe_ctx)2173{2174 struct dc_link *link = pipe_ctx->stream->link;2175 2176 link->dc->hwss.enable_dp_link_output(link,2177 &pipe_ctx->link_res,2178 SIGNAL_TYPE_DISPLAY_PORT,2179 pipe_ctx->clock_source->id,2180 &pipe_ctx->link_config.dp_link_settings);2181 return DC_OK;2182}2183 2184static enum dc_status enable_link(2185 struct dc_state *state,2186 struct pipe_ctx *pipe_ctx)2187{2188 enum dc_status status = DC_ERROR_UNEXPECTED;2189 struct dc_stream_state *stream = pipe_ctx->stream;2190 struct dc_link *link = stream->link;2191 2192 /* There's some scenarios where driver is unloaded with display2193 * still enabled. When driver is reloaded, it may cause a display2194 * to not light up if there is a mismatch between old and new2195 * link settings. Need to call disable first before enabling at2196 * new link settings.2197 */2198 if (link->link_status.link_active)2199 disable_link(link, &pipe_ctx->link_res, pipe_ctx->stream->signal);2200 2201 switch (pipe_ctx->stream->signal) {2202 case SIGNAL_TYPE_DISPLAY_PORT:2203 status = enable_link_dp(state, pipe_ctx);2204 break;2205 case SIGNAL_TYPE_EDP:2206 status = enable_link_edp(state, pipe_ctx);2207 break;2208 case SIGNAL_TYPE_DISPLAY_PORT_MST:2209 status = enable_link_dp_mst(state, pipe_ctx);2210 msleep(200);2211 break;2212 case SIGNAL_TYPE_DVI_SINGLE_LINK:2213 case SIGNAL_TYPE_DVI_DUAL_LINK:2214 case SIGNAL_TYPE_HDMI_TYPE_A:2215 enable_link_hdmi(pipe_ctx);2216 status = DC_OK;2217 break;2218 case SIGNAL_TYPE_LVDS:2219 enable_link_lvds(pipe_ctx);2220 status = DC_OK;2221 break;2222 case SIGNAL_TYPE_VIRTUAL:2223 status = enable_link_virtual(pipe_ctx);2224 break;2225 default:2226 break;2227 }2228 2229 if (status == DC_OK) {2230 pipe_ctx->stream->link->link_status.link_active = true;2231 }2232 2233 return status;2234}2235 2236static bool allocate_usb4_bandwidth_for_stream(struct dc_stream_state *stream, int bw)2237{2238 struct dc_link *link = stream->sink->link;2239 int req_bw = bw;2240 2241 DC_LOGGER_INIT(link->ctx->logger);2242 2243 if (!link->dpia_bw_alloc_config.bw_alloc_enabled)2244 return false;2245 2246 if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {2247 int sink_index = 0;2248 int i = 0;2249 2250 for (i = 0; i < link->sink_count; i++) {2251 if (link->remote_sinks[i] == NULL)2252 continue;2253 2254 if (stream->sink->sink_id != link->remote_sinks[i]->sink_id)2255 req_bw += link->dpia_bw_alloc_config.remote_sink_req_bw[i];2256 else2257 sink_index = i;2258 }2259 2260 link->dpia_bw_alloc_config.remote_sink_req_bw[sink_index] = bw;2261 }2262 2263 /* get dp overhead for dp tunneling */2264 link->dpia_bw_alloc_config.dp_overhead = link_dp_dpia_get_dp_overhead_in_dp_tunneling(link);2265 req_bw += link->dpia_bw_alloc_config.dp_overhead;2266 2267 if (link_dp_dpia_allocate_usb4_bandwidth_for_stream(link, req_bw)) {2268 if (req_bw <= link->dpia_bw_alloc_config.allocated_bw) {2269 DC_LOG_DEBUG("%s, Success in allocate bw for link(%d), allocated_bw(%d), dp_overhead(%d)\n",2270 __func__, link->link_index, link->dpia_bw_alloc_config.allocated_bw,2271 link->dpia_bw_alloc_config.dp_overhead);2272 } else {2273 // Cannot get the required bandwidth.2274 DC_LOG_ERROR("%s, Failed to allocate bw for link(%d), allocated_bw(%d), dp_overhead(%d)\n",2275 __func__, link->link_index, link->dpia_bw_alloc_config.allocated_bw,2276 link->dpia_bw_alloc_config.dp_overhead);2277 return false;2278 }2279 } else {2280 DC_LOG_DEBUG("%s, usb4 request bw timeout\n", __func__);2281 return false;2282 }2283 2284 if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {2285 int i = 0;2286 2287 for (i = 0; i < link->sink_count; i++) {2288 if (link->remote_sinks[i] == NULL)2289 continue;2290 DC_LOG_DEBUG("%s, remote_sink=%s, request_bw=%d\n", __func__,2291 (const char *)(&link->remote_sinks[i]->edid_caps.display_name[0]),2292 link->dpia_bw_alloc_config.remote_sink_req_bw[i]);2293 }2294 }2295 2296 return true;2297}2298 2299static bool allocate_usb4_bandwidth(struct dc_stream_state *stream)2300{2301 bool ret;2302 2303 int bw = dc_bandwidth_in_kbps_from_timing(&stream->timing,2304 dc_link_get_highest_encoding_format(stream->sink->link));2305 2306 ret = allocate_usb4_bandwidth_for_stream(stream, bw);2307 2308 return ret;2309}2310 2311static bool deallocate_usb4_bandwidth(struct dc_stream_state *stream)2312{2313 bool ret;2314 2315 ret = allocate_usb4_bandwidth_for_stream(stream, 0);2316 2317 return ret;2318}2319 2320void link_set_dpms_off(struct pipe_ctx *pipe_ctx)2321{2322 struct dc *dc = pipe_ctx->stream->ctx->dc;2323 struct dc_stream_state *stream = pipe_ctx->stream;2324 struct dc_link *link = stream->sink->link;2325 struct vpg *vpg = pipe_ctx->stream_res.stream_enc->vpg;2326 enum dp_panel_mode panel_mode_dp = dp_get_panel_mode(link);2327 2328 DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);2329 2330 ASSERT(is_master_pipe_for_link(link, pipe_ctx));2331 2332 if (dp_is_128b_132b_signal(pipe_ctx))2333 vpg = pipe_ctx->stream_res.hpo_dp_stream_enc->vpg;2334 if (dc_is_virtual_signal(pipe_ctx->stream->signal))2335 return;2336 2337 if (pipe_ctx->stream->sink) {2338 if (pipe_ctx->stream->sink->sink_signal != SIGNAL_TYPE_VIRTUAL &&2339 pipe_ctx->stream->sink->sink_signal != SIGNAL_TYPE_NONE) {2340 DC_LOG_DC("%s pipe_ctx dispname=%s signal=%x\n", __func__,2341 pipe_ctx->stream->sink->edid_caps.display_name,2342 pipe_ctx->stream->signal);2343 }2344 }2345 2346 if (!pipe_ctx->stream->sink->edid_caps.panel_patch.skip_avmute) {2347 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))2348 set_avmute(pipe_ctx, true);2349 }2350 2351 dc->hwss.disable_audio_stream(pipe_ctx);2352 2353 update_psp_stream_config(pipe_ctx, true);2354 dc->hwss.blank_stream(pipe_ctx);2355 2356 if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)2357 deallocate_usb4_bandwidth(pipe_ctx->stream);2358 2359 if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)2360 deallocate_mst_payload(pipe_ctx);2361 else if (dc_is_dp_sst_signal(pipe_ctx->stream->signal) &&2362 dp_is_128b_132b_signal(pipe_ctx))2363 update_sst_payload(pipe_ctx, false);2364 2365 if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {2366 struct ext_hdmi_settings settings = {0};2367 enum engine_id eng_id = pipe_ctx->stream_res.stream_enc->id;2368 2369 unsigned short masked_chip_caps = link->chip_caps &2370 EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK;2371 //Need to inform that sink is going to use legacy HDMI mode.2372 write_scdc_data(2373 link->ddc,2374 165000,//vbios only handles 165Mhz.2375 false);2376 if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) {2377 /* DP159, Retimer settings */2378 if (get_ext_hdmi_settings(pipe_ctx, eng_id, &settings))2379 write_i2c_retimer_setting(pipe_ctx,2380 false, false, &settings);2381 else2382 write_i2c_default_retimer_setting(pipe_ctx,2383 false, false);2384 } else if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_PI3EQX1204) {2385 /* PI3EQX1204, Redriver settings */2386 write_i2c_redriver_setting(pipe_ctx, false);2387 }2388 }2389 2390 if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&2391 !dp_is_128b_132b_signal(pipe_ctx)) {2392 2393 /* In DP1.x SST mode, our encoder will go to TPS12394 * when link is on but stream is off.2395 * Disabling link before stream will avoid exposing TPS1 pattern2396 * during the disable sequence as it will confuse some receivers2397 * state machine.2398 * In DP2 or MST mode, our encoder will stay video active2399 */2400 disable_link(pipe_ctx->stream->link, &pipe_ctx->link_res, pipe_ctx->stream->signal);2401 dc->hwss.disable_stream(pipe_ctx);2402 } else {2403 dc->hwss.disable_stream(pipe_ctx);2404 disable_link(pipe_ctx->stream->link, &pipe_ctx->link_res, pipe_ctx->stream->signal);2405 }2406 edp_set_panel_assr(link, pipe_ctx, &panel_mode_dp, false);2407 2408 if (pipe_ctx->stream->timing.flags.DSC) {2409 if (dc_is_dp_signal(pipe_ctx->stream->signal))2410 link_set_dsc_enable(pipe_ctx, false);2411 }2412 if (dp_is_128b_132b_signal(pipe_ctx)) {2413 if (pipe_ctx->stream_res.tg->funcs->set_out_mux)2414 pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, OUT_MUX_DIO);2415 }2416 2417 if (vpg && vpg->funcs->vpg_powerdown)2418 vpg->funcs->vpg_powerdown(vpg);2419 2420 /* for psp not exist case */2421 if (link->connector_signal == SIGNAL_TYPE_EDP && dc->debug.psp_disabled_wa) {2422 /* reset internal save state to default since eDP is off */2423 enum dp_panel_mode panel_mode = dp_get_panel_mode(pipe_ctx->stream->link);2424 /* since current psp not loaded, we need to reset it to default*/2425 link->panel_mode = panel_mode;2426 }2427}2428 2429void link_set_dpms_on(2430 struct dc_state *state,2431 struct pipe_ctx *pipe_ctx)2432{2433 struct dc *dc = pipe_ctx->stream->ctx->dc;2434 struct dc_stream_state *stream = pipe_ctx->stream;2435 struct dc_link *link = stream->sink->link;2436 enum dc_status status;2437 struct link_encoder *link_enc;2438 enum otg_out_mux_dest otg_out_dest = OUT_MUX_DIO;2439 struct vpg *vpg = pipe_ctx->stream_res.stream_enc->vpg;2440 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);2441 bool apply_edp_fast_boot_optimization =2442 pipe_ctx->stream->apply_edp_fast_boot_optimization;2443 2444 DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);2445 2446 ASSERT(is_master_pipe_for_link(link, pipe_ctx));2447 2448 if (dp_is_128b_132b_signal(pipe_ctx))2449 vpg = pipe_ctx->stream_res.hpo_dp_stream_enc->vpg;2450 if (dc_is_virtual_signal(pipe_ctx->stream->signal))2451 return;2452 2453 if (pipe_ctx->stream->sink) {2454 if (pipe_ctx->stream->sink->sink_signal != SIGNAL_TYPE_VIRTUAL &&2455 pipe_ctx->stream->sink->sink_signal != SIGNAL_TYPE_NONE) {2456 DC_LOG_DC("%s pipe_ctx dispname=%s signal=%x\n", __func__,2457 pipe_ctx->stream->sink->edid_caps.display_name,2458 pipe_ctx->stream->signal);2459 }2460 }2461 2462 link_enc = link_enc_cfg_get_link_enc(link);2463 ASSERT(link_enc);2464 2465 if (!dc_is_virtual_signal(pipe_ctx->stream->signal)2466 && !dp_is_128b_132b_signal(pipe_ctx)) {2467 if (link_enc)2468 link_enc->funcs->setup(2469 link_enc,2470 pipe_ctx->stream->signal);2471 }2472 2473 pipe_ctx->stream->link->link_state_valid = true;2474 2475 if (pipe_ctx->stream_res.tg->funcs->set_out_mux) {2476 if (dp_is_128b_132b_signal(pipe_ctx))2477 otg_out_dest = OUT_MUX_HPO_DP;2478 else2479 otg_out_dest = OUT_MUX_DIO;2480 pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, otg_out_dest);2481 }2482 2483 link_hwss->setup_stream_attribute(pipe_ctx);2484 2485 pipe_ctx->stream->apply_edp_fast_boot_optimization = false;2486 2487 // Enable VPG before building infoframe2488 if (vpg && vpg->funcs->vpg_poweron)2489 vpg->funcs->vpg_poweron(vpg);2490 2491 resource_build_info_frame(pipe_ctx);2492 dc->hwss.update_info_frame(pipe_ctx);2493 2494 if (dc_is_dp_signal(pipe_ctx->stream->signal))2495 dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME);2496 2497 /* Do not touch link on seamless boot optimization. */2498 if (pipe_ctx->stream->apply_seamless_boot_optimization) {2499 pipe_ctx->stream->dpms_off = false;2500 2501 /* Still enable stream features & audio on seamless boot for DP external displays */2502 if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT) {2503 enable_stream_features(pipe_ctx);2504 dc->hwss.enable_audio_stream(pipe_ctx);2505 }2506 2507 update_psp_stream_config(pipe_ctx, false);2508 return;2509 }2510 2511 /* eDP lit up by bios already, no need to enable again. */2512 if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP &&2513 apply_edp_fast_boot_optimization &&2514 !pipe_ctx->stream->timing.flags.DSC &&2515 !pipe_ctx->next_odm_pipe) {2516 pipe_ctx->stream->dpms_off = false;2517 update_psp_stream_config(pipe_ctx, false);2518 return;2519 }2520 2521 if (pipe_ctx->stream->dpms_off)2522 return;2523 2524 /* Have to setup DSC before DIG FE and BE are connected (which happens before the2525 * link training). This is to make sure the bandwidth sent to DIG BE won't be2526 * bigger than what the link and/or DIG BE can handle. VBID[6]/CompressedStream_flag2527 * will be automatically set at a later time when the video is enabled2528 * (DP_VID_STREAM_EN = 1).2529 */2530 if (pipe_ctx->stream->timing.flags.DSC) {2531 if (dc_is_dp_signal(pipe_ctx->stream->signal) ||2532 dc_is_virtual_signal(pipe_ctx->stream->signal))2533 link_set_dsc_enable(pipe_ctx, true);2534 }2535 2536 status = enable_link(state, pipe_ctx);2537 2538 if (status != DC_OK) {2539 DC_LOG_WARNING("enabling link %u failed: %d\n",2540 pipe_ctx->stream->link->link_index,2541 status);2542 2543 /* Abort stream enable *unless* the failure was due to2544 * DP link training - some DP monitors will recover and2545 * show the stream anyway. But MST displays can't proceed2546 * without link training.2547 */2548 if (status != DC_FAIL_DP_LINK_TRAINING ||2549 pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {2550 if (false == stream->link->link_status.link_active)2551 disable_link(stream->link, &pipe_ctx->link_res,2552 pipe_ctx->stream->signal);2553 BREAK_TO_DEBUGGER();2554 return;2555 }2556 }2557 2558 /* turn off otg test pattern if enable */2559 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)2560 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,2561 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,2562 COLOR_DEPTH_UNDEFINED);2563 2564 /* This second call is needed to reconfigure the DIG2565 * as a workaround for the incorrect value being applied2566 * from transmitter control.2567 */2568 if (!(dc_is_virtual_signal(pipe_ctx->stream->signal) ||2569 dp_is_128b_132b_signal(pipe_ctx))) {2570 2571 if (link_enc)2572 link_enc->funcs->setup(2573 link_enc,2574 pipe_ctx->stream->signal);2575 2576 }2577 2578 dc->hwss.enable_stream(pipe_ctx);2579 2580 /* Set DPS PPS SDP (AKA "info frames") */2581 if (pipe_ctx->stream->timing.flags.DSC) {2582 if (dc_is_dp_signal(pipe_ctx->stream->signal) ||2583 dc_is_virtual_signal(pipe_ctx->stream->signal)) {2584 dp_set_dsc_on_rx(pipe_ctx, true);2585 link_set_dsc_pps_packet(pipe_ctx, true, true);2586 }2587 }2588 2589 if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)2590 allocate_usb4_bandwidth(pipe_ctx->stream);2591 2592 if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)2593 allocate_mst_payload(pipe_ctx);2594 else if (dc_is_dp_sst_signal(pipe_ctx->stream->signal) &&2595 dp_is_128b_132b_signal(pipe_ctx))2596 update_sst_payload(pipe_ctx, true);2597 2598 dc->hwss.unblank_stream(pipe_ctx,2599 &pipe_ctx->stream->link->cur_link_settings);2600 2601 if (stream->sink_patches.delay_ignore_msa > 0)2602 msleep(stream->sink_patches.delay_ignore_msa);2603 2604 if (dc_is_dp_signal(pipe_ctx->stream->signal))2605 enable_stream_features(pipe_ctx);2606 update_psp_stream_config(pipe_ctx, false);2607 2608 dc->hwss.enable_audio_stream(pipe_ctx);2609 2610 if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {2611 set_avmute(pipe_ctx, false);2612 }2613}2614