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 #include "dm_services.h" 26 27 #include "amdgpu.h" 28 29 #include "dc.h" 30 31 #include "core_status.h" 32 #include "core_types.h" 33 #include "hw_sequencer.h" 34 #include "dce/dce_hwseq.h" 35 #include "hw/dccg.h" 36 37 #include "resource.h" 38 #include "dc_state.h" 39 #include "dc_state_priv.h" 40 #include "dc_plane.h" 41 #include "dc_plane_priv.h" 42 #include "dc_stream_priv.h" 43 44 #include "gpio_service_interface.h" 45 #include "clk_mgr.h" 46 #include "clock_source.h" 47 #include "dc_bios_types.h" 48 49 #include "bios_parser_interface.h" 50 #include "bios/bios_parser_helper.h" 51 #include "include/irq_service_interface.h" 52 #include "transform.h" 53 #include "dmcu.h" 54 #include "dpp.h" 55 #include "timing_generator.h" 56 #include "abm.h" 57 #include "dio/virtual/virtual_link_encoder.h" 58 #include "hubp.h" 59 60 #include "link_hwss.h" 61 #include "link_encoder.h" 62 #include "link_enc_cfg.h" 63 64 #include "link_service.h" 65 #include "link/protocols/link_dp_capability.h" 66 #include "dm_helpers.h" 67 #include "mem_input.h" 68 69 #include "dc_dmub_srv.h" 70 71 #include "dsc.h" 72 73 #include "vm_helper.h" 74 75 #include "dce/dce_i2c.h" 76 77 #include "dmub/dmub_srv.h" 78 79 #include "dce/dmub_psr.h" 80 81 #include "dce/dmub_hw_lock_mgr.h" 82 83 #include "dc_trace.h" 84 85 #include "hw_sequencer_private.h" 86 87 #if defined(CONFIG_DRM_AMD_DC_FP) 88 #include "dml2_0/dml2_internal_types.h" 89 #include "soc_and_ip_translator.h" 90 #endif 91 92 #include "dce/dmub_outbox.h" 93 94 #define CTX \ 95 dc->ctx 96 97 #define DC_LOGGER \ 98 dc->ctx->logger 99 100 static const char DC_BUILD_ID[] = "production-build"; 101 102 /** 103 * DOC: Overview 104 * 105 * DC is the OS-agnostic component of the amdgpu DC driver. 106 * 107 * DC maintains and validates a set of structs representing the state of the 108 * driver and writes that state to AMD hardware 109 * 110 * Main DC HW structs: 111 * 112 * struct dc - The central struct. One per driver. Created on driver load, 113 * destroyed on driver unload. 114 * 115 * struct dc_context - One per driver. 116 * Used as a backpointer by most other structs in dc. 117 * 118 * struct dc_link - One per connector (the physical DP, HDMI, miniDP, or eDP 119 * plugpoints). Created on driver load, destroyed on driver unload. 120 * 121 * struct dc_sink - One per display. Created on boot or hotplug. 122 * Destroyed on shutdown or hotunplug. A dc_link can have a local sink 123 * (the display directly attached). It may also have one or more remote 124 * sinks (in the Multi-Stream Transport case) 125 * 126 * struct resource_pool - One per driver. Represents the hw blocks not in the 127 * main pipeline. Not directly accessible by dm. 128 * 129 * Main dc state structs: 130 * 131 * These structs can be created and destroyed as needed. There is a full set of 132 * these structs in dc->current_state representing the currently programmed state. 133 * 134 * struct dc_state - The global DC state to track global state information, 135 * such as bandwidth values. 136 * 137 * struct dc_stream_state - Represents the hw configuration for the pipeline from 138 * a framebuffer to a display. Maps one-to-one with dc_sink. 139 * 140 * struct dc_plane_state - Represents a framebuffer. Each stream has at least one, 141 * and may have more in the Multi-Plane Overlay case. 142 * 143 * struct resource_context - Represents the programmable state of everything in 144 * the resource_pool. Not directly accessible by dm. 145 * 146 * struct pipe_ctx - A member of struct resource_context. Represents the 147 * internal hardware pipeline components. Each dc_plane_state has either 148 * one or two (in the pipe-split case). 149 */ 150 151 /* Private functions */ 152 153 static inline void elevate_update_type( 154 struct surface_update_descriptor *descriptor, 155 enum surface_update_type new_type, 156 enum dc_lock_descriptor new_locks 157 ) 158 { 159 if (new_type > descriptor->update_type) 160 descriptor->update_type = new_type; 161 162 descriptor->lock_descriptor |= new_locks; 163 } 164 165 static void destroy_links(struct dc *dc) 166 { 167 uint32_t i; 168 169 for (i = 0; i < dc->link_count; i++) { 170 if (NULL != dc->links[i]) 171 dc->link_srv->destroy_link(&dc->links[i]); 172 } 173 } 174 175 static uint32_t get_num_of_internal_disp(struct dc_link **links, uint32_t num_links) 176 { 177 uint32_t i; 178 uint32_t count = 0; 179 180 for (i = 0; i < num_links; i++) { 181 if (links[i]->connector_signal == SIGNAL_TYPE_EDP || 182 links[i]->is_internal_display) 183 count++; 184 } 185 186 return count; 187 } 188 189 static int get_seamless_boot_stream_count(struct dc_state *ctx) 190 { 191 uint8_t i; 192 uint8_t seamless_boot_stream_count = 0; 193 194 for (i = 0; i < ctx->stream_count; i++) 195 if (ctx->streams[i]->apply_seamless_boot_optimization) 196 seamless_boot_stream_count++; 197 198 return seamless_boot_stream_count; 199 } 200 201 static bool create_links( 202 struct dc *dc, 203 uint32_t num_virtual_links) 204 { 205 uint32_t i; 206 int connectors_num; 207 struct dc_bios *bios = dc->ctx->dc_bios; 208 209 dc->link_count = 0; 210 211 connectors_num = bios->funcs->get_connectors_number(bios); 212 213 DC_LOG_DC("BIOS object table - number of connectors: %d", connectors_num); 214 215 if (connectors_num > ENUM_ID_COUNT) { 216 dm_error( 217 "DC: Number of connectors %d exceeds maximum of %d!\n", 218 connectors_num, 219 ENUM_ID_COUNT); 220 return false; 221 } 222 223 dm_output_to_console( 224 "DC: %s: connectors_num: physical:%d, virtual:%d\n", 225 __func__, 226 connectors_num, 227 num_virtual_links); 228 229 /* When getting the number of connectors, the VBIOS reports the number of valid indices, 230 * but it doesn't say which indices are valid, and not every index has an actual connector. 231 * So, if we don't find a connector on an index, that is not an error. 232 * 233 * - There is no guarantee that the first N indices will be valid 234 * - VBIOS may report a higher amount of valid indices than there are actual connectors 235 * - Some VBIOS have valid configurations for more connectors than there actually are 236 * on the card. This may be because the manufacturer used the same VBIOS for different 237 * variants of the same card. 238 */ 239 for (i = 0; dc->link_count < connectors_num && i < MAX_LINKS; i++) { 240 struct graphics_object_id connector_id = bios->funcs->get_connector_id(bios, (uint8_t)i); 241 struct link_init_data link_init_params = {0}; 242 struct dc_link *link; 243 244 if (connector_id.id == CONNECTOR_ID_UNKNOWN) 245 continue; 246 247 DC_LOG_DC("BIOS object table - printing link object info for connector number: %d, link_index: %d", i, dc->link_count); 248 249 link_init_params.ctx = dc->ctx; 250 /* next BIOS object table connector */ 251 link_init_params.connector_index = (uint8_t)i; 252 link_init_params.link_index = dc->link_count; 253 link_init_params.dc = dc; 254 link = dc->link_srv->create_link(&link_init_params); 255 256 if (link) { 257 dc->links[dc->link_count] = link; 258 link->dc = dc; 259 ++dc->link_count; 260 } 261 } 262 263 DC_LOG_DC("BIOS object table - end"); 264 265 /* Create a link for each usb4 dpia port */ 266 dc->lowest_dpia_link_index = MAX_LINKS; 267 for (i = 0; i < dc->res_pool->usb4_dpia_count; i++) { 268 struct link_init_data link_init_params = {0}; 269 struct dc_link *link; 270 271 link_init_params.ctx = dc->ctx; 272 link_init_params.connector_index = (uint8_t)i; 273 link_init_params.link_index = dc->link_count; 274 link_init_params.dc = dc; 275 link_init_params.is_dpia_link = true; 276 277 link = dc->link_srv->create_link(&link_init_params); 278 if (link) { 279 if (dc->lowest_dpia_link_index > dc->link_count) 280 dc->lowest_dpia_link_index = dc->link_count; 281 282 dc->links[dc->link_count] = link; 283 link->dc = dc; 284 ++dc->link_count; 285 } 286 } 287 288 for (i = 0; i < num_virtual_links; i++) { 289 struct dc_link *link = kzalloc_obj(*link); 290 struct encoder_init_data enc_init = {0}; 291 292 if (link == NULL) { 293 BREAK_TO_DEBUGGER(); 294 goto failed_alloc; 295 } 296 297 link->link_index = dc->link_count; 298 dc->links[dc->link_count] = link; 299 dc->link_count++; 300 301 link->ctx = dc->ctx; 302 link->dc = dc; 303 link->connector_signal = SIGNAL_TYPE_VIRTUAL; 304 link->link_id.type = OBJECT_TYPE_CONNECTOR; 305 link->link_id.id = CONNECTOR_ID_VIRTUAL; 306 link->link_id.enum_id = ENUM_ID_1; 307 link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED; 308 link->replay_settings.config.replay_version = DC_REPLAY_VERSION_UNSUPPORTED; 309 link->link_enc = kzalloc_obj(*link->link_enc); 310 311 if (!link->link_enc) { 312 BREAK_TO_DEBUGGER(); 313 goto failed_alloc; 314 } 315 316 link->link_status.dpcd_caps = &link->dpcd_caps; 317 318 enc_init.ctx = dc->ctx; 319 enc_init.channel = CHANNEL_ID_UNKNOWN; 320 enc_init.hpd_source = HPD_SOURCEID_UNKNOWN; 321 enc_init.transmitter = TRANSMITTER_UNKNOWN; 322 enc_init.connector = link->link_id; 323 enc_init.encoder.type = OBJECT_TYPE_ENCODER; 324 enc_init.encoder.id = ENCODER_ID_INTERNAL_VIRTUAL; 325 enc_init.encoder.enum_id = ENUM_ID_1; 326 virtual_link_encoder_construct(link->link_enc, &enc_init); 327 } 328 329 dc->caps.num_of_internal_disp = get_num_of_internal_disp(dc->links, dc->link_count); 330 331 return true; 332 333 failed_alloc: 334 return false; 335 } 336 337 /* Create additional DIG link encoder objects if fewer than the platform 338 * supports were created during link construction. This can happen if the 339 * number of physical connectors is less than the number of DIGs. 340 */ 341 static bool create_link_encoders(struct dc *dc) 342 { 343 bool res = true; 344 unsigned int num_usb4_dpia = dc->res_pool->res_cap->num_usb4_dpia; 345 unsigned int num_dig_link_enc = dc->res_pool->res_cap->num_dig_link_enc; 346 unsigned int i; 347 348 /* A platform without USB4 DPIA endpoints has a fixed mapping between DIG 349 * link encoders and physical display endpoints and does not require 350 * additional link encoder objects. 351 */ 352 if (num_usb4_dpia == 0) 353 return res; 354 355 /* Create as many link encoder objects as the platform supports. DPIA 356 * endpoints can be programmably mapped to any DIG. 357 */ 358 if (num_dig_link_enc > dc->res_pool->dig_link_enc_count) { 359 for (i = 0; i < num_dig_link_enc; i++) { 360 struct link_encoder *link_enc = dc->res_pool->link_encoders[i]; 361 362 if (!link_enc && dc->res_pool->funcs->link_enc_create_minimal) { 363 link_enc = dc->res_pool->funcs->link_enc_create_minimal(dc->ctx, 364 (enum engine_id)(ENGINE_ID_DIGA + i)); 365 if (link_enc) { 366 dc->res_pool->link_encoders[i] = link_enc; 367 dc->res_pool->dig_link_enc_count++; 368 } else { 369 res = false; 370 } 371 } 372 } 373 } 374 375 return res; 376 } 377 378 /* Destroy any additional DIG link encoder objects created by 379 * create_link_encoders(). 380 * NB: Must only be called after destroy_links(). 381 */ 382 static void destroy_link_encoders(struct dc *dc) 383 { 384 unsigned int num_usb4_dpia; 385 unsigned int num_dig_link_enc; 386 unsigned int i; 387 388 if (!dc->res_pool) 389 return; 390 391 num_usb4_dpia = dc->res_pool->res_cap->num_usb4_dpia; 392 num_dig_link_enc = dc->res_pool->res_cap->num_dig_link_enc; 393 394 /* A platform without USB4 DPIA endpoints has a fixed mapping between DIG 395 * link encoders and physical display endpoints and does not require 396 * additional link encoder objects. 397 */ 398 if (num_usb4_dpia == 0) 399 return; 400 401 for (i = 0; i < num_dig_link_enc; i++) { 402 struct link_encoder *link_enc = dc->res_pool->link_encoders[i]; 403 404 if (link_enc) { 405 link_enc->funcs->destroy(&link_enc); 406 dc->res_pool->link_encoders[i] = NULL; 407 dc->res_pool->dig_link_enc_count--; 408 } 409 } 410 } 411 412 static struct dc_perf_trace *dc_perf_trace_create(void) 413 { 414 return kzalloc_obj(struct dc_perf_trace); 415 } 416 417 static void dc_perf_trace_destroy(struct dc_perf_trace **perf_trace) 418 { 419 kfree(*perf_trace); 420 *perf_trace = NULL; 421 } 422 423 static bool set_long_vtotal(struct dc *dc, struct dc_stream_state *stream, struct dc_crtc_timing_adjust *adjust) 424 { 425 if (!dc || !stream || !adjust) 426 return false; 427 428 if (!dc->current_state) 429 return false; 430 431 int i; 432 433 for (i = 0; i < MAX_PIPES; i++) { 434 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 435 436 if (pipe->stream == stream && pipe->stream_res.tg) { 437 if (dc->hwss.set_long_vtotal) 438 dc->hwss.set_long_vtotal(&pipe, 1, adjust->v_total_min, adjust->v_total_max); 439 440 return true; 441 } 442 } 443 444 return false; 445 } 446 447 /** 448 * dc_stream_get_last_used_drr_vtotal - Looks up the pipe context of 449 * dc_stream_state and gets the last VTOTAL used by DRR (Dynamic Refresh Rate) 450 * 451 * @dc: [in] dc reference 452 * @stream: [in] Initial dc stream state 453 * @refresh_rate: [in] new refresh_rate 454 * 455 * Return: %true if the pipe context is found and there is an associated 456 * timing_generator for the DC; 457 * %false if the pipe context is not found or there is no 458 * timing_generator for the DC. 459 */ 460 bool dc_stream_get_last_used_drr_vtotal(struct dc *dc, 461 struct dc_stream_state *stream, 462 uint32_t *refresh_rate) 463 { 464 bool status = false; 465 466 int i = 0; 467 468 dc_exit_ips_for_hw_access(dc); 469 470 for (i = 0; i < MAX_PIPES; i++) { 471 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 472 473 if (pipe->stream == stream && pipe->stream_res.tg) { 474 /* Only execute if a function pointer has been defined for 475 * the DC version in question 476 */ 477 if (pipe->stream_res.tg->funcs->get_last_used_drr_vtotal) { 478 pipe->stream_res.tg->funcs->get_last_used_drr_vtotal(pipe->stream_res.tg, refresh_rate); 479 480 status = true; 481 482 break; 483 } 484 } 485 } 486 487 return status; 488 } 489 490 #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) 491 static inline void 492 dc_stream_forward_dmub_crc_window(struct dc_dmub_srv *dmub_srv, 493 struct rect *rect, struct otg_phy_mux *mux_mapping, bool is_stop) 494 { 495 union dmub_rb_cmd cmd = {0}; 496 497 cmd.secure_display.roi_info.phy_id = mux_mapping->phy_output_num; 498 cmd.secure_display.roi_info.otg_id = mux_mapping->otg_output_num; 499 500 if (is_stop) { 501 cmd.secure_display.header.type = DMUB_CMD__SECURE_DISPLAY; 502 cmd.secure_display.header.sub_type = DMUB_CMD__SECURE_DISPLAY_CRC_STOP_UPDATE; 503 } else { 504 cmd.secure_display.header.type = DMUB_CMD__SECURE_DISPLAY; 505 cmd.secure_display.header.sub_type = DMUB_CMD__SECURE_DISPLAY_CRC_WIN_NOTIFY; 506 cmd.secure_display.roi_info.x_start = rect->x; 507 cmd.secure_display.roi_info.y_start = rect->y; 508 cmd.secure_display.roi_info.x_end = rect->x + rect->width; 509 cmd.secure_display.roi_info.y_end = rect->y + rect->height; 510 } 511 512 dc_wake_and_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); 513 } 514 515 static inline void 516 dc_stream_forward_dmcu_crc_window(struct dmcu *dmcu, 517 struct rect *rect, struct otg_phy_mux *mux_mapping, bool is_stop) 518 { 519 if (is_stop) 520 dmcu->funcs->stop_crc_win_update(dmcu, mux_mapping); 521 else 522 dmcu->funcs->forward_crc_window(dmcu, rect, mux_mapping); 523 } 524 525 bool 526 dc_stream_forward_crc_window(struct dc_stream_state *stream, 527 struct rect *rect, uint8_t phy_id, bool is_stop) 528 { 529 struct dmcu *dmcu; 530 struct dc_dmub_srv *dmub_srv; 531 struct otg_phy_mux mux_mapping; 532 struct pipe_ctx *pipe; 533 int i; 534 struct dc *dc = stream->ctx->dc; 535 536 for (i = 0; i < MAX_PIPES; i++) { 537 pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 538 if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe) 539 break; 540 } 541 542 /* Stream not found */ 543 if (i == MAX_PIPES) 544 return false; 545 546 mux_mapping.phy_output_num = phy_id; 547 mux_mapping.otg_output_num = pipe->stream_res.tg->inst; 548 549 dmcu = dc->res_pool->dmcu; 550 dmub_srv = dc->ctx->dmub_srv; 551 552 /* forward to dmub */ 553 if (dmub_srv) 554 dc_stream_forward_dmub_crc_window(dmub_srv, rect, &mux_mapping, is_stop); 555 /* forward to dmcu */ 556 else if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) 557 dc_stream_forward_dmcu_crc_window(dmcu, rect, &mux_mapping, is_stop); 558 else 559 return false; 560 561 return true; 562 } 563 564 static void 565 dc_stream_forward_dmub_multiple_crc_window(struct dc_dmub_srv *dmub_srv, 566 struct crc_window *window, struct otg_phy_mux *mux_mapping, bool stop) 567 { 568 int i; 569 union dmub_rb_cmd cmd = {0}; 570 571 cmd.secure_display.mul_roi_ctl.phy_id = mux_mapping->phy_output_num; 572 cmd.secure_display.mul_roi_ctl.otg_id = mux_mapping->otg_output_num; 573 574 cmd.secure_display.header.type = DMUB_CMD__SECURE_DISPLAY; 575 576 if (stop) { 577 cmd.secure_display.header.sub_type = DMUB_CMD__SECURE_DISPLAY_MULTIPLE_CRC_STOP_UPDATE; 578 } else { 579 cmd.secure_display.header.sub_type = DMUB_CMD__SECURE_DISPLAY_MULTIPLE_CRC_WIN_NOTIFY; 580 for (i = 0; i < MAX_CRC_WINDOW_NUM; i++) { 581 cmd.secure_display.mul_roi_ctl.roi_ctl[i].x_start = window[i].rect.x; 582 cmd.secure_display.mul_roi_ctl.roi_ctl[i].y_start = window[i].rect.y; 583 cmd.secure_display.mul_roi_ctl.roi_ctl[i].x_end = window[i].rect.x + window[i].rect.width; 584 cmd.secure_display.mul_roi_ctl.roi_ctl[i].y_end = window[i].rect.y + window[i].rect.height; 585 cmd.secure_display.mul_roi_ctl.roi_ctl[i].enable = window[i].enable; 586 } 587 } 588 589 dc_wake_and_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); 590 } 591 592 bool 593 dc_stream_forward_multiple_crc_window(struct dc_stream_state *stream, 594 struct crc_window *window, uint8_t phy_id, bool stop) 595 { 596 struct dc_dmub_srv *dmub_srv; 597 struct otg_phy_mux mux_mapping; 598 struct pipe_ctx *pipe; 599 int i; 600 struct dc *dc = stream->ctx->dc; 601 602 for (i = 0; i < MAX_PIPES; i++) { 603 pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 604 if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe) 605 break; 606 } 607 608 /* Stream not found */ 609 if (i == MAX_PIPES) 610 return false; 611 612 mux_mapping.phy_output_num = phy_id; 613 mux_mapping.otg_output_num = pipe->stream_res.tg->inst; 614 615 dmub_srv = dc->ctx->dmub_srv; 616 617 /* forward to dmub only. no dmcu support*/ 618 if (dmub_srv) 619 dc_stream_forward_dmub_multiple_crc_window(dmub_srv, window, &mux_mapping, stop); 620 else 621 return false; 622 623 return true; 624 } 625 #endif /* CONFIG_DRM_AMD_SECURE_DISPLAY */ 626 627 /** 628 * dc_stream_configure_crc() - Configure CRC capture for the given stream. 629 * @dc: DC Object 630 * @stream: The stream to configure CRC on. 631 * @crc_window: CRC window (x/y start/end) information 632 * @enable: Enable CRC if true, disable otherwise. 633 * @continuous: Capture CRC on every frame if true. Otherwise, only capture 634 * once. 635 * @idx: Capture CRC on which CRC engine instance 636 * @reset: Reset CRC engine before the configuration 637 * @crc_poly_mode: CRC polynomial mode 638 * 639 * By default, the entire frame is used to calculate the CRC. 640 * 641 * Return: %false if the stream is not found or CRC capture is not supported; 642 * %true if the stream has been configured. 643 */ 644 bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream, 645 struct crc_params *crc_window, bool enable, bool continuous, 646 uint8_t idx, bool reset, enum crc_poly_mode crc_poly_mode) 647 { 648 struct pipe_ctx *pipe; 649 struct crc_params param; 650 struct timing_generator *tg; 651 652 pipe = resource_get_otg_master_for_stream( 653 &dc->current_state->res_ctx, stream); 654 655 /* Stream not found */ 656 if (pipe == NULL) 657 return false; 658 659 dc_exit_ips_for_hw_access(dc); 660 661 /* By default, capture the full frame */ 662 param.windowa_x_start = 0; 663 param.windowa_y_start = 0; 664 param.windowa_x_end = (uint16_t)pipe->stream->timing.h_addressable; 665 param.windowa_y_end = (uint16_t)pipe->stream->timing.v_addressable; 666 param.windowb_x_start = 0; 667 param.windowb_y_start = 0; 668 param.windowb_x_end = (uint16_t)pipe->stream->timing.h_addressable; 669 param.windowb_y_end = (uint16_t)pipe->stream->timing.v_addressable; 670 param.crc_poly_mode = crc_poly_mode; 671 672 if (crc_window) { 673 param.windowa_x_start = crc_window->windowa_x_start; 674 param.windowa_y_start = crc_window->windowa_y_start; 675 param.windowa_x_end = crc_window->windowa_x_end; 676 param.windowa_y_end = crc_window->windowa_y_end; 677 param.windowb_x_start = crc_window->windowb_x_start; 678 param.windowb_y_start = crc_window->windowb_y_start; 679 param.windowb_x_end = crc_window->windowb_x_end; 680 param.windowb_y_end = crc_window->windowb_y_end; 681 } 682 683 param.dsc_mode = pipe->stream->timing.flags.DSC ? 1:0; 684 param.odm_mode = pipe->next_odm_pipe ? 1:0; 685 686 /* Default to the union of both windows */ 687 param.selection = UNION_WINDOW_A_B; 688 param.continuous_mode = continuous; 689 param.enable = enable; 690 691 param.crc_eng_inst = idx; 692 param.reset = reset; 693 694 tg = pipe->stream_res.tg; 695 696 /* Only call if supported */ 697 if (tg->funcs->configure_crc) 698 return tg->funcs->configure_crc(tg, ¶m); 699 DC_LOG_WARNING("CRC capture not supported."); 700 return false; 701 } 702 703 /** 704 * dc_stream_get_crc() - Get CRC values for the given stream. 705 * 706 * @dc: DC object. 707 * @stream: The DC stream state of the stream to get CRCs from. 708 * @idx: index of crc engine to get CRC from 709 * @r_cr: CRC value for the red component. 710 * @g_y: CRC value for the green component. 711 * @b_cb: CRC value for the blue component. 712 * 713 * dc_stream_configure_crc needs to be called beforehand to enable CRCs. 714 * 715 * Return: 716 * %false if stream is not found, or if CRCs are not enabled. 717 */ 718 bool dc_stream_get_crc(struct dc *dc, struct dc_stream_state *stream, uint8_t idx, 719 uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb) 720 { 721 int i; 722 struct pipe_ctx *pipe = NULL; 723 struct timing_generator *tg; 724 725 dc_exit_ips_for_hw_access(dc); 726 727 for (i = 0; i < MAX_PIPES; i++) { 728 pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 729 if (pipe->stream == stream) 730 break; 731 } 732 /* Stream not found */ 733 if (i == MAX_PIPES) 734 return false; 735 736 tg = pipe->stream_res.tg; 737 738 if (tg->funcs->get_crc) 739 return tg->funcs->get_crc(tg, idx, r_cr, g_y, b_cb); 740 DC_LOG_WARNING("CRC capture not supported."); 741 return false; 742 } 743 744 void dc_stream_set_dyn_expansion(struct dc *dc, struct dc_stream_state *stream, 745 enum dc_dynamic_expansion option) 746 { 747 /* OPP FMT dyn expansion updates*/ 748 int i; 749 struct pipe_ctx *pipe_ctx; 750 751 dc_exit_ips_for_hw_access(dc); 752 753 for (i = 0; i < MAX_PIPES; i++) { 754 if (dc->current_state->res_ctx.pipe_ctx[i].stream 755 == stream) { 756 pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; 757 pipe_ctx->stream_res.opp->dyn_expansion = option; 758 pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( 759 pipe_ctx->stream_res.opp, 760 COLOR_SPACE_YCBCR601, 761 stream->timing.display_color_depth, 762 stream->signal); 763 } 764 } 765 } 766 767 void dc_stream_set_dither_option(struct dc_stream_state *stream, 768 enum dc_dither_option option) 769 { 770 struct bit_depth_reduction_params params; 771 struct dc_link *link = stream->link; 772 struct pipe_ctx *pipes = NULL; 773 int i; 774 775 for (i = 0; i < MAX_PIPES; i++) { 776 if (link->dc->current_state->res_ctx.pipe_ctx[i].stream == 777 stream) { 778 pipes = &link->dc->current_state->res_ctx.pipe_ctx[i]; 779 break; 780 } 781 } 782 783 if (!pipes) 784 return; 785 if (option > DITHER_OPTION_MAX) 786 return; 787 788 dc_exit_ips_for_hw_access(stream->ctx->dc); 789 790 stream->dither_option = option; 791 792 memset(¶ms, 0, sizeof(params)); 793 resource_build_bit_depth_reduction_params(stream, ¶ms); 794 stream->bit_depth_params = params; 795 796 if (pipes->plane_res.xfm && 797 pipes->plane_res.xfm->funcs->transform_set_pixel_storage_depth) { 798 pipes->plane_res.xfm->funcs->transform_set_pixel_storage_depth( 799 pipes->plane_res.xfm, 800 pipes->plane_res.scl_data.lb_params.depth, 801 &stream->bit_depth_params); 802 } 803 804 pipes->stream_res.opp->funcs-> 805 opp_program_bit_depth_reduction(pipes->stream_res.opp, ¶ms); 806 } 807 808 bool dc_stream_set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream) 809 { 810 int i; 811 bool ret = false; 812 struct pipe_ctx *pipes; 813 814 dc_exit_ips_for_hw_access(dc); 815 816 for (i = 0; i < MAX_PIPES; i++) { 817 if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) { 818 pipes = &dc->current_state->res_ctx.pipe_ctx[i]; 819 dc->hwss.program_gamut_remap(pipes); 820 ret = true; 821 } 822 } 823 824 return ret; 825 } 826 827 bool dc_stream_program_csc_matrix(struct dc *dc, struct dc_stream_state *stream) 828 { 829 int i; 830 bool ret = false; 831 struct pipe_ctx *pipes; 832 833 dc_exit_ips_for_hw_access(dc); 834 835 for (i = 0; i < MAX_PIPES; i++) { 836 if (dc->current_state->res_ctx.pipe_ctx[i].stream 837 == stream) { 838 839 pipes = &dc->current_state->res_ctx.pipe_ctx[i]; 840 dc->hwss.program_output_csc(dc, 841 pipes, 842 stream->output_color_space, 843 stream->csc_color_matrix.matrix, 844 pipes->stream_res.opp->inst); 845 ret = true; 846 } 847 } 848 849 return ret; 850 } 851 852 void dc_stream_set_static_screen_params(struct dc *dc, 853 struct dc_stream_state **streams, 854 int num_streams, 855 const struct dc_static_screen_params *params) 856 { 857 int i, j; 858 struct pipe_ctx *pipes_affected[MAX_PIPES]; 859 int num_pipes_affected = 0; 860 861 dc_exit_ips_for_hw_access(dc); 862 863 for (i = 0; i < num_streams; i++) { 864 struct dc_stream_state *stream = streams[i]; 865 866 for (j = 0; j < MAX_PIPES; j++) { 867 if (dc->current_state->res_ctx.pipe_ctx[j].stream 868 == stream) { 869 pipes_affected[num_pipes_affected++] = 870 &dc->current_state->res_ctx.pipe_ctx[j]; 871 } 872 } 873 } 874 875 dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, params); 876 } 877 878 static void dc_destruct(struct dc *dc) 879 { 880 // reset link encoder assignment table on destruct 881 if (dc->res_pool && dc->res_pool->funcs->link_encs_assign && 882 !dc->config.unify_link_enc_assignment) 883 link_enc_cfg_init(dc, dc->current_state); 884 885 if (dc->current_state) { 886 dc_state_release(dc->current_state); 887 dc->current_state = NULL; 888 } 889 890 destroy_links(dc); 891 892 destroy_link_encoders(dc); 893 894 if (dc->clk_mgr) { 895 dc_destroy_clk_mgr(dc->clk_mgr); 896 dc->clk_mgr = NULL; 897 } 898 899 dc_destroy_resource_pool(dc); 900 #ifdef CONFIG_DRM_AMD_DC_FP 901 dc_destroy_soc_and_ip_translator(&dc->soc_and_ip_translator); 902 #endif 903 if (dc->link_srv) 904 link_destroy_link_service(&dc->link_srv); 905 906 if (dc->ctx) { 907 if (dc->ctx->gpio_service) 908 dal_gpio_service_destroy(&dc->ctx->gpio_service); 909 910 if (dc->ctx->created_bios) 911 dal_bios_parser_destroy(&dc->ctx->dc_bios); 912 kfree(dc->ctx->logger); 913 dc_perf_trace_destroy(&dc->ctx->perf_trace); 914 915 kfree(dc->ctx); 916 dc->ctx = NULL; 917 } 918 919 kfree(dc->bw_vbios); 920 dc->bw_vbios = NULL; 921 922 kfree(dc->bw_dceip); 923 dc->bw_dceip = NULL; 924 925 kfree(dc->dcn_soc); 926 dc->dcn_soc = NULL; 927 928 kfree(dc->dcn_ip); 929 dc->dcn_ip = NULL; 930 931 kfree(dc->vm_helper); 932 dc->vm_helper = NULL; 933 934 } 935 936 static bool dc_construct_ctx(struct dc *dc, 937 const struct dc_init_data *init_params) 938 { 939 struct dc_context *dc_ctx; 940 941 dc_ctx = kzalloc_obj(*dc_ctx); 942 if (!dc_ctx) 943 return false; 944 945 dc_stream_init_rmcm_3dlut(dc); 946 947 dc_ctx->cgs_device = init_params->cgs_device; 948 dc_ctx->driver_context = init_params->driver; 949 dc_ctx->dc = dc; 950 dc_ctx->asic_id = init_params->asic_id; 951 dc_ctx->dc_sink_id_count = 0; 952 dc_ctx->dc_stream_id_count = 0; 953 dc_ctx->dce_environment = init_params->dce_environment; 954 dc_ctx->dcn_reg_offsets = init_params->dcn_reg_offsets; 955 dc_ctx->nbio_reg_offsets = init_params->nbio_reg_offsets; 956 dc_ctx->clk_reg_offsets = init_params->clk_reg_offsets; 957 958 /* Create logger */ 959 dc_ctx->logger = kmalloc_obj(*dc_ctx->logger); 960 961 if (!dc_ctx->logger) { 962 kfree(dc_ctx); 963 return false; 964 } 965 966 dc_ctx->logger->dev = adev_to_drm(init_params->driver); 967 dc->dml.logger = dc_ctx->logger; 968 969 dc_ctx->dce_version = resource_parse_asic_id(init_params->asic_id); 970 971 dc_ctx->perf_trace = dc_perf_trace_create(); 972 if (!dc_ctx->perf_trace) { 973 kfree(dc_ctx); 974 ASSERT_CRITICAL(false); 975 return false; 976 } 977 978 dc->ctx = dc_ctx; 979 980 dc->link_srv = link_create_link_service(); 981 if (!dc->link_srv) 982 return false; 983 984 return true; 985 } 986 987 static bool dc_construct(struct dc *dc, 988 const struct dc_init_data *init_params) 989 { 990 struct dc_context *dc_ctx; 991 struct bw_calcs_dceip *dc_dceip; 992 struct bw_calcs_vbios *dc_vbios; 993 struct dcn_soc_bounding_box *dcn_soc; 994 struct dcn_ip_params *dcn_ip; 995 996 dc->config = init_params->flags; 997 998 // Allocate memory for the vm_helper 999 dc->vm_helper = kzalloc_obj(struct vm_helper); 1000 if (!dc->vm_helper) { 1001 dm_error("%s: failed to create dc->vm_helper\n", __func__); 1002 goto fail; 1003 } 1004 1005 memcpy(&dc->bb_overrides, &init_params->bb_overrides, sizeof(dc->bb_overrides)); 1006 1007 dc_dceip = kzalloc_obj(*dc_dceip); 1008 if (!dc_dceip) { 1009 dm_error("%s: failed to create dceip\n", __func__); 1010 goto fail; 1011 } 1012 1013 dc->bw_dceip = dc_dceip; 1014 1015 dc_vbios = kzalloc_obj(*dc_vbios); 1016 if (!dc_vbios) { 1017 dm_error("%s: failed to create vbios\n", __func__); 1018 goto fail; 1019 } 1020 1021 dc->bw_vbios = dc_vbios; 1022 dcn_soc = kzalloc_obj(*dcn_soc); 1023 if (!dcn_soc) { 1024 dm_error("%s: failed to create dcn_soc\n", __func__); 1025 goto fail; 1026 } 1027 1028 dc->dcn_soc = dcn_soc; 1029 1030 dcn_ip = kzalloc_obj(*dcn_ip); 1031 if (!dcn_ip) { 1032 dm_error("%s: failed to create dcn_ip\n", __func__); 1033 goto fail; 1034 } 1035 1036 dc->dcn_ip = dcn_ip; 1037 1038 if (init_params->bb_from_dmub) 1039 dc->dml2_options.bb_from_dmub = init_params->bb_from_dmub; 1040 else 1041 dc->dml2_options.bb_from_dmub = NULL; 1042 1043 if (!dc_construct_ctx(dc, init_params)) { 1044 dm_error("%s: failed to create ctx\n", __func__); 1045 goto fail; 1046 } 1047 1048 dc_ctx = dc->ctx; 1049 1050 /* Resource should construct all asic specific resources. 1051 * This should be the only place where we need to parse the asic id 1052 */ 1053 if (init_params->vbios_override) 1054 dc_ctx->dc_bios = init_params->vbios_override; 1055 else { 1056 /* Create BIOS parser */ 1057 struct bp_init_data bp_init_data; 1058 1059 bp_init_data.ctx = dc_ctx; 1060 bp_init_data.bios = init_params->asic_id.atombios_base_address; 1061 1062 dc_ctx->dc_bios = dal_bios_parser_create( 1063 &bp_init_data, dc_ctx->dce_version); 1064 1065 if (!dc_ctx->dc_bios) { 1066 ASSERT_CRITICAL(false); 1067 goto fail; 1068 } 1069 1070 dc_ctx->created_bios = true; 1071 } 1072 1073 dc->vendor_signature = init_params->vendor_signature; 1074 1075 /* Create GPIO service */ 1076 dc_ctx->gpio_service = dal_gpio_service_create( 1077 dc_ctx->dce_version, 1078 dc_ctx->dce_environment, 1079 dc_ctx); 1080 1081 if (!dc_ctx->gpio_service) { 1082 ASSERT_CRITICAL(false); 1083 goto fail; 1084 } 1085 1086 dc->res_pool = dc_create_resource_pool(dc, init_params, dc_ctx->dce_version); 1087 if (!dc->res_pool) 1088 goto fail; 1089 1090 /* set i2c speed if not done by the respective dcnxxx__resource.c */ 1091 if (dc->caps.i2c_speed_in_khz_hdcp == 0) 1092 dc->caps.i2c_speed_in_khz_hdcp = dc->caps.i2c_speed_in_khz; 1093 if (dc->check_config.max_optimizable_video_width == 0) 1094 dc->check_config.max_optimizable_video_width = 5120; 1095 dc->clk_mgr = dc_clk_mgr_create(dc->ctx, dc->res_pool->pp_smu, dc->res_pool->dccg); 1096 if (!dc->clk_mgr) 1097 goto fail; 1098 #ifdef CONFIG_DRM_AMD_DC_FP 1099 dc->clk_mgr->force_smu_not_present = init_params->force_smu_not_present; 1100 1101 if (dc->res_pool->funcs->update_bw_bounding_box) 1102 dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params); 1103 dc->soc_and_ip_translator = dc_create_soc_and_ip_translator(dc_ctx->dce_version); 1104 if (!dc->soc_and_ip_translator) 1105 goto fail; 1106 #endif 1107 1108 if (!create_links(dc, init_params->num_virtual_links)) 1109 goto fail; 1110 1111 /* Create additional DIG link encoder objects if fewer than the platform 1112 * supports were created during link construction. 1113 */ 1114 if (!create_link_encoders(dc)) 1115 goto fail; 1116 1117 /* Creation of current_state must occur after dc->dml 1118 * is initialized in dc_create_resource_pool because 1119 * on creation it copies the contents of dc->dml 1120 */ 1121 dc->current_state = dc_state_create(dc, NULL); 1122 1123 if (!dc->current_state) { 1124 dm_error("%s: failed to create validate ctx\n", __func__); 1125 goto fail; 1126 } 1127 1128 return true; 1129 1130 fail: 1131 return false; 1132 } 1133 1134 static void disable_all_writeback_pipes_for_stream( 1135 const struct dc *dc, 1136 struct dc_stream_state *stream, 1137 struct dc_state *context) 1138 { 1139 (void)dc; 1140 (void)context; 1141 unsigned int i; 1142 1143 for (i = 0; i < stream->num_wb_info; i++) 1144 stream->writeback_info[i].wb_enabled = false; 1145 } 1146 1147 static void apply_ctx_interdependent_lock(struct dc *dc, 1148 struct dc_state *context, 1149 struct dc_stream_state *stream, 1150 bool lock) 1151 { 1152 (void)dc; 1153 (void)context; 1154 unsigned int i; 1155 1156 /* Checks if interdependent update function pointer is NULL or not, takes care of DCE110 case */ 1157 if (dc->hwss.interdependent_update_lock) 1158 dc->hwss.interdependent_update_lock(dc, context, lock); 1159 else { 1160 for (i = 0; i < dc->res_pool->pipe_count; i++) { 1161 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 1162 struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; 1163 1164 // Copied conditions that were previously in dce110_apply_ctx_for_surface 1165 if (stream == pipe_ctx->stream) { 1166 if (resource_is_pipe_type(pipe_ctx, OPP_HEAD) && 1167 (pipe_ctx->plane_state || old_pipe_ctx->plane_state)) 1168 dc->hwss.pipe_control_lock(dc, pipe_ctx, lock); 1169 } 1170 } 1171 } 1172 } 1173 1174 static void dc_update_visual_confirm_color(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx) 1175 { 1176 if (dc->debug.visual_confirm & VISUAL_CONFIRM_EXPLICIT) { 1177 memcpy(&pipe_ctx->visual_confirm_color, &pipe_ctx->plane_state->visual_confirm_color, 1178 sizeof(pipe_ctx->visual_confirm_color)); 1179 return; 1180 } 1181 1182 if (dc->ctx->dce_version >= DCN_VERSION_1_0) { 1183 memset(&pipe_ctx->visual_confirm_color, 0, sizeof(struct tg_color)); 1184 1185 if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR) 1186 get_hdr_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); 1187 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) 1188 get_surface_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); 1189 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SWIZZLE) 1190 get_surface_tile_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); 1191 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_HW_CURSOR) 1192 get_cursor_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); 1193 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_DCC) 1194 get_dcc_visual_confirm_color(dc, pipe_ctx, &(pipe_ctx->visual_confirm_color)); 1195 else { 1196 if (dc->ctx->dce_version < DCN_VERSION_2_0) 1197 color_space_to_black_color( 1198 dc, pipe_ctx->stream->output_color_space, &(pipe_ctx->visual_confirm_color)); 1199 } 1200 if (dc->ctx->dce_version >= DCN_VERSION_2_0) { 1201 if (dc->debug.visual_confirm == VISUAL_CONFIRM_MPCTREE) 1202 get_mpctree_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); 1203 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SUBVP) 1204 get_subvp_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); 1205 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_MCLK_SWITCH) 1206 get_mclk_switch_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); 1207 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_FAMS2) 1208 get_fams2_visual_confirm_color(dc, context, pipe_ctx, &(pipe_ctx->visual_confirm_color)); 1209 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_VABC) 1210 get_vabc_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); 1211 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_BOOSTED_REFRESH_RATE) 1212 get_refresh_rate_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); 1213 } 1214 } 1215 } 1216 1217 void dc_get_visual_confirm_for_stream( 1218 struct dc *dc, 1219 struct dc_stream_state *stream_state, 1220 struct tg_color *color) 1221 { 1222 struct dc_stream_status *stream_status = dc_stream_get_status(stream_state); 1223 struct pipe_ctx *pipe_ctx; 1224 int i; 1225 struct dc_plane_state *plane_state = NULL; 1226 1227 if (!stream_status) 1228 return; 1229 1230 switch (dc->debug.visual_confirm) { 1231 case VISUAL_CONFIRM_DISABLE: 1232 return; 1233 case VISUAL_CONFIRM_PSR: 1234 case VISUAL_CONFIRM_FAMS: 1235 pipe_ctx = dc_stream_get_pipe_ctx(stream_state); 1236 if (!pipe_ctx) 1237 return; 1238 dc_dmub_srv_get_visual_confirm_color_cmd(dc, pipe_ctx); 1239 memcpy(color, &dc->ctx->dmub_srv->dmub->visual_confirm_color, sizeof(struct tg_color)); 1240 return; 1241 1242 default: 1243 /* find plane with highest layer_index */ 1244 for (i = 0; i < stream_status->plane_count; i++) { 1245 if (stream_status->plane_states[i]->visible) 1246 plane_state = stream_status->plane_states[i]; 1247 } 1248 if (!plane_state) 1249 return; 1250 /* find pipe that contains plane with highest layer index */ 1251 for (i = 0; i < MAX_PIPES; i++) { 1252 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 1253 1254 if (pipe->plane_state == plane_state) { 1255 memcpy(color, &pipe->visual_confirm_color, sizeof(struct tg_color)); 1256 return; 1257 } 1258 } 1259 } 1260 } 1261 1262 /** 1263 * dc_stream_adjust_vmin_vmax - look up pipe context & update parts of DRR 1264 * @dc: dc reference 1265 * @stream: Initial dc stream state 1266 * @adjust: Updated parameters for vertical_total_min and vertical_total_max 1267 * 1268 * Looks up the pipe context of dc_stream_state and updates the 1269 * vertical_total_min and vertical_total_max of the DRR, Dynamic Refresh 1270 * Rate, which is a power-saving feature that targets reducing panel 1271 * refresh rate while the screen is static 1272 * 1273 * Return: %true if the pipe context is found and adjusted; 1274 * %false if the pipe context is not found. 1275 */ 1276 bool dc_stream_adjust_vmin_vmax(struct dc *dc, 1277 struct dc_stream_state *stream, 1278 struct dc_crtc_timing_adjust *adjust) 1279 { 1280 int i; 1281 1282 /* 1283 * Don't adjust DRR while there's bandwidth optimizations pending to 1284 * avoid conflicting with firmware updates. 1285 */ 1286 if (dc->ctx->dce_version > DCE_VERSION_MAX) { 1287 if (dc->optimized_required && 1288 (stream->adjust.v_total_max != adjust->v_total_max || 1289 stream->adjust.v_total_min != adjust->v_total_min)) { 1290 stream->adjust.timing_adjust_pending = true; 1291 return false; 1292 } 1293 } 1294 1295 dc_exit_ips_for_hw_access(dc); 1296 1297 stream->adjust.v_total_max = adjust->v_total_max; 1298 stream->adjust.v_total_mid = adjust->v_total_mid; 1299 stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num; 1300 stream->adjust.v_total_min = adjust->v_total_min; 1301 stream->adjust.allow_otg_v_count_halt = adjust->allow_otg_v_count_halt; 1302 1303 if (dc->caps.max_v_total != 0 && 1304 (adjust->v_total_max > dc->caps.max_v_total || adjust->v_total_min > dc->caps.max_v_total)) { 1305 stream->adjust.timing_adjust_pending = false; 1306 if (adjust->allow_otg_v_count_halt) 1307 return set_long_vtotal(dc, stream, adjust); 1308 else 1309 return false; 1310 } 1311 1312 for (i = 0; i < MAX_PIPES; i++) { 1313 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 1314 1315 if (pipe->stream == stream && pipe->stream_res.tg) { 1316 dc->hwss.set_drr(&pipe, 1317 1, 1318 *adjust); 1319 stream->adjust.timing_adjust_pending = false; 1320 1321 if (dc->debug.visual_confirm == VISUAL_CONFIRM_BOOSTED_REFRESH_RATE) { 1322 if (pipe->stream && pipe->plane_state) { 1323 dc_update_visual_confirm_color(dc, dc->current_state, pipe); 1324 dc->hwss.update_visual_confirm_color(dc, pipe, pipe->plane_res.hubp->mpcc_id); 1325 1326 } 1327 } 1328 1329 if (dc->hwss.notify_cursor_offload_drr_update) 1330 dc->hwss.notify_cursor_offload_drr_update(dc, dc->current_state, stream); 1331 1332 return true; 1333 } 1334 } 1335 1336 return false; 1337 } 1338 1339 static void disable_dangling_plane(struct dc *dc, struct dc_state *context) 1340 { 1341 unsigned int i, j; 1342 struct dc_state *dangling_context = dc_state_create_current_copy(dc); 1343 struct dc_state *current_ctx; 1344 struct pipe_ctx *pipe; 1345 struct timing_generator *tg; 1346 1347 if (dangling_context == NULL) 1348 return; 1349 1350 for (i = 0; i < dc->res_pool->pipe_count; i++) { 1351 struct dc_stream_state *old_stream = 1352 dc->current_state->res_ctx.pipe_ctx[i].stream; 1353 bool should_disable = true; 1354 bool pipe_split_change = false; 1355 1356 if ((context->res_ctx.pipe_ctx[i].top_pipe) && 1357 (dc->current_state->res_ctx.pipe_ctx[i].top_pipe)) 1358 pipe_split_change = context->res_ctx.pipe_ctx[i].top_pipe->pipe_idx != 1359 dc->current_state->res_ctx.pipe_ctx[i].top_pipe->pipe_idx; 1360 else 1361 pipe_split_change = context->res_ctx.pipe_ctx[i].top_pipe != 1362 dc->current_state->res_ctx.pipe_ctx[i].top_pipe; 1363 1364 for (j = 0; j < context->stream_count; j++) { 1365 if (old_stream == context->streams[j]) { 1366 should_disable = false; 1367 break; 1368 } 1369 } 1370 if (!should_disable && pipe_split_change && 1371 dc->current_state->stream_count != context->stream_count) 1372 should_disable = true; 1373 1374 if (old_stream && !dc->current_state->res_ctx.pipe_ctx[i].top_pipe && 1375 !dc->current_state->res_ctx.pipe_ctx[i].prev_odm_pipe) { 1376 struct pipe_ctx *old_pipe, *new_pipe; 1377 1378 old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 1379 new_pipe = &context->res_ctx.pipe_ctx[i]; 1380 1381 if (old_pipe->plane_state && !new_pipe->plane_state) 1382 should_disable = true; 1383 } 1384 1385 if (should_disable && old_stream) { 1386 bool is_phantom = dc_state_get_stream_subvp_type(dc->current_state, old_stream) == SUBVP_PHANTOM; 1387 pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 1388 tg = pipe->stream_res.tg; 1389 /* When disabling plane for a phantom pipe, we must turn on the 1390 * phantom OTG so the disable programming gets the double buffer 1391 * update. Otherwise the pipe will be left in a partially disabled 1392 * state that can result in underflow or hang when enabling it 1393 * again for different use. 1394 */ 1395 if (is_phantom) { 1396 if (tg->funcs->enable_crtc) { 1397 if (dc->hwseq->funcs.blank_pixel_data) 1398 dc->hwseq->funcs.blank_pixel_data(dc, pipe, true); 1399 tg->funcs->enable_crtc(tg); 1400 } 1401 } 1402 1403 if (is_phantom) 1404 dc_state_rem_all_phantom_planes_for_stream(dc, old_stream, dangling_context, true); 1405 else 1406 dc_state_rem_all_planes_for_stream(dc, old_stream, dangling_context); 1407 disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context); 1408 1409 if (pipe->stream && pipe->plane_state) { 1410 if (!dc->debug.using_dml2) 1411 set_p_state_switch_method(dc, context, pipe); 1412 dc_update_visual_confirm_color(dc, context, pipe); 1413 } 1414 1415 if (dc->hwss.apply_ctx_for_surface) { 1416 apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, true); 1417 dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context); 1418 apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, false); 1419 dc->hwss.post_unlock_program_front_end(dc, dangling_context); 1420 } 1421 1422 if (dc->res_pool->funcs->prepare_mcache_programming) 1423 dc->res_pool->funcs->prepare_mcache_programming(dc, dangling_context); 1424 if (dc->hwss.program_front_end_for_ctx) { 1425 dc->hwss.interdependent_update_lock(dc, dc->current_state, true); 1426 dc->hwss.program_front_end_for_ctx(dc, dangling_context); 1427 dc->hwss.interdependent_update_lock(dc, dc->current_state, false); 1428 dc->hwss.post_unlock_program_front_end(dc, dangling_context); 1429 } 1430 /* We need to put the phantom OTG back into it's default (disabled) state or we 1431 * can get corruption when transition from one SubVP config to a different one. 1432 * The OTG is set to disable on falling edge of VUPDATE so the plane disable 1433 * will still get it's double buffer update. 1434 */ 1435 if (is_phantom) { 1436 if (tg->funcs->disable_phantom_crtc) 1437 tg->funcs->disable_phantom_crtc(tg); 1438 } 1439 } 1440 } 1441 1442 current_ctx = dc->current_state; 1443 dc->current_state = dangling_context; 1444 dc_state_release(current_ctx); 1445 } 1446 1447 static void disable_vbios_mode_if_required( 1448 struct dc *dc, 1449 struct dc_state *context) 1450 { 1451 unsigned int i, j; 1452 1453 /* check if timing_changed, disable stream*/ 1454 for (i = 0; i < dc->res_pool->pipe_count; i++) { 1455 struct dc_stream_state *stream = NULL; 1456 struct dc_link *link = NULL; 1457 struct pipe_ctx *pipe = NULL; 1458 1459 pipe = &context->res_ctx.pipe_ctx[i]; 1460 stream = pipe->stream; 1461 if (stream == NULL) 1462 continue; 1463 1464 if (stream->apply_seamless_boot_optimization) 1465 continue; 1466 1467 // only looking for first odm pipe 1468 if (pipe->prev_odm_pipe) 1469 continue; 1470 1471 if (stream->link->local_sink && 1472 stream->link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { 1473 link = stream->link; 1474 } 1475 1476 if (link != NULL && link->link_enc->funcs->is_dig_enabled(link->link_enc)) { 1477 unsigned int enc_inst, tg_inst = 0; 1478 unsigned int pix_clk_100hz = 0; 1479 1480 enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc); 1481 if (enc_inst != ENGINE_ID_UNKNOWN) { 1482 for (j = 0; j < dc->res_pool->stream_enc_count; j++) { 1483 if (dc->res_pool->stream_enc[j]->id == enc_inst) { 1484 tg_inst = dc->res_pool->stream_enc[j]->funcs->dig_source_otg( 1485 dc->res_pool->stream_enc[j]); 1486 break; 1487 } 1488 } 1489 1490 dc->res_pool->dp_clock_source->funcs->get_dp_dto_frequency_100hz( 1491 dc->res_pool->dp_clock_source, 1492 tg_inst, &pix_clk_100hz); 1493 1494 if (link->link_status.link_active) { 1495 uint32_t requested_pix_clk_100hz = 1496 pipe->stream_res.pix_clk_params.requested_pix_clk_100hz; 1497 1498 if (pix_clk_100hz != requested_pix_clk_100hz) { 1499 dc->link_srv->set_dpms_off(pipe); 1500 pipe->stream->dpms_off = false; 1501 } 1502 } 1503 } 1504 } 1505 } 1506 } 1507 1508 /* Public functions */ 1509 1510 struct dc *dc_create(const struct dc_init_data *init_params) 1511 { 1512 struct dc *dc = kzalloc_obj(*dc); 1513 unsigned int full_pipe_count; 1514 1515 if (!dc) 1516 return NULL; 1517 1518 if (init_params->dce_environment == DCE_ENV_VIRTUAL_HW) { 1519 dc->caps.linear_pitch_alignment = 64; 1520 if (!dc_construct_ctx(dc, init_params)) 1521 goto destruct_dc; 1522 } else { 1523 if (!dc_construct(dc, init_params)) 1524 goto destruct_dc; 1525 1526 full_pipe_count = dc->res_pool->pipe_count; 1527 if (dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE) 1528 full_pipe_count--; 1529 dc->caps.max_streams = min( 1530 full_pipe_count, 1531 dc->res_pool->stream_enc_count); 1532 1533 dc->caps.max_links = dc->link_count; 1534 dc->caps.max_audios = dc->res_pool->audio_count; 1535 dc->caps.linear_pitch_alignment = 64; 1536 1537 dc->caps.max_dp_protocol_version = DP_VERSION_1_4; 1538 1539 dc->caps.max_otg_num = dc->res_pool->res_cap->num_timing_generator; 1540 1541 if (dc->res_pool->dmcu != NULL) 1542 dc->versions.dmcu_version = dc->res_pool->dmcu->dmcu_version; 1543 } 1544 1545 dc->dcn_reg_offsets = init_params->dcn_reg_offsets; 1546 dc->nbio_reg_offsets = init_params->nbio_reg_offsets; 1547 dc->clk_reg_offsets = init_params->clk_reg_offsets; 1548 1549 /* Populate versioning information */ 1550 dc->versions.dc_ver = DC_VER; 1551 1552 dc->build_id = DC_BUILD_ID; 1553 1554 DC_LOG_DC("Display Core initialized\n"); 1555 1556 return dc; 1557 1558 destruct_dc: 1559 dc_destruct(dc); 1560 kfree(dc); 1561 return NULL; 1562 } 1563 1564 static void detect_edp_presence(struct dc *dc) 1565 { 1566 struct dc_link *edp_links[MAX_NUM_EDP]; 1567 struct dc_link *edp_link = NULL; 1568 enum dc_connection_type type; 1569 unsigned int i, edp_num; 1570 1571 dc_get_edp_links(dc, edp_links, &edp_num); 1572 if (!edp_num) 1573 return; 1574 1575 for (i = 0; i < edp_num; i++) { 1576 edp_link = edp_links[i]; 1577 if (dc->config.edp_not_connected) { 1578 edp_link->edp_sink_present = false; 1579 } else { 1580 dc_link_detect_connection_type(edp_link, &type); 1581 edp_link->edp_sink_present = (type != dc_connection_none); 1582 } 1583 } 1584 } 1585 1586 void dc_hardware_init(struct dc *dc) 1587 { 1588 1589 detect_edp_presence(dc); 1590 if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW) 1591 dc->hwss.init_hw(dc); 1592 dc_dmub_srv_notify_fw_dc_power_state(dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D0); 1593 } 1594 1595 void dc_init_callbacks(struct dc *dc, 1596 const struct dc_callback_init *init_params) 1597 { 1598 dc->ctx->cp_psp = init_params->cp_psp; 1599 } 1600 1601 void dc_deinit_callbacks(struct dc *dc) 1602 { 1603 memset(&dc->ctx->cp_psp, 0, sizeof(dc->ctx->cp_psp)); 1604 } 1605 1606 void dc_destroy(struct dc **dc) 1607 { 1608 dc_destruct(*dc); 1609 kfree(*dc); 1610 *dc = NULL; 1611 } 1612 1613 static void enable_timing_multisync( 1614 struct dc *dc, 1615 struct dc_state *ctx) 1616 { 1617 int i, multisync_count = 0; 1618 int pipe_count = dc->res_pool->pipe_count; 1619 struct pipe_ctx *multisync_pipes[MAX_PIPES] = { NULL }; 1620 1621 for (i = 0; i < pipe_count; i++) { 1622 if (!ctx->res_ctx.pipe_ctx[i].stream || 1623 !ctx->res_ctx.pipe_ctx[i].stream->triggered_crtc_reset.enabled) 1624 continue; 1625 if (ctx->res_ctx.pipe_ctx[i].stream == ctx->res_ctx.pipe_ctx[i].stream->triggered_crtc_reset.event_source) 1626 continue; 1627 multisync_pipes[multisync_count] = &ctx->res_ctx.pipe_ctx[i]; 1628 multisync_count++; 1629 } 1630 1631 if (multisync_count > 0) { 1632 dc->hwss.enable_per_frame_crtc_position_reset( 1633 dc, multisync_count, multisync_pipes); 1634 } 1635 } 1636 1637 static void program_timing_sync( 1638 struct dc *dc, 1639 struct dc_state *ctx) 1640 { 1641 int i, j, k; 1642 int group_index = 0; 1643 int num_group = 0; 1644 int pipe_count = dc->res_pool->pipe_count; 1645 struct pipe_ctx *unsynced_pipes[MAX_PIPES] = { NULL }; 1646 1647 for (i = 0; i < pipe_count; i++) { 1648 if (!ctx->res_ctx.pipe_ctx[i].stream 1649 || ctx->res_ctx.pipe_ctx[i].top_pipe 1650 || ctx->res_ctx.pipe_ctx[i].prev_odm_pipe) 1651 continue; 1652 1653 unsynced_pipes[i] = &ctx->res_ctx.pipe_ctx[i]; 1654 } 1655 1656 for (i = 0; i < pipe_count; i++) { 1657 int group_size = 1; 1658 enum timing_synchronization_type sync_type = NOT_SYNCHRONIZABLE; 1659 struct pipe_ctx *pipe_set[MAX_PIPES]; 1660 1661 if (!unsynced_pipes[i]) 1662 continue; 1663 1664 pipe_set[0] = unsynced_pipes[i]; 1665 unsynced_pipes[i] = NULL; 1666 1667 /* Add tg to the set, search rest of the tg's for ones with 1668 * same timing, add all tgs with same timing to the group 1669 */ 1670 for (j = i + 1; j < pipe_count; j++) { 1671 if (!unsynced_pipes[j]) 1672 continue; 1673 if (sync_type != TIMING_SYNCHRONIZABLE && 1674 dc->hwss.enable_vblanks_synchronization && 1675 unsynced_pipes[j]->stream_res.tg->funcs->align_vblanks && 1676 resource_are_vblanks_synchronizable( 1677 unsynced_pipes[j]->stream, 1678 pipe_set[0]->stream)) { 1679 sync_type = VBLANK_SYNCHRONIZABLE; 1680 pipe_set[group_size] = unsynced_pipes[j]; 1681 unsynced_pipes[j] = NULL; 1682 group_size++; 1683 } else 1684 if (sync_type != VBLANK_SYNCHRONIZABLE && 1685 resource_are_streams_timing_synchronizable( 1686 unsynced_pipes[j]->stream, 1687 pipe_set[0]->stream)) { 1688 sync_type = TIMING_SYNCHRONIZABLE; 1689 pipe_set[group_size] = unsynced_pipes[j]; 1690 unsynced_pipes[j] = NULL; 1691 group_size++; 1692 } 1693 } 1694 1695 /* set first unblanked pipe as master */ 1696 for (j = 0; j < group_size; j++) { 1697 bool is_blanked; 1698 1699 if (pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked) 1700 is_blanked = 1701 pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked(pipe_set[j]->stream_res.opp); 1702 else 1703 is_blanked = 1704 pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg); 1705 if (!is_blanked) { 1706 if (j == 0) 1707 break; 1708 1709 swap(pipe_set[0], pipe_set[j]); 1710 break; 1711 } 1712 } 1713 1714 for (k = 0; k < group_size; k++) { 1715 struct dc_stream_status *status = dc_state_get_stream_status(ctx, pipe_set[k]->stream); 1716 1717 if (!status) 1718 continue; 1719 1720 status->timing_sync_info.group_id = num_group; 1721 status->timing_sync_info.group_size = group_size; 1722 if (k == 0) 1723 status->timing_sync_info.master = true; 1724 else 1725 status->timing_sync_info.master = false; 1726 1727 } 1728 1729 /* remove any other unblanked pipes as they have already been synced */ 1730 if (dc->config.use_pipe_ctx_sync_logic) { 1731 /* check pipe's syncd to decide which pipe to be removed */ 1732 for (j = 1; j < group_size; j++) { 1733 if (pipe_set[j]->pipe_idx_syncd == pipe_set[0]->pipe_idx_syncd) { 1734 group_size--; 1735 pipe_set[j] = pipe_set[group_size]; 1736 j--; 1737 } else 1738 /* link slave pipe's syncd with master pipe */ 1739 pipe_set[j]->pipe_idx_syncd = pipe_set[0]->pipe_idx_syncd; 1740 } 1741 } else { 1742 /* remove any other pipes by checking valid plane */ 1743 for (j = j + 1; j < group_size; j++) { 1744 bool is_blanked; 1745 1746 if (pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked) 1747 is_blanked = 1748 pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked(pipe_set[j]->stream_res.opp); 1749 else 1750 is_blanked = 1751 pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg); 1752 if (!is_blanked) { 1753 group_size--; 1754 pipe_set[j] = pipe_set[group_size]; 1755 j--; 1756 } 1757 } 1758 } 1759 1760 if (group_size > 1) { 1761 if (sync_type == TIMING_SYNCHRONIZABLE) { 1762 dc->hwss.enable_timing_synchronization( 1763 dc, ctx, group_index, group_size, pipe_set); 1764 } else 1765 if (sync_type == VBLANK_SYNCHRONIZABLE) { 1766 dc->hwss.enable_vblanks_synchronization( 1767 dc, group_index, group_size, pipe_set); 1768 } 1769 group_index++; 1770 } 1771 num_group++; 1772 } 1773 } 1774 1775 static bool streams_changed(struct dc *dc, 1776 struct dc_stream_state *streams[], 1777 uint8_t stream_count) 1778 { 1779 uint8_t i; 1780 1781 if (stream_count != dc->current_state->stream_count) 1782 return true; 1783 1784 for (i = 0; i < dc->current_state->stream_count; i++) { 1785 if (dc->current_state->streams[i] != streams[i]) 1786 return true; 1787 if (!streams[i]->link->link_state_valid) 1788 return true; 1789 } 1790 1791 return false; 1792 } 1793 1794 bool dc_validate_boot_timing(const struct dc *dc, 1795 const struct dc_sink *sink, 1796 struct dc_crtc_timing *crtc_timing) 1797 { 1798 struct timing_generator *tg; 1799 struct stream_encoder *se = NULL; 1800 1801 struct dc_crtc_timing hw_crtc_timing = {0}; 1802 1803 struct dc_link *link = sink->link; 1804 unsigned int i, enc_inst; 1805 unsigned int tg_inst = 0; 1806 1807 /* Support seamless boot on EDP displays only */ 1808 if (sink->sink_signal != SIGNAL_TYPE_EDP) { 1809 return false; 1810 } 1811 1812 if (dc->debug.force_odm_combine) { 1813 DC_LOG_DEBUG("boot timing validation failed due to force_odm_combine\n"); 1814 return false; 1815 } 1816 1817 /* Check for enabled DIG to identify enabled display */ 1818 if (!link->link_enc->funcs->is_dig_enabled(link->link_enc)) { 1819 DC_LOG_DEBUG("boot timing validation failed due to disabled DIG\n"); 1820 return false; 1821 } 1822 1823 enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc); 1824 1825 if (enc_inst == ENGINE_ID_UNKNOWN) { 1826 DC_LOG_DEBUG("boot timing validation failed due to unknown DIG engine ID\n"); 1827 return false; 1828 } 1829 1830 for (i = 0; i < dc->res_pool->stream_enc_count; i++) { 1831 if (dc->res_pool->stream_enc[i]->id == enc_inst) { 1832 1833 se = dc->res_pool->stream_enc[i]; 1834 1835 tg_inst = dc->res_pool->stream_enc[i]->funcs->dig_source_otg( 1836 dc->res_pool->stream_enc[i]); 1837 break; 1838 } 1839 } 1840 1841 // tg_inst not found 1842 if (i == dc->res_pool->stream_enc_count) { 1843 DC_LOG_DEBUG("boot timing validation failed due to timing generator instance not found\n"); 1844 return false; 1845 } 1846 1847 if (tg_inst >= dc->res_pool->timing_generator_count) { 1848 DC_LOG_DEBUG("boot timing validation failed due to invalid timing generator count\n"); 1849 return false; 1850 } 1851 1852 if (tg_inst != link->link_enc->preferred_engine) { 1853 DC_LOG_DEBUG("boot timing validation failed due to non-preferred timing generator\n"); 1854 return false; 1855 } 1856 1857 tg = dc->res_pool->timing_generators[tg_inst]; 1858 1859 if (!tg->funcs->get_hw_timing) { 1860 DC_LOG_DEBUG("boot timing validation failed due to missing get_hw_timing callback\n"); 1861 return false; 1862 } 1863 1864 if (!tg->funcs->get_hw_timing(tg, &hw_crtc_timing)) { 1865 DC_LOG_DEBUG("boot timing validation failed due to failed get_hw_timing return\n"); 1866 return false; 1867 } 1868 1869 if (crtc_timing->h_total != hw_crtc_timing.h_total) { 1870 DC_LOG_DEBUG("boot timing validation failed due to h_total mismatch\n"); 1871 return false; 1872 } 1873 1874 if (crtc_timing->h_border_left != hw_crtc_timing.h_border_left) { 1875 DC_LOG_DEBUG("boot timing validation failed due to h_border_left mismatch\n"); 1876 return false; 1877 } 1878 1879 if (crtc_timing->h_addressable != hw_crtc_timing.h_addressable) { 1880 DC_LOG_DEBUG("boot timing validation failed due to h_addressable mismatch\n"); 1881 return false; 1882 } 1883 1884 if (crtc_timing->h_border_right != hw_crtc_timing.h_border_right) { 1885 DC_LOG_DEBUG("boot timing validation failed due to h_border_right mismatch\n"); 1886 return false; 1887 } 1888 1889 if (crtc_timing->h_front_porch != hw_crtc_timing.h_front_porch) { 1890 DC_LOG_DEBUG("boot timing validation failed due to h_front_porch mismatch\n"); 1891 return false; 1892 } 1893 1894 if (crtc_timing->h_sync_width != hw_crtc_timing.h_sync_width) { 1895 DC_LOG_DEBUG("boot timing validation failed due to h_sync_width mismatch\n"); 1896 return false; 1897 } 1898 1899 if (crtc_timing->v_total != hw_crtc_timing.v_total) { 1900 DC_LOG_DEBUG("boot timing validation failed due to v_total mismatch\n"); 1901 return false; 1902 } 1903 1904 if (crtc_timing->v_border_top != hw_crtc_timing.v_border_top) { 1905 DC_LOG_DEBUG("boot timing validation failed due to v_border_top mismatch\n"); 1906 return false; 1907 } 1908 1909 if (crtc_timing->v_addressable != hw_crtc_timing.v_addressable) { 1910 DC_LOG_DEBUG("boot timing validation failed due to v_addressable mismatch\n"); 1911 return false; 1912 } 1913 1914 if (crtc_timing->v_border_bottom != hw_crtc_timing.v_border_bottom) { 1915 DC_LOG_DEBUG("boot timing validation failed due to v_border_bottom mismatch\n"); 1916 return false; 1917 } 1918 1919 if (crtc_timing->v_front_porch != hw_crtc_timing.v_front_porch) { 1920 DC_LOG_DEBUG("boot timing validation failed due to v_front_porch mismatch\n"); 1921 return false; 1922 } 1923 1924 if (crtc_timing->v_sync_width != hw_crtc_timing.v_sync_width) { 1925 DC_LOG_DEBUG("boot timing validation failed due to v_sync_width mismatch\n"); 1926 return false; 1927 } 1928 1929 if (crtc_timing->flags.DSC) { 1930 struct display_stream_compressor *dsc = NULL; 1931 struct dcn_dsc_state dsc_state = {0}; 1932 1933 /* Find DSC associated with this timing generator */ 1934 if (tg_inst < (unsigned int)dc->res_pool->res_cap->num_dsc) { 1935 dsc = dc->res_pool->dscs[tg_inst]; 1936 } 1937 1938 if (!dsc || !dsc->funcs->dsc_read_state) { 1939 DC_LOG_DEBUG("boot timing validation failed due to no DSC resource or read function\n"); 1940 return false; 1941 } 1942 1943 /* Read current DSC hardware state */ 1944 dsc->funcs->dsc_read_state(dsc, &dsc_state); 1945 1946 /* Check if DSC is actually enabled in hardware */ 1947 if (dsc_state.dsc_clock_en == 0) { 1948 DC_LOG_DEBUG("boot timing validation failed due to DSC not enabled in hardware\n"); 1949 return false; 1950 } 1951 1952 uint32_t num_slices_h = 0; 1953 uint32_t num_slices_v = 0; 1954 1955 if (dsc_state.dsc_slice_width > 0) { 1956 num_slices_h = (crtc_timing->h_addressable + dsc_state.dsc_slice_width - 1) / dsc_state.dsc_slice_width; 1957 } 1958 1959 if (dsc_state.dsc_slice_height > 0) { 1960 num_slices_v = (crtc_timing->v_addressable + dsc_state.dsc_slice_height - 1) / dsc_state.dsc_slice_height; 1961 } 1962 1963 if (crtc_timing->dsc_cfg.num_slices_h != num_slices_h) { 1964 DC_LOG_DEBUG("boot timing validation failed due to num_slices_h mismatch\n"); 1965 return false; 1966 } 1967 1968 if (crtc_timing->dsc_cfg.num_slices_v != num_slices_v) { 1969 DC_LOG_DEBUG("boot timing validation failed due to num_slices_v mismatch\n"); 1970 return false; 1971 } 1972 1973 if (crtc_timing->dsc_cfg.bits_per_pixel != dsc_state.dsc_bits_per_pixel) { 1974 DC_LOG_DEBUG("boot timing validation failed due to bits_per_pixel mismatch\n"); 1975 return false; 1976 } 1977 1978 if (crtc_timing->dsc_cfg.block_pred_enable != dsc_state.dsc_block_pred_enable) { 1979 DC_LOG_DEBUG("boot timing validation failed due to block_pred_enable mismatch\n"); 1980 return false; 1981 } 1982 1983 if (crtc_timing->dsc_cfg.linebuf_depth != dsc_state.dsc_line_buf_depth) { 1984 DC_LOG_DEBUG("boot timing validation failed due to linebuf_depth mismatch\n"); 1985 return false; 1986 } 1987 1988 if (crtc_timing->dsc_cfg.version_minor != dsc_state.dsc_version_minor) { 1989 DC_LOG_DEBUG("boot timing validation failed due to version_minor mismatch\n"); 1990 return false; 1991 } 1992 1993 if (crtc_timing->dsc_cfg.ycbcr422_simple != dsc_state.dsc_simple_422) { 1994 DC_LOG_DEBUG("boot timing validation failed due to pixel encoding mismatch\n"); 1995 return false; 1996 } 1997 1998 // Skip checks for is_frl, is_dp, and rc_buffer_size which are not programmed by vbios 1999 // or not necessary for seamless boot validation. 2000 } 2001 2002 if (dc_is_dp_signal(link->connector_signal)) { 2003 unsigned int pix_clk_100hz = 0; 2004 uint32_t numOdmPipes = 1; 2005 uint32_t id_src[4] = {0}; 2006 2007 dc->res_pool->dp_clock_source->funcs->get_dp_dto_frequency_100hz( 2008 dc->res_pool->dp_clock_source, 2009 tg_inst, &pix_clk_100hz); 2010 2011 if (tg->funcs->get_optc_source) 2012 tg->funcs->get_optc_source(tg, 2013 &numOdmPipes, &id_src[0], &id_src[1]); 2014 2015 if (numOdmPipes == 2) { 2016 pix_clk_100hz *= 2; 2017 } else if (numOdmPipes == 4) { 2018 pix_clk_100hz *= 4; 2019 } else if (se && se->funcs->get_pixels_per_cycle) { 2020 uint32_t pixels_per_cycle = se->funcs->get_pixels_per_cycle(se); 2021 2022 if (pixels_per_cycle != 1 && !dc->debug.enable_dp_dig_pixel_rate_div_policy) { 2023 DC_LOG_DEBUG("boot timing validation failed due to pixels_per_cycle\n"); 2024 return false; 2025 } 2026 2027 pix_clk_100hz *= pixels_per_cycle; 2028 } 2029 2030 // Note: In rare cases, HW pixclk may differ from crtc's pixclk 2031 // slightly due to rounding issues in 10 kHz units. 2032 if (crtc_timing->pix_clk_100hz != pix_clk_100hz) { 2033 DC_LOG_DEBUG("boot timing validation failed due to pix_clk_100hz mismatch\n"); 2034 return false; 2035 } 2036 2037 if (!se || !se->funcs->dp_get_pixel_format) { 2038 DC_LOG_DEBUG("boot timing validation failed due to missing dp_get_pixel_format\n"); 2039 return false; 2040 } 2041 2042 if (!se->funcs->dp_get_pixel_format( 2043 se, 2044 &hw_crtc_timing.pixel_encoding, 2045 &hw_crtc_timing.display_color_depth)) { 2046 DC_LOG_DEBUG("boot timing validation failed due to dp_get_pixel_format failure\n"); 2047 return false; 2048 } 2049 2050 if (hw_crtc_timing.display_color_depth != crtc_timing->display_color_depth) { 2051 DC_LOG_DEBUG("boot timing validation failed due to display_color_depth mismatch\n"); 2052 return false; 2053 } 2054 2055 if (hw_crtc_timing.pixel_encoding != crtc_timing->pixel_encoding) { 2056 DC_LOG_DEBUG("boot timing validation failed due to pixel_encoding mismatch\n"); 2057 return false; 2058 } 2059 } 2060 2061 2062 if (link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED) { 2063 DC_LOG_DEBUG("boot timing validation failed due to VSC SDP colorimetry\n"); 2064 return false; 2065 } 2066 2067 if (link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) { 2068 DC_LOG_DEBUG("boot timing validation failed due to DP 128b/132b\n"); 2069 return false; 2070 } 2071 2072 if (dc->link_srv->edp_is_ilr_optimization_required(link, crtc_timing)) { 2073 DC_LOG_EVENT_LINK_TRAINING("Seamless boot disabled to optimize eDP link rate\n"); 2074 return false; 2075 } 2076 2077 return true; 2078 } 2079 2080 static inline bool should_update_pipe_for_stream( 2081 struct dc_state *context, 2082 struct pipe_ctx *pipe_ctx, 2083 struct dc_stream_state *stream) 2084 { 2085 return (pipe_ctx->stream && pipe_ctx->stream == stream); 2086 } 2087 2088 static inline bool should_update_pipe_for_plane( 2089 struct dc_state *context, 2090 struct pipe_ctx *pipe_ctx, 2091 struct dc_plane_state *plane_state) 2092 { 2093 return (pipe_ctx->plane_state == plane_state); 2094 } 2095 2096 void dc_enable_stereo( 2097 struct dc *dc, 2098 struct dc_state *context, 2099 struct dc_stream_state *streams[], 2100 uint8_t stream_count) 2101 { 2102 int i, j; 2103 struct pipe_ctx *pipe; 2104 2105 dc_exit_ips_for_hw_access(dc); 2106 2107 for (i = 0; i < MAX_PIPES; i++) { 2108 if (context != NULL) { 2109 pipe = &context->res_ctx.pipe_ctx[i]; 2110 } else { 2111 context = dc->current_state; 2112 pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 2113 } 2114 2115 for (j = 0; pipe && j < stream_count; j++) { 2116 if (should_update_pipe_for_stream(context, pipe, streams[j]) && 2117 dc->hwss.setup_stereo) 2118 dc->hwss.setup_stereo(pipe, dc); 2119 } 2120 } 2121 } 2122 2123 void dc_trigger_sync(struct dc *dc, struct dc_state *context) 2124 { 2125 if (context->stream_count > 1 && !dc->debug.disable_timing_sync) { 2126 dc_exit_ips_for_hw_access(dc); 2127 2128 enable_timing_multisync(dc, context); 2129 program_timing_sync(dc, context); 2130 } 2131 } 2132 2133 static uint8_t get_stream_mask(struct dc *dc, struct dc_state *context) 2134 { 2135 unsigned int i; 2136 unsigned int stream_mask = 0; 2137 2138 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2139 if (context->res_ctx.pipe_ctx[i].stream) 2140 stream_mask |= 1 << i; 2141 } 2142 2143 return (uint8_t)stream_mask; 2144 } 2145 2146 void dc_z10_restore(const struct dc *dc) 2147 { 2148 if (dc->hwss.z10_restore) 2149 dc->hwss.z10_restore(dc); 2150 } 2151 2152 void dc_z10_save_init(struct dc *dc) 2153 { 2154 if (dc->hwss.z10_save_init) 2155 dc->hwss.z10_save_init(dc); 2156 } 2157 2158 /* Set a pipe unlock order based on the change in DET allocation and stores it in dc scratch memory 2159 * Prevents over allocation of DET during unlock process 2160 * e.g. 2 pipe config with different streams with a max of 20 DET segments 2161 * Before: After: 2162 * - Pipe0: 10 DET segments - Pipe0: 12 DET segments 2163 * - Pipe1: 10 DET segments - Pipe1: 8 DET segments 2164 * If Pipe0 gets updated first, 22 DET segments will be allocated 2165 */ 2166 static void determine_pipe_unlock_order(struct dc *dc, struct dc_state *context) 2167 { 2168 unsigned int i = 0; 2169 struct pipe_ctx *pipe = NULL; 2170 struct timing_generator *tg = NULL; 2171 2172 if (!dc->config.set_pipe_unlock_order) 2173 return; 2174 2175 memset(dc->scratch.pipes_to_unlock_first, 0, sizeof(dc->scratch.pipes_to_unlock_first)); 2176 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2177 pipe = &context->res_ctx.pipe_ctx[i]; 2178 tg = pipe->stream_res.tg; 2179 2180 if (!resource_is_pipe_type(pipe, OTG_MASTER) || 2181 !tg->funcs->is_tg_enabled(tg) || 2182 dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) { 2183 continue; 2184 } 2185 2186 if (resource_calculate_det_for_stream(context, pipe) < 2187 resource_calculate_det_for_stream(dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i])) { 2188 dc->scratch.pipes_to_unlock_first[i] = true; 2189 } 2190 } 2191 } 2192 2193 /** 2194 * dc_commit_state_no_check - Apply context to the hardware 2195 * 2196 * @dc: DC object with the current status to be updated 2197 * @context: New state that will become the current status at the end of this function 2198 * 2199 * Applies given context to the hardware and copy it into current context. 2200 * It's up to the user to release the src context afterwards. 2201 * 2202 * Return: an enum dc_status result code for the operation 2203 */ 2204 static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *context) 2205 { 2206 struct dc_bios *dcb = dc->ctx->dc_bios; 2207 enum dc_status result = DC_ERROR_UNEXPECTED; 2208 struct pipe_ctx *pipe; 2209 unsigned int i, k, l; 2210 struct dc_stream_state *dc_streams[MAX_STREAMS] = {0}; 2211 struct dc_state *old_state; 2212 bool subvp_prev_use = false; 2213 2214 dc_z10_restore(dc); 2215 dc_allow_idle_optimizations(dc, false); 2216 2217 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2218 struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 2219 2220 /* Check old context for SubVP */ 2221 subvp_prev_use |= (dc_state_get_pipe_subvp_type(dc->current_state, old_pipe) == SUBVP_PHANTOM); 2222 if (subvp_prev_use) 2223 break; 2224 } 2225 2226 for (i = 0; i < context->stream_count; i++) 2227 dc_streams[i] = context->streams[i]; 2228 2229 if (!dcb->funcs->is_accelerated_mode(dcb)) { 2230 disable_vbios_mode_if_required(dc, context); 2231 dc->hwss.enable_accelerated_mode(dc, context); 2232 } else if (get_seamless_boot_stream_count(dc->current_state) > 0) { 2233 /* If the previous Stream still retains the apply seamless boot flag, 2234 * it means the OS has not actually performed a flip yet. 2235 * At this point, if we receive dc_commit_streams again, we should 2236 * once more check whether the actual HW timing matches what the OS 2237 * has provided 2238 */ 2239 disable_vbios_mode_if_required(dc, context); 2240 } 2241 2242 if (dc->hwseq->funcs.wait_for_pipe_update_if_needed) { 2243 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2244 pipe = &context->res_ctx.pipe_ctx[i]; 2245 //Only delay otg master for a given config 2246 if (resource_is_pipe_type(pipe, OTG_MASTER)) { 2247 //dc_commit_state_no_check is always a full update 2248 dc->hwseq->funcs.wait_for_pipe_update_if_needed(dc, pipe, false); 2249 break; 2250 } 2251 } 2252 } 2253 2254 if (context->stream_count > get_seamless_boot_stream_count(context) || 2255 context->stream_count == 0) 2256 dc->hwss.prepare_bandwidth(dc, context); 2257 2258 /* When SubVP is active, all HW programming must be done while 2259 * SubVP lock is acquired 2260 */ 2261 if (dc->hwss.subvp_pipe_control_lock) 2262 dc->hwss.subvp_pipe_control_lock(dc, context, true, true, NULL, subvp_prev_use); 2263 if (dc->hwss.dmub_hw_control_lock) 2264 dc->hwss.dmub_hw_control_lock(dc, context, true); 2265 2266 if (dc->hwss.update_dsc_pg) 2267 dc->hwss.update_dsc_pg(dc, context, false); 2268 2269 disable_dangling_plane(dc, context); 2270 /* re-program planes for existing stream, in case we need to 2271 * free up plane resource for later use 2272 */ 2273 if (dc->hwss.apply_ctx_for_surface) { 2274 for (i = 0; i < context->stream_count; i++) { 2275 if (context->streams[i]->mode_changed) 2276 continue; 2277 apply_ctx_interdependent_lock(dc, context, context->streams[i], true); 2278 dc->hwss.apply_ctx_for_surface( 2279 dc, context->streams[i], 2280 context->stream_status[i].plane_count, 2281 context); /* use new pipe config in new context */ 2282 apply_ctx_interdependent_lock(dc, context, context->streams[i], false); 2283 dc->hwss.post_unlock_program_front_end(dc, context); 2284 } 2285 } 2286 2287 /* Program hardware */ 2288 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2289 pipe = &context->res_ctx.pipe_ctx[i]; 2290 dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); 2291 } 2292 2293 for (i = 0; i < dc->current_state->stream_count; i++) 2294 dc_dmub_srv_control_cursor_offload(dc, dc->current_state, dc->current_state->streams[i], false); 2295 2296 result = dc->hwss.apply_ctx_to_hw(dc, context); 2297 2298 for (i = 0; i < context->stream_count; i++) 2299 dc_dmub_srv_control_cursor_offload(dc, context, context->streams[i], true); 2300 2301 if (result != DC_OK) { 2302 /* Application of dc_state to hardware stopped. */ 2303 dc->current_state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_STEADY; 2304 return result; 2305 } 2306 2307 dc_trigger_sync(dc, context); 2308 2309 /* Full update should unconditionally be triggered when dc_commit_state_no_check is called */ 2310 for (i = 0; i < context->stream_count; i++) { 2311 uint32_t prev_dsc_changed = context->streams[i]->update_flags.bits.dsc_changed; 2312 2313 context->streams[i]->update_flags.raw = 0xFFFFFFFF; 2314 context->streams[i]->update_flags.bits.dsc_changed = prev_dsc_changed; 2315 } 2316 2317 determine_pipe_unlock_order(dc, context); 2318 /* Program all planes within new context*/ 2319 if (dc->res_pool->funcs->prepare_mcache_programming) 2320 dc->res_pool->funcs->prepare_mcache_programming(dc, context); 2321 if (dc->hwss.program_front_end_for_ctx) { 2322 dc->hwss.interdependent_update_lock(dc, context, true); 2323 dc->hwss.program_front_end_for_ctx(dc, context); 2324 2325 if (dc->hwseq->funcs.set_wait_for_update_needed_for_pipe) { 2326 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2327 pipe = &context->res_ctx.pipe_ctx[i]; 2328 dc->hwseq->funcs.set_wait_for_update_needed_for_pipe(dc, pipe); 2329 } 2330 } 2331 2332 dc->hwss.interdependent_update_lock(dc, context, false); 2333 dc->hwss.post_unlock_program_front_end(dc, context); 2334 } 2335 2336 if (dc->hwss.commit_subvp_config) 2337 dc->hwss.commit_subvp_config(dc, context); 2338 if (dc->hwss.subvp_pipe_control_lock) 2339 dc->hwss.subvp_pipe_control_lock(dc, context, false, true, NULL, subvp_prev_use); 2340 if (dc->hwss.dmub_hw_control_lock) 2341 dc->hwss.dmub_hw_control_lock(dc, context, false); 2342 2343 for (i = 0; i < context->stream_count; i++) { 2344 const struct dc_link *link = context->streams[i]->link; 2345 2346 if (!context->streams[i]->mode_changed) 2347 continue; 2348 2349 if (dc->hwss.apply_ctx_for_surface) { 2350 apply_ctx_interdependent_lock(dc, context, context->streams[i], true); 2351 dc->hwss.apply_ctx_for_surface( 2352 dc, context->streams[i], 2353 context->stream_status[i].plane_count, 2354 context); 2355 apply_ctx_interdependent_lock(dc, context, context->streams[i], false); 2356 dc->hwss.post_unlock_program_front_end(dc, context); 2357 } 2358 2359 /* 2360 * enable stereo 2361 * TODO rework dc_enable_stereo call to work with validation sets? 2362 */ 2363 for (k = 0; k < MAX_PIPES; k++) { 2364 pipe = &context->res_ctx.pipe_ctx[k]; 2365 2366 for (l = 0 ; pipe && l < context->stream_count; l++) { 2367 if (context->streams[l] && 2368 context->streams[l] == pipe->stream && 2369 dc->hwss.setup_stereo) 2370 dc->hwss.setup_stereo(pipe, dc); 2371 } 2372 } 2373 2374 CONN_MSG_MODE(link, "{%dx%d, %dx%d@%dKhz}", 2375 context->streams[i]->timing.h_addressable, 2376 context->streams[i]->timing.v_addressable, 2377 context->streams[i]->timing.h_total, 2378 context->streams[i]->timing.v_total, 2379 context->streams[i]->timing.pix_clk_100hz / 10); 2380 } 2381 2382 dc_enable_stereo(dc, context, dc_streams, context->stream_count); 2383 2384 if (get_seamless_boot_stream_count(context) == 0 || 2385 context->stream_count == 0) { 2386 /* Must wait for no flips to be pending before doing optimize bw */ 2387 hwss_wait_for_no_pipes_pending(dc, context); 2388 /* 2389 * optimized dispclk depends on ODM setup. Need to wait for ODM 2390 * update pending complete before optimizing bandwidth. 2391 */ 2392 hwss_wait_for_odm_update_pending_complete(dc, context); 2393 /* pplib is notified if disp_num changed */ 2394 dc->hwss.optimize_bandwidth(dc, context); 2395 /* Need to do otg sync again as otg could be out of sync due to otg 2396 * workaround applied during clock update 2397 */ 2398 dc_trigger_sync(dc, context); 2399 } 2400 2401 if (dc->hwss.update_dsc_pg) 2402 dc->hwss.update_dsc_pg(dc, context, true); 2403 2404 if (dc->ctx->dce_version >= DCE_VERSION_MAX) 2405 TRACE_DCN_CLOCK_STATE(&context->bw_ctx.bw.dcn.clk); 2406 else 2407 TRACE_DCE_CLOCK_STATE(&context->bw_ctx.bw.dce); 2408 2409 context->stream_mask = get_stream_mask(dc, context); 2410 2411 if (context->stream_mask != dc->current_state->stream_mask) 2412 dc_dmub_srv_notify_stream_mask(dc->ctx->dmub_srv, context->stream_mask); 2413 2414 for (i = 0; i < context->stream_count; i++) 2415 context->streams[i]->mode_changed = false; 2416 2417 /* Clear update flags that were set earlier to avoid redundant programming */ 2418 for (i = 0; i < context->stream_count; i++) { 2419 context->streams[i]->update_flags.raw = 0x0; 2420 } 2421 2422 old_state = dc->current_state; 2423 dc->current_state = context; 2424 2425 dc_state_release(old_state); 2426 2427 dc_state_retain(dc->current_state); 2428 2429 return result; 2430 } 2431 2432 static bool commit_minimal_transition_state(struct dc *dc, 2433 struct dc_state *transition_base_context); 2434 2435 /** 2436 * dc_commit_streams - Commit current stream state 2437 * 2438 * @dc: DC object with the commit state to be configured in the hardware 2439 * @params: Parameters for the commit, including the streams to be committed 2440 * 2441 * Function responsible for commit streams change to the hardware. 2442 * 2443 * Return: 2444 * Return DC_OK if everything work as expected, otherwise, return a dc_status 2445 * code. 2446 */ 2447 enum dc_status dc_commit_streams(struct dc *dc, struct dc_commit_streams_params *params) 2448 { 2449 unsigned int i, j; 2450 struct dc_state *context; 2451 enum dc_status res = DC_OK; 2452 struct dc_validation_set set[MAX_STREAMS] = {0}; 2453 struct pipe_ctx *pipe; 2454 bool handle_exit_odm2to1 = false; 2455 2456 if (!params) 2457 return DC_ERROR_UNEXPECTED; 2458 2459 if (dc->ctx->dce_environment == DCE_ENV_VIRTUAL_HW) 2460 return res; 2461 2462 if (!streams_changed(dc, params->streams, params->stream_count) && 2463 dc->current_state->power_source == params->power_source) 2464 return res; 2465 2466 dc_exit_ips_for_hw_access(dc); 2467 2468 DC_LOG_DC("%s: %d streams\n", __func__, params->stream_count); 2469 2470 for (i = 0; i < params->stream_count; i++) { 2471 struct dc_stream_state *stream = params->streams[i]; 2472 struct dc_stream_status *status = dc_stream_get_status(stream); 2473 struct dc_sink *sink = stream->sink; 2474 2475 /* revalidate streams */ 2476 if (!dc_is_virtual_signal(sink->sink_signal)) { 2477 res = dc_validate_stream(dc, stream); 2478 if (res != DC_OK) 2479 return res; 2480 } 2481 2482 2483 dc_stream_log(dc, stream); 2484 2485 set[i].stream = stream; 2486 2487 if (status) { 2488 set[i].plane_count = (uint8_t)status->plane_count; 2489 for (j = 0; j < (unsigned int)status->plane_count; j++) 2490 set[i].plane_states[j] = status->plane_states[j]; 2491 } 2492 } 2493 2494 /* ODM Combine 2:1 power optimization is only applied for single stream 2495 * scenario, it uses extra pipes than needed to reduce power consumption 2496 * We need to switch off this feature to make room for new streams. 2497 */ 2498 if (params->stream_count > dc->current_state->stream_count && 2499 dc->current_state->stream_count == 1) { 2500 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2501 pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 2502 if (pipe->next_odm_pipe) 2503 handle_exit_odm2to1 = true; 2504 } 2505 } 2506 2507 if (handle_exit_odm2to1) 2508 res = commit_minimal_transition_state(dc, dc->current_state); 2509 2510 context = dc_state_create_current_copy(dc); 2511 if (!context) 2512 goto context_alloc_fail; 2513 2514 context->power_source = params->power_source; 2515 2516 res = dc_validate_with_context(dc, set, params->stream_count, context, DC_VALIDATE_MODE_AND_PROGRAMMING); 2517 2518 /* 2519 * Only update link encoder to stream assignment after bandwidth validation passed. 2520 */ 2521 if (res == DC_OK && dc->res_pool->funcs->link_encs_assign && !dc->config.unify_link_enc_assignment) 2522 dc->res_pool->funcs->link_encs_assign( 2523 dc, context, context->streams, context->stream_count); 2524 2525 if (res != DC_OK) { 2526 BREAK_TO_DEBUGGER(); 2527 goto fail; 2528 } 2529 2530 /* 2531 * If not already seamless, make transition seamless by inserting intermediate minimal transition 2532 */ 2533 if (dc->hwss.is_pipe_topology_transition_seamless && 2534 !dc->hwss.is_pipe_topology_transition_seamless(dc, dc->current_state, context)) { 2535 res = commit_minimal_transition_state(dc, context); 2536 if (res != DC_OK) { 2537 BREAK_TO_DEBUGGER(); 2538 goto fail; 2539 } 2540 } 2541 2542 res = dc_commit_state_no_check(dc, context); 2543 2544 for (i = 0; i < params->stream_count; i++) { 2545 for (j = 0; j < context->stream_count; j++) { 2546 if (params->streams[i]->stream_id == context->streams[j]->stream_id) 2547 params->streams[i]->out.otg_offset = (uint8_t)context->stream_status[j].primary_otg_inst; 2548 2549 if (dc_is_embedded_signal(params->streams[i]->signal)) { 2550 struct dc_stream_status *status = dc_state_get_stream_status(context, params->streams[i]); 2551 2552 if (!status) 2553 continue; 2554 2555 if (dc->hwss.is_abm_supported) 2556 status->is_abm_supported = dc->hwss.is_abm_supported(dc, context, params->streams[i]); 2557 else 2558 status->is_abm_supported = true; 2559 } 2560 } 2561 } 2562 2563 fail: 2564 dc_state_release(context); 2565 2566 context_alloc_fail: 2567 2568 DC_LOG_DC("%s Finished.\n", __func__); 2569 2570 return res; 2571 } 2572 2573 bool dc_acquire_release_mpc_3dlut( 2574 struct dc *dc, bool acquire, 2575 struct dc_stream_state *stream, 2576 struct dc_3dlut **lut, 2577 struct dc_transfer_func **shaper) 2578 { 2579 unsigned int pipe_idx; 2580 bool ret = false; 2581 bool found_pipe_idx = false; 2582 const struct resource_pool *pool = dc->res_pool; 2583 struct resource_context *res_ctx = &dc->current_state->res_ctx; 2584 int mpcc_id = 0; 2585 2586 if (pool && res_ctx) { 2587 if (acquire) { 2588 /*find pipe idx for the given stream*/ 2589 for (pipe_idx = 0; pipe_idx < pool->pipe_count; pipe_idx++) { 2590 if (res_ctx->pipe_ctx[pipe_idx].stream == stream) { 2591 found_pipe_idx = true; 2592 mpcc_id = res_ctx->pipe_ctx[pipe_idx].plane_res.hubp->inst; 2593 break; 2594 } 2595 } 2596 } else 2597 found_pipe_idx = true;/*for release pipe_idx is not required*/ 2598 2599 if (found_pipe_idx) { 2600 if (acquire && pool->funcs->acquire_post_bldn_3dlut) 2601 ret = pool->funcs->acquire_post_bldn_3dlut(res_ctx, pool, mpcc_id, lut, shaper); 2602 else if (!acquire && pool->funcs->release_post_bldn_3dlut) 2603 ret = pool->funcs->release_post_bldn_3dlut(res_ctx, pool, lut, shaper); 2604 } 2605 } 2606 return ret; 2607 } 2608 2609 static bool is_flip_pending_in_pipes(struct dc *dc, struct dc_state *context) 2610 { 2611 int i; 2612 struct pipe_ctx *pipe; 2613 2614 for (i = 0; i < MAX_PIPES; i++) { 2615 pipe = &context->res_ctx.pipe_ctx[i]; 2616 2617 // Don't check flip pending on phantom pipes 2618 if (!pipe->plane_state || (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM)) 2619 continue; 2620 2621 /* Must set to false to start with, due to OR in update function */ 2622 pipe->plane_state->status.is_flip_pending = false; 2623 dc->hwss.update_pending_status(pipe); 2624 if (pipe->plane_state->status.is_flip_pending) 2625 return true; 2626 } 2627 return false; 2628 } 2629 2630 /* Perform updates here which need to be deferred until next vupdate 2631 * 2632 * i.e. blnd lut, 3dlut, and shaper lut bypass regs are double buffered 2633 * but forcing lut memory to shutdown state is immediate. This causes 2634 * single frame corruption as lut gets disabled mid-frame unless shutdown 2635 * is deferred until after entering bypass. 2636 */ 2637 static void process_deferred_updates(struct dc *dc) 2638 { 2639 int i = 0; 2640 2641 if (dc->debug.enable_mem_low_power.bits.cm) { 2642 ASSERT(dc->dcn_ip->max_num_dpp); 2643 for (i = 0; i < dc->dcn_ip->max_num_dpp; i++) 2644 if (dc->res_pool->dpps[i]->funcs->dpp_deferred_update) 2645 dc->res_pool->dpps[i]->funcs->dpp_deferred_update(dc->res_pool->dpps[i]); 2646 } 2647 } 2648 2649 void dc_post_update_surfaces_to_stream(struct dc *dc) 2650 { 2651 unsigned int i; 2652 struct dc_state *context = dc->current_state; 2653 2654 if ((!dc->optimized_required) || get_seamless_boot_stream_count(context) > 0) 2655 return; 2656 2657 post_surface_trace(dc); 2658 2659 /* 2660 * Only relevant for DCN behavior where we can guarantee the optimization 2661 * is safe to apply - retain the legacy behavior for DCE. 2662 */ 2663 2664 if (dc->ctx->dce_version < DCE_VERSION_MAX) 2665 TRACE_DCE_CLOCK_STATE(&context->bw_ctx.bw.dce); 2666 else { 2667 TRACE_DCN_CLOCK_STATE(&context->bw_ctx.bw.dcn.clk); 2668 2669 if (is_flip_pending_in_pipes(dc, context)) 2670 return; 2671 2672 for (i = 0; i < dc->res_pool->pipe_count; i++) 2673 if (context->res_ctx.pipe_ctx[i].stream == NULL || 2674 context->res_ctx.pipe_ctx[i].plane_state == NULL) { 2675 context->res_ctx.pipe_ctx[i].pipe_idx = (uint8_t)i; 2676 dc->hwss.disable_plane(dc, context, &context->res_ctx.pipe_ctx[i]); 2677 } 2678 2679 process_deferred_updates(dc); 2680 2681 dc->hwss.optimize_bandwidth(dc, context); 2682 2683 if (dc->hwss.update_dsc_pg) 2684 dc->hwss.update_dsc_pg(dc, context, true); 2685 } 2686 2687 dc->optimized_required = false; 2688 } 2689 2690 void dc_get_default_tiling_info(const struct dc *dc, struct dc_tiling_info *tiling_info) 2691 { 2692 if (!dc || !tiling_info) 2693 return; 2694 if (dc->res_pool && dc->res_pool->funcs && dc->res_pool->funcs->get_default_tiling_info) { 2695 dc->res_pool->funcs->get_default_tiling_info(tiling_info); 2696 return; 2697 } 2698 } 2699 2700 bool dc_set_generic_gpio_for_stereo(bool enable, 2701 struct gpio_service *gpio_service) 2702 { 2703 enum gpio_result gpio_result = GPIO_RESULT_NON_SPECIFIC_ERROR; 2704 struct gpio_pin_info pin_info; 2705 struct gpio *generic; 2706 struct gpio_generic_mux_config *config = kzalloc_obj(struct gpio_generic_mux_config); 2707 2708 if (!config) 2709 return false; 2710 pin_info = dal_gpio_get_generic_pin_info(gpio_service, GPIO_ID_GENERIC, 0); 2711 2712 if (pin_info.mask == 0xFFFFFFFF || pin_info.offset == 0xFFFFFFFF) { 2713 kfree(config); 2714 return false; 2715 } else { 2716 generic = dal_gpio_service_create_generic_mux( 2717 gpio_service, 2718 pin_info.offset, 2719 pin_info.mask); 2720 } 2721 2722 if (!generic) { 2723 kfree(config); 2724 return false; 2725 } 2726 2727 gpio_result = dal_gpio_open(generic, GPIO_MODE_OUTPUT); 2728 2729 config->enable_output_from_mux = enable; 2730 config->mux_select = GPIO_SIGNAL_SOURCE_PASS_THROUGH_STEREO_SYNC; 2731 2732 if (gpio_result == GPIO_RESULT_OK) 2733 gpio_result = dal_mux_setup_config(generic, config); 2734 2735 if (gpio_result == GPIO_RESULT_OK) { 2736 dal_gpio_close(generic); 2737 dal_gpio_destroy_generic_mux(&generic); 2738 kfree(config); 2739 return true; 2740 } else { 2741 dal_gpio_close(generic); 2742 dal_gpio_destroy_generic_mux(&generic); 2743 kfree(config); 2744 return false; 2745 } 2746 } 2747 2748 static bool is_surface_in_context( 2749 const struct dc_state *context, 2750 const struct dc_plane_state *plane_state) 2751 { 2752 int j; 2753 2754 for (j = 0; j < MAX_PIPES; j++) { 2755 const struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 2756 2757 if (plane_state == pipe_ctx->plane_state) { 2758 return true; 2759 } 2760 } 2761 2762 return false; 2763 } 2764 2765 static struct surface_update_descriptor get_plane_info_update_type(const struct dc_surface_update *u) 2766 { 2767 union surface_update_flags *update_flags = &u->surface->update_flags; 2768 struct surface_update_descriptor update_type = { UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_NONE }; 2769 2770 if (!u->plane_info) 2771 return update_type; 2772 2773 // `plane_info` present means at least `STREAM` lock is required 2774 elevate_update_type(&update_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 2775 2776 if (u->plane_info->color_space != u->surface->color_space) { 2777 update_flags->bits.color_space_change = 1; 2778 elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM); 2779 } 2780 2781 if (u->plane_info->horizontal_mirror != u->surface->horizontal_mirror) { 2782 update_flags->bits.horizontal_mirror_change = 1; 2783 elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM); 2784 } 2785 2786 if (u->plane_info->rotation != u->surface->rotation) { 2787 update_flags->bits.rotation_change = 1; 2788 elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); 2789 } 2790 2791 if (u->plane_info->format != u->surface->format) { 2792 update_flags->bits.pixel_format_change = 1; 2793 elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); 2794 } 2795 2796 if (u->plane_info->stereo_format != u->surface->stereo_format) { 2797 update_flags->bits.stereo_format_change = 1; 2798 elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); 2799 } 2800 2801 if (u->plane_info->per_pixel_alpha != u->surface->per_pixel_alpha) { 2802 update_flags->bits.per_pixel_alpha_change = 1; 2803 elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM); 2804 } 2805 2806 if (u->plane_info->global_alpha_value != u->surface->global_alpha_value) { 2807 update_flags->bits.global_alpha_change = 1; 2808 elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM); 2809 } 2810 2811 if (u->plane_info->dcc.enable != u->surface->dcc.enable 2812 || u->plane_info->dcc.dcc_ind_blk != u->surface->dcc.dcc_ind_blk 2813 || u->plane_info->dcc.meta_pitch != u->surface->dcc.meta_pitch) { 2814 /* During DCC on/off, stutter period is calculated before 2815 * DCC has fully transitioned. This results in incorrect 2816 * stutter period calculation. Triggering a full update will 2817 * recalculate stutter period. 2818 */ 2819 update_flags->bits.dcc_change = 1; 2820 elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); 2821 } 2822 2823 if (resource_pixel_format_to_bpp(u->plane_info->format) != 2824 resource_pixel_format_to_bpp(u->surface->format)) { 2825 /* different bytes per element will require full bandwidth 2826 * and DML calculation 2827 */ 2828 update_flags->bits.bpp_change = 1; 2829 elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); 2830 } 2831 2832 if (u->plane_info->plane_size.surface_pitch != u->surface->plane_size.surface_pitch 2833 || u->plane_info->plane_size.chroma_pitch != u->surface->plane_size.chroma_pitch) { 2834 update_flags->bits.plane_size_change = 1; 2835 elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM); 2836 } 2837 2838 const struct dc_tiling_info *tiling = &u->plane_info->tiling_info; 2839 2840 if (memcmp(tiling, &u->surface->tiling_info, sizeof(*tiling)) != 0) { 2841 update_flags->bits.swizzle_change = 1; 2842 2843 if (tiling->flags.avoid_full_update_on_tiling_change) { 2844 elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM); 2845 } else { 2846 update_flags->bits.bandwidth_change = 1; 2847 elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); 2848 } 2849 } 2850 2851 /* This should be UPDATE_TYPE_FAST if nothing has changed. */ 2852 return update_type; 2853 } 2854 2855 static struct surface_update_descriptor get_scaling_info_update_type( 2856 const struct dc_check_config *check_config, 2857 const struct dc_surface_update *u) 2858 { 2859 union surface_update_flags *update_flags = &u->surface->update_flags; 2860 struct surface_update_descriptor update_type = { UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_NONE }; 2861 2862 if (!u->scaling_info) 2863 return update_type; 2864 2865 // `scaling_info` present means at least `STREAM` lock is required 2866 elevate_update_type(&update_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 2867 2868 if (u->scaling_info->src_rect.width != u->surface->src_rect.width 2869 || u->scaling_info->src_rect.height != u->surface->src_rect.height 2870 || u->scaling_info->dst_rect.width != u->surface->dst_rect.width 2871 || u->scaling_info->dst_rect.height != u->surface->dst_rect.height 2872 || u->scaling_info->clip_rect.width != u->surface->clip_rect.width 2873 || u->scaling_info->clip_rect.height != u->surface->clip_rect.height 2874 || u->scaling_info->scaling_quality.integer_scaling != 2875 u->surface->scaling_quality.integer_scaling) { 2876 update_flags->bits.scaling_change = 1; 2877 elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); 2878 2879 if (u->scaling_info->src_rect.width > u->surface->src_rect.width 2880 || u->scaling_info->src_rect.height > u->surface->src_rect.height) 2881 /* Making src rect bigger requires a bandwidth change */ 2882 update_flags->bits.clock_change = 1; 2883 2884 if ((u->scaling_info->dst_rect.width < u->surface->dst_rect.width 2885 || u->scaling_info->dst_rect.height < u->surface->dst_rect.height) 2886 && (u->scaling_info->dst_rect.width < u->surface->src_rect.width 2887 || u->scaling_info->dst_rect.height < u->surface->src_rect.height)) 2888 /* Making dst rect smaller requires a bandwidth change */ 2889 update_flags->bits.bandwidth_change = 1; 2890 2891 if (u->scaling_info->src_rect.width > (int)check_config->max_optimizable_video_width && 2892 (u->scaling_info->clip_rect.width > u->surface->clip_rect.width || 2893 u->scaling_info->clip_rect.height > u->surface->clip_rect.height)) 2894 /* Changing clip size of a large surface may result in MPC slice count change */ 2895 update_flags->bits.bandwidth_change = 1; 2896 } 2897 2898 if (u->scaling_info->src_rect.x != u->surface->src_rect.x 2899 || u->scaling_info->src_rect.y != u->surface->src_rect.y 2900 || u->scaling_info->clip_rect.x != u->surface->clip_rect.x 2901 || u->scaling_info->clip_rect.y != u->surface->clip_rect.y 2902 || u->scaling_info->dst_rect.x != u->surface->dst_rect.x 2903 || u->scaling_info->dst_rect.y != u->surface->dst_rect.y) { 2904 elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM); 2905 update_flags->bits.position_change = 1; 2906 } 2907 2908 return update_type; 2909 } 2910 2911 static struct surface_update_descriptor det_surface_update( 2912 const struct dc_check_config *check_config, 2913 struct dc_surface_update *u) 2914 { 2915 struct surface_update_descriptor overall_type = { UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_NONE }; 2916 union surface_update_flags *update_flags = &u->surface->update_flags; 2917 2918 if (u->surface->force_full_update) { 2919 update_flags->raw = 0xFFFFFFFF; 2920 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); 2921 return overall_type; 2922 } 2923 2924 update_flags->raw = 0; // Reset all flags 2925 2926 struct surface_update_descriptor inner_type = get_plane_info_update_type(u); 2927 2928 elevate_update_type(&overall_type, inner_type.update_type, inner_type.lock_descriptor); 2929 2930 inner_type = get_scaling_info_update_type(check_config, u); 2931 elevate_update_type(&overall_type, inner_type.update_type, inner_type.lock_descriptor); 2932 2933 if (u->flip_addr) { 2934 update_flags->bits.addr_update = 1; 2935 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 2936 2937 if (u->flip_addr->address.tmz_surface != u->surface->address.tmz_surface) { 2938 update_flags->bits.tmz_changed = 1; 2939 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); 2940 } 2941 } 2942 if (u->in_transfer_func) { 2943 update_flags->bits.in_transfer_func_change = 1; 2944 elevate_update_type(&overall_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM); 2945 } 2946 2947 if (u->input_csc_color_matrix) { 2948 update_flags->bits.input_csc_change = 1; 2949 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 2950 } 2951 2952 if (u->cursor_csc_color_matrix) { 2953 update_flags->bits.cursor_csc_color_matrix_change = 1; 2954 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 2955 } 2956 2957 if (u->coeff_reduction_factor) { 2958 update_flags->bits.coeff_reduction_change = 1; 2959 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 2960 } 2961 2962 if (u->gamut_remap_matrix) { 2963 update_flags->bits.gamut_remap_change = 1; 2964 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 2965 } 2966 2967 if (u->blend_tf || (u->gamma && dce_use_lut(u->plane_info ? u->plane_info->format : u->surface->format))) { 2968 update_flags->bits.gamma_change = 1; 2969 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 2970 } 2971 2972 if (u->lut3d_func || u->func_shaper) { 2973 update_flags->bits.lut_3d = 1; 2974 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 2975 } 2976 2977 if (u->hdr_mult.value) 2978 if (u->hdr_mult.value != u->surface->hdr_mult.value) { 2979 // TODO: Should be fast? 2980 update_flags->bits.hdr_mult = 1; 2981 elevate_update_type(&overall_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM); 2982 } 2983 2984 if (u->sdr_white_level_nits) 2985 if (u->sdr_white_level_nits != u->surface->sdr_white_level_nits) { 2986 // TODO: Should be fast? 2987 update_flags->bits.sdr_white_level_nits = 1; 2988 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); 2989 } 2990 2991 if (u->cm_hist_control) { 2992 update_flags->bits.cm_hist_change = 1; 2993 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 2994 } 2995 if (u->cm2_params) { 2996 if (u->cm2_params->component_settings.shaper_3dlut_setting != u->surface->mcm_shaper_3dlut_setting 2997 || u->cm2_params->component_settings.lut1d_enable != u->surface->mcm_lut1d_enable 2998 || u->cm2_params->cm2_luts.lut3d_data.lut3d_src != u->surface->mcm_luts.lut3d_data.lut3d_src) { 2999 update_flags->bits.mcm_transfer_function_enable_change = 1; 3000 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); 3001 } 3002 } 3003 3004 if (update_flags->bits.lut_3d && 3005 u->surface->mcm_luts.lut3d_data.lut3d_src != DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) { 3006 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); 3007 } 3008 3009 if (check_config->enable_legacy_fast_update && 3010 (update_flags->bits.gamma_change || 3011 update_flags->bits.gamut_remap_change || 3012 update_flags->bits.input_csc_change || 3013 update_flags->bits.cm_hist_change || 3014 update_flags->bits.coeff_reduction_change)) { 3015 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); 3016 } 3017 return overall_type; 3018 } 3019 3020 /* May need to flip the desktop plane in cases where MPO plane receives a flip but desktop plane doesn't 3021 * while both planes are flip_immediate 3022 */ 3023 static void force_immediate_gsl_plane_flip(struct dc *dc, struct dc_surface_update *updates, int surface_count) 3024 { 3025 (void)dc; 3026 bool has_flip_immediate_plane = false; 3027 int i; 3028 3029 for (i = 0; i < surface_count; i++) { 3030 if (updates[i].surface->flip_immediate) { 3031 has_flip_immediate_plane = true; 3032 break; 3033 } 3034 } 3035 3036 if (has_flip_immediate_plane && surface_count > 1) { 3037 for (i = 0; i < surface_count; i++) { 3038 if (updates[i].surface->flip_immediate) 3039 updates[i].surface->update_flags.bits.addr_update = 1; 3040 } 3041 } 3042 } 3043 3044 static struct surface_update_descriptor check_update_surfaces_for_stream( 3045 const struct dc_check_config *check_config, 3046 struct dc_surface_update *updates, 3047 int surface_count, 3048 struct dc_stream_update *stream_update) 3049 { 3050 struct surface_update_descriptor overall_type = { UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_NONE }; 3051 3052 /* When countdown finishes, promote this flip to full to trigger deferred final transition */ 3053 if (check_config->deferred_transition_state && !check_config->transition_countdown_to_steady_state) { 3054 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); 3055 } 3056 3057 if (stream_update && stream_update->pending_test_pattern) { 3058 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); 3059 } 3060 3061 if (stream_update && stream_update->hw_cursor_req) { 3062 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); 3063 } 3064 3065 /* some stream updates require passive update */ 3066 if (stream_update) { 3067 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 3068 3069 union stream_update_flags *su_flags = &stream_update->stream->update_flags; 3070 3071 if ((stream_update->src.height != 0 && stream_update->src.width != 0) || 3072 (stream_update->dst.height != 0 && stream_update->dst.width != 0) || 3073 stream_update->integer_scaling_update) 3074 su_flags->bits.scaling = 1; 3075 3076 if (check_config->enable_legacy_fast_update && stream_update->out_transfer_func) 3077 su_flags->bits.out_tf = 1; 3078 3079 if (stream_update->abm_level) 3080 su_flags->bits.abm_level = 1; 3081 3082 if (stream_update->dpms_off) { 3083 su_flags->bits.dpms_off = 1; 3084 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL | LOCK_DESCRIPTOR_LINK); 3085 } 3086 3087 if (check_config->enable_legacy_fast_update && stream_update->gamut_remap) 3088 su_flags->bits.gamut_remap = 1; 3089 3090 if (stream_update->wb_update) 3091 su_flags->bits.wb_update = 1; 3092 3093 if (stream_update->dsc_config) 3094 su_flags->bits.dsc_changed = 1; 3095 3096 if (stream_update->mst_bw_update) 3097 su_flags->bits.mst_bw = 1; 3098 3099 if (stream_update->stream->freesync_on_desktop && 3100 (stream_update->vrr_infopacket || stream_update->allow_freesync || 3101 stream_update->vrr_active_variable || stream_update->vrr_active_fixed)) 3102 su_flags->bits.fams_changed = 1; 3103 3104 if (stream_update->scaler_sharpener_update) 3105 su_flags->bits.scaler_sharpener = 1; 3106 3107 if (stream_update->sharpening_required) 3108 su_flags->bits.sharpening_required = 1; 3109 3110 if (stream_update->output_color_space) 3111 su_flags->bits.out_csc = 1; 3112 3113 // TODO: Make each elevation explicit, as to not override fast stream in crct_timing_adjust 3114 if (su_flags->raw) 3115 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); 3116 3117 // Non-global cases 3118 3119 if (stream_update->gamut_remap) { 3120 su_flags->bits.gamut_remap = 1; 3121 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 3122 } 3123 3124 if ((stream_update->hdr_static_metadata && !stream_update->stream->use_dynamic_meta) || 3125 stream_update->vrr_infopacket || 3126 stream_update->vsc_infopacket || 3127 stream_update->vsp_infopacket || 3128 stream_update->hfvsif_infopacket || 3129 stream_update->adaptive_sync_infopacket || 3130 stream_update->vtem_infopacket || 3131 stream_update->avi_infopacket) { 3132 su_flags->bits.info_frame = 1; 3133 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 3134 } 3135 3136 if (stream_update->hdr_static_metadata && stream_update->stream->use_dynamic_meta) { 3137 su_flags->bits.dmdata = 1; 3138 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 3139 } 3140 3141 if (stream_update->output_csc_transform) { 3142 su_flags->bits.out_csc = 1; 3143 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 3144 } 3145 3146 if (!check_config->enable_legacy_fast_update && stream_update->out_transfer_func) { 3147 su_flags->bits.out_tf = 1; 3148 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 3149 } 3150 3151 if (stream_update->periodic_interrupt) { 3152 su_flags->bits.periodic_interrupt = 1; 3153 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 3154 } 3155 3156 if (stream_update->dither_option) { 3157 su_flags->bits.dither = 1; 3158 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 3159 } 3160 3161 if (stream_update->cursor_attributes) { 3162 su_flags->bits.cursor_attr = 1; 3163 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 3164 } 3165 3166 if (stream_update->cursor_position) { 3167 su_flags->bits.cursor_pos = 1; 3168 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); 3169 } 3170 } 3171 3172 for (int i = 0 ; i < surface_count; i++) { 3173 struct surface_update_descriptor inner_type = 3174 det_surface_update(check_config, &updates[i]); 3175 3176 elevate_update_type(&overall_type, inner_type.update_type, inner_type.lock_descriptor); 3177 } 3178 3179 return overall_type; 3180 } 3181 3182 /* 3183 * dc_check_update_surfaces_for_stream() - Determine update type (fast, med, or full) 3184 * 3185 * See :c:type:`enum surface_update_type <surface_update_type>` for explanation of update types 3186 */ 3187 struct surface_update_descriptor dc_check_update_surfaces_for_stream( 3188 const struct dc_check_config *check_config, 3189 struct dc_surface_update *updates, 3190 int surface_count, 3191 struct dc_stream_update *stream_update) 3192 { 3193 if (stream_update) 3194 stream_update->stream->update_flags.raw = 0; 3195 for (int i = 0; i < surface_count; i++) 3196 updates[i].surface->update_flags.raw = 0; 3197 3198 return check_update_surfaces_for_stream(check_config, updates, surface_count, stream_update); 3199 } 3200 3201 static struct dc_stream_status *stream_get_status( 3202 struct dc_state *ctx, 3203 struct dc_stream_state *stream) 3204 { 3205 uint8_t i; 3206 3207 for (i = 0; i < ctx->stream_count; i++) { 3208 if (stream == ctx->streams[i]) { 3209 return &ctx->stream_status[i]; 3210 } 3211 } 3212 3213 return NULL; 3214 } 3215 3216 static const enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; 3217 3218 static void copy_surface_update_to_plane( 3219 struct dc_plane_state *surface, 3220 struct dc_surface_update *srf_update) 3221 { 3222 if (srf_update->flip_addr) { 3223 surface->address = srf_update->flip_addr->address; 3224 surface->flip_immediate = 3225 srf_update->flip_addr->flip_immediate; 3226 surface->time.time_elapsed_in_us[surface->time.index] = 3227 (unsigned int)(srf_update->flip_addr->flip_timestamp_in_us - 3228 surface->time.prev_update_time_in_us); 3229 surface->time.prev_update_time_in_us = 3230 (unsigned int)srf_update->flip_addr->flip_timestamp_in_us; 3231 surface->time.index++; 3232 if (surface->time.index >= DC_PLANE_UPDATE_TIMES_MAX) 3233 surface->time.index = 0; 3234 3235 surface->triplebuffer_flips = srf_update->flip_addr->triplebuffer_flips; 3236 } 3237 3238 if (srf_update->scaling_info) { 3239 surface->scaling_quality = 3240 srf_update->scaling_info->scaling_quality; 3241 surface->dst_rect = 3242 srf_update->scaling_info->dst_rect; 3243 surface->src_rect = 3244 srf_update->scaling_info->src_rect; 3245 surface->clip_rect = 3246 srf_update->scaling_info->clip_rect; 3247 } 3248 3249 if (srf_update->plane_info) { 3250 surface->color_space = 3251 srf_update->plane_info->color_space; 3252 surface->format = 3253 srf_update->plane_info->format; 3254 surface->plane_size = 3255 srf_update->plane_info->plane_size; 3256 surface->rotation = 3257 srf_update->plane_info->rotation; 3258 surface->horizontal_mirror = 3259 srf_update->plane_info->horizontal_mirror; 3260 surface->stereo_format = 3261 srf_update->plane_info->stereo_format; 3262 surface->tiling_info = 3263 srf_update->plane_info->tiling_info; 3264 surface->visible = 3265 srf_update->plane_info->visible; 3266 surface->per_pixel_alpha = 3267 srf_update->plane_info->per_pixel_alpha; 3268 surface->global_alpha = 3269 srf_update->plane_info->global_alpha; 3270 surface->global_alpha_value = 3271 srf_update->plane_info->global_alpha_value; 3272 surface->dcc = 3273 srf_update->plane_info->dcc; 3274 surface->layer_index = 3275 srf_update->plane_info->layer_index; 3276 } 3277 3278 if (srf_update->gamma) { 3279 memcpy(&surface->gamma_correction.entries, 3280 &srf_update->gamma->entries, 3281 sizeof(struct dc_gamma_entries)); 3282 surface->gamma_correction.is_identity = 3283 srf_update->gamma->is_identity; 3284 surface->gamma_correction.num_entries = 3285 srf_update->gamma->num_entries; 3286 surface->gamma_correction.type = 3287 srf_update->gamma->type; 3288 } 3289 if (srf_update->cm_hist_control) { 3290 memcpy(&surface->cm_hist_control, 3291 srf_update->cm_hist_control, 3292 sizeof(surface->cm_hist_control)); 3293 } 3294 3295 if (srf_update->in_transfer_func) { 3296 surface->in_transfer_func.sdr_ref_white_level = 3297 srf_update->in_transfer_func->sdr_ref_white_level; 3298 surface->in_transfer_func.tf = 3299 srf_update->in_transfer_func->tf; 3300 surface->in_transfer_func.type = 3301 srf_update->in_transfer_func->type; 3302 memcpy(&surface->in_transfer_func.tf_pts, 3303 &srf_update->in_transfer_func->tf_pts, 3304 sizeof(struct dc_transfer_func_distributed_points)); 3305 } 3306 3307 if (srf_update->cm2_params) { 3308 surface->mcm_shaper_3dlut_setting = srf_update->cm2_params->component_settings.shaper_3dlut_setting; 3309 surface->mcm_lut1d_enable = srf_update->cm2_params->component_settings.lut1d_enable; 3310 surface->mcm_luts = srf_update->cm2_params->cm2_luts; 3311 } 3312 3313 if (srf_update->func_shaper) { 3314 memcpy(&surface->in_shaper_func, srf_update->func_shaper, 3315 sizeof(surface->in_shaper_func)); 3316 3317 if (surface->mcm_shaper_3dlut_setting >= DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER) 3318 surface->mcm_luts.shaper = &surface->in_shaper_func; 3319 } 3320 3321 if (srf_update->lut3d_func) 3322 memcpy(&surface->lut3d_func, srf_update->lut3d_func, 3323 sizeof(surface->lut3d_func)); 3324 3325 if (srf_update->hdr_mult.value) 3326 surface->hdr_mult = 3327 srf_update->hdr_mult; 3328 3329 if (srf_update->sdr_white_level_nits) 3330 surface->sdr_white_level_nits = 3331 srf_update->sdr_white_level_nits; 3332 3333 if (srf_update->blend_tf) { 3334 memcpy(&surface->blend_tf, srf_update->blend_tf, 3335 sizeof(surface->blend_tf)); 3336 3337 if (surface->mcm_lut1d_enable) 3338 surface->mcm_luts.lut1d_func = &surface->blend_tf; 3339 } 3340 3341 if (srf_update->cm2_params || srf_update->blend_tf) 3342 surface->lut_bank_a = !surface->lut_bank_a; 3343 3344 if (srf_update->input_csc_color_matrix) 3345 surface->input_csc_color_matrix = 3346 *srf_update->input_csc_color_matrix; 3347 3348 if (srf_update->coeff_reduction_factor) 3349 surface->coeff_reduction_factor = 3350 *srf_update->coeff_reduction_factor; 3351 3352 if (srf_update->gamut_remap_matrix) 3353 surface->gamut_remap_matrix = 3354 *srf_update->gamut_remap_matrix; 3355 3356 if (srf_update->cursor_csc_color_matrix) 3357 surface->cursor_csc_color_matrix = 3358 *srf_update->cursor_csc_color_matrix; 3359 3360 if (srf_update->bias_and_scale.bias_and_scale_valid) 3361 surface->bias_and_scale = 3362 srf_update->bias_and_scale; 3363 } 3364 3365 static void copy_stream_update_to_stream(struct dc *dc, 3366 struct dc_state *context, 3367 struct dc_stream_state *stream, 3368 struct dc_stream_update *update) 3369 { 3370 (void)context; 3371 struct dc_context *dc_ctx = dc->ctx; 3372 3373 if (update == NULL || stream == NULL) 3374 return; 3375 3376 if (update->src.height && update->src.width) 3377 stream->src = update->src; 3378 3379 if (update->dst.height && update->dst.width) 3380 stream->dst = update->dst; 3381 3382 if (update->out_transfer_func) { 3383 stream->out_transfer_func.sdr_ref_white_level = 3384 update->out_transfer_func->sdr_ref_white_level; 3385 stream->out_transfer_func.tf = update->out_transfer_func->tf; 3386 stream->out_transfer_func.type = 3387 update->out_transfer_func->type; 3388 memcpy(&stream->out_transfer_func.tf_pts, 3389 &update->out_transfer_func->tf_pts, 3390 sizeof(struct dc_transfer_func_distributed_points)); 3391 } 3392 3393 if (update->hdr_static_metadata) 3394 stream->hdr_static_metadata = *update->hdr_static_metadata; 3395 3396 if (update->abm_level) 3397 stream->abm_level = *update->abm_level; 3398 3399 if (update->periodic_interrupt) 3400 stream->periodic_interrupt = *update->periodic_interrupt; 3401 3402 if (update->gamut_remap) 3403 stream->gamut_remap_matrix = *update->gamut_remap; 3404 3405 /* Note: this being updated after mode set is currently not a use case 3406 * however if it arises OCSC would need to be reprogrammed at the 3407 * minimum 3408 */ 3409 if (update->output_color_space) 3410 stream->output_color_space = *update->output_color_space; 3411 3412 if (update->output_csc_transform) 3413 stream->csc_color_matrix = *update->output_csc_transform; 3414 3415 if (update->vrr_infopacket) 3416 stream->vrr_infopacket = *update->vrr_infopacket; 3417 3418 if (update->hw_cursor_req) 3419 stream->hw_cursor_req = *update->hw_cursor_req; 3420 3421 if (update->allow_freesync) 3422 stream->allow_freesync = *update->allow_freesync; 3423 3424 if (update->vrr_active_variable) 3425 stream->vrr_active_variable = *update->vrr_active_variable; 3426 3427 if (update->vrr_active_fixed) 3428 stream->vrr_active_fixed = *update->vrr_active_fixed; 3429 3430 if (update->crtc_timing_adjust) { 3431 if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min || 3432 stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max || 3433 stream->adjust.timing_adjust_pending) 3434 update->crtc_timing_adjust->timing_adjust_pending = true; 3435 stream->adjust = *update->crtc_timing_adjust; 3436 update->crtc_timing_adjust->timing_adjust_pending = false; 3437 } 3438 3439 if (update->dpms_off) 3440 stream->dpms_off = *update->dpms_off; 3441 3442 if (update->hfvsif_infopacket) 3443 stream->hfvsif_infopacket = *update->hfvsif_infopacket; 3444 3445 if (update->vtem_infopacket) 3446 stream->vtem_infopacket = *update->vtem_infopacket; 3447 3448 if (update->vsc_infopacket) 3449 stream->vsc_infopacket = *update->vsc_infopacket; 3450 3451 if (update->vsp_infopacket) 3452 stream->vsp_infopacket = *update->vsp_infopacket; 3453 3454 if (update->adaptive_sync_infopacket) 3455 stream->adaptive_sync_infopacket = *update->adaptive_sync_infopacket; 3456 3457 if (update->avi_infopacket) 3458 stream->avi_infopacket = *update->avi_infopacket; 3459 3460 if (update->dither_option) 3461 stream->dither_option = *update->dither_option; 3462 3463 if (update->pending_test_pattern) 3464 stream->test_pattern = *update->pending_test_pattern; 3465 /* update current stream with writeback info */ 3466 if (update->wb_update) { 3467 unsigned int i; 3468 3469 stream->num_wb_info = update->wb_update->num_wb_info; 3470 ASSERT(stream->num_wb_info <= MAX_DWB_PIPES); 3471 for (i = 0; i < stream->num_wb_info; i++) 3472 stream->writeback_info[i] = 3473 update->wb_update->writeback_info[i]; 3474 } 3475 if (update->dsc_config) { 3476 struct dc_dsc_config old_dsc_cfg = stream->timing.dsc_cfg; 3477 uint32_t old_dsc_enabled = stream->timing.flags.DSC; 3478 uint32_t enable_dsc = (update->dsc_config->num_slices_h != 0 && 3479 update->dsc_config->num_slices_v != 0); 3480 3481 /* Use temporarry context for validating new DSC config */ 3482 struct dc_state *dsc_validate_context = dc_state_create_copy(dc->current_state); 3483 3484 if (dsc_validate_context) { 3485 stream->timing.dsc_cfg = *update->dsc_config; 3486 stream->timing.flags.DSC = enable_dsc; 3487 if (dc->res_pool->funcs->validate_bandwidth(dc, dsc_validate_context, 3488 DC_VALIDATE_MODE_ONLY) != DC_OK) { 3489 stream->timing.dsc_cfg = old_dsc_cfg; 3490 stream->timing.flags.DSC = old_dsc_enabled; 3491 update->dsc_config = NULL; 3492 } 3493 3494 dc_state_release(dsc_validate_context); 3495 } else { 3496 DC_ERROR("Failed to allocate new validate context for DSC change\n"); 3497 update->dsc_config = NULL; 3498 } 3499 } 3500 if (update->scaler_sharpener_update) 3501 stream->scaler_sharpener_update = *update->scaler_sharpener_update; 3502 if (update->sharpening_required) 3503 stream->sharpening_required = *update->sharpening_required; 3504 3505 if (update->drr_trigger_mode) { 3506 stream->drr_trigger_mode = *update->drr_trigger_mode; 3507 } 3508 } 3509 3510 static void backup_planes_and_stream_state( 3511 struct dc_scratch_space *scratch, 3512 struct dc_stream_state *stream) 3513 { 3514 int i; 3515 struct dc_stream_status *status = dc_stream_get_status(stream); 3516 3517 if (!status) 3518 return; 3519 3520 for (i = 0; i < status->plane_count; i++) { 3521 dc_plane_copy_config(&scratch->plane_states[i], status->plane_states[i]); 3522 } 3523 scratch->stream_state = *stream; 3524 } 3525 3526 static void restore_planes_and_stream_state( 3527 struct dc_scratch_space *scratch, 3528 struct dc_stream_state *stream) 3529 { 3530 int i; 3531 struct dc_stream_status *status = dc_stream_get_status(stream); 3532 3533 if (!status) 3534 return; 3535 3536 for (i = 0; i < status->plane_count; i++) { 3537 dc_plane_copy_config(status->plane_states[i], &scratch->plane_states[i]); 3538 } 3539 3540 // refcount is persistent 3541 struct kref temp_refcount = stream->refcount; 3542 *stream = scratch->stream_state; 3543 stream->refcount = temp_refcount; 3544 } 3545 3546 /** 3547 * update_seamless_boot_flags() - Helper function for updating seamless boot flags 3548 * 3549 * @dc: Current DC state 3550 * @context: New DC state to be programmed 3551 * @surface_count: Number of surfaces that have an updated 3552 * @stream: Corresponding stream to be updated in the current flip 3553 * 3554 * Updating seamless boot flags do not need to be part of the commit sequence. This 3555 * helper function will update the seamless boot flags on each flip (if required) 3556 * outside of the HW commit sequence (fast or slow). 3557 * 3558 * Return: void 3559 */ 3560 static void update_seamless_boot_flags(struct dc *dc, 3561 struct dc_state *context, 3562 int surface_count, 3563 struct dc_stream_state *stream) 3564 { 3565 if (get_seamless_boot_stream_count(context) > 0 && (surface_count > 0 || stream->dpms_off)) { 3566 /* Optimize seamless boot flag keeps clocks and watermarks high until 3567 * first flip. After first flip, optimization is required to lower 3568 * bandwidth. Important to note that it is expected UEFI will 3569 * only light up a single display on POST, therefore we only expect 3570 * one stream with seamless boot flag set. 3571 */ 3572 if (stream->apply_seamless_boot_optimization) { 3573 stream->apply_seamless_boot_optimization = false; 3574 3575 if (get_seamless_boot_stream_count(context) == 0) 3576 dc->optimized_required = true; 3577 } 3578 } 3579 } 3580 3581 static bool full_update_required_weak( 3582 const struct dc *dc, 3583 const struct dc_surface_update *srf_updates, 3584 int surface_count, 3585 const struct dc_stream_update *stream_update, 3586 const struct dc_stream_state *stream); 3587 3588 struct pipe_split_policy_backup { 3589 bool dynamic_odm_policy; 3590 bool subvp_policy; 3591 enum pipe_split_policy mpc_policy; 3592 char force_odm[MAX_PIPES]; 3593 }; 3594 3595 static void backup_and_set_minimal_pipe_split_policy(struct dc *dc, 3596 struct dc_state *context, 3597 struct pipe_split_policy_backup *policy) 3598 { 3599 int i; 3600 3601 if (!dc->config.is_vmin_only_asic) { 3602 policy->mpc_policy = dc->debug.pipe_split_policy; 3603 dc->debug.pipe_split_policy = MPC_SPLIT_AVOID; 3604 } 3605 policy->dynamic_odm_policy = dc->debug.enable_single_display_2to1_odm_policy; 3606 dc->debug.enable_single_display_2to1_odm_policy = false; 3607 policy->subvp_policy = dc->debug.force_disable_subvp; 3608 dc->debug.force_disable_subvp = true; 3609 for (i = 0; i < context->stream_count; i++) { 3610 policy->force_odm[i] = context->streams[i]->debug.force_odm_combine_segments; 3611 if (context->streams[i]->debug.allow_transition_for_forced_odm) 3612 context->streams[i]->debug.force_odm_combine_segments = 0; 3613 } 3614 } 3615 3616 static void restore_minimal_pipe_split_policy(struct dc *dc, 3617 struct dc_state *context, 3618 struct pipe_split_policy_backup *policy) 3619 { 3620 uint8_t i; 3621 3622 if (!dc->config.is_vmin_only_asic) 3623 dc->debug.pipe_split_policy = policy->mpc_policy; 3624 dc->debug.enable_single_display_2to1_odm_policy = 3625 policy->dynamic_odm_policy; 3626 dc->debug.force_disable_subvp = policy->subvp_policy; 3627 for (i = 0; i < context->stream_count; i++) 3628 context->streams[i]->debug.force_odm_combine_segments = policy->force_odm[i]; 3629 } 3630 3631 /** 3632 * update_planes_and_stream_state() - The function takes planes and stream 3633 * updates as inputs and determines the appropriate update type. If update type 3634 * is FULL, the function allocates a new context, populates and validates it. 3635 * Otherwise, it updates current dc context. The function will return both 3636 * new_context and new_update_type back to the caller. The function also backs 3637 * up both current and new contexts into corresponding dc state scratch memory. 3638 * TODO: The function does too many things, and even conditionally allocates dc 3639 * context memory implicitly. We should consider to break it down. 3640 * 3641 * @dc: Current DC state 3642 * @srf_updates: an array of surface updates 3643 * @surface_count: surface update count 3644 * @stream: Corresponding stream to be updated 3645 * @stream_update: stream update 3646 * @update_descriptor: describes what plane and stream changes to apply 3647 * @new_update_type: [out] determined update type by the function 3648 * @new_context: [out] new context allocated and validated if update type is 3649 * FULL, reference to current context if update type is less than FULL. 3650 * 3651 * Return: true if a valid update is populated into new_context, false 3652 * otherwise. 3653 */ 3654 static bool update_planes_and_stream_state(struct dc *dc, 3655 struct dc_surface_update *srf_updates, int surface_count, 3656 struct dc_stream_state *stream, 3657 struct dc_stream_update *stream_update, 3658 enum surface_update_type *new_update_type, 3659 struct dc_state **new_context) 3660 { 3661 struct dc_state *context; 3662 int i; 3663 unsigned int j; 3664 enum surface_update_type update_type; 3665 const struct dc_stream_status *stream_status; 3666 struct dc_context *dc_ctx = dc->ctx; 3667 3668 stream_status = dc_stream_get_status(stream); 3669 3670 if (!stream_status) { 3671 if (surface_count) /* Only an error condition if surf_count non-zero*/ 3672 ASSERT(false); 3673 3674 return false; /* Cannot commit surface to stream that is not committed */ 3675 } 3676 3677 context = dc->current_state; 3678 update_type = dc_check_update_surfaces_for_stream( 3679 &dc->check_config, srf_updates, surface_count, stream_update).update_type; 3680 if (full_update_required_weak(dc, srf_updates, surface_count, stream_update, stream)) 3681 update_type = UPDATE_TYPE_FULL; 3682 3683 /* It is possible to receive a flip for one plane while there are multiple flip_immediate planes in the same stream. 3684 * E.g. Desktop and MPO plane are flip_immediate but only the MPO plane received a flip 3685 * Force the other flip_immediate planes to flip so GSL doesn't wait for a flip that won't come. 3686 */ 3687 force_immediate_gsl_plane_flip(dc, srf_updates, surface_count); 3688 if (update_type == UPDATE_TYPE_FULL) 3689 backup_planes_and_stream_state(&dc->scratch.current_state, stream); 3690 3691 /* update current stream with the new updates */ 3692 copy_stream_update_to_stream(dc, context, stream, stream_update); 3693 3694 /* do not perform surface update if surface has invalid dimensions 3695 * (all zero) and no scaling_info is provided 3696 */ 3697 if (surface_count > 0) { 3698 for (i = 0; i < surface_count; i++) { 3699 if ((srf_updates[i].surface->src_rect.width == 0 || 3700 srf_updates[i].surface->src_rect.height == 0 || 3701 srf_updates[i].surface->dst_rect.width == 0 || 3702 srf_updates[i].surface->dst_rect.height == 0) && 3703 (!srf_updates[i].scaling_info || 3704 srf_updates[i].scaling_info->src_rect.width == 0 || 3705 srf_updates[i].scaling_info->src_rect.height == 0 || 3706 srf_updates[i].scaling_info->dst_rect.width == 0 || 3707 srf_updates[i].scaling_info->dst_rect.height == 0)) { 3708 DC_ERROR("Invalid src/dst rects in surface update!\n"); 3709 return false; 3710 } 3711 } 3712 } 3713 3714 if (update_type == UPDATE_TYPE_FULL) { 3715 if (stream_update) { 3716 uint32_t dsc_changed = stream_update->stream->update_flags.bits.dsc_changed; 3717 stream_update->stream->update_flags.raw = 0xFFFFFFFF; 3718 stream_update->stream->update_flags.bits.dsc_changed = dsc_changed; 3719 } 3720 for (i = 0; i < surface_count; i++) 3721 srf_updates[i].surface->update_flags.raw = 0xFFFFFFFF; 3722 } 3723 3724 if (update_type >= update_surface_trace_level) 3725 update_surface_trace(dc, srf_updates, surface_count); 3726 3727 for (i = 0; i < surface_count; i++) 3728 copy_surface_update_to_plane(srf_updates[i].surface, &srf_updates[i]); 3729 3730 if (update_type >= UPDATE_TYPE_FULL) { 3731 struct dc_plane_state *new_planes[MAX_SURFACES] = {0}; 3732 3733 for (i = 0; i < surface_count; i++) 3734 new_planes[i] = srf_updates[i].surface; 3735 3736 /* initialize scratch memory for building context */ 3737 context = dc_state_create_copy(dc->current_state); 3738 if (context == NULL) { 3739 DC_ERROR("Failed to allocate new validate context!\n"); 3740 return false; 3741 } 3742 3743 /* For each full update, remove all existing phantom pipes first. 3744 * Ensures that we have enough pipes for newly added MPO planes 3745 */ 3746 dc_state_remove_phantom_streams_and_planes(dc, context); 3747 dc_state_release_phantom_streams_and_planes(dc, context); 3748 3749 /*remove old surfaces from context */ 3750 if (!dc_state_rem_all_planes_for_stream(dc, stream, context)) { 3751 3752 BREAK_TO_DEBUGGER(); 3753 goto fail; 3754 } 3755 3756 /* add surface to context */ 3757 if (!dc_state_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) { 3758 3759 BREAK_TO_DEBUGGER(); 3760 goto fail; 3761 } 3762 } 3763 3764 /* save update parameters into surface */ 3765 for (i = 0; i < surface_count; i++) { 3766 struct dc_plane_state *surface = srf_updates[i].surface; 3767 3768 if (update_type != UPDATE_TYPE_MED) 3769 continue; 3770 if (surface->update_flags.bits.position_change) { 3771 for (j = 0; j < dc->res_pool->pipe_count; j++) { 3772 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 3773 3774 if (pipe_ctx->plane_state != surface) 3775 continue; 3776 3777 resource_build_scaling_params(pipe_ctx); 3778 } 3779 } 3780 } 3781 3782 if (update_type == UPDATE_TYPE_FULL) { 3783 struct pipe_split_policy_backup policy; 3784 bool minimize = false; 3785 3786 if (dc->check_config.deferred_transition_state) { 3787 if (dc->check_config.transition_countdown_to_steady_state) { 3788 /* During countdown, all new contexts created as minimal transition states */ 3789 minimize = true; 3790 } else { 3791 dc->check_config.deferred_transition_state = false; 3792 } 3793 } 3794 3795 if (minimize) 3796 backup_and_set_minimal_pipe_split_policy(dc, context, &policy); 3797 3798 if (dc->res_pool->funcs->validate_bandwidth(dc, context, DC_VALIDATE_MODE_AND_PROGRAMMING) != DC_OK) { 3799 if (minimize) 3800 restore_minimal_pipe_split_policy(dc, context, &policy); 3801 BREAK_TO_DEBUGGER(); 3802 goto fail; 3803 } 3804 3805 if (minimize) 3806 restore_minimal_pipe_split_policy(dc, context, &policy); 3807 } 3808 update_seamless_boot_flags(dc, context, surface_count, stream); 3809 3810 *new_context = context; 3811 *new_update_type = update_type; 3812 if (update_type == UPDATE_TYPE_FULL) 3813 backup_planes_and_stream_state(&dc->scratch.new_state, stream); 3814 3815 return true; 3816 3817 fail: 3818 dc_state_release(context); 3819 3820 return false; 3821 3822 } 3823 3824 static void program_cursor_attributes_sequence( 3825 struct dc *dc, 3826 struct dc_stream_state *stream, 3827 struct dc_state *context, 3828 struct block_sequence_state *seq_state) 3829 { 3830 int k; 3831 struct pipe_ctx *pipe_to_program = NULL; 3832 bool enable_cursor_offload = dc_dmub_srv_is_cursor_offload_enabled(dc); 3833 3834 for (k = 0; k < (int)dc->res_pool->pipe_count; k++) { 3835 struct pipe_ctx *tmp_pipe = &context->res_ctx.pipe_ctx[k]; 3836 3837 if (tmp_pipe->stream != stream) 3838 continue; 3839 3840 if (!pipe_to_program) { 3841 pipe_to_program = tmp_pipe; 3842 3843 if (enable_cursor_offload && dc->hwss.begin_cursor_offload_update) { 3844 hwss_add_begin_cursor_offload_update(seq_state, dc, tmp_pipe); 3845 } else { 3846 hwss_add_cursor_lock(seq_state, dc, pipe_to_program, true); 3847 if (pipe_to_program->next_odm_pipe) 3848 hwss_add_cursor_lock(seq_state, dc, pipe_to_program->next_odm_pipe, true); 3849 } 3850 } 3851 3852 hwss_add_set_cursor_attribute(seq_state, dc, tmp_pipe); 3853 if (dc->ctx->dmub_srv) 3854 hwss_add_send_update_cursor_info_to_dmu(seq_state, tmp_pipe, k); 3855 if (dc->hwss.set_cursor_sdr_white_level) 3856 hwss_add_set_cursor_sdr_white_level(seq_state, dc, tmp_pipe); 3857 if (enable_cursor_offload && dc->hwss.update_cursor_offload_pipe) 3858 hwss_add_update_cursor_offload_pipe(seq_state, dc, tmp_pipe); 3859 } 3860 3861 if (pipe_to_program) { 3862 if (enable_cursor_offload && dc->hwss.commit_cursor_offload_update) { 3863 hwss_add_commit_cursor_offload_update(seq_state, dc, pipe_to_program); 3864 } else { 3865 hwss_add_cursor_lock(seq_state, dc, pipe_to_program, false); 3866 if (pipe_to_program->next_odm_pipe) 3867 hwss_add_cursor_lock(seq_state, dc, pipe_to_program->next_odm_pipe, false); 3868 } 3869 } 3870 } 3871 3872 static void program_cursor_position_sequence( 3873 struct dc *dc, 3874 struct dc_stream_state *stream, 3875 struct dc_state *context, 3876 struct block_sequence_state *seq_state) 3877 { 3878 int k; 3879 struct pipe_ctx *pipe_to_program = NULL; 3880 bool enable_cursor_offload = dc_dmub_srv_is_cursor_offload_enabled(dc); 3881 3882 for (k = 0; k < (int)dc->res_pool->pipe_count; k++) { 3883 struct pipe_ctx *tmp_pipe = &context->res_ctx.pipe_ctx[k]; 3884 3885 if (tmp_pipe->stream != stream || 3886 (!tmp_pipe->plane_res.mi && !tmp_pipe->plane_res.hubp) || 3887 !tmp_pipe->plane_state || 3888 (!tmp_pipe->plane_res.xfm && !tmp_pipe->plane_res.dpp) || 3889 (!tmp_pipe->plane_res.ipp && !tmp_pipe->plane_res.dpp)) 3890 continue; 3891 3892 if (!pipe_to_program) { 3893 pipe_to_program = tmp_pipe; 3894 3895 if (enable_cursor_offload && dc->hwss.begin_cursor_offload_update) 3896 hwss_add_begin_cursor_offload_update(seq_state, dc, tmp_pipe); 3897 else 3898 hwss_add_cursor_lock(seq_state, dc, pipe_to_program, true); 3899 } 3900 3901 hwss_add_set_cursor_position(seq_state, dc, tmp_pipe); 3902 if (enable_cursor_offload && dc->hwss.update_cursor_offload_pipe) 3903 hwss_add_update_cursor_offload_pipe(seq_state, dc, tmp_pipe); 3904 3905 if (dc->ctx->dmub_srv) 3906 hwss_add_send_update_cursor_info_to_dmu(seq_state, tmp_pipe, k); 3907 } 3908 3909 if (pipe_to_program) { 3910 if (enable_cursor_offload && dc->hwss.commit_cursor_offload_update) 3911 hwss_add_commit_cursor_offload_update(seq_state, dc, pipe_to_program); 3912 else 3913 hwss_add_cursor_lock(seq_state, dc, pipe_to_program, false); 3914 } 3915 } 3916 3917 static void add_update_info_frame_sequence( 3918 struct block_sequence_state *seq_state, 3919 struct pipe_ctx *pipe_ctx) 3920 { 3921 bool is_hdmi_tmds; 3922 bool is_dp; 3923 bool is_hdmi_frl; 3924 3925 if (!pipe_ctx || !pipe_ctx->stream) 3926 return; 3927 3928 if (pipe_ctx->stream_res.stream_enc == NULL && 3929 pipe_ctx->stream_res.hpo_frl_stream_enc == NULL) 3930 return; 3931 3932 is_hdmi_tmds = dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal); 3933 is_dp = dc_is_dp_signal(pipe_ctx->stream->signal); 3934 3935 is_hdmi_frl = dc_is_hdmi_frl_signal(pipe_ctx->stream->signal); 3936 if (!is_hdmi_tmds && !is_dp && !is_hdmi_frl) 3937 return; 3938 3939 if (is_hdmi_tmds) { 3940 hwss_add_stream_enc_update_hdmi_info_packets(seq_state, pipe_ctx); 3941 return; 3942 } 3943 3944 if (is_hdmi_frl) { 3945 hwss_add_hpo_frl_stream_enc_update_hdmi_info_packets(seq_state, pipe_ctx); 3946 return; 3947 } 3948 3949 if (is_dp) { 3950 if (dp_is_128b_132b_signal(pipe_ctx)) { 3951 hwss_add_hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num(seq_state, pipe_ctx); 3952 hwss_add_hpo_dp_stream_enc_update_dp_info_packets(seq_state, pipe_ctx); 3953 } else { 3954 hwss_add_stream_enc_update_dp_info_packets_sdp_line_num(seq_state, pipe_ctx); 3955 hwss_add_stream_enc_update_dp_info_packets(seq_state, pipe_ctx); 3956 } 3957 } 3958 } 3959 3960 static void add_link_update_dsc_config_sequence( 3961 struct block_sequence_state *seq_state, 3962 struct pipe_ctx *pipe_ctx, 3963 struct dsc_config *dsc_cfg, 3964 struct dsc_optc_config *dsc_optc_cfg) 3965 { 3966 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; 3967 struct dc_stream_state *stream = pipe_ctx->stream; 3968 struct dc *dc = stream->ctx->dc; 3969 struct dccg *dccg = dc->res_pool->dccg; 3970 struct pipe_ctx *top_pipe = pipe_ctx; 3971 struct pipe_ctx *odm_pipe = NULL; 3972 int opp_cnt = 1; 3973 bool should_use_dto_dscclk = false; 3974 struct dsc_config dsc_pps_cfg; 3975 uint8_t *dsc_packed_pps = stream->dsc_packed_pps; 3976 int last_dsc_set_config_step = 0; 3977 3978 if (!stream->timing.flags.DSC || !dsc) 3979 return; 3980 3981 while (top_pipe->prev_odm_pipe) 3982 top_pipe = top_pipe->prev_odm_pipe; 3983 3984 for (odm_pipe = top_pipe->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) 3985 opp_cnt++; 3986 3987 memset(dsc_cfg, 0, sizeof(*dsc_cfg)); 3988 memset(dsc_optc_cfg, 0, sizeof(*dsc_optc_cfg)); 3989 3990 dsc_cfg->pic_width = (stream->timing.h_addressable + 3991 top_pipe->dsc_padding_params.dsc_hactive_padding + 3992 stream->timing.h_border_left + 3993 stream->timing.h_border_right) / opp_cnt; 3994 dsc_cfg->pic_height = stream->timing.v_addressable + 3995 stream->timing.v_border_top + 3996 stream->timing.v_border_bottom; 3997 dsc_cfg->pixel_encoding = stream->timing.pixel_encoding; 3998 dsc_cfg->color_depth = stream->timing.display_color_depth; 3999 dsc_cfg->is_odm = top_pipe->next_odm_pipe ? true : false; 4000 dsc_cfg->dc_dsc_cfg = stream->timing.dsc_cfg; 4001 ASSERT(dsc_cfg->dc_dsc_cfg.num_slices_h % opp_cnt == 0); 4002 dsc_cfg->dc_dsc_cfg.num_slices_h /= opp_cnt; 4003 dsc_cfg->dsc_padding = 0; 4004 4005 if (dccg && dccg->funcs->set_dto_dscclk && 4006 stream->timing.pix_clk_100hz > 480000) 4007 should_use_dto_dscclk = true; 4008 4009 if (should_use_dto_dscclk) 4010 hwss_add_dccg_set_dto_dscclk(seq_state, dccg, dsc->inst, 4011 dsc_cfg->dc_dsc_cfg.num_slices_h); 4012 4013 last_dsc_set_config_step = *seq_state->num_steps; 4014 hwss_add_dsc_set_config(seq_state, dsc, dsc_cfg, dsc_optc_cfg); 4015 hwss_add_dsc_enable_with_opp(seq_state, top_pipe); 4016 4017 for (odm_pipe = top_pipe->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { 4018 struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc; 4019 4020 if (should_use_dto_dscclk) 4021 hwss_add_dccg_set_dto_dscclk(seq_state, dccg, odm_dsc->inst, 4022 dsc_cfg->dc_dsc_cfg.num_slices_h); 4023 4024 last_dsc_set_config_step = *seq_state->num_steps; 4025 hwss_add_dsc_set_config(seq_state, odm_dsc, dsc_cfg, dsc_optc_cfg); 4026 hwss_add_dsc_enable_with_opp(seq_state, odm_pipe); 4027 } 4028 4029 if (dc_is_dp_signal(stream->signal) && !dp_is_128b_132b_signal(pipe_ctx)) 4030 hwss_add_stream_enc_dp_set_dsc_config(seq_state, 4031 pipe_ctx->stream_res.stream_enc, 4032 &seq_state->steps[last_dsc_set_config_step].params.dsc_set_config_simple_params.dsc_optc_cfg); 4033 4034 hwss_add_tg_set_dsc_config(seq_state, top_pipe->stream_res.tg, 4035 &seq_state->steps[last_dsc_set_config_step].params.dsc_set_config_simple_params.dsc_optc_cfg, true); 4036 4037 memset(&dsc_pps_cfg, 0, sizeof(dsc_pps_cfg)); 4038 dsc_pps_cfg.pic_width = stream->timing.h_addressable + 4039 stream->timing.h_border_left + stream->timing.h_border_right; 4040 dsc_pps_cfg.pic_height = stream->timing.v_addressable + 4041 stream->timing.v_border_top + stream->timing.v_border_bottom; 4042 dsc_pps_cfg.pixel_encoding = stream->timing.pixel_encoding; 4043 dsc_pps_cfg.color_depth = stream->timing.display_color_depth; 4044 dsc_pps_cfg.is_odm = top_pipe->next_odm_pipe ? true : false; 4045 dsc_pps_cfg.dc_dsc_cfg = stream->timing.dsc_cfg; 4046 dsc_pps_cfg.dsc_padding = top_pipe->dsc_padding_params.dsc_hactive_padding; 4047 4048 if (dsc->funcs->dsc_get_packed_pps) { 4049 dsc->funcs->dsc_get_packed_pps(dsc, &dsc_pps_cfg, dsc_packed_pps); 4050 4051 if (dc_is_dp_signal(stream->signal)) { 4052 if (dp_is_128b_132b_signal(pipe_ctx)) 4053 hwss_add_hpo_dp_stream_enc_dp_set_dsc_pps_info_packet(seq_state, 4054 pipe_ctx->stream_res.hpo_dp_stream_enc, 4055 true, dsc_packed_pps, false); 4056 else 4057 hwss_add_stream_enc_dp_set_dsc_pps_info_packet(seq_state, 4058 pipe_ctx->stream_res.stream_enc, 4059 true, dsc_packed_pps, false); 4060 } 4061 else if (dc_is_hdmi_frl_signal(stream->signal)) { 4062 hwss_add_hpo_frl_stream_enc_set_dsc_config(seq_state, 4063 pipe_ctx->stream_res.hpo_frl_stream_enc, 4064 &stream->timing, 4065 dsc_packed_pps); 4066 } 4067 } 4068 } 4069 4070 static void commit_planes_do_stream_update_sequence(struct dc *dc, 4071 struct dc_stream_state *stream, 4072 struct dc_stream_update *stream_update, 4073 enum surface_update_type update_type, 4074 struct dc_state *context, 4075 struct block_sequence block_sequence[MAX_HWSS_BLOCK_SEQUENCE_SIZE], 4076 unsigned int *num_steps) 4077 { 4078 int j; 4079 struct block_sequence_state seq_state = { .steps = block_sequence, .num_steps = num_steps }; 4080 struct dsc_config dsc_cfgs[MAX_PIPES]; 4081 struct dsc_optc_config dsc_optc_cfgs[MAX_PIPES]; 4082 unsigned int dsc_cfg_index = 0; 4083 *num_steps = 0; // Initialize to 0 4084 4085 // Stream updates 4086 for (j = 0; j < (int)dc->res_pool->pipe_count; j++) { 4087 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 4088 4089 if (resource_is_pipe_type(pipe_ctx, OTG_MASTER) && pipe_ctx->stream == stream) { 4090 4091 if (stream_update->periodic_interrupt && dc->hwss.setup_periodic_interrupt) 4092 hwss_add_setup_periodic_interrupt(&seq_state, dc, pipe_ctx); 4093 4094 if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) || 4095 stream_update->vrr_infopacket || 4096 stream_update->vsc_infopacket || 4097 stream_update->vsp_infopacket || 4098 stream_update->hfvsif_infopacket || 4099 stream_update->adaptive_sync_infopacket || 4100 stream_update->vtem_infopacket || 4101 stream_update->avi_infopacket) { 4102 resource_build_info_frame(pipe_ctx); 4103 add_update_info_frame_sequence(&seq_state, pipe_ctx); 4104 4105 if (dc_is_dp_signal(pipe_ctx->stream->signal)) 4106 hwss_add_dp_trace_source_sequence(&seq_state, 4107 pipe_ctx->stream->link, 4108 DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME); 4109 } 4110 4111 if (stream_update->hdr_static_metadata && 4112 stream->use_dynamic_meta && 4113 dc->hwss.set_dmdata_attributes && 4114 pipe_ctx->stream->dmdata_address.quad_part != 0) 4115 hwss_add_set_dmdata_attributes(&seq_state, pipe_ctx); 4116 4117 if (stream_update->gamut_remap) 4118 hwss_add_dpp_program_gamut_remap(&seq_state, pipe_ctx); 4119 4120 if (stream_update->output_csc_transform) 4121 hwss_add_program_output_csc(&seq_state, dc, pipe_ctx, 4122 stream->output_color_space, 4123 stream->csc_color_matrix.matrix, 4124 pipe_ctx->stream_res.opp->inst); 4125 4126 if (stream_update->dither_option) { 4127 struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe; 4128 resource_build_bit_depth_reduction_params(pipe_ctx->stream, 4129 &pipe_ctx->stream->bit_depth_params); 4130 hwss_add_opp_program_fmt(&seq_state, pipe_ctx->stream_res.opp, 4131 &stream->bit_depth_params, 4132 &stream->clamping); 4133 while (odm_pipe) { 4134 hwss_add_opp_program_fmt(&seq_state, odm_pipe->stream_res.opp, 4135 &stream->bit_depth_params, 4136 &stream->clamping); 4137 odm_pipe = odm_pipe->next_odm_pipe; 4138 } 4139 } 4140 4141 if (stream_update->cursor_attributes) 4142 program_cursor_attributes_sequence(dc, stream, context, &seq_state); 4143 4144 if (stream_update->cursor_position) 4145 program_cursor_position_sequence(dc, stream, context, &seq_state); 4146 4147 /* Full fe update*/ 4148 if (update_type == UPDATE_TYPE_FAST) 4149 continue; 4150 4151 if (stream_update->dsc_config) 4152 if (dsc_cfg_index < MAX_PIPES) { 4153 add_link_update_dsc_config_sequence(&seq_state, 4154 pipe_ctx, 4155 &dsc_cfgs[dsc_cfg_index], 4156 &dsc_optc_cfgs[dsc_cfg_index]); 4157 dsc_cfg_index++; 4158 } 4159 4160 if (stream_update->mst_bw_update) { 4161 if (stream_update->mst_bw_update->is_increase) 4162 hwss_add_link_increase_mst_payload(&seq_state, 4163 pipe_ctx, 4164 stream_update->mst_bw_update->mst_stream_bw); 4165 else 4166 hwss_add_link_reduce_mst_payload(&seq_state, 4167 pipe_ctx, 4168 stream_update->mst_bw_update->mst_stream_bw); 4169 } 4170 4171 if (stream_update->pending_test_pattern) { 4172 /* 4173 * test pattern params depends on ODM topology 4174 * changes that we could be applying to front 4175 * end. Since at the current stage front end 4176 * changes are not yet applied. We can only 4177 * apply test pattern in hw based on current 4178 * state and populate the final test pattern 4179 * params in new state. If current and new test 4180 * pattern params are different as result of 4181 * different ODM topology being used, it will be 4182 * detected and handle during front end 4183 * programming update. 4184 */ 4185 hwss_add_dp_set_test_pattern(&seq_state, 4186 stream->link, 4187 stream->test_pattern.type, 4188 stream->test_pattern.color_space, 4189 stream->test_pattern.p_link_settings, 4190 stream->test_pattern.p_custom_pattern, 4191 stream->test_pattern.cust_pattern_size); 4192 resource_build_test_pattern_params(&context->res_ctx, pipe_ctx); 4193 } 4194 4195 if (stream_update->dpms_off) { 4196 // DPMS should not use partially updated pipe context 4197 struct pipe_ctx *dpms_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[j]; 4198 4199 if (*stream_update->dpms_off) { 4200 hwss_add_link_set_dpms_off(&seq_state, dpms_pipe_ctx); 4201 /* for dpms, keep acquired resources*/ 4202 if (dpms_pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only) 4203 hwss_add_disable_audio_stream(&seq_state, dpms_pipe_ctx); 4204 4205 hwss_add_dc_set_optimized_required(&seq_state, dc, true); 4206 4207 } else { 4208 if (get_seamless_boot_stream_count(context) == 0) 4209 hwss_add_prepare_bandwidth(&seq_state, dc, dc->current_state); 4210 hwss_add_link_set_dpms_on(&seq_state, dc->current_state, dpms_pipe_ctx); 4211 } 4212 } else if (pipe_ctx->stream->link->wa_flags.blank_stream_on_ocs_change && stream_update->output_color_space 4213 && !stream->dpms_off && dc_is_dp_signal(pipe_ctx->stream->signal)) { 4214 /* 4215 * Workaround for firmware issue in some receivers where they don't pick up 4216 * correct output color space unless DP link is disabled/re-enabled 4217 */ 4218 hwss_add_link_set_dpms_on(&seq_state, dc->current_state, pipe_ctx); 4219 } 4220 4221 if (stream_update->abm_level && pipe_ctx->stream_res.abm) { 4222 bool should_program_abm = true; 4223 4224 // if otg funcs defined check if blanked before programming 4225 if (pipe_ctx->stream_res.tg->funcs->is_blanked) 4226 if (pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg)) 4227 should_program_abm = false; 4228 4229 if (should_program_abm) { 4230 if (*stream_update->abm_level == ABM_LEVEL_IMMEDIATE_DISABLE) { 4231 hwss_add_abm_set_immediate_disable(&seq_state, dc, pipe_ctx); 4232 } else { 4233 hwss_add_abm_set_level(&seq_state, pipe_ctx->stream_res.abm, stream->abm_level); 4234 } 4235 } 4236 } 4237 } 4238 } 4239 } 4240 4241 static void commit_planes_do_stream_update(struct dc *dc, 4242 struct dc_stream_state *stream, 4243 struct dc_stream_update *stream_update, 4244 enum surface_update_type update_type, 4245 struct dc_state *context) 4246 { 4247 unsigned int j; 4248 4249 // Check if block sequence programming is enabled 4250 if (dc->debug.enable_block_sequence_programming) { 4251 unsigned int num_steps = 0; 4252 4253 // Build the block sequence using context's pre-allocated array 4254 commit_planes_do_stream_update_sequence(dc, stream, stream_update, 4255 update_type, context, context->block_sequence, &num_steps); 4256 4257 // Execute the block sequence 4258 if (num_steps > 0) 4259 hwss_execute_sequence(dc, context->block_sequence, num_steps); 4260 4261 return; 4262 } 4263 4264 // Legacy path (existing implementation) 4265 // Stream updates 4266 for (j = 0; j < dc->res_pool->pipe_count; j++) { 4267 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 4268 4269 if (resource_is_pipe_type(pipe_ctx, OTG_MASTER) && pipe_ctx->stream == stream) { 4270 4271 if (stream_update->periodic_interrupt && dc->hwss.setup_periodic_interrupt) 4272 dc->hwss.setup_periodic_interrupt(dc, pipe_ctx); 4273 4274 if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) || 4275 stream_update->vrr_infopacket || 4276 stream_update->vsc_infopacket || 4277 stream_update->vsp_infopacket || 4278 stream_update->hfvsif_infopacket || 4279 stream_update->adaptive_sync_infopacket || 4280 stream_update->vtem_infopacket || 4281 stream_update->avi_infopacket) { 4282 resource_build_info_frame(pipe_ctx); 4283 dc->hwss.update_info_frame(pipe_ctx); 4284 4285 if (dc_is_dp_signal(pipe_ctx->stream->signal)) 4286 dc->link_srv->dp_trace_source_sequence( 4287 pipe_ctx->stream->link, 4288 DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME); 4289 } 4290 4291 if (stream_update->hdr_static_metadata && 4292 stream->use_dynamic_meta && 4293 dc->hwss.set_dmdata_attributes && 4294 pipe_ctx->stream->dmdata_address.quad_part != 0) 4295 dc->hwss.set_dmdata_attributes(pipe_ctx); 4296 4297 if (stream_update->gamut_remap) 4298 dc_stream_set_gamut_remap(dc, stream); 4299 4300 if (stream_update->output_csc_transform) 4301 dc_stream_program_csc_matrix(dc, stream); 4302 4303 if (stream_update->dither_option) { 4304 struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe; 4305 resource_build_bit_depth_reduction_params(pipe_ctx->stream, 4306 &pipe_ctx->stream->bit_depth_params); 4307 pipe_ctx->stream_res.opp->funcs->opp_program_fmt(pipe_ctx->stream_res.opp, 4308 &stream->bit_depth_params, 4309 &stream->clamping); 4310 while (odm_pipe) { 4311 odm_pipe->stream_res.opp->funcs->opp_program_fmt(odm_pipe->stream_res.opp, 4312 &stream->bit_depth_params, 4313 &stream->clamping); 4314 odm_pipe = odm_pipe->next_odm_pipe; 4315 } 4316 } 4317 4318 if (stream_update->cursor_attributes) 4319 program_cursor_attributes(dc, stream); 4320 4321 if (stream_update->cursor_position) 4322 program_cursor_position(dc, stream); 4323 4324 /* Full fe update*/ 4325 if (update_type == UPDATE_TYPE_FAST) 4326 continue; 4327 4328 if (stream_update->dsc_config) 4329 dc->link_srv->update_dsc_config(pipe_ctx); 4330 4331 if (stream_update->mst_bw_update) { 4332 if (stream_update->mst_bw_update->is_increase) 4333 dc->link_srv->increase_mst_payload(pipe_ctx, 4334 stream_update->mst_bw_update->mst_stream_bw); 4335 else 4336 dc->link_srv->reduce_mst_payload(pipe_ctx, 4337 stream_update->mst_bw_update->mst_stream_bw); 4338 } 4339 4340 if (stream_update->pending_test_pattern) { 4341 /* 4342 * test pattern params depends on ODM topology 4343 * changes that we could be applying to front 4344 * end. Since at the current stage front end 4345 * changes are not yet applied. We can only 4346 * apply test pattern in hw based on current 4347 * state and populate the final test pattern 4348 * params in new state. If current and new test 4349 * pattern params are different as result of 4350 * different ODM topology being used, it will be 4351 * detected and handle during front end 4352 * programming update. 4353 */ 4354 dc->link_srv->dp_set_test_pattern(stream->link, 4355 stream->test_pattern.type, 4356 stream->test_pattern.color_space, 4357 stream->test_pattern.p_link_settings, 4358 stream->test_pattern.p_custom_pattern, 4359 stream->test_pattern.cust_pattern_size); 4360 resource_build_test_pattern_params(&context->res_ctx, pipe_ctx); 4361 } 4362 4363 // DPMS should not use partially updated pipe context 4364 struct pipe_ctx *dpms_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[j]; 4365 4366 if (stream_update->dpms_off) { 4367 if (*stream_update->dpms_off) { 4368 dc->link_srv->set_dpms_off(dpms_pipe_ctx); 4369 /* for dpms, keep acquired resources*/ 4370 if (dpms_pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only) { 4371 struct audio *audio = dpms_pipe_ctx->stream_res.audio; 4372 4373 audio->funcs->az_disable(audio); 4374 } 4375 4376 dc->optimized_required = true; 4377 4378 } else { 4379 if (get_seamless_boot_stream_count(context) == 0) 4380 dc->hwss.prepare_bandwidth(dc, dc->current_state); 4381 dc->link_srv->set_dpms_on(dc->current_state, dpms_pipe_ctx); 4382 } 4383 } else if (dpms_pipe_ctx->stream->link->wa_flags.blank_stream_on_ocs_change && 4384 stream_update->output_color_space && 4385 !stream->dpms_off && dc_is_dp_signal(dpms_pipe_ctx->stream->signal)) { 4386 /* 4387 * Workaround for firmware issue in some receivers where they don't pick up 4388 * correct output color space unless DP link is disabled/re-enabled 4389 */ 4390 dc->link_srv->set_dpms_on(dc->current_state, dpms_pipe_ctx); 4391 } 4392 4393 if (stream_update->abm_level && pipe_ctx->stream_res.abm) { 4394 bool should_program_abm = true; 4395 4396 // if otg funcs defined check if blanked before programming 4397 if (pipe_ctx->stream_res.tg->funcs->is_blanked) 4398 if (pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg)) 4399 should_program_abm = false; 4400 4401 if (should_program_abm) { 4402 if (*stream_update->abm_level == ABM_LEVEL_IMMEDIATE_DISABLE) { 4403 dc->hwss.set_abm_immediate_disable(pipe_ctx); 4404 } else { 4405 pipe_ctx->stream_res.abm->funcs->set_abm_level( 4406 pipe_ctx->stream_res.abm, stream->abm_level); 4407 } 4408 } 4409 } 4410 } 4411 } 4412 } 4413 4414 static bool dc_dmub_should_send_dirty_rect_cmd(struct dc *dc, struct dc_stream_state *stream) 4415 { 4416 (void)dc; 4417 if ((stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1 4418 || stream->link->psr_settings.psr_version == DC_PSR_VERSION_1) 4419 && stream->ctx->dce_version >= DCN_VERSION_3_1) 4420 return true; 4421 4422 if (stream->link->replay_settings.config.replay_supported) 4423 return true; 4424 4425 if (stream->ctx->dce_version >= DCN_VERSION_3_5 && stream->abm_level) 4426 return true; 4427 4428 return false; 4429 } 4430 4431 void dc_dmub_update_dirty_rect(struct dc *dc, 4432 int surface_count, 4433 struct dc_stream_state *stream, 4434 const struct dc_surface_update *srf_updates, 4435 struct dc_state *context) 4436 { 4437 union dmub_rb_cmd cmd; 4438 struct dmub_cmd_update_dirty_rect_data *update_dirty_rect; 4439 int i; 4440 unsigned int j; 4441 unsigned int panel_inst = 0; 4442 4443 if (!dc_dmub_should_send_dirty_rect_cmd(dc, stream)) 4444 return; 4445 4446 if (!dc->config.frame_update_cmd_version2 && !dc_get_edp_link_panel_inst(dc, stream->link, &panel_inst)) 4447 return; 4448 4449 memset(&cmd, 0x0, sizeof(cmd)); 4450 cmd.update_dirty_rect.header.type = DMUB_CMD__UPDATE_DIRTY_RECT; 4451 cmd.update_dirty_rect.header.sub_type = 0; 4452 cmd.update_dirty_rect.header.payload_bytes = 4453 sizeof(cmd.update_dirty_rect) - 4454 sizeof(cmd.update_dirty_rect.header); 4455 update_dirty_rect = &cmd.update_dirty_rect.update_dirty_rect_data; 4456 for (i = 0; i < surface_count; i++) { 4457 struct dc_plane_state *plane_state = srf_updates[i].surface; 4458 const struct dc_flip_addrs *flip_addr = srf_updates[i].flip_addr; 4459 4460 if (!srf_updates[i].surface || !flip_addr) 4461 continue; 4462 /* Do not send in immediate flip mode */ 4463 if (srf_updates[i].surface->flip_immediate) 4464 continue; 4465 4466 if (dc->config.frame_update_cmd_version2) 4467 update_dirty_rect->cmd_version = DMUB_CMD_CURSOR_UPDATE_VERSION_2; 4468 else 4469 update_dirty_rect->cmd_version = DMUB_CMD_CURSOR_UPDATE_VERSION_1; 4470 4471 update_dirty_rect->dirty_rect_count = (uint8_t)flip_addr->dirty_rect_count; 4472 memcpy(update_dirty_rect->src_dirty_rects, flip_addr->dirty_rects, 4473 sizeof(flip_addr->dirty_rects)); 4474 for (j = 0; j < dc->res_pool->pipe_count; j++) { 4475 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 4476 4477 if (pipe_ctx->stream != stream) 4478 continue; 4479 if (pipe_ctx->plane_state != plane_state) 4480 continue; 4481 4482 update_dirty_rect->panel_inst = (uint8_t)panel_inst; 4483 update_dirty_rect->pipe_idx = (uint8_t)j; 4484 update_dirty_rect->otg_inst = (uint8_t)pipe_ctx->stream_res.tg->inst; 4485 dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); 4486 } 4487 } 4488 } 4489 4490 static void build_dmub_update_dirty_rect( 4491 struct dc *dc, 4492 int surface_count, 4493 struct dc_stream_state *stream, 4494 struct dc_surface_update *srf_updates, 4495 struct dc_state *context, 4496 struct dc_dmub_cmd dc_dmub_cmd[], 4497 unsigned int *dmub_cmd_count) 4498 { 4499 union dmub_rb_cmd cmd; 4500 struct dmub_cmd_update_dirty_rect_data *update_dirty_rect; 4501 int i; 4502 unsigned int j; 4503 unsigned int panel_inst = 0; 4504 4505 if (!dc_dmub_should_send_dirty_rect_cmd(dc, stream)) 4506 return; 4507 4508 if (!dc->config.frame_update_cmd_version2 && !dc_get_edp_link_panel_inst(dc, stream->link, &panel_inst)) 4509 return; 4510 4511 memset(&cmd, 0x0, sizeof(cmd)); 4512 cmd.update_dirty_rect.header.type = DMUB_CMD__UPDATE_DIRTY_RECT; 4513 cmd.update_dirty_rect.header.sub_type = 0; 4514 cmd.update_dirty_rect.header.payload_bytes = 4515 sizeof(cmd.update_dirty_rect) - 4516 sizeof(cmd.update_dirty_rect.header); 4517 update_dirty_rect = &cmd.update_dirty_rect.update_dirty_rect_data; 4518 for (i = 0; i < surface_count; i++) { 4519 struct dc_plane_state *plane_state = srf_updates[i].surface; 4520 const struct dc_flip_addrs *flip_addr = srf_updates[i].flip_addr; 4521 4522 if (!srf_updates[i].surface || !flip_addr) 4523 continue; 4524 /* Do not send in immediate flip mode */ 4525 if (srf_updates[i].surface->flip_immediate) 4526 continue; 4527 4528 if (dc->config.frame_update_cmd_version2) 4529 update_dirty_rect->cmd_version = DMUB_CMD_CURSOR_UPDATE_VERSION_2; 4530 else 4531 update_dirty_rect->cmd_version = DMUB_CMD_CURSOR_UPDATE_VERSION_1; 4532 4533 update_dirty_rect->dirty_rect_count = (uint8_t)flip_addr->dirty_rect_count; 4534 memcpy(update_dirty_rect->src_dirty_rects, flip_addr->dirty_rects, 4535 sizeof(flip_addr->dirty_rects)); 4536 for (j = 0; j < dc->res_pool->pipe_count; j++) { 4537 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 4538 4539 if (pipe_ctx->stream != stream) 4540 continue; 4541 if (pipe_ctx->plane_state != plane_state) 4542 continue; 4543 update_dirty_rect->panel_inst = (uint8_t)panel_inst; 4544 update_dirty_rect->pipe_idx = (uint8_t)j; 4545 update_dirty_rect->otg_inst = (uint8_t)pipe_ctx->stream_res.tg->inst; 4546 dc_dmub_cmd[*dmub_cmd_count].dmub_cmd = cmd; 4547 dc_dmub_cmd[*dmub_cmd_count].wait_type = DM_DMUB_WAIT_TYPE_NO_WAIT; 4548 (*dmub_cmd_count)++; 4549 } 4550 } 4551 } 4552 4553 static bool check_address_only_update(union surface_update_flags update_flags) 4554 { 4555 union surface_update_flags addr_only_update_flags; 4556 addr_only_update_flags.raw = 0; 4557 addr_only_update_flags.bits.addr_update = 1; 4558 4559 return update_flags.bits.addr_update && 4560 !(update_flags.raw & ~addr_only_update_flags.raw); 4561 } 4562 4563 /** 4564 * build_dmub_cmd_list() - Build an array of DMCUB commands to be sent to DMCUB 4565 * 4566 * @dc: Current DC state 4567 * @srf_updates: Array of surface updates 4568 * @surface_count: Number of surfaces that have an updated 4569 * @stream: Corresponding stream to be updated in the current flip 4570 * @context: New DC state to be programmed 4571 * 4572 * @dc_dmub_cmd: Array of DMCUB commands to be sent to DMCUB 4573 * @dmub_cmd_count: Count indicating the number of DMCUB commands in dc_dmub_cmd array 4574 * 4575 * This function builds an array of DMCUB commands to be sent to DMCUB. This function is required 4576 * to build an array of commands and have them sent while the OTG lock is acquired. 4577 * 4578 * Return: void 4579 */ 4580 static void build_dmub_cmd_list(struct dc *dc, 4581 struct dc_surface_update *srf_updates, 4582 int surface_count, 4583 struct dc_stream_state *stream, 4584 struct dc_state *context, 4585 struct dc_dmub_cmd dc_dmub_cmd[], 4586 unsigned int *dmub_cmd_count) 4587 { 4588 // Initialize cmd count to 0 4589 *dmub_cmd_count = 0; 4590 build_dmub_update_dirty_rect(dc, surface_count, stream, srf_updates, context, dc_dmub_cmd, dmub_cmd_count); 4591 } 4592 4593 static void commit_plane_for_stream_offload_fams2_flip(struct dc *dc, 4594 struct dc_surface_update *srf_updates, 4595 int surface_count, 4596 struct dc_stream_state *stream, 4597 struct dc_state *context) 4598 { 4599 int i; 4600 unsigned int j; 4601 4602 /* update dirty rect for PSR */ 4603 dc_dmub_update_dirty_rect(dc, surface_count, stream, 4604 srf_updates, context); 4605 4606 /* Perform requested Updates */ 4607 for (i = 0; i < surface_count; i++) { 4608 struct dc_plane_state *plane_state = srf_updates[i].surface; 4609 4610 for (j = 0; j < dc->res_pool->pipe_count; j++) { 4611 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 4612 4613 if (!should_update_pipe_for_stream(context, pipe_ctx, stream)) 4614 continue; 4615 4616 if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state)) 4617 continue; 4618 4619 /* update pipe context for plane */ 4620 if (pipe_ctx->plane_state->update_flags.bits.addr_update) 4621 dc->hwss.update_plane_addr(dc, pipe_ctx); 4622 } 4623 } 4624 4625 /* Send commands to DMCUB */ 4626 dc_dmub_srv_fams2_passthrough_flip(dc, 4627 context, 4628 stream, 4629 srf_updates, 4630 surface_count); 4631 } 4632 4633 static void commit_planes_for_stream_fast(struct dc *dc, 4634 struct dc_surface_update *srf_updates, 4635 int surface_count, 4636 struct dc_stream_state *stream, 4637 struct dc_stream_update *stream_update, 4638 enum surface_update_type update_type, 4639 struct dc_state *context) 4640 { 4641 int i; 4642 unsigned int j; 4643 struct pipe_ctx *top_pipe_to_program = NULL; 4644 struct dc_stream_status *stream_status = NULL; 4645 bool should_offload_fams2_flip = false; 4646 bool should_lock_all_pipes = (update_type != UPDATE_TYPE_FAST); 4647 4648 if (should_lock_all_pipes) 4649 determine_pipe_unlock_order(dc, context); 4650 4651 if (dc->debug.fams2_config.bits.enable && 4652 dc->debug.fams2_config.bits.enable_offload_flip && 4653 dc_state_is_fams2_in_use(dc, context)) { 4654 /* if not offloading to HWFQ, offload to FAMS2 if needed */ 4655 should_offload_fams2_flip = true; 4656 for (i = 0; i < surface_count; i++) { 4657 if (srf_updates[i].surface && 4658 srf_updates[i].surface->update_flags.raw && 4659 !check_address_only_update(srf_updates[i].surface->update_flags)) { 4660 /* more than address update, need to acquire FAMS2 lock */ 4661 should_offload_fams2_flip = false; 4662 break; 4663 } 4664 } 4665 if (stream_update) { 4666 /* more than address update, need to acquire FAMS2 lock */ 4667 should_offload_fams2_flip = false; 4668 } 4669 } 4670 4671 dc_exit_ips_for_hw_access(dc); 4672 4673 dc_z10_restore(dc); 4674 4675 top_pipe_to_program = resource_get_otg_master_for_stream( 4676 &context->res_ctx, 4677 stream); 4678 4679 if (!top_pipe_to_program) 4680 return; 4681 4682 for (i = 0; i < (int)dc->res_pool->pipe_count; i++) { 4683 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; 4684 4685 if (pipe->stream && pipe->plane_state) { 4686 if (!dc->debug.using_dml2) 4687 set_p_state_switch_method(dc, context, pipe); 4688 4689 if (dc->debug.visual_confirm) 4690 dc_update_visual_confirm_color(dc, context, pipe); 4691 } 4692 } 4693 4694 for (i = 0; i < surface_count; i++) { 4695 struct dc_plane_state *plane_state = srf_updates[i].surface; 4696 /*set logical flag for lock/unlock use*/ 4697 for (j = 0; j < dc->res_pool->pipe_count; j++) { 4698 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 4699 4700 if (!pipe_ctx->plane_state) 4701 continue; 4702 if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state)) 4703 continue; 4704 4705 pipe_ctx->plane_state->triplebuffer_flips = false; 4706 if (update_type == UPDATE_TYPE_FAST && 4707 dc->hwss.program_triplebuffer != NULL && 4708 !pipe_ctx->plane_state->flip_immediate && dc->debug.enable_tri_buf) { 4709 /*triple buffer for VUpdate only*/ 4710 pipe_ctx->plane_state->triplebuffer_flips = true; 4711 } 4712 } 4713 } 4714 4715 stream_status = dc_state_get_stream_status(context, stream); 4716 4717 if (should_offload_fams2_flip) { 4718 commit_plane_for_stream_offload_fams2_flip(dc, 4719 srf_updates, 4720 surface_count, 4721 stream, 4722 context); 4723 } else if (stream_status) { 4724 build_dmub_cmd_list(dc, 4725 srf_updates, 4726 surface_count, 4727 stream, 4728 context, 4729 context->dc_dmub_cmd, 4730 &(context->dmub_cmd_count)); 4731 hwss_build_fast_sequence(dc, 4732 context->dc_dmub_cmd, 4733 context->dmub_cmd_count, 4734 context->block_sequence, 4735 &(context->block_sequence_steps), 4736 top_pipe_to_program, 4737 stream_status, 4738 context); 4739 hwss_execute_sequence(dc, 4740 context->block_sequence, 4741 context->block_sequence_steps); 4742 } 4743 4744 /* Clear update flags so next flip doesn't have redundant programming 4745 * (if there's no stream update, the update flags are not cleared). 4746 * Surface updates are cleared unconditionally at the beginning of each flip, 4747 * so no need to clear here. 4748 */ 4749 if (top_pipe_to_program->stream) 4750 top_pipe_to_program->stream->update_flags.raw = 0; 4751 } 4752 4753 static void commit_planes_for_stream(struct dc *dc, 4754 const struct dc_surface_update *srf_updates, 4755 int surface_count, 4756 struct dc_stream_state *stream, 4757 struct dc_stream_update *stream_update, 4758 enum surface_update_type update_type, 4759 struct dc_state *context) 4760 { 4761 int i; 4762 unsigned int j, pipe_idx; 4763 struct pipe_ctx *top_pipe_to_program = NULL; 4764 bool should_lock_all_pipes = (update_type != UPDATE_TYPE_FAST); 4765 bool subvp_prev_use = false; 4766 bool subvp_curr_use = false; 4767 uint8_t current_stream_mask = 0; 4768 4769 if (should_lock_all_pipes) 4770 determine_pipe_unlock_order(dc, context); 4771 // Once we apply the new subvp context to hardware it won't be in the 4772 // dc->current_state anymore, so we have to cache it before we apply 4773 // the new SubVP context 4774 subvp_prev_use = false; 4775 dc_exit_ips_for_hw_access(dc); 4776 4777 dc_z10_restore(dc); 4778 if (update_type == UPDATE_TYPE_FULL && dc->optimized_required) 4779 hwss_process_outstanding_hw_updates(dc, dc->current_state); 4780 4781 if (update_type != UPDATE_TYPE_FAST && dc->res_pool->funcs->prepare_mcache_programming) 4782 dc->res_pool->funcs->prepare_mcache_programming(dc, context); 4783 4784 for (pipe_idx = 0; pipe_idx < dc->res_pool->pipe_count; pipe_idx++) { 4785 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[pipe_idx]; 4786 4787 if (pipe->stream && pipe->plane_state) { 4788 if (!dc->debug.using_dml2) 4789 set_p_state_switch_method(dc, context, pipe); 4790 4791 if (dc->debug.visual_confirm) 4792 dc_update_visual_confirm_color(dc, context, pipe); 4793 } 4794 } 4795 4796 if (update_type == UPDATE_TYPE_FULL) { 4797 dc_allow_idle_optimizations(dc, false); 4798 4799 if (get_seamless_boot_stream_count(context) == 0) 4800 dc->hwss.prepare_bandwidth(dc, context); 4801 4802 if (dc->hwss.update_dsc_pg) 4803 dc->hwss.update_dsc_pg(dc, context, false); 4804 4805 context_clock_trace(dc, context); 4806 } 4807 4808 if (update_type == UPDATE_TYPE_FULL) 4809 hwss_wait_for_outstanding_hw_updates(dc, dc->current_state); 4810 4811 top_pipe_to_program = resource_get_otg_master_for_stream( 4812 &context->res_ctx, 4813 stream); 4814 ASSERT(top_pipe_to_program != NULL); 4815 4816 for (pipe_idx = 0; pipe_idx < dc->res_pool->pipe_count; pipe_idx++) { 4817 struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[pipe_idx]; 4818 4819 // Check old context for SubVP 4820 subvp_prev_use |= (dc_state_get_pipe_subvp_type(dc->current_state, old_pipe) == SUBVP_PHANTOM); 4821 if (subvp_prev_use) 4822 break; 4823 } 4824 4825 for (pipe_idx = 0; pipe_idx < dc->res_pool->pipe_count; pipe_idx++) { 4826 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[pipe_idx]; 4827 4828 if (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) { 4829 subvp_curr_use = true; 4830 break; 4831 } 4832 } 4833 4834 if (stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE) { 4835 struct pipe_ctx *mpcc_pipe; 4836 struct pipe_ctx *odm_pipe; 4837 4838 for (mpcc_pipe = top_pipe_to_program; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe) 4839 for (odm_pipe = mpcc_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) 4840 odm_pipe->ttu_regs.min_ttu_vblank = MAX_TTU; 4841 } 4842 4843 if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed) 4844 if (top_pipe_to_program && 4845 top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) { 4846 if (should_use_dmub_inbox1_lock(dc, stream->link)) { 4847 union dmub_hw_lock_flags hw_locks = { 0 }; 4848 struct dmub_hw_lock_inst_flags inst_flags = { 0 }; 4849 4850 hw_locks.bits.lock_dig = 1; 4851 inst_flags.dig_inst = (uint8_t)top_pipe_to_program->stream_res.tg->inst; 4852 4853 dmub_hw_lock_mgr_cmd(dc->ctx->dmub_srv, 4854 true, 4855 &hw_locks, 4856 &inst_flags); 4857 } else 4858 top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable( 4859 top_pipe_to_program->stream_res.tg); 4860 } 4861 4862 if (dc->hwss.wait_for_dcc_meta_propagation) { 4863 dc->hwss.wait_for_dcc_meta_propagation(dc, top_pipe_to_program); 4864 } 4865 4866 if (dc->hwseq->funcs.wait_for_pipe_update_if_needed) 4867 dc->hwseq->funcs.wait_for_pipe_update_if_needed(dc, top_pipe_to_program, update_type < UPDATE_TYPE_FULL); 4868 4869 if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) { 4870 if (dc->hwss.subvp_pipe_control_lock) 4871 dc->hwss.subvp_pipe_control_lock(dc, context, true, should_lock_all_pipes, NULL, subvp_prev_use); 4872 4873 if (dc->hwss.dmub_hw_control_lock) 4874 dc->hwss.dmub_hw_control_lock(dc, context, true); 4875 4876 dc->hwss.interdependent_update_lock(dc, context, true); 4877 } else { 4878 if (dc->hwss.subvp_pipe_control_lock) 4879 dc->hwss.subvp_pipe_control_lock(dc, context, true, should_lock_all_pipes, top_pipe_to_program, subvp_prev_use); 4880 4881 if (dc->hwss.dmub_hw_control_lock) 4882 dc->hwss.dmub_hw_control_lock(dc, context, true); 4883 4884 /* Lock the top pipe while updating plane addrs, since freesync requires 4885 * plane addr update event triggers to be synchronized. 4886 * top_pipe_to_program is expected to never be NULL 4887 */ 4888 dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true); 4889 } 4890 4891 dc_dmub_update_dirty_rect(dc, surface_count, stream, srf_updates, context); 4892 4893 // Stream updates 4894 if (stream_update) 4895 commit_planes_do_stream_update(dc, stream, stream_update, update_type, context); 4896 4897 if (surface_count == 0) { 4898 /* 4899 * In case of turning off screen, no need to program front end a second time. 4900 * just return after program blank. 4901 */ 4902 if (dc->hwss.apply_ctx_for_surface) 4903 dc->hwss.apply_ctx_for_surface(dc, stream, 0, context); 4904 if (dc->hwss.program_front_end_for_ctx) 4905 dc->hwss.program_front_end_for_ctx(dc, context); 4906 4907 if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) { 4908 dc->hwss.interdependent_update_lock(dc, context, false); 4909 } else { 4910 dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); 4911 } 4912 dc->hwss.post_unlock_program_front_end(dc, context); 4913 4914 if (update_type != UPDATE_TYPE_FAST) 4915 if (dc->hwss.commit_subvp_config) 4916 dc->hwss.commit_subvp_config(dc, context); 4917 4918 /* Since phantom pipe programming is moved to post_unlock_program_front_end, 4919 * move the SubVP lock to after the phantom pipes have been setup 4920 */ 4921 if (dc->hwss.subvp_pipe_control_lock) 4922 dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, 4923 NULL, subvp_prev_use); 4924 4925 if (dc->hwss.dmub_hw_control_lock) 4926 dc->hwss.dmub_hw_control_lock(dc, context, false); 4927 return; 4928 } 4929 4930 if (update_type != UPDATE_TYPE_FAST) { 4931 for (j = 0; j < dc->res_pool->pipe_count; j++) { 4932 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 4933 4934 if ((dc->debug.visual_confirm == VISUAL_CONFIRM_SUBVP || 4935 dc->debug.visual_confirm == VISUAL_CONFIRM_MCLK_SWITCH) && 4936 pipe_ctx->stream && pipe_ctx->plane_state) { 4937 /* Only update visual confirm for SUBVP and Mclk switching here. 4938 * The bar appears on all pipes, so we need to update the bar on all displays, 4939 * so the information doesn't get stale. 4940 */ 4941 dc->hwss.update_visual_confirm_color(dc, pipe_ctx, 4942 pipe_ctx->plane_res.hubp->inst); 4943 } 4944 } 4945 } 4946 4947 for (i = 0; i < surface_count; i++) { 4948 struct dc_plane_state *plane_state = srf_updates[i].surface; 4949 4950 /*set logical flag for lock/unlock use*/ 4951 for (j = 0; j < dc->res_pool->pipe_count; j++) { 4952 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 4953 if (!pipe_ctx->plane_state) 4954 continue; 4955 if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state)) 4956 continue; 4957 pipe_ctx->plane_state->triplebuffer_flips = false; 4958 if (update_type == UPDATE_TYPE_FAST && 4959 dc->hwss.program_triplebuffer != NULL && 4960 !pipe_ctx->plane_state->flip_immediate && dc->debug.enable_tri_buf) { 4961 /*triple buffer for VUpdate only*/ 4962 pipe_ctx->plane_state->triplebuffer_flips = true; 4963 } 4964 } 4965 if (update_type == UPDATE_TYPE_FULL) { 4966 /* force vsync flip when reconfiguring pipes to prevent underflow */ 4967 plane_state->flip_immediate = false; 4968 plane_state->triplebuffer_flips = false; 4969 } 4970 } 4971 4972 // Update Type FULL, Surface updates 4973 for (j = 0; j < dc->res_pool->pipe_count; j++) { 4974 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 4975 4976 if (!pipe_ctx->top_pipe && 4977 !pipe_ctx->prev_odm_pipe && 4978 should_update_pipe_for_stream(context, pipe_ctx, stream)) { 4979 struct dc_stream_status *pipe_stream_status = NULL; 4980 4981 if (!pipe_ctx->plane_state) 4982 continue; 4983 4984 /* Full fe update*/ 4985 if (update_type == UPDATE_TYPE_FAST) 4986 continue; 4987 4988 pipe_stream_status = 4989 stream_get_status(context, pipe_ctx->stream); 4990 4991 if (dc->hwss.apply_ctx_for_surface && pipe_stream_status) 4992 dc->hwss.apply_ctx_for_surface( 4993 dc, pipe_ctx->stream, pipe_stream_status->plane_count, context); 4994 } 4995 } 4996 4997 for (j = 0; j < dc->res_pool->pipe_count; j++) { 4998 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 4999 5000 if (!pipe_ctx->plane_state) 5001 continue; 5002 5003 /* Full fe update*/ 5004 if (update_type == UPDATE_TYPE_FAST) 5005 continue; 5006 5007 ASSERT(!pipe_ctx->plane_state->triplebuffer_flips); 5008 if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) { 5009 /*turn off triple buffer for full update*/ 5010 dc->hwss.program_triplebuffer( 5011 dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips); 5012 } 5013 } 5014 5015 if (dc->hwss.program_front_end_for_ctx && update_type != UPDATE_TYPE_FAST) { 5016 dc->hwss.program_front_end_for_ctx(dc, context); 5017 5018 //Pipe busy until some frame and line # 5019 if (dc->hwseq->funcs.set_wait_for_update_needed_for_pipe && update_type == UPDATE_TYPE_FULL) { 5020 for (j = 0; j < dc->res_pool->pipe_count; j++) { 5021 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 5022 5023 dc->hwseq->funcs.set_wait_for_update_needed_for_pipe(dc, pipe_ctx); 5024 } 5025 } 5026 5027 if (dc->debug.validate_dml_output) { 5028 for (pipe_idx = 0; pipe_idx < dc->res_pool->pipe_count; pipe_idx++) { 5029 struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; 5030 if (cur_pipe->stream == NULL) 5031 continue; 5032 5033 cur_pipe->plane_res.hubp->funcs->validate_dml_output( 5034 cur_pipe->plane_res.hubp, dc->ctx, 5035 &context->res_ctx.pipe_ctx[pipe_idx].rq_regs, 5036 &context->res_ctx.pipe_ctx[pipe_idx].dlg_regs, 5037 &context->res_ctx.pipe_ctx[pipe_idx].ttu_regs); 5038 } 5039 } 5040 } 5041 5042 // Update Type FAST, Surface updates 5043 if (update_type == UPDATE_TYPE_FAST) { 5044 if (dc->hwss.set_flip_control_gsl) 5045 for (i = 0; i < surface_count; i++) { 5046 struct dc_plane_state *plane_state = srf_updates[i].surface; 5047 5048 for (j = 0; j < dc->res_pool->pipe_count; j++) { 5049 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 5050 5051 if (!should_update_pipe_for_stream(context, pipe_ctx, stream)) 5052 continue; 5053 5054 if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state)) 5055 continue; 5056 5057 // GSL has to be used for flip immediate 5058 dc->hwss.set_flip_control_gsl(pipe_ctx, 5059 pipe_ctx->plane_state->flip_immediate); 5060 } 5061 } 5062 5063 /* Perform requested Updates */ 5064 for (i = 0; i < surface_count; i++) { 5065 struct dc_plane_state *plane_state = srf_updates[i].surface; 5066 5067 for (j = 0; j < dc->res_pool->pipe_count; j++) { 5068 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 5069 5070 if (!should_update_pipe_for_stream(context, pipe_ctx, stream)) 5071 continue; 5072 5073 if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state)) 5074 continue; 5075 5076 if (srf_updates[i].cm2_params && 5077 srf_updates[i].cm2_params->cm2_luts.lut3d_data.lut3d_src == 5078 DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM && 5079 srf_updates[i].cm2_params->component_settings.shaper_3dlut_setting == 5080 DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT && 5081 dc->hwss.trigger_3dlut_dma_load) 5082 dc->hwss.trigger_3dlut_dma_load(dc, pipe_ctx); 5083 5084 /*program triple buffer after lock based on flip type*/ 5085 if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) { 5086 /*only enable triplebuffer for fast_update*/ 5087 dc->hwss.program_triplebuffer( 5088 dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips); 5089 } 5090 if (pipe_ctx->plane_state->update_flags.bits.addr_update) 5091 dc->hwss.update_plane_addr(dc, pipe_ctx); 5092 } 5093 } 5094 } 5095 5096 if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) { 5097 dc->hwss.interdependent_update_lock(dc, context, false); 5098 } else { 5099 dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); 5100 } 5101 5102 if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed) 5103 if (top_pipe_to_program && 5104 top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) { 5105 top_pipe_to_program->stream_res.tg->funcs->wait_for_state( 5106 top_pipe_to_program->stream_res.tg, 5107 CRTC_STATE_VACTIVE); 5108 top_pipe_to_program->stream_res.tg->funcs->wait_for_state( 5109 top_pipe_to_program->stream_res.tg, 5110 CRTC_STATE_VBLANK); 5111 top_pipe_to_program->stream_res.tg->funcs->wait_for_state( 5112 top_pipe_to_program->stream_res.tg, 5113 CRTC_STATE_VACTIVE); 5114 5115 if (should_use_dmub_inbox1_lock(dc, stream->link)) { 5116 union dmub_hw_lock_flags hw_locks = { 0 }; 5117 struct dmub_hw_lock_inst_flags inst_flags = { 0 }; 5118 5119 hw_locks.bits.lock_dig = 1; 5120 inst_flags.dig_inst = (uint8_t)top_pipe_to_program->stream_res.tg->inst; 5121 5122 dmub_hw_lock_mgr_cmd(dc->ctx->dmub_srv, 5123 false, 5124 &hw_locks, 5125 &inst_flags); 5126 } else 5127 top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_disable( 5128 top_pipe_to_program->stream_res.tg); 5129 } 5130 5131 if (subvp_curr_use) { 5132 /* If enabling subvp or transitioning from subvp->subvp, enable the 5133 * phantom streams before we program front end for the phantom pipes. 5134 */ 5135 if (update_type != UPDATE_TYPE_FAST) { 5136 if (dc->hwss.enable_phantom_streams) 5137 dc->hwss.enable_phantom_streams(dc, context); 5138 } 5139 } 5140 5141 if (update_type != UPDATE_TYPE_FAST) 5142 dc->hwss.post_unlock_program_front_end(dc, context); 5143 5144 if (subvp_prev_use && !subvp_curr_use) { 5145 /* If disabling subvp, disable phantom streams after front end 5146 * programming has completed (we turn on phantom OTG in order 5147 * to complete the plane disable for phantom pipes). 5148 */ 5149 5150 if (dc->hwss.disable_phantom_streams) 5151 dc->hwss.disable_phantom_streams(dc, context); 5152 } 5153 5154 if (update_type != UPDATE_TYPE_FAST) 5155 if (dc->hwss.commit_subvp_config) 5156 dc->hwss.commit_subvp_config(dc, context); 5157 /* Since phantom pipe programming is moved to post_unlock_program_front_end, 5158 * move the SubVP lock to after the phantom pipes have been setup 5159 */ 5160 if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) { 5161 if (dc->hwss.subvp_pipe_control_lock) 5162 dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use); 5163 if (dc->hwss.dmub_hw_control_lock) 5164 dc->hwss.dmub_hw_control_lock(dc, context, false); 5165 } else { 5166 if (dc->hwss.subvp_pipe_control_lock) 5167 dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, top_pipe_to_program, subvp_prev_use); 5168 if (dc->hwss.dmub_hw_control_lock) 5169 dc->hwss.dmub_hw_control_lock(dc, context, false); 5170 } 5171 5172 // Fire manual trigger only when bottom plane is flipped 5173 for (j = 0; j < dc->res_pool->pipe_count; j++) { 5174 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 5175 5176 if (!pipe_ctx->plane_state) 5177 continue; 5178 5179 if (pipe_ctx->bottom_pipe || pipe_ctx->next_odm_pipe || 5180 !pipe_ctx->stream || !should_update_pipe_for_stream(context, pipe_ctx, stream) || 5181 !pipe_ctx->plane_state->update_flags.bits.addr_update || 5182 pipe_ctx->plane_state->skip_manual_trigger) 5183 continue; 5184 5185 if (dc->hwss.program_cursor_offload_now) 5186 dc->hwss.program_cursor_offload_now(dc, pipe_ctx); 5187 if (pipe_ctx->stream_res.tg->funcs->program_manual_trigger) 5188 pipe_ctx->stream_res.tg->funcs->program_manual_trigger(pipe_ctx->stream_res.tg); 5189 } 5190 5191 current_stream_mask = get_stream_mask(dc, context); 5192 if (current_stream_mask != context->stream_mask) { 5193 context->stream_mask = current_stream_mask; 5194 dc_dmub_srv_notify_stream_mask(dc->ctx->dmub_srv, current_stream_mask); 5195 } 5196 } 5197 5198 /** 5199 * could_mpcc_tree_change_for_active_pipes - Check if an OPP associated with MPCC might change 5200 * 5201 * @dc: Used to get the current state status 5202 * @stream: Target stream, which we want to remove the attached planes 5203 * @srf_updates: Array of surface updates 5204 * @surface_count: Number of surface update 5205 * @is_plane_addition: [in] Fill out with true if it is a plane addition case 5206 * 5207 * DCN32x and newer support a feature named Dynamic ODM which can conflict with 5208 * the MPO if used simultaneously in some specific configurations (e.g., 5209 * 4k@144). This function checks if the incoming context requires applying a 5210 * transition state with unnecessary pipe splitting and ODM disabled to 5211 * circumvent our hardware limitations to prevent this edge case. If the OPP 5212 * associated with an MPCC might change due to plane additions, this function 5213 * returns true. 5214 * 5215 * Return: 5216 * Return true if OPP and MPCC might change, otherwise, return false. 5217 */ 5218 static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc, 5219 struct dc_stream_state *stream, 5220 struct dc_surface_update *srf_updates, 5221 int surface_count, 5222 bool *is_plane_addition) 5223 { 5224 (void)srf_updates; 5225 5226 struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream); 5227 bool force_minimal_pipe_splitting = false; 5228 bool subvp_active = false; 5229 uint32_t i; 5230 5231 *is_plane_addition = false; 5232 5233 if (cur_stream_status && 5234 dc->current_state->stream_count > 0 && 5235 dc->debug.pipe_split_policy != MPC_SPLIT_AVOID) { 5236 /* determine if minimal transition is required due to MPC*/ 5237 if (surface_count > 0) { 5238 if (cur_stream_status->plane_count > surface_count) { 5239 force_minimal_pipe_splitting = true; 5240 } else if (cur_stream_status->plane_count < surface_count) { 5241 force_minimal_pipe_splitting = true; 5242 *is_plane_addition = true; 5243 } 5244 } 5245 } 5246 5247 if (cur_stream_status && 5248 dc->current_state->stream_count == 1 && 5249 dc->debug.enable_single_display_2to1_odm_policy) { 5250 /* determine if minimal transition is required due to dynamic ODM*/ 5251 if (surface_count > 0) { 5252 if (cur_stream_status->plane_count > 2 && cur_stream_status->plane_count > surface_count) { 5253 force_minimal_pipe_splitting = true; 5254 } else if (surface_count > 2 && cur_stream_status->plane_count < surface_count) { 5255 force_minimal_pipe_splitting = true; 5256 *is_plane_addition = true; 5257 } 5258 } 5259 } 5260 5261 for (i = 0; i < dc->res_pool->pipe_count; i++) { 5262 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 5263 5264 if (dc_state_get_pipe_subvp_type(dc->current_state, pipe) != SUBVP_NONE) { 5265 subvp_active = true; 5266 break; 5267 } 5268 } 5269 5270 /* For SubVP when adding or removing planes we need to add a minimal transition 5271 * (even when disabling all planes). Whenever disabling a phantom pipe, we 5272 * must use the minimal transition path to disable the pipe correctly. 5273 * 5274 * We want to use the minimal transition whenever subvp is active, not only if 5275 * a plane is being added / removed from a subvp stream (MPO plane can be added 5276 * to a DRR pipe of SubVP + DRR config, in which case we still want to run through 5277 * a min transition to disable subvp. 5278 */ 5279 if (cur_stream_status && subvp_active) { 5280 /* determine if minimal transition is required due to SubVP*/ 5281 if (cur_stream_status->plane_count > surface_count) { 5282 force_minimal_pipe_splitting = true; 5283 } else if (cur_stream_status->plane_count < surface_count) { 5284 force_minimal_pipe_splitting = true; 5285 *is_plane_addition = true; 5286 } 5287 } 5288 5289 return force_minimal_pipe_splitting; 5290 } 5291 5292 5293 static void release_minimal_transition_state(struct dc *dc, 5294 struct dc_state *minimal_transition_context, 5295 struct dc_state *base_context, 5296 struct pipe_split_policy_backup *policy) 5297 { 5298 restore_minimal_pipe_split_policy(dc, base_context, policy); 5299 dc_state_release(minimal_transition_context); 5300 } 5301 5302 static void force_vsync_flip_in_minimal_transition_context(struct dc_state *context) 5303 { 5304 uint8_t i; 5305 int j; 5306 struct dc_stream_status *stream_status; 5307 5308 for (i = 0; i < context->stream_count; i++) { 5309 stream_status = &context->stream_status[i]; 5310 5311 for (j = 0; j < stream_status->plane_count; j++) 5312 stream_status->plane_states[j]->flip_immediate = false; 5313 } 5314 } 5315 5316 static struct dc_state *create_minimal_transition_state(struct dc *dc, 5317 struct dc_state *base_context, struct pipe_split_policy_backup *policy) 5318 { 5319 struct dc_state *minimal_transition_context = NULL; 5320 5321 minimal_transition_context = dc_state_create_copy(base_context); 5322 if (!minimal_transition_context) 5323 return NULL; 5324 5325 backup_and_set_minimal_pipe_split_policy(dc, base_context, policy); 5326 /* commit minimal state */ 5327 if (dc->res_pool->funcs->validate_bandwidth(dc, minimal_transition_context, 5328 DC_VALIDATE_MODE_AND_PROGRAMMING) == DC_OK) { 5329 /* prevent underflow and corruption when reconfiguring pipes */ 5330 force_vsync_flip_in_minimal_transition_context(minimal_transition_context); 5331 } else { 5332 /* 5333 * This should never happen, minimal transition state should 5334 * always be validated first before adding pipe split features. 5335 */ 5336 release_minimal_transition_state(dc, minimal_transition_context, base_context, policy); 5337 BREAK_TO_DEBUGGER(); 5338 minimal_transition_context = NULL; 5339 } 5340 return minimal_transition_context; 5341 } 5342 5343 static bool is_pipe_topology_transition_seamless_with_intermediate_step( 5344 struct dc *dc, 5345 struct dc_state *initial_state, 5346 struct dc_state *intermediate_state, 5347 struct dc_state *final_state) 5348 { 5349 return dc->hwss.is_pipe_topology_transition_seamless(dc, initial_state, 5350 intermediate_state) && 5351 dc->hwss.is_pipe_topology_transition_seamless(dc, 5352 intermediate_state, final_state); 5353 } 5354 5355 static void swap_and_release_current_context(struct dc *dc, 5356 struct dc_state *new_context, struct dc_stream_state *stream) 5357 { 5358 5359 unsigned int i; 5360 struct dc_state *old = dc->current_state; 5361 struct pipe_ctx *pipe_ctx; 5362 5363 /* Since memory free requires elevated IRQ, an interrupt 5364 * request is generated by mem free. If this happens 5365 * between freeing and reassigning the context, our vsync 5366 * interrupt will call into dc and cause a memory 5367 * corruption. Hence, we first reassign the context, 5368 * then free the old context. 5369 */ 5370 dc->current_state = new_context; 5371 dc_state_release(old); 5372 5373 // clear any forced full updates 5374 for (i = 0; i < dc->res_pool->pipe_count; i++) { 5375 pipe_ctx = &new_context->res_ctx.pipe_ctx[i]; 5376 5377 if (pipe_ctx->plane_state && pipe_ctx->stream == stream) 5378 pipe_ctx->plane_state->force_full_update = false; 5379 } 5380 } 5381 5382 static int initialize_empty_surface_updates( 5383 struct dc_stream_state *stream, 5384 struct dc_surface_update *srf_updates) 5385 { 5386 struct dc_stream_status *status = dc_stream_get_status(stream); 5387 int i; 5388 5389 if (!status) 5390 return 0; 5391 5392 for (i = 0; i < status->plane_count; i++) 5393 srf_updates[i].surface = status->plane_states[i]; 5394 5395 return status->plane_count; 5396 } 5397 5398 static bool commit_minimal_transition_based_on_new_context(struct dc *dc, 5399 struct dc_state *new_context, 5400 struct dc_stream_state *stream, 5401 struct dc_stream_update *stream_update, 5402 struct dc_surface_update *srf_updates, 5403 int surface_count) 5404 { 5405 bool success = false; 5406 struct pipe_split_policy_backup policy; 5407 struct dc_state *intermediate_context = 5408 create_minimal_transition_state(dc, new_context, 5409 &policy); 5410 5411 if (intermediate_context) { 5412 if (is_pipe_topology_transition_seamless_with_intermediate_step( 5413 dc, 5414 dc->current_state, 5415 intermediate_context, 5416 new_context)) { 5417 DC_LOG_DC("commit minimal transition state: base = new state\n"); 5418 commit_planes_for_stream(dc, srf_updates, 5419 surface_count, stream, stream_update, 5420 UPDATE_TYPE_FULL, intermediate_context); 5421 swap_and_release_current_context( 5422 dc, intermediate_context, stream); 5423 dc_state_retain(dc->current_state); 5424 success = true; 5425 } 5426 release_minimal_transition_state( 5427 dc, intermediate_context, new_context, &policy); 5428 } 5429 return success; 5430 } 5431 5432 static bool commit_minimal_transition_based_on_current_context(struct dc *dc, 5433 struct dc_state *new_context, struct dc_stream_state *stream) 5434 { 5435 bool success = false; 5436 struct pipe_split_policy_backup policy; 5437 struct dc_state *intermediate_context; 5438 struct dc_state *old_current_state = dc->current_state; 5439 struct dc_surface_update srf_updates[MAX_SURFACES] = {0}; 5440 int surface_count; 5441 5442 /* 5443 * Both current and new contexts share the same stream and plane state 5444 * pointers. When new context is validated, stream and planes get 5445 * populated with new updates such as new plane addresses. This makes 5446 * the current context no longer valid because stream and planes are 5447 * modified from the original. We backup current stream and plane states 5448 * into scratch space whenever we are populating new context. So we can 5449 * restore the original values back by calling the restore function now. 5450 * This restores back the original stream and plane states associated 5451 * with the current state. 5452 */ 5453 restore_planes_and_stream_state(&dc->scratch.current_state, stream); 5454 dc_state_retain(old_current_state); 5455 intermediate_context = create_minimal_transition_state(dc, 5456 old_current_state, &policy); 5457 5458 if (intermediate_context) { 5459 if (is_pipe_topology_transition_seamless_with_intermediate_step( 5460 dc, 5461 dc->current_state, 5462 intermediate_context, 5463 new_context)) { 5464 DC_LOG_DC("commit minimal transition state: base = current state\n"); 5465 surface_count = initialize_empty_surface_updates( 5466 stream, srf_updates); 5467 commit_planes_for_stream(dc, srf_updates, 5468 surface_count, stream, NULL, 5469 UPDATE_TYPE_FULL, intermediate_context); 5470 swap_and_release_current_context( 5471 dc, intermediate_context, stream); 5472 dc_state_retain(dc->current_state); 5473 success = true; 5474 } 5475 release_minimal_transition_state(dc, intermediate_context, 5476 old_current_state, &policy); 5477 } 5478 dc_state_release(old_current_state); 5479 /* 5480 * Restore stream and plane states back to the values associated with 5481 * new context. 5482 */ 5483 restore_planes_and_stream_state(&dc->scratch.new_state, stream); 5484 return success; 5485 } 5486 5487 /** 5488 * commit_minimal_transition_state_in_dc_update - Commit a minimal state based 5489 * on current or new context 5490 * 5491 * @dc: DC structure, used to get the current state 5492 * @new_context: New context 5493 * @stream: Stream getting the update for the flip 5494 * @srf_updates: Surface updates 5495 * @surface_count: Number of surfaces 5496 * 5497 * The function takes in current state and new state and determine a minimal 5498 * transition state as the intermediate step which could make the transition 5499 * between current and new states seamless. If found, it will commit the minimal 5500 * transition state and update current state to this minimal transition state 5501 * and return true, if not, it will return false. 5502 * 5503 * Return: 5504 * Return True if the minimal transition succeeded, false otherwise 5505 */ 5506 static bool commit_minimal_transition_state_in_dc_update(struct dc *dc, 5507 struct dc_state *new_context, 5508 struct dc_stream_state *stream, 5509 struct dc_surface_update *srf_updates, 5510 int surface_count) 5511 { 5512 bool success = commit_minimal_transition_based_on_new_context( 5513 dc, new_context, stream, NULL, 5514 srf_updates, surface_count); 5515 if (!success) 5516 success = commit_minimal_transition_based_on_current_context(dc, 5517 new_context, stream); 5518 if (!success) 5519 DC_LOG_ERROR("Fail to commit a seamless minimal transition state between current and new states.\nThis pipe topology update is non-seamless!\n"); 5520 return success; 5521 } 5522 5523 /** 5524 * commit_minimal_transition_state - Create a transition pipe split state 5525 * 5526 * @dc: Used to get the current state status 5527 * @transition_base_context: New transition state 5528 * 5529 * In some specific configurations, such as pipe split on multi-display with 5530 * MPO and/or Dynamic ODM, removing a plane may cause unsupported pipe 5531 * programming when moving to new planes. To mitigate those types of problems, 5532 * this function adds a transition state that minimizes pipe usage before 5533 * programming the new configuration. When adding a new plane, the current 5534 * state requires the least pipes, so it is applied without splitting. When 5535 * removing a plane, the new state requires the least pipes, so it is applied 5536 * without splitting. 5537 * 5538 * Return: 5539 * Return false if something is wrong in the transition state. 5540 */ 5541 static bool commit_minimal_transition_state(struct dc *dc, 5542 struct dc_state *transition_base_context) 5543 { 5544 struct dc_state *transition_context; 5545 struct pipe_split_policy_backup policy; 5546 enum dc_status ret = DC_ERROR_UNEXPECTED; 5547 unsigned int i, j; 5548 unsigned int pipe_in_use = 0; 5549 bool subvp_in_use = false; 5550 bool odm_in_use = false; 5551 5552 /* check current pipes in use*/ 5553 for (i = 0; i < dc->res_pool->pipe_count; i++) { 5554 struct pipe_ctx *pipe = &transition_base_context->res_ctx.pipe_ctx[i]; 5555 5556 if (pipe->plane_state) 5557 pipe_in_use++; 5558 } 5559 5560 /* If SubVP is enabled and we are adding or removing planes from any main subvp 5561 * pipe, we must use the minimal transition. 5562 */ 5563 for (i = 0; i < dc->res_pool->pipe_count; i++) { 5564 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 5565 5566 if (pipe->stream && dc_state_get_pipe_subvp_type(dc->current_state, pipe) == SUBVP_PHANTOM) { 5567 subvp_in_use = true; 5568 break; 5569 } 5570 } 5571 5572 /* If ODM is enabled and we are adding or removing planes from any ODM 5573 * pipe, we must use the minimal transition. 5574 */ 5575 for (i = 0; i < dc->res_pool->pipe_count; i++) { 5576 struct pipe_ctx *pipe = &transition_base_context->res_ctx.pipe_ctx[i]; 5577 5578 if (resource_is_pipe_type(pipe, OTG_MASTER)) { 5579 odm_in_use = resource_get_odm_slice_count(pipe) > 1; 5580 break; 5581 } 5582 } 5583 5584 /* When the OS add a new surface if we have been used all of pipes with odm combine 5585 * and mpc split feature, it need use commit_minimal_transition_state to transition safely. 5586 * After OS exit MPO, it will back to use odm and mpc split with all of pipes, we need 5587 * call it again. Otherwise return true to skip. 5588 * 5589 * Reduce the scenarios to use dc_commit_state_no_check in the stage of flip. Especially 5590 * enter/exit MPO when DCN still have enough resources. 5591 */ 5592 if (pipe_in_use != dc->res_pool->pipe_count && !subvp_in_use && !odm_in_use) 5593 return true; 5594 5595 DC_LOG_DC("%s base = %s state, reason = %s\n", __func__, 5596 dc->current_state == transition_base_context ? "current" : "new", 5597 subvp_in_use ? "Subvp In Use" : 5598 odm_in_use ? "ODM in Use" : 5599 dc->debug.pipe_split_policy != MPC_SPLIT_AVOID ? "MPC in Use" : 5600 "Unknown"); 5601 5602 dc_state_retain(transition_base_context); 5603 transition_context = create_minimal_transition_state(dc, 5604 transition_base_context, &policy); 5605 if (transition_context) { 5606 ret = dc_commit_state_no_check(dc, transition_context); 5607 release_minimal_transition_state(dc, transition_context, transition_base_context, &policy); 5608 } 5609 dc_state_release(transition_base_context); 5610 5611 if (ret != DC_OK) { 5612 /* this should never happen */ 5613 BREAK_TO_DEBUGGER(); 5614 return false; 5615 } 5616 5617 /* force full surface update */ 5618 for (i = 0; i < dc->current_state->stream_count; i++) { 5619 for (j = 0; j < (unsigned int)dc->current_state->stream_status[i].plane_count; j++) { 5620 dc->current_state->stream_status[i].plane_states[j]->update_flags.raw = 0xFFFFFFFF; 5621 } 5622 } 5623 5624 return true; 5625 } 5626 5627 void populate_fast_updates(struct dc_fast_update *fast_update, 5628 struct dc_surface_update *srf_updates, 5629 int surface_count, 5630 struct dc_stream_update *stream_update) 5631 { 5632 int i = 0; 5633 5634 if (stream_update) { 5635 fast_update[0].out_transfer_func = stream_update->out_transfer_func; 5636 fast_update[0].output_csc_transform = stream_update->output_csc_transform; 5637 fast_update[0].cursor_attributes = stream_update->cursor_attributes; 5638 fast_update[0].cursor_position = stream_update->cursor_position; 5639 fast_update[0].periodic_interrupt = stream_update->periodic_interrupt; 5640 fast_update[0].dither_option = stream_update->dither_option; 5641 fast_update[0].gamut_remap = stream_update->gamut_remap; 5642 fast_update[0].vrr_infopacket = stream_update->vrr_infopacket; 5643 fast_update[0].vsc_infopacket = stream_update->vsc_infopacket; 5644 fast_update[0].vsp_infopacket = stream_update->vsp_infopacket; 5645 fast_update[0].hfvsif_infopacket = stream_update->hfvsif_infopacket; 5646 fast_update[0].vtem_infopacket = stream_update->vtem_infopacket; 5647 fast_update[0].adaptive_sync_infopacket = stream_update->adaptive_sync_infopacket; 5648 fast_update[0].avi_infopacket = stream_update->avi_infopacket; 5649 fast_update[0].hdr_static_metadata = stream_update->hdr_static_metadata; 5650 } else { 5651 fast_update[0].out_transfer_func = NULL; 5652 fast_update[0].output_csc_transform = NULL; 5653 fast_update[0].cursor_attributes = NULL; 5654 fast_update[0].cursor_position = NULL; 5655 fast_update[0].periodic_interrupt = NULL; 5656 fast_update[0].dither_option = NULL; 5657 fast_update[0].gamut_remap = NULL; 5658 fast_update[0].vrr_infopacket = NULL; 5659 fast_update[0].vsc_infopacket = NULL; 5660 fast_update[0].vsp_infopacket = NULL; 5661 fast_update[0].hfvsif_infopacket = NULL; 5662 fast_update[0].vtem_infopacket = NULL; 5663 fast_update[0].adaptive_sync_infopacket = NULL; 5664 fast_update[0].avi_infopacket = NULL; 5665 fast_update[0].hdr_static_metadata = NULL; 5666 } 5667 5668 for (i = 0; i < surface_count; i++) { 5669 fast_update[i].flip_addr = srf_updates[i].flip_addr; 5670 fast_update[i].gamma = srf_updates[i].gamma; 5671 fast_update[i].gamut_remap_matrix = srf_updates[i].gamut_remap_matrix; 5672 fast_update[i].input_csc_color_matrix = srf_updates[i].input_csc_color_matrix; 5673 fast_update[i].coeff_reduction_factor = srf_updates[i].coeff_reduction_factor; 5674 fast_update[i].cursor_csc_color_matrix = srf_updates[i].cursor_csc_color_matrix; 5675 fast_update[i].cm_hist_control = srf_updates[i].cm_hist_control; 5676 } 5677 } 5678 5679 static bool fast_updates_exist(const struct dc_fast_update *fast_update, int surface_count) 5680 { 5681 int i; 5682 5683 if (fast_update[0].out_transfer_func || 5684 fast_update[0].output_csc_transform || 5685 fast_update[0].cursor_attributes || 5686 fast_update[0].cursor_position || 5687 fast_update[0].periodic_interrupt || 5688 fast_update[0].dither_option || 5689 fast_update[0].gamut_remap || 5690 fast_update[0].vrr_infopacket || 5691 fast_update[0].vsc_infopacket || 5692 fast_update[0].vsp_infopacket || 5693 fast_update[0].hfvsif_infopacket || 5694 fast_update[0].vtem_infopacket || 5695 fast_update[0].adaptive_sync_infopacket || 5696 fast_update[0].avi_infopacket || 5697 fast_update[0].hdr_static_metadata) 5698 return true; 5699 5700 for (i = 0; i < surface_count; i++) { 5701 if (fast_update[i].flip_addr || 5702 fast_update[i].gamma || 5703 fast_update[i].gamut_remap_matrix || 5704 fast_update[i].input_csc_color_matrix || 5705 fast_update[i].cursor_csc_color_matrix || 5706 fast_update[i].cm_hist_control || 5707 fast_update[i].coeff_reduction_factor) 5708 return true; 5709 } 5710 5711 return false; 5712 } 5713 5714 bool fast_nonaddr_updates_exist(struct dc_fast_update *fast_update, int surface_count) 5715 { 5716 int i; 5717 5718 if (fast_update[0].out_transfer_func || 5719 fast_update[0].output_csc_transform || 5720 fast_update[0].gamut_remap || 5721 fast_update[0].cursor_attributes || 5722 fast_update[0].cursor_position || 5723 fast_update[0].periodic_interrupt || 5724 fast_update[0].dither_option || 5725 fast_update[0].vrr_infopacket || 5726 fast_update[0].vsc_infopacket || 5727 fast_update[0].vsp_infopacket || 5728 fast_update[0].hfvsif_infopacket || 5729 fast_update[0].vtem_infopacket || 5730 fast_update[0].adaptive_sync_infopacket || 5731 fast_update[0].avi_infopacket || 5732 fast_update[0].hdr_static_metadata) 5733 return true; 5734 5735 for (i = 0; i < surface_count; i++) { 5736 if (fast_update[i].input_csc_color_matrix || 5737 fast_update[i].gamma || 5738 fast_update[i].gamut_remap_matrix || 5739 fast_update[i].coeff_reduction_factor || 5740 fast_update[i].cm_hist_control || 5741 fast_update[i].cursor_csc_color_matrix) 5742 return true; 5743 } 5744 5745 return false; 5746 } 5747 5748 static bool full_update_required_weak( 5749 const struct dc *dc, 5750 const struct dc_surface_update *srf_updates, 5751 int surface_count, 5752 const struct dc_stream_update *stream_update, 5753 const struct dc_stream_state *stream) 5754 { 5755 (void)stream_update; 5756 const struct dc_state *context = dc->current_state; 5757 if (srf_updates) 5758 for (int i = 0; i < surface_count; i++) 5759 if (!is_surface_in_context(context, srf_updates[i].surface)) 5760 return true; 5761 5762 if (stream) { 5763 const struct dc_stream_status *stream_status = dc_stream_get_status_const(stream); 5764 if (stream_status == NULL || stream_status->plane_count != surface_count) 5765 return true; 5766 } 5767 if (dc->idle_optimizations_allowed) 5768 return true; 5769 5770 if (dc_can_clear_cursor_limit(dc)) 5771 return true; 5772 5773 return false; 5774 } 5775 5776 static bool full_update_required( 5777 const struct dc *dc, 5778 const struct dc_surface_update *srf_updates, 5779 int surface_count, 5780 const struct dc_stream_update *stream_update, 5781 const struct dc_stream_state *stream) 5782 { 5783 if (full_update_required_weak(dc, srf_updates, surface_count, stream_update, stream)) 5784 return true; 5785 5786 for (int i = 0; i < surface_count; i++) { 5787 if (srf_updates && 5788 (srf_updates[i].plane_info || 5789 srf_updates[i].scaling_info || 5790 (srf_updates[i].hdr_mult.value && 5791 srf_updates[i].hdr_mult.value != srf_updates->surface->hdr_mult.value) || 5792 (srf_updates[i].sdr_white_level_nits && 5793 srf_updates[i].sdr_white_level_nits != srf_updates->surface->sdr_white_level_nits) || 5794 srf_updates[i].in_transfer_func || 5795 srf_updates[i].func_shaper || 5796 srf_updates[i].lut3d_func || 5797 srf_updates[i].surface->force_full_update || 5798 (srf_updates[i].flip_addr && 5799 srf_updates[i].flip_addr->address.tmz_surface != srf_updates[i].surface->address.tmz_surface) || 5800 (srf_updates[i].cm2_params && 5801 (srf_updates[i].cm2_params->component_settings.shaper_3dlut_setting != srf_updates[i].surface->mcm_shaper_3dlut_setting || 5802 srf_updates[i].cm2_params->component_settings.lut1d_enable != srf_updates[i].surface->mcm_lut1d_enable)))) 5803 return true; 5804 } 5805 5806 if (stream_update && 5807 (((stream_update->src.height != 0 && stream_update->src.width != 0) || 5808 (stream_update->dst.height != 0 && stream_update->dst.width != 0) || 5809 stream_update->integer_scaling_update) || 5810 stream_update->abm_level || 5811 stream_update->dpms_off || 5812 stream_update->allow_freesync || 5813 stream_update->vrr_active_variable || 5814 stream_update->vrr_active_fixed || 5815 stream_update->output_color_space || 5816 stream_update->wb_update || 5817 stream_update->dsc_config || 5818 stream_update->mst_bw_update || 5819 stream_update->func_shaper || 5820 stream_update->lut3d_func || 5821 stream_update->pending_test_pattern || 5822 stream_update->crtc_timing_adjust || 5823 stream_update->scaler_sharpener_update || 5824 stream_update->hw_cursor_req)) 5825 return true; 5826 5827 return false; 5828 } 5829 5830 static bool fast_update_only( 5831 const struct dc *dc, 5832 const struct dc_fast_update *fast_update, 5833 const struct dc_surface_update *srf_updates, 5834 int surface_count, 5835 const struct dc_stream_update *stream_update, 5836 const struct dc_stream_state *stream) 5837 { 5838 return fast_updates_exist(fast_update, surface_count) 5839 && !full_update_required(dc, srf_updates, surface_count, stream_update, stream); 5840 } 5841 5842 static bool update_planes_and_stream_v2(struct dc *dc, 5843 struct dc_surface_update *srf_updates, int surface_count, 5844 struct dc_stream_state *stream, 5845 struct dc_stream_update *stream_update) 5846 { 5847 struct dc_state *context; 5848 enum surface_update_type update_type; 5849 struct dc_fast_update fast_update[MAX_SURFACES] = {0}; 5850 5851 /* In cases where MPO and split or ODM are used transitions can 5852 * cause underflow. Apply stream configuration with minimal pipe 5853 * split first to avoid unsupported transitions for active pipes. 5854 */ 5855 bool force_minimal_pipe_splitting = 0; 5856 bool is_plane_addition = 0; 5857 bool is_fast_update_only; 5858 5859 populate_fast_updates(fast_update, srf_updates, surface_count, stream_update); 5860 is_fast_update_only = fast_update_only(dc, fast_update, srf_updates, 5861 surface_count, stream_update, stream); 5862 force_minimal_pipe_splitting = could_mpcc_tree_change_for_active_pipes( 5863 dc, 5864 stream, 5865 srf_updates, 5866 surface_count, 5867 &is_plane_addition); 5868 5869 /* on plane addition, minimal state is the current one */ 5870 if (force_minimal_pipe_splitting && is_plane_addition && 5871 !commit_minimal_transition_state(dc, dc->current_state)) 5872 return false; 5873 5874 if (!update_planes_and_stream_state( 5875 dc, 5876 srf_updates, 5877 surface_count, 5878 stream, 5879 stream_update, 5880 &update_type, 5881 &context)) 5882 return false; 5883 5884 /* on plane removal, minimal state is the new one */ 5885 if (force_minimal_pipe_splitting && !is_plane_addition) { 5886 if (!commit_minimal_transition_state(dc, context)) { 5887 dc_state_release(context); 5888 return false; 5889 } 5890 update_type = UPDATE_TYPE_FULL; 5891 } 5892 5893 if (dc->hwss.is_pipe_topology_transition_seamless && 5894 !dc->hwss.is_pipe_topology_transition_seamless( 5895 dc, dc->current_state, context)) 5896 commit_minimal_transition_state_in_dc_update(dc, context, stream, 5897 srf_updates, surface_count); 5898 5899 if (is_fast_update_only && !dc->check_config.enable_legacy_fast_update) { 5900 commit_planes_for_stream_fast(dc, 5901 srf_updates, 5902 surface_count, 5903 stream, 5904 stream_update, 5905 update_type, 5906 context); 5907 } else { 5908 if (!stream_update && 5909 dc->hwss.is_pipe_topology_transition_seamless && 5910 !dc->hwss.is_pipe_topology_transition_seamless( 5911 dc, dc->current_state, context)) { 5912 DC_LOG_ERROR("performing non-seamless pipe topology transition with surface only update!\n"); 5913 BREAK_TO_DEBUGGER(); 5914 } 5915 commit_planes_for_stream( 5916 dc, 5917 srf_updates, 5918 surface_count, 5919 stream, 5920 stream_update, 5921 update_type, 5922 context); 5923 } 5924 if (dc->current_state != context) 5925 swap_and_release_current_context(dc, context, stream); 5926 return true; 5927 } 5928 5929 static void commit_planes_and_stream_update_on_current_context(struct dc *dc, 5930 struct dc_surface_update *srf_updates, int surface_count, 5931 struct dc_stream_state *stream, 5932 struct dc_stream_update *stream_update, 5933 enum surface_update_type update_type) 5934 { 5935 struct dc_fast_update fast_update[MAX_SURFACES] = {0}; 5936 5937 ASSERT(update_type < UPDATE_TYPE_FULL); 5938 populate_fast_updates(fast_update, srf_updates, surface_count, 5939 stream_update); 5940 if (fast_update_only(dc, fast_update, srf_updates, surface_count, 5941 stream_update, stream) && 5942 !dc->check_config.enable_legacy_fast_update) 5943 commit_planes_for_stream_fast(dc, 5944 srf_updates, 5945 surface_count, 5946 stream, 5947 stream_update, 5948 update_type, 5949 dc->current_state); 5950 else 5951 commit_planes_for_stream( 5952 dc, 5953 srf_updates, 5954 surface_count, 5955 stream, 5956 stream_update, 5957 update_type, 5958 dc->current_state); 5959 } 5960 5961 static void commit_planes_and_stream_update_with_new_context(struct dc *dc, 5962 struct dc_surface_update *srf_updates, int surface_count, 5963 struct dc_stream_state *stream, 5964 struct dc_stream_update *stream_update, 5965 enum surface_update_type update_type, 5966 struct dc_state *new_context) 5967 { 5968 bool skip_new_context = false; 5969 ASSERT(update_type >= UPDATE_TYPE_FULL); 5970 /* 5971 * It is required by the feature design that all pipe topologies 5972 * using extra free pipes for power saving purposes such as 5973 * dynamic ODM or SubVp shall only be enabled when it can be 5974 * transitioned seamlessly to AND from its minimal transition 5975 * state. A minimal transition state is defined as the same dc 5976 * state but with all power saving features disabled. So it uses 5977 * the minimum pipe topology. When we can't seamlessly 5978 * transition from state A to state B, we will insert the 5979 * minimal transition state A' or B' in between so seamless 5980 * transition between A and B can be made possible. 5981 * 5982 * To optimize for the time it takes to execute flips, 5983 * the transition from the minimal state to the final state is 5984 * deferred until a steady state (no more transitions) is reached. 5985 */ 5986 if (!dc->hwss.is_pipe_topology_transition_seamless(dc, dc->current_state, new_context)) { 5987 if (!dc->debug.disable_deferred_minimal_transitions) { 5988 dc->check_config.deferred_transition_state = true; 5989 dc->check_config.transition_countdown_to_steady_state = 5990 dc->debug.num_fast_flips_to_steady_state_override ? 5991 dc->debug.num_fast_flips_to_steady_state_override : 5992 NUM_FAST_FLIPS_TO_STEADY_STATE; 5993 5994 if (commit_minimal_transition_based_on_new_context(dc, new_context, stream, stream_update, 5995 srf_updates, surface_count)) { 5996 skip_new_context = true; 5997 dc_state_release(new_context); 5998 new_context = dc->current_state; 5999 } else { 6000 /* 6001 * In this case a new mpo plane is being enabled on pipes that were 6002 * previously in use, and the surface update to the existing plane 6003 * includes an alpha box where the new plane will be, so the update 6004 * from minimal to final cannot be deferred as the alpha box would 6005 * be visible to the user 6006 */ 6007 commit_minimal_transition_based_on_current_context(dc, new_context, stream); 6008 } 6009 } else { 6010 commit_minimal_transition_state_in_dc_update(dc, new_context, stream, 6011 srf_updates, surface_count); 6012 } 6013 } else if (dc->check_config.deferred_transition_state) { 6014 /* reset countdown as steady state not reached */ 6015 dc->check_config.transition_countdown_to_steady_state = 6016 dc->debug.num_fast_flips_to_steady_state_override ? 6017 dc->debug.num_fast_flips_to_steady_state_override : 6018 NUM_FAST_FLIPS_TO_STEADY_STATE; 6019 } 6020 6021 if (!skip_new_context) { 6022 commit_planes_for_stream(dc, srf_updates, surface_count, stream, stream_update, update_type, new_context); 6023 swap_and_release_current_context(dc, new_context, stream); 6024 } 6025 } 6026 6027 static bool update_planes_and_stream_v3(struct dc *dc, 6028 struct dc_surface_update *srf_updates, int surface_count, 6029 struct dc_stream_state *stream, 6030 struct dc_stream_update *stream_update) 6031 { 6032 struct dc_state *new_context; 6033 enum surface_update_type update_type; 6034 6035 /* 6036 * When this function returns true and new_context is not equal to 6037 * current state, the function allocates and validates a new dc state 6038 * and assigns it to new_context. The function expects that the caller 6039 * is responsible to free this memory when new_context is no longer 6040 * used. We swap current with new context and free current instead. So 6041 * new_context's memory will live until the next full update after it is 6042 * replaced by a newer context. Refer to the use of 6043 * swap_and_free_current_context below. 6044 */ 6045 if (!update_planes_and_stream_state(dc, srf_updates, surface_count, 6046 stream, stream_update, &update_type, 6047 &new_context)) 6048 return false; 6049 6050 if (new_context == dc->current_state) { 6051 commit_planes_and_stream_update_on_current_context(dc, 6052 srf_updates, surface_count, stream, 6053 stream_update, update_type); 6054 6055 if (dc->check_config.transition_countdown_to_steady_state) 6056 dc->check_config.transition_countdown_to_steady_state--; 6057 } else { 6058 commit_planes_and_stream_update_with_new_context(dc, 6059 srf_updates, surface_count, stream, 6060 stream_update, update_type, new_context); 6061 } 6062 6063 return true; 6064 } 6065 6066 static void clear_update_flags(struct dc_surface_update *srf_updates, 6067 int surface_count, struct dc_stream_state *stream) 6068 { 6069 int i; 6070 6071 if (stream) 6072 stream->update_flags.raw = 0; 6073 6074 for (i = 0; i < surface_count; i++) 6075 if (srf_updates[i].surface) 6076 srf_updates[i].surface->update_flags.raw = 0; 6077 } 6078 6079 bool dc_update_planes_and_stream(struct dc *dc, 6080 struct dc_surface_update *srf_updates, int surface_count, 6081 struct dc_stream_state *stream, 6082 struct dc_stream_update *stream_update) 6083 { 6084 struct dc_update_scratch_space *scratch = dc_update_planes_and_stream_init( 6085 dc, 6086 srf_updates, 6087 surface_count, 6088 stream, 6089 stream_update 6090 ); 6091 bool more = true; 6092 6093 while (more) { 6094 if (!dc_update_planes_and_stream_prepare(scratch)) 6095 return false; 6096 6097 dc_update_planes_and_stream_execute(scratch); 6098 more = dc_update_planes_and_stream_cleanup(scratch); 6099 } 6100 return true; 6101 } 6102 6103 void dc_commit_updates_for_stream(struct dc *dc, 6104 struct dc_surface_update *srf_updates, 6105 int surface_count, 6106 struct dc_stream_state *stream, 6107 struct dc_stream_update *stream_update, 6108 struct dc_state *state) 6109 { 6110 (void)state; 6111 bool ret = false; 6112 6113 dc_exit_ips_for_hw_access(dc); 6114 /* TODO: Since change commit sequence can have a huge impact, 6115 * we decided to only enable it for DCN3x. However, as soon as 6116 * we get more confident about this change we'll need to enable 6117 * the new sequence for all ASICs. 6118 */ 6119 if (dc->ctx->dce_version >= DCN_VERSION_4_01) { 6120 ret = update_planes_and_stream_v3(dc, srf_updates, surface_count, 6121 stream, stream_update); 6122 } else { 6123 ret = update_planes_and_stream_v2(dc, srf_updates, surface_count, 6124 stream, stream_update); 6125 } 6126 6127 if (ret && dc->ctx->dce_version >= DCN_VERSION_3_2) 6128 clear_update_flags(srf_updates, surface_count, stream); 6129 } 6130 6131 uint8_t dc_get_current_stream_count(struct dc *dc) 6132 { 6133 return dc->current_state->stream_count; 6134 } 6135 6136 struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i) 6137 { 6138 if (i < dc->current_state->stream_count) 6139 return dc->current_state->streams[i]; 6140 return NULL; 6141 } 6142 6143 enum dc_irq_source dc_interrupt_to_irq_source( 6144 struct dc *dc, 6145 uint32_t src_id, 6146 uint32_t ext_id) 6147 { 6148 return dal_irq_service_to_irq_source(dc->res_pool->irqs, src_id, ext_id); 6149 } 6150 6151 /* 6152 * dc_interrupt_set() - Enable/disable an AMD hw interrupt source 6153 */ 6154 bool dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable) 6155 { 6156 6157 if (dc == NULL) 6158 return false; 6159 6160 return dal_irq_service_set(dc->res_pool->irqs, src, enable); 6161 } 6162 6163 void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src) 6164 { 6165 dal_irq_service_ack(dc->res_pool->irqs, src); 6166 } 6167 6168 void dc_power_down_on_boot(struct dc *dc) 6169 { 6170 if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW && 6171 dc->hwss.power_down_on_boot) { 6172 if (dc->current_state->stream_count > 0) 6173 return; 6174 6175 if (dc->caps.ips_support) 6176 dc_exit_ips_for_hw_access(dc); 6177 dc->hwss.power_down_on_boot(dc); 6178 } 6179 } 6180 6181 void dc_set_power_state(struct dc *dc, enum dc_acpi_cm_power_state power_state) 6182 { 6183 if (!dc->current_state) 6184 return; 6185 6186 dc_exit_ips_for_hw_access(dc); 6187 6188 switch (power_state) { 6189 case DC_ACPI_CM_POWER_STATE_D0: 6190 dc_state_construct(dc, dc->current_state); 6191 6192 dc_z10_restore(dc); 6193 6194 dc_dmub_srv_notify_fw_dc_power_state(dc->ctx->dmub_srv, power_state); 6195 6196 dc->hwss.init_hw(dc); 6197 6198 if (dc->hwss.init_sys_ctx != NULL && 6199 dc->vm_pa_config.valid) { 6200 dc->hwss.init_sys_ctx(dc->hwseq, dc, &dc->vm_pa_config); 6201 } 6202 break; 6203 case DC_ACPI_CM_POWER_STATE_D3: 6204 if (dc->caps.ips_support) 6205 dc_dmub_srv_notify_fw_dc_power_state(dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D3); 6206 6207 if (dc->caps.ips_v2_support) { 6208 if (dc->clk_mgr->funcs->set_low_power_state) 6209 dc->clk_mgr->funcs->set_low_power_state(dc->clk_mgr); 6210 } 6211 break; 6212 default: 6213 ASSERT(dc->current_state->stream_count == 0); 6214 dc_dmub_srv_notify_fw_dc_power_state(dc->ctx->dmub_srv, power_state); 6215 6216 dc_state_destruct(dc->current_state); 6217 6218 break; 6219 } 6220 } 6221 6222 void dc_resume(struct dc *dc) 6223 { 6224 uint32_t i; 6225 6226 for (i = 0; i < dc->link_count; i++) 6227 dc->link_srv->resume(dc->links[i]); 6228 } 6229 6230 bool dc_is_dmcu_initialized(struct dc *dc) 6231 { 6232 struct dmcu *dmcu = dc->res_pool->dmcu; 6233 6234 if (dmcu) 6235 return dmcu->funcs->is_dmcu_initialized(dmcu); 6236 return false; 6237 } 6238 6239 enum dc_status dc_set_clock(struct dc *dc, enum dc_clock_type clock_type, uint32_t clk_khz, uint32_t stepping) 6240 { 6241 if (dc->hwss.set_clock) 6242 return dc->hwss.set_clock(dc, clock_type, clk_khz, stepping); 6243 return DC_ERROR_UNEXPECTED; 6244 } 6245 void dc_get_clock(struct dc *dc, enum dc_clock_type clock_type, struct dc_clock_config *clock_cfg) 6246 { 6247 if (dc->hwss.get_clock) 6248 dc->hwss.get_clock(dc, clock_type, clock_cfg); 6249 } 6250 6251 /* enable/disable eDP PSR without specify stream for eDP */ 6252 bool dc_set_psr_allow_active(struct dc *dc, bool enable) 6253 { 6254 int i; 6255 bool allow_active; 6256 6257 for (i = 0; i < dc->current_state->stream_count ; i++) { 6258 struct dc_link *link; 6259 struct dc_stream_state *stream = dc->current_state->streams[i]; 6260 6261 link = stream->link; 6262 if (!link) 6263 continue; 6264 6265 if (link->psr_settings.psr_feature_enabled) { 6266 if (enable && !link->psr_settings.psr_allow_active) { 6267 allow_active = true; 6268 if (!dc_link_set_psr_allow_active(link, &allow_active, false, false, NULL)) 6269 return false; 6270 } else if (!enable && link->psr_settings.psr_allow_active) { 6271 allow_active = false; 6272 if (!dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL)) 6273 return false; 6274 } 6275 } 6276 } 6277 6278 return true; 6279 } 6280 6281 /* enable/disable eDP Replay without specify stream for eDP */ 6282 bool dc_set_replay_allow_active(struct dc *dc, bool active) 6283 { 6284 int i; 6285 bool allow_active; 6286 6287 for (i = 0; i < dc->current_state->stream_count; i++) { 6288 struct dc_link *link; 6289 struct dc_stream_state *stream = dc->current_state->streams[i]; 6290 6291 link = stream->link; 6292 if (!link) 6293 continue; 6294 6295 if (link->replay_settings.replay_feature_enabled) { 6296 if (active && !link->replay_settings.replay_allow_active) { 6297 allow_active = true; 6298 if (!dc_link_set_replay_allow_active(link, &allow_active, 6299 false, false, NULL)) 6300 return false; 6301 } else if (!active && link->replay_settings.replay_allow_active) { 6302 allow_active = false; 6303 if (!dc_link_set_replay_allow_active(link, &allow_active, 6304 true, false, NULL)) 6305 return false; 6306 } 6307 } 6308 } 6309 6310 return true; 6311 } 6312 6313 /* set IPS disable state */ 6314 bool dc_set_ips_disable(struct dc *dc, unsigned int disable_ips) 6315 { 6316 dc_exit_ips_for_hw_access(dc); 6317 6318 dc->config.disable_ips = disable_ips; 6319 6320 return true; 6321 } 6322 6323 void dc_allow_idle_optimizations_internal(struct dc *dc, bool allow, char const *caller_name) 6324 { 6325 int idle_fclk_khz = 0, idle_dramclk_khz = 0; 6326 unsigned int i = 0; 6327 enum mall_stream_type subvp_pipe_type[MAX_PIPES] = {0}; 6328 struct pipe_ctx *pipe = NULL; 6329 struct dc_state *context = dc->current_state; 6330 6331 if (dc->debug.disable_idle_power_optimizations) { 6332 DC_LOG_DEBUG("%s: disabled\n", __func__); 6333 return; 6334 } 6335 6336 if (allow != dc->idle_optimizations_allowed) 6337 DC_LOG_IPS("%s: allow_idle old=%d new=%d (caller=%s)\n", __func__, 6338 dc->idle_optimizations_allowed, allow, caller_name); 6339 6340 if (dc->caps.ips_support && (dc->config.disable_ips == DMUB_IPS_DISABLE_ALL)) 6341 return; 6342 6343 if (dc->clk_mgr != NULL && dc->clk_mgr->funcs->is_smu_present) 6344 if (!dc->clk_mgr->funcs->is_smu_present(dc->clk_mgr)) 6345 return; 6346 6347 if (allow == dc->idle_optimizations_allowed) 6348 return; 6349 6350 if (dc->hwss.apply_idle_power_optimizations && dc->clk_mgr != NULL && 6351 dc->hwss.apply_idle_power_optimizations(dc, allow)) { 6352 dc->idle_optimizations_allowed = allow; 6353 DC_LOG_DEBUG("%s: %s\n", __func__, allow ? "enabled" : "disabled"); 6354 } 6355 6356 // log idle clocks and sub vp pipe types at idle optimization time 6357 if (dc->clk_mgr != NULL && dc->clk_mgr->funcs->get_hard_min_fclk) 6358 idle_fclk_khz = dc->clk_mgr->funcs->get_hard_min_fclk(dc->clk_mgr); 6359 6360 if (dc->clk_mgr != NULL && dc->clk_mgr->funcs->get_hard_min_memclk) 6361 idle_dramclk_khz = dc->clk_mgr->funcs->get_hard_min_memclk(dc->clk_mgr); 6362 6363 if (dc->res_pool && context) { 6364 for (i = 0; i < dc->res_pool->pipe_count; i++) { 6365 pipe = &context->res_ctx.pipe_ctx[i]; 6366 subvp_pipe_type[i] = dc_state_get_pipe_subvp_type(context, pipe); 6367 } 6368 } 6369 if (!dc->caps.is_apu) 6370 DC_LOG_DC("%s: allow_idle=%d\n HardMinUClk_Khz=%d HardMinDramclk_Khz=%d\n Pipe_0=%d Pipe_1=%d Pipe_2=%d Pipe_3=%d Pipe_4=%d Pipe_5=%d (caller=%s)\n", 6371 __func__, allow, idle_fclk_khz, idle_dramclk_khz, subvp_pipe_type[0], subvp_pipe_type[1], subvp_pipe_type[2], 6372 subvp_pipe_type[3], subvp_pipe_type[4], subvp_pipe_type[5], caller_name); 6373 6374 } 6375 6376 void dc_exit_ips_for_hw_access_internal(struct dc *dc, const char *caller_name) 6377 { 6378 if (dc->caps.ips_support) 6379 dc_allow_idle_optimizations_internal(dc, false, caller_name); 6380 } 6381 6382 bool dc_dmub_is_ips_idle_state(struct dc *dc) 6383 { 6384 if (dc->debug.disable_idle_power_optimizations) 6385 return false; 6386 6387 if (!dc->caps.ips_support || (dc->config.disable_ips == DMUB_IPS_DISABLE_ALL)) 6388 return false; 6389 6390 if (!dc->ctx->dmub_srv) 6391 return false; 6392 6393 return dc->ctx->dmub_srv->idle_allowed; 6394 } 6395 6396 /* set min and max memory clock to lowest and highest DPM level, respectively */ 6397 void dc_unlock_memory_clock_frequency(struct dc *dc) 6398 { 6399 if (dc->clk_mgr->funcs->set_hard_min_memclk) 6400 dc->clk_mgr->funcs->set_hard_min_memclk(dc->clk_mgr, false); 6401 6402 if (dc->clk_mgr->funcs->set_hard_max_memclk) 6403 dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr); 6404 } 6405 6406 /* set min memory clock to the min required for current mode, max to maxDPM */ 6407 void dc_lock_memory_clock_frequency(struct dc *dc) 6408 { 6409 if (dc->clk_mgr->funcs->get_memclk_states_from_smu) 6410 dc->clk_mgr->funcs->get_memclk_states_from_smu(dc->clk_mgr); 6411 6412 if (dc->clk_mgr->funcs->set_hard_min_memclk) 6413 dc->clk_mgr->funcs->set_hard_min_memclk(dc->clk_mgr, true); 6414 6415 if (dc->clk_mgr->funcs->set_hard_max_memclk) 6416 dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr); 6417 } 6418 6419 static void blank_and_force_memclk(struct dc *dc, bool apply, unsigned int memclk_mhz) 6420 { 6421 (void)apply; 6422 struct dc_state *context = dc->current_state; 6423 struct hubp *hubp; 6424 struct pipe_ctx *pipe; 6425 unsigned int i; 6426 6427 for (i = 0; i < dc->res_pool->pipe_count; i++) { 6428 pipe = &context->res_ctx.pipe_ctx[i]; 6429 6430 if (pipe->stream != NULL) { 6431 dc->hwss.disable_pixel_data(dc, pipe, true); 6432 6433 // wait for double buffer 6434 pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, CRTC_STATE_VACTIVE); 6435 pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, CRTC_STATE_VBLANK); 6436 pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, CRTC_STATE_VACTIVE); 6437 6438 hubp = pipe->plane_res.hubp; 6439 hubp->funcs->set_blank_regs(hubp, true); 6440 } 6441 } 6442 if (dc->clk_mgr->funcs->set_max_memclk) 6443 dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, memclk_mhz); 6444 if (dc->clk_mgr->funcs->set_min_memclk) 6445 dc->clk_mgr->funcs->set_min_memclk(dc->clk_mgr, memclk_mhz); 6446 6447 for (i = 0; i < dc->res_pool->pipe_count; i++) { 6448 pipe = &context->res_ctx.pipe_ctx[i]; 6449 6450 if (pipe->stream != NULL) { 6451 dc->hwss.disable_pixel_data(dc, pipe, false); 6452 6453 hubp = pipe->plane_res.hubp; 6454 hubp->funcs->set_blank_regs(hubp, false); 6455 } 6456 } 6457 } 6458 6459 6460 /** 6461 * dc_enable_dcmode_clk_limit() - lower clocks in dc (battery) mode 6462 * @dc: pointer to dc of the dm calling this 6463 * @enable: True = transition to DC mode, false = transition back to AC mode 6464 * 6465 * Some SoCs define additional clock limits when in DC mode, DM should 6466 * invoke this function when the platform undergoes a power source transition 6467 * so DC can apply/unapply the limit. This interface may be disruptive to 6468 * the onscreen content. 6469 * 6470 * Context: Triggered by OS through DM interface, or manually by escape calls. 6471 * Need to hold a dclock when doing so. 6472 * 6473 * Return: none (void function) 6474 * 6475 */ 6476 void dc_enable_dcmode_clk_limit(struct dc *dc, bool enable) 6477 { 6478 unsigned int softMax = 0, maxDPM = 0, funcMin = 0, i; 6479 bool p_state_change_support; 6480 6481 if (!dc->config.dc_mode_clk_limit_support) 6482 return; 6483 6484 softMax = dc->clk_mgr->bw_params->dc_mode_softmax_memclk; 6485 for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries; i++) { 6486 if (dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz > maxDPM) 6487 maxDPM = dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz; 6488 } 6489 funcMin = (dc->clk_mgr->clks.dramclk_khz + 999) / 1000; 6490 p_state_change_support = dc->clk_mgr->clks.p_state_change_support; 6491 6492 if (enable && !dc->clk_mgr->dc_mode_softmax_enabled) { 6493 if (p_state_change_support) { 6494 if (funcMin <= softMax && dc->clk_mgr->funcs->set_max_memclk) 6495 dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, softMax); 6496 // else: No-Op 6497 } else { 6498 if (funcMin <= softMax) 6499 blank_and_force_memclk(dc, true, softMax); 6500 // else: No-Op 6501 } 6502 } else if (!enable && dc->clk_mgr->dc_mode_softmax_enabled) { 6503 if (p_state_change_support) { 6504 if (funcMin <= softMax && dc->clk_mgr->funcs->set_max_memclk) 6505 dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, maxDPM); 6506 // else: No-Op 6507 } else { 6508 if (funcMin <= softMax) 6509 blank_and_force_memclk(dc, true, maxDPM); 6510 // else: No-Op 6511 } 6512 } 6513 dc->clk_mgr->dc_mode_softmax_enabled = enable; 6514 } 6515 bool dc_is_plane_eligible_for_idle_optimizations(struct dc *dc, 6516 unsigned int pitch, 6517 unsigned int height, 6518 enum surface_pixel_format format, 6519 struct dc_cursor_attributes *cursor_attr) 6520 { 6521 if (dc->hwss.does_plane_fit_in_mall && dc->hwss.does_plane_fit_in_mall(dc, pitch, height, format, cursor_attr)) 6522 return true; 6523 return false; 6524 } 6525 6526 /* cleanup on driver unload */ 6527 void dc_hardware_release(struct dc *dc) 6528 { 6529 dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(dc); 6530 6531 if (dc->hwss.hardware_release) 6532 dc->hwss.hardware_release(dc); 6533 } 6534 6535 void dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(struct dc *dc) 6536 { 6537 if (dc->current_state) 6538 dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching_shut_down = true; 6539 } 6540 6541 /** 6542 * dc_is_dmub_outbox_supported - Check if DMUB firmware support outbox notification 6543 * 6544 * @dc: [in] dc structure 6545 * 6546 * Checks whether DMUB FW supports outbox notifications, if supported DM 6547 * should register outbox interrupt prior to actually enabling interrupts 6548 * via dc_enable_dmub_outbox 6549 * 6550 * Return: 6551 * True if DMUB FW supports outbox notifications, False otherwise 6552 */ 6553 bool dc_is_dmub_outbox_supported(struct dc *dc) 6554 { 6555 if (!dc->caps.dmcub_support) 6556 return false; 6557 6558 switch (dc->ctx->asic_id.chip_family) { 6559 6560 case FAMILY_YELLOW_CARP: 6561 /* DCN31 B0 USB4 DPIA needs dmub notifications for interrupts */ 6562 if (dc->ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0 && 6563 !dc->debug.dpia_debug.bits.disable_dpia) 6564 return true; 6565 break; 6566 6567 case AMDGPU_FAMILY_GC_11_0_1: 6568 case AMDGPU_FAMILY_GC_11_5_0: 6569 case AMDGPU_FAMILY_GC_11_5_4: 6570 if (!dc->debug.dpia_debug.bits.disable_dpia) 6571 return true; 6572 break; 6573 6574 default: 6575 break; 6576 } 6577 6578 /* dmub aux needs dmub notifications to be enabled */ 6579 return dc->debug.enable_dmub_aux_for_legacy_ddc; 6580 6581 } 6582 6583 /** 6584 * dc_enable_dmub_notifications - Check if dmub fw supports outbox 6585 * 6586 * @dc: [in] dc structure 6587 * 6588 * Calls dc_is_dmub_outbox_supported to check if dmub fw supports outbox 6589 * notifications. All DMs shall switch to dc_is_dmub_outbox_supported. This 6590 * API shall be removed after switching. 6591 * 6592 * Return: 6593 * True if DMUB FW supports outbox notifications, False otherwise 6594 */ 6595 bool dc_enable_dmub_notifications(struct dc *dc) 6596 { 6597 return dc_is_dmub_outbox_supported(dc); 6598 } 6599 6600 /** 6601 * dc_enable_dmub_outbox - Enables DMUB unsolicited notification 6602 * 6603 * @dc: [in] dc structure 6604 * 6605 * Enables DMUB unsolicited notifications to x86 via outbox. 6606 */ 6607 void dc_enable_dmub_outbox(struct dc *dc) 6608 { 6609 struct dc_context *dc_ctx = dc->ctx; 6610 6611 dmub_enable_outbox_notification(dc_ctx->dmub_srv); 6612 DC_LOG_DC("%s: dmub outbox notifications enabled\n", __func__); 6613 } 6614 6615 /** 6616 * dc_process_dmub_aux_transfer_async - Submits aux command to dmub via inbox message 6617 * Sets port index appropriately for legacy DDC 6618 * @dc: dc structure 6619 * @link_index: link index 6620 * @payload: aux payload 6621 * 6622 * Returns: True if successful, False if failure 6623 */ 6624 bool dc_process_dmub_aux_transfer_async(struct dc *dc, 6625 uint32_t link_index, 6626 struct aux_payload *payload) 6627 { 6628 uint8_t action; 6629 union dmub_rb_cmd cmd = {0}; 6630 6631 if (link_index >= dc->link_count || !dc->links[link_index]) 6632 return false; 6633 6634 if (payload->length > sizeof(cmd.dp_aux_access.aux_control.dpaux.data)) 6635 return false; 6636 6637 cmd.dp_aux_access.header.type = DMUB_CMD__DP_AUX_ACCESS; 6638 cmd.dp_aux_access.header.payload_bytes = 0; 6639 /* For dpia, ddc_pin is set to NULL */ 6640 if (!dc->links[link_index]->ddc->ddc_pin) 6641 cmd.dp_aux_access.aux_control.type = AUX_CHANNEL_DPIA; 6642 else 6643 cmd.dp_aux_access.aux_control.type = AUX_CHANNEL_LEGACY_DDC; 6644 6645 cmd.dp_aux_access.aux_control.instance = (uint8_t)dc->links[link_index]->ddc_hw_inst; 6646 cmd.dp_aux_access.aux_control.sw_crc_enabled = 0; 6647 cmd.dp_aux_access.aux_control.timeout = 0; 6648 cmd.dp_aux_access.aux_control.dpaux.address = payload->address; 6649 cmd.dp_aux_access.aux_control.dpaux.is_i2c_over_aux = payload->i2c_over_aux; 6650 cmd.dp_aux_access.aux_control.dpaux.length = (uint8_t)payload->length; 6651 6652 /* set aux action */ 6653 if (payload->i2c_over_aux) { 6654 if (payload->write) { 6655 if (payload->mot) 6656 action = DP_AUX_REQ_ACTION_I2C_WRITE_MOT; 6657 else 6658 action = DP_AUX_REQ_ACTION_I2C_WRITE; 6659 } else { 6660 if (payload->mot) 6661 action = DP_AUX_REQ_ACTION_I2C_READ_MOT; 6662 else 6663 action = DP_AUX_REQ_ACTION_I2C_READ; 6664 } 6665 } else { 6666 if (payload->write) 6667 action = DP_AUX_REQ_ACTION_DPCD_WRITE; 6668 else 6669 action = DP_AUX_REQ_ACTION_DPCD_READ; 6670 } 6671 6672 cmd.dp_aux_access.aux_control.dpaux.action = action; 6673 6674 if (payload->length && payload->write) { 6675 memcpy(cmd.dp_aux_access.aux_control.dpaux.data, 6676 payload->data, 6677 payload->length 6678 ); 6679 } 6680 6681 dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 6682 6683 return true; 6684 } 6685 6686 bool dc_smart_power_oled_enable(const struct dc_link *link, bool enable, uint16_t peak_nits, 6687 uint8_t debug_control, uint16_t fixed_CLL, uint32_t triggerline) 6688 { 6689 bool status = false; 6690 struct dc *dc = link->ctx->dc; 6691 union dmub_rb_cmd cmd; 6692 uint8_t otg_inst = 0; 6693 unsigned int panel_inst = 0; 6694 struct pipe_ctx *pipe_ctx = NULL; 6695 struct resource_context *res_ctx = &link->ctx->dc->current_state->res_ctx; 6696 int i = 0; 6697 6698 // get panel_inst 6699 if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) 6700 return status; 6701 6702 // get otg_inst 6703 for (i = 0; i < MAX_PIPES; i++) { 6704 if (res_ctx && 6705 res_ctx->pipe_ctx[i].stream && 6706 res_ctx->pipe_ctx[i].stream->link && 6707 res_ctx->pipe_ctx[i].stream->link == link && 6708 res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) { 6709 pipe_ctx = &res_ctx->pipe_ctx[i]; 6710 //TODO: refactor for multi edp support 6711 break; 6712 } 6713 } 6714 6715 if (pipe_ctx) 6716 otg_inst = (uint8_t)pipe_ctx->stream_res.tg->inst; 6717 6718 // before enable smart power OLED, we need to call set pipe for DMUB to set ABM config 6719 if (enable) { 6720 if (dc->hwss.set_pipe && pipe_ctx) 6721 dc->hwss.set_pipe(pipe_ctx); 6722 } 6723 6724 // fill in cmd 6725 memset(&cmd, 0, sizeof(cmd)); 6726 6727 cmd.smart_power_oled_enable.header.type = DMUB_CMD__SMART_POWER_OLED; 6728 cmd.smart_power_oled_enable.header.sub_type = DMUB_CMD__SMART_POWER_OLED_ENABLE; 6729 cmd.smart_power_oled_enable.header.payload_bytes = 6730 sizeof(struct dmub_rb_cmd_smart_power_oled_enable_data) - sizeof(struct dmub_cmd_header); 6731 cmd.smart_power_oled_enable.header.ret_status = 1; 6732 cmd.smart_power_oled_enable.data.enable = enable; 6733 cmd.smart_power_oled_enable.data.panel_inst = (uint8_t)panel_inst; 6734 cmd.smart_power_oled_enable.data.peak_nits = peak_nits; 6735 cmd.smart_power_oled_enable.data.otg_inst = otg_inst; 6736 cmd.smart_power_oled_enable.data.digfe_inst = (uint8_t)link->link_enc->preferred_engine; 6737 cmd.smart_power_oled_enable.data.digbe_inst = (uint8_t)link->link_enc->transmitter; 6738 6739 cmd.smart_power_oled_enable.data.debugcontrol = debug_control; 6740 cmd.smart_power_oled_enable.data.triggerline = triggerline; 6741 cmd.smart_power_oled_enable.data.fixed_max_cll = fixed_CLL; 6742 6743 // send cmd 6744 status = dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 6745 6746 // Update firmware_controlled_hdr_info_packet state on successful command execution 6747 if (status && pipe_ctx) 6748 pipe_ctx->stream->firmware_controlled_hdr_info_packet = enable; 6749 6750 return status; 6751 } 6752 6753 bool dc_smart_power_oled_get_max_cll(const struct dc_link *link, unsigned int *pCurrent_MaxCLL) 6754 { 6755 struct dc *dc = link->ctx->dc; 6756 union dmub_rb_cmd cmd; 6757 bool status = false; 6758 unsigned int panel_inst = 0; 6759 6760 // get panel_inst 6761 if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) 6762 return status; 6763 6764 // fill in cmd 6765 memset(&cmd, 0, sizeof(cmd)); 6766 6767 cmd.smart_power_oled_getmaxcll.header.type = DMUB_CMD__SMART_POWER_OLED; 6768 cmd.smart_power_oled_getmaxcll.header.sub_type = DMUB_CMD__SMART_POWER_OLED_GETMAXCLL; 6769 cmd.smart_power_oled_getmaxcll.header.payload_bytes = sizeof(cmd.smart_power_oled_getmaxcll.data); 6770 cmd.smart_power_oled_getmaxcll.header.ret_status = 1; 6771 6772 cmd.smart_power_oled_getmaxcll.data.input.panel_inst = (uint8_t)panel_inst; 6773 6774 // send cmd and wait for reply 6775 status = dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY); 6776 6777 if (status) 6778 *pCurrent_MaxCLL = cmd.smart_power_oled_getmaxcll.data.output.current_max_cll; 6779 else 6780 *pCurrent_MaxCLL = 0; 6781 6782 return status; 6783 } 6784 6785 uint8_t get_link_index_from_dpia_port_index(const struct dc *dc, 6786 uint8_t dpia_port_index) 6787 { 6788 uint8_t index, link_index = 0xFF; 6789 6790 for (index = 0; index < dc->link_count; index++) { 6791 /* ddc_hw_inst has dpia port index for dpia links 6792 * and ddc instance for legacy links 6793 */ 6794 if (!dc->links[index]->ddc->ddc_pin) { 6795 if (dc->links[index]->ddc_hw_inst == dpia_port_index) { 6796 link_index = index; 6797 break; 6798 } 6799 } 6800 } 6801 ASSERT(link_index != 0xFF); 6802 return link_index; 6803 } 6804 6805 /** 6806 * dc_process_dmub_set_config_async - Submits set_config command 6807 * 6808 * @dc: [in] dc structure 6809 * @link_index: [in] link_index: link index 6810 * @payload: [in] aux payload 6811 * @notify: [out] set_config immediate reply 6812 * 6813 * Submits set_config command to dmub via inbox message. 6814 * 6815 * Return: 6816 * True if successful, False if failure 6817 */ 6818 bool dc_process_dmub_set_config_async(struct dc *dc, 6819 uint32_t link_index, 6820 struct set_config_cmd_payload *payload, 6821 struct dmub_notification *notify) 6822 { 6823 union dmub_rb_cmd cmd = {0}; 6824 bool is_cmd_complete = true; 6825 6826 /* prepare SET_CONFIG command */ 6827 cmd.set_config_access.header.type = DMUB_CMD__DPIA; 6828 cmd.set_config_access.header.sub_type = DMUB_CMD__DPIA_SET_CONFIG_ACCESS; 6829 6830 cmd.set_config_access.set_config_control.instance = (uint8_t)dc->links[link_index]->ddc_hw_inst; 6831 cmd.set_config_access.set_config_control.cmd_pkt.msg_type = payload->msg_type; 6832 cmd.set_config_access.set_config_control.cmd_pkt.msg_data = payload->msg_data; 6833 6834 if (!dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) { 6835 /* command is not processed by dmub */ 6836 notify->sc_status = SET_CONFIG_UNKNOWN_ERROR; 6837 return is_cmd_complete; 6838 } 6839 6840 /* command processed by dmub, if ret_status is 1, it is completed instantly */ 6841 if (cmd.set_config_access.header.ret_status == 1) 6842 notify->sc_status = cmd.set_config_access.set_config_control.immed_status; 6843 else 6844 /* cmd pending, will receive notification via outbox */ 6845 is_cmd_complete = false; 6846 6847 return is_cmd_complete; 6848 } 6849 6850 /** 6851 * dc_process_dmub_set_mst_slots - Submits MST solt allocation 6852 * 6853 * @dc: [in] dc structure 6854 * @link_index: [in] link index 6855 * @mst_alloc_slots: [in] mst slots to be allotted 6856 * @mst_slots_in_use: [out] mst slots in use returned in failure case 6857 * 6858 * Submits mst slot allocation command to dmub via inbox message 6859 * 6860 * Return: 6861 * DC_OK if successful, DC_ERROR if failure 6862 */ 6863 enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc, 6864 uint32_t link_index, 6865 uint8_t mst_alloc_slots, 6866 uint8_t *mst_slots_in_use) 6867 { 6868 union dmub_rb_cmd cmd = {0}; 6869 6870 /* prepare MST_ALLOC_SLOTS command */ 6871 cmd.set_mst_alloc_slots.header.type = DMUB_CMD__DPIA; 6872 cmd.set_mst_alloc_slots.header.sub_type = DMUB_CMD__DPIA_MST_ALLOC_SLOTS; 6873 6874 cmd.set_mst_alloc_slots.mst_slots_control.instance = (uint8_t)dc->links[link_index]->ddc_hw_inst; 6875 cmd.set_mst_alloc_slots.mst_slots_control.mst_alloc_slots = mst_alloc_slots; 6876 6877 if (!dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) 6878 /* command is not processed by dmub */ 6879 return DC_ERROR_UNEXPECTED; 6880 6881 /* command processed by dmub, if ret_status is 1 */ 6882 if (cmd.set_config_access.header.ret_status != 1) 6883 /* command processing error */ 6884 return DC_ERROR_UNEXPECTED; 6885 6886 /* command processed and we have a status of 2, mst not enabled in dpia */ 6887 if (cmd.set_mst_alloc_slots.mst_slots_control.immed_status == 2) 6888 return DC_FAIL_UNSUPPORTED_1; 6889 6890 /* previously configured mst alloc and used slots did not match */ 6891 if (cmd.set_mst_alloc_slots.mst_slots_control.immed_status == 3) { 6892 *mst_slots_in_use = cmd.set_mst_alloc_slots.mst_slots_control.mst_slots_in_use; 6893 return DC_NOT_SUPPORTED; 6894 } 6895 6896 return DC_OK; 6897 } 6898 6899 /** 6900 * dc_process_dmub_dpia_set_tps_notification - Submits tps notification 6901 * 6902 * @dc: [in] dc structure 6903 * @link_index: [in] link index 6904 * @tps: [in] request tps 6905 * 6906 * Submits set_tps_notification command to dmub via inbox message 6907 */ 6908 void dc_process_dmub_dpia_set_tps_notification(const struct dc *dc, uint32_t link_index, uint8_t tps) 6909 { 6910 union dmub_rb_cmd cmd = {0}; 6911 6912 cmd.set_tps_notification.header.type = DMUB_CMD__DPIA; 6913 cmd.set_tps_notification.header.sub_type = DMUB_CMD__DPIA_SET_TPS_NOTIFICATION; 6914 cmd.set_tps_notification.tps_notification.instance = (uint8_t)dc->links[link_index]->ddc_hw_inst; 6915 cmd.set_tps_notification.tps_notification.tps = tps; 6916 6917 dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 6918 } 6919 6920 /** 6921 * dc_process_dmub_dpia_hpd_int_enable - Submits DPIA DPD interruption 6922 * 6923 * @dc: [in] dc structure 6924 * @hpd_int_enable: [in] 1 for hpd int enable, 0 to disable 6925 * 6926 * Submits dpia hpd int enable command to dmub via inbox message 6927 */ 6928 void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc, 6929 uint32_t hpd_int_enable) 6930 { 6931 union dmub_rb_cmd cmd = {0}; 6932 6933 cmd.dpia_hpd_int_enable.header.type = DMUB_CMD__DPIA_HPD_INT_ENABLE; 6934 cmd.dpia_hpd_int_enable.enable = hpd_int_enable; 6935 6936 dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 6937 6938 DC_LOG_DEBUG("%s: hpd_int_enable(%d)\n", __func__, hpd_int_enable); 6939 } 6940 6941 /** 6942 * dc_print_dmub_diagnostic_data - Print DMUB diagnostic data for debugging 6943 * 6944 * @dc: [in] dc structure 6945 * 6946 * 6947 */ 6948 void dc_print_dmub_diagnostic_data(const struct dc *dc) 6949 { 6950 dc_dmub_srv_log_diagnostic_data(dc->ctx->dmub_srv); 6951 } 6952 6953 /** 6954 * dc_disable_accelerated_mode - disable accelerated mode 6955 * @dc: dc structure 6956 */ 6957 void dc_disable_accelerated_mode(struct dc *dc) 6958 { 6959 bios_set_scratch_acc_mode_change(dc->ctx->dc_bios, 0); 6960 } 6961 6962 6963 /** 6964 * dc_notify_vsync_int_state - notifies vsync enable/disable state 6965 * @dc: dc structure 6966 * @stream: stream where vsync int state changed 6967 * @enable: whether vsync is enabled or disabled 6968 * 6969 * Called when vsync is enabled/disabled Will notify DMUB to start/stop ABM 6970 * interrupts after steady state is reached. 6971 */ 6972 void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bool enable) 6973 { 6974 unsigned int i, edp_num; 6975 struct pipe_ctx *pipe = NULL; 6976 struct dc_link *link = stream->sink->link; 6977 struct dc_link *edp_links[MAX_NUM_EDP]; 6978 6979 6980 if (link->psr_settings.psr_feature_enabled) 6981 return; 6982 6983 if (link->replay_settings.replay_feature_enabled) 6984 return; 6985 6986 /*find primary pipe associated with stream*/ 6987 for (i = 0; i < MAX_PIPES; i++) { 6988 pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 6989 6990 if (pipe->stream == stream && pipe->stream_res.tg) 6991 break; 6992 } 6993 6994 if (i == MAX_PIPES) { 6995 ASSERT(0); 6996 return; 6997 } 6998 6999 dc_get_edp_links(dc, edp_links, &edp_num); 7000 7001 /* Determine panel inst */ 7002 for (i = 0; i < edp_num; i++) { 7003 if (edp_links[i] == link) 7004 break; 7005 } 7006 7007 if (i == edp_num) { 7008 return; 7009 } 7010 7011 if (pipe->stream_res.abm && pipe->stream_res.abm->funcs->set_abm_pause) 7012 pipe->stream_res.abm->funcs->set_abm_pause(pipe->stream_res.abm, !enable, i, pipe->stream_res.tg->inst); 7013 } 7014 7015 /***************************************************************************** 7016 * dc_abm_save_restore() - Interface to DC for save+pause and restore+un-pause 7017 * ABM 7018 * @dc: dc structure 7019 * @stream: stream where vsync int state changed 7020 * @pData: abm hw states 7021 * 7022 ****************************************************************************/ 7023 bool dc_abm_save_restore( 7024 struct dc *dc, 7025 struct dc_stream_state *stream, 7026 struct abm_save_restore *pData) 7027 { 7028 unsigned int i, edp_num; 7029 struct pipe_ctx *pipe = NULL; 7030 struct dc_link *link = stream->sink->link; 7031 struct dc_link *edp_links[MAX_NUM_EDP]; 7032 7033 if (link->replay_settings.replay_feature_enabled) 7034 return false; 7035 7036 /*find primary pipe associated with stream*/ 7037 for (i = 0; i < MAX_PIPES; i++) { 7038 pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 7039 7040 if (pipe->stream == stream && pipe->stream_res.tg) 7041 break; 7042 } 7043 7044 if (i == MAX_PIPES) { 7045 ASSERT(0); 7046 return false; 7047 } 7048 7049 dc_get_edp_links(dc, edp_links, &edp_num); 7050 7051 /* Determine panel inst */ 7052 for (i = 0; i < edp_num; i++) 7053 if (edp_links[i] == link) 7054 break; 7055 7056 if (i == edp_num) 7057 return false; 7058 7059 if (pipe->stream_res.abm && 7060 pipe->stream_res.abm->funcs->save_restore) 7061 return pipe->stream_res.abm->funcs->save_restore( 7062 pipe->stream_res.abm, 7063 i, 7064 pData); 7065 return false; 7066 } 7067 7068 void dc_query_current_properties(struct dc *dc, struct dc_current_properties *properties) 7069 { 7070 unsigned int i; 7071 unsigned int max_cursor_size = dc->caps.max_cursor_size; 7072 unsigned int stream_cursor_size; 7073 7074 if (dc->debug.allow_sw_cursor_fallback && dc->res_pool->funcs->get_max_hw_cursor_size) { 7075 for (i = 0; i < dc->current_state->stream_count; i++) { 7076 stream_cursor_size = dc->res_pool->funcs->get_max_hw_cursor_size(dc, 7077 dc->current_state, 7078 dc->current_state->streams[i]); 7079 7080 if (stream_cursor_size < max_cursor_size) { 7081 max_cursor_size = stream_cursor_size; 7082 } 7083 } 7084 } 7085 7086 properties->cursor_size_limit = max_cursor_size; 7087 } 7088 7089 /** 7090 * dc_set_edp_power() - DM controls eDP power to be ON/OFF 7091 * 7092 * Called when DM wants to power on/off eDP. 7093 * Only work on links with flag skip_implict_edp_power_control is set. 7094 * 7095 * @dc: Current DC state 7096 * @edp_link: a link with eDP connector signal type 7097 * @powerOn: power on/off eDP 7098 * 7099 * Return: void 7100 */ 7101 void dc_set_edp_power(const struct dc *dc, struct dc_link *edp_link, 7102 bool powerOn) 7103 { 7104 (void)dc; 7105 if (edp_link->connector_signal != SIGNAL_TYPE_EDP) 7106 return; 7107 7108 if (edp_link->skip_implict_edp_power_control == false) 7109 return; 7110 7111 edp_link->dc->link_srv->edp_set_panel_power(edp_link, powerOn); 7112 } 7113 7114 /** 7115 * dc_get_power_profile_for_dc_state() - extracts power profile from dc state 7116 * 7117 * Called when DM wants to make power policy decisions based on dc_state 7118 * 7119 * @context: Pointer to the dc_state from which the power profile is extracted. 7120 * 7121 * Return: The power profile structure containing the power level information. 7122 */ 7123 struct dc_power_profile dc_get_power_profile_for_dc_state(const struct dc_state *context) 7124 { 7125 struct dc_power_profile profile = { 0 }; 7126 7127 profile.power_level = !context->bw_ctx.bw.dcn.clk.p_state_change_support; 7128 if (!context->clk_mgr || !context->clk_mgr->ctx || !context->clk_mgr->ctx->dc) 7129 return profile; 7130 struct dc *dc = context->clk_mgr->ctx->dc; 7131 7132 if (dc->res_pool->funcs->get_power_profile) 7133 profile.power_level = dc->res_pool->funcs->get_power_profile(context); 7134 return profile; 7135 } 7136 7137 /** 7138 * dc_get_det_buffer_size_from_state() - extracts detile buffer size from dc state 7139 * 7140 * This function is called to log the detile buffer size from the dc_state. 7141 * 7142 * @context: a pointer to the dc_state from which the detile buffer size is extracted. 7143 * 7144 * Return: the size of the detile buffer, or 0 if not available. 7145 */ 7146 unsigned int dc_get_det_buffer_size_from_state(const struct dc_state *context) 7147 { 7148 struct dc *dc = context->clk_mgr->ctx->dc; 7149 7150 if (dc->res_pool->funcs->get_det_buffer_size) 7151 return dc->res_pool->funcs->get_det_buffer_size(context); 7152 else 7153 return 0; 7154 } 7155 7156 /** 7157 * dc_get_host_router_index: Get index of host router from a dpia link 7158 * 7159 * This function return a host router index of the target link. If the target link is dpia link. 7160 * 7161 * @link: Pointer to the target link (input) 7162 * @host_router_index: Pointer to store the host router index of the target link (output). 7163 * 7164 * Return: true if the host router index is found and valid. 7165 * 7166 */ 7167 bool dc_get_host_router_index(const struct dc_link *link, unsigned int *host_router_index) 7168 { 7169 struct dc *dc; 7170 7171 if (!link || !host_router_index || link->ep_type != DISPLAY_ENDPOINT_USB4_DPIA) 7172 return false; 7173 7174 dc = link->ctx->dc; 7175 7176 if (link->link_index < dc->lowest_dpia_link_index) 7177 return false; 7178 7179 *host_router_index = (link->link_index - dc->lowest_dpia_link_index) / dc->caps.num_of_dpias_per_host_router; 7180 if (*host_router_index < dc->caps.num_of_host_routers) 7181 return true; 7182 else 7183 return false; 7184 } 7185 7186 bool dc_is_cursor_limit_pending(struct dc *dc) 7187 { 7188 uint32_t i; 7189 7190 for (i = 0; i < dc->current_state->stream_count; i++) { 7191 if (dc_stream_is_cursor_limit_pending(dc, dc->current_state->streams[i])) 7192 return true; 7193 } 7194 7195 return false; 7196 } 7197 7198 bool dc_can_clear_cursor_limit(const struct dc *dc) 7199 { 7200 uint32_t i; 7201 7202 for (i = 0; i < dc->current_state->stream_count; i++) { 7203 if (dc_state_can_clear_stream_cursor_subvp_limit(dc->current_state->streams[i], dc->current_state)) 7204 return true; 7205 } 7206 7207 return false; 7208 } 7209 7210 void dc_get_underflow_debug_data_for_otg(struct dc *dc, unsigned int primary_otg_inst, 7211 struct dc_underflow_debug_data *out_data) 7212 { 7213 struct timing_generator *tg = NULL; 7214 7215 for (int i = 0; i < MAX_PIPES; i++) { 7216 if (dc->res_pool->timing_generators[i] && 7217 dc->res_pool->timing_generators[i]->inst == primary_otg_inst) { 7218 tg = dc->res_pool->timing_generators[i]; 7219 break; 7220 } 7221 } 7222 7223 dc_exit_ips_for_hw_access(dc); 7224 if (dc->hwss.get_underflow_debug_data) 7225 dc->hwss.get_underflow_debug_data(dc, tg, out_data); 7226 } 7227 7228 void dc_get_power_feature_status(struct dc *dc, unsigned int primary_otg_inst, 7229 struct power_features *out_data) 7230 { 7231 (void)primary_otg_inst; 7232 out_data->uclk_p_state = dc->current_state->clk_mgr->clks.p_state_change_support; 7233 out_data->fams = dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching; 7234 } 7235 7236 bool dc_capture_register_software_state(struct dc *dc, struct dc_register_software_state *state) 7237 { 7238 struct dc_state *context; 7239 struct resource_context *res_ctx; 7240 unsigned int i; 7241 const unsigned int max_pipes = MAX_PIPES; 7242 7243 if (!dc || !dc->current_state || !state) { 7244 if (state) 7245 state->state_valid = false; 7246 return false; 7247 } 7248 7249 /* Initialize the state structure */ 7250 memset(state, 0, sizeof(struct dc_register_software_state)); 7251 7252 context = dc->current_state; 7253 res_ctx = &context->res_ctx; 7254 7255 /* Count active pipes and streams */ 7256 state->active_pipe_count = 0; 7257 state->active_stream_count = context->stream_count; 7258 7259 for (i = 0; i < dc->res_pool->pipe_count; i++) { 7260 if (res_ctx->pipe_ctx[i].stream) 7261 state->active_pipe_count++; 7262 } 7263 7264 /* Capture HUBP programming state for each pipe */ 7265 for (i = 0; i < max_pipes && i < dc->res_pool->pipe_count; i++) { 7266 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 7267 7268 state->hubp[i].valid_stream = false; 7269 if (!pipe_ctx->stream) 7270 continue; 7271 7272 state->hubp[i].valid_stream = true; 7273 7274 /* HUBP register programming variables */ 7275 if (pipe_ctx->stream_res.tg) 7276 state->hubp[i].vtg_sel = pipe_ctx->stream_res.tg->inst; 7277 7278 state->hubp[i].hubp_clock_enable = (pipe_ctx->plane_res.hubp != NULL) ? 1 : 0; 7279 7280 state->hubp[i].valid_plane_state = false; 7281 if (pipe_ctx->plane_state) { 7282 state->hubp[i].valid_plane_state = true; 7283 state->hubp[i].surface_pixel_format = pipe_ctx->plane_state->format; 7284 state->hubp[i].rotation_angle = pipe_ctx->plane_state->rotation; 7285 state->hubp[i].h_mirror_en = pipe_ctx->plane_state->horizontal_mirror ? 1 : 0; 7286 7287 /* Surface size */ 7288 if (pipe_ctx->plane_state->plane_size.surface_size.width > 0) { 7289 state->hubp[i].surface_size_width = pipe_ctx->plane_state->plane_size.surface_size.width; 7290 state->hubp[i].surface_size_height = pipe_ctx->plane_state->plane_size.surface_size.height; 7291 } 7292 7293 /* Viewport dimensions from scaler data */ 7294 if (pipe_ctx->plane_state->src_rect.width > 0) { 7295 state->hubp[i].pri_viewport_width = pipe_ctx->plane_state->src_rect.width; 7296 state->hubp[i].pri_viewport_height = pipe_ctx->plane_state->src_rect.height; 7297 state->hubp[i].pri_viewport_x_start = pipe_ctx->plane_state->src_rect.x; 7298 state->hubp[i].pri_viewport_y_start = pipe_ctx->plane_state->src_rect.y; 7299 } 7300 7301 /* DCC settings */ 7302 state->hubp[i].surface_dcc_en = (pipe_ctx->plane_state->dcc.enable) ? 1 : 0; 7303 state->hubp[i].surface_dcc_ind_64b_blk = pipe_ctx->plane_state->dcc.independent_64b_blks; 7304 state->hubp[i].surface_dcc_ind_128b_blk = pipe_ctx->plane_state->dcc.dcc_ind_blk; 7305 7306 /* Surface pitch */ 7307 state->hubp[i].surface_pitch = pipe_ctx->plane_state->plane_size.surface_pitch; 7308 state->hubp[i].meta_pitch = pipe_ctx->plane_state->dcc.meta_pitch; 7309 state->hubp[i].chroma_pitch = pipe_ctx->plane_state->plane_size.chroma_pitch; 7310 state->hubp[i].meta_pitch_c = pipe_ctx->plane_state->dcc.meta_pitch_c; 7311 7312 /* Surface addresses - primary */ 7313 state->hubp[i].primary_surface_address_low = pipe_ctx->plane_state->address.grph.addr.low_part; 7314 state->hubp[i].primary_surface_address_high = pipe_ctx->plane_state->address.grph.addr.high_part; 7315 state->hubp[i].primary_meta_surface_address_low = pipe_ctx->plane_state->address.grph.meta_addr.low_part; 7316 state->hubp[i].primary_meta_surface_address_high = pipe_ctx->plane_state->address.grph.meta_addr.high_part; 7317 7318 /* TMZ settings */ 7319 state->hubp[i].primary_surface_tmz = pipe_ctx->plane_state->address.tmz_surface; 7320 state->hubp[i].primary_meta_surface_tmz = pipe_ctx->plane_state->address.tmz_surface; 7321 7322 /* Tiling configuration */ 7323 state->hubp[i].min_dc_gfx_version9 = false; 7324 if (pipe_ctx->plane_state->tiling_info.gfxversion >= DcGfxVersion9) { 7325 state->hubp[i].min_dc_gfx_version9 = true; 7326 state->hubp[i].sw_mode = pipe_ctx->plane_state->tiling_info.gfx9.swizzle; 7327 state->hubp[i].num_pipes = pipe_ctx->plane_state->tiling_info.gfx9.num_pipes; 7328 state->hubp[i].num_banks = pipe_ctx->plane_state->tiling_info.gfx9.num_banks; 7329 state->hubp[i].pipe_interleave = pipe_ctx->plane_state->tiling_info.gfx9.pipe_interleave; 7330 state->hubp[i].num_shader_engines = pipe_ctx->plane_state->tiling_info.gfx9.num_shader_engines; 7331 state->hubp[i].num_rb_per_se = pipe_ctx->plane_state->tiling_info.gfx9.num_rb_per_se; 7332 state->hubp[i].num_pkrs = pipe_ctx->plane_state->tiling_info.gfx9.num_pkrs; 7333 } 7334 } 7335 7336 /* DML Request Size Configuration */ 7337 if (pipe_ctx->rq_regs.rq_regs_l.chunk_size > 0) { 7338 state->hubp[i].rq_chunk_size = pipe_ctx->rq_regs.rq_regs_l.chunk_size; 7339 state->hubp[i].rq_min_chunk_size = pipe_ctx->rq_regs.rq_regs_l.min_chunk_size; 7340 state->hubp[i].rq_meta_chunk_size = pipe_ctx->rq_regs.rq_regs_l.meta_chunk_size; 7341 state->hubp[i].rq_min_meta_chunk_size = pipe_ctx->rq_regs.rq_regs_l.min_meta_chunk_size; 7342 state->hubp[i].rq_dpte_group_size = pipe_ctx->rq_regs.rq_regs_l.dpte_group_size; 7343 state->hubp[i].rq_mpte_group_size = pipe_ctx->rq_regs.rq_regs_l.mpte_group_size; 7344 state->hubp[i].rq_swath_height_l = pipe_ctx->rq_regs.rq_regs_l.swath_height; 7345 state->hubp[i].rq_pte_row_height_l = pipe_ctx->rq_regs.rq_regs_l.pte_row_height_linear; 7346 } 7347 7348 /* Chroma request size configuration */ 7349 if (pipe_ctx->rq_regs.rq_regs_c.chunk_size > 0) { 7350 state->hubp[i].rq_chunk_size_c = pipe_ctx->rq_regs.rq_regs_c.chunk_size; 7351 state->hubp[i].rq_min_chunk_size_c = pipe_ctx->rq_regs.rq_regs_c.min_chunk_size; 7352 state->hubp[i].rq_meta_chunk_size_c = pipe_ctx->rq_regs.rq_regs_c.meta_chunk_size; 7353 state->hubp[i].rq_min_meta_chunk_size_c = pipe_ctx->rq_regs.rq_regs_c.min_meta_chunk_size; 7354 state->hubp[i].rq_dpte_group_size_c = pipe_ctx->rq_regs.rq_regs_c.dpte_group_size; 7355 state->hubp[i].rq_mpte_group_size_c = pipe_ctx->rq_regs.rq_regs_c.mpte_group_size; 7356 state->hubp[i].rq_swath_height_c = pipe_ctx->rq_regs.rq_regs_c.swath_height; 7357 state->hubp[i].rq_pte_row_height_c = pipe_ctx->rq_regs.rq_regs_c.pte_row_height_linear; 7358 } 7359 7360 /* DML expansion modes */ 7361 state->hubp[i].drq_expansion_mode = pipe_ctx->rq_regs.drq_expansion_mode; 7362 state->hubp[i].prq_expansion_mode = pipe_ctx->rq_regs.prq_expansion_mode; 7363 state->hubp[i].mrq_expansion_mode = pipe_ctx->rq_regs.mrq_expansion_mode; 7364 state->hubp[i].crq_expansion_mode = pipe_ctx->rq_regs.crq_expansion_mode; 7365 7366 /* DML DLG parameters - nominal */ 7367 state->hubp[i].dst_y_per_vm_vblank = pipe_ctx->dlg_regs.dst_y_per_vm_vblank; 7368 state->hubp[i].dst_y_per_row_vblank = pipe_ctx->dlg_regs.dst_y_per_row_vblank; 7369 state->hubp[i].dst_y_per_vm_flip = pipe_ctx->dlg_regs.dst_y_per_vm_flip; 7370 state->hubp[i].dst_y_per_row_flip = pipe_ctx->dlg_regs.dst_y_per_row_flip; 7371 7372 /* DML prefetch settings */ 7373 state->hubp[i].dst_y_prefetch = pipe_ctx->dlg_regs.dst_y_prefetch; 7374 state->hubp[i].vratio_prefetch = pipe_ctx->dlg_regs.vratio_prefetch; 7375 state->hubp[i].vratio_prefetch_c = pipe_ctx->dlg_regs.vratio_prefetch_c; 7376 7377 /* TTU parameters */ 7378 state->hubp[i].qos_level_low_wm = pipe_ctx->ttu_regs.qos_level_low_wm; 7379 state->hubp[i].qos_level_high_wm = pipe_ctx->ttu_regs.qos_level_high_wm; 7380 state->hubp[i].qos_level_flip = pipe_ctx->ttu_regs.qos_level_flip; 7381 state->hubp[i].min_ttu_vblank = pipe_ctx->ttu_regs.min_ttu_vblank; 7382 } 7383 7384 /* Capture HUBBUB programming state */ 7385 if (dc->res_pool->hubbub) { 7386 /* Individual DET buffer sizes - software state variables that program DET registers */ 7387 for (i = 0; i < 4u && i < dc->res_pool->pipe_count; i++) { 7388 uint32_t det_size = res_ctx->pipe_ctx[i].det_buffer_size_kb; 7389 switch (i) { 7390 case 0: 7391 state->hubbub.det0_size = det_size; 7392 break; 7393 case 1: 7394 state->hubbub.det1_size = det_size; 7395 break; 7396 case 2: 7397 state->hubbub.det2_size = det_size; 7398 break; 7399 case 3: 7400 state->hubbub.det3_size = det_size; 7401 break; 7402 } 7403 } 7404 7405 /* Compression buffer configuration - software state that programs COMPBUF_SIZE register */ 7406 // TODO: Handle logic for legacy DCN pre-DCN401 7407 state->hubbub.compbuf_size = context->bw_ctx.bw.dcn.arb_regs.compbuf_size; 7408 } 7409 7410 /* Capture DPP programming state for each pipe */ 7411 for (i = 0; i < max_pipes && i < dc->res_pool->pipe_count; i++) { 7412 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 7413 7414 if (!pipe_ctx->stream) 7415 continue; 7416 7417 state->dpp[i].dpp_clock_enable = (pipe_ctx->plane_res.dpp != NULL) ? 1 : 0; 7418 7419 if (pipe_ctx->plane_state && pipe_ctx->plane_res.scl_data.recout.width > 0) { 7420 /* Access dscl_prog_data directly - this contains the actual software state used for register programming */ 7421 struct dscl_prog_data *dscl_data = &pipe_ctx->plane_res.scl_data.dscl_prog_data; 7422 7423 /* Recout (Rectangle of Interest) configuration - software state that programs RECOUT registers */ 7424 state->dpp[i].recout_start_x = dscl_data->recout.x; 7425 state->dpp[i].recout_start_y = dscl_data->recout.y; 7426 state->dpp[i].recout_width = dscl_data->recout.width; 7427 state->dpp[i].recout_height = dscl_data->recout.height; 7428 7429 /* MPC (Multiple Pipe/Plane Combiner) size - software state that programs MPC_SIZE registers */ 7430 state->dpp[i].mpc_width = dscl_data->mpc_size.width; 7431 state->dpp[i].mpc_height = dscl_data->mpc_size.height; 7432 7433 /* DSCL mode - software state that programs SCL_MODE registers */ 7434 state->dpp[i].dscl_mode = dscl_data->dscl_mode; 7435 7436 /* Scaler ratios - software state that programs scale ratio registers (use actual programmed ratios) */ 7437 state->dpp[i].horz_ratio_int = dscl_data->ratios.h_scale_ratio >> 19; // Extract integer part from programmed ratio 7438 state->dpp[i].vert_ratio_int = dscl_data->ratios.v_scale_ratio >> 19; // Extract integer part from programmed ratio 7439 7440 /* Basic scaler taps - software state that programs tap control registers (use actual programmed taps) */ 7441 state->dpp[i].h_taps = dscl_data->taps.h_taps + 1; // dscl_prog_data.taps stores (taps - 1), so add 1 back 7442 state->dpp[i].v_taps = dscl_data->taps.v_taps + 1; // dscl_prog_data.taps stores (taps - 1), so add 1 back 7443 } 7444 } 7445 7446 /* Capture essential clock state for underflow analysis */ 7447 if (dc->clk_mgr && dc->clk_mgr->clks.dispclk_khz > 0) { 7448 /* Core display clocks affecting bandwidth and timing */ 7449 state->dccg.dispclk_khz = dc->clk_mgr->clks.dispclk_khz; 7450 7451 /* Per-pipe clock configuration - only capture what's essential */ 7452 for (i = 0; i < max_pipes && i < dc->res_pool->pipe_count; i++) { 7453 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 7454 if (pipe_ctx->stream) { 7455 /* Essential clocks that directly affect underflow risk */ 7456 state->dccg.dppclk_khz[i] = dc->clk_mgr->clks.dppclk_khz; 7457 state->dccg.pixclk_khz[i] = pipe_ctx->stream->timing.pix_clk_100hz / 10; 7458 state->dccg.dppclk_enable[i] = 1; 7459 7460 /* DP stream clock only for DP signals */ 7461 if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || 7462 pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { 7463 state->dccg.dpstreamclk_enable[i] = 1; 7464 } else { 7465 state->dccg.dpstreamclk_enable[i] = 0; 7466 } 7467 } else { 7468 /* Inactive pipe - no clocks */ 7469 state->dccg.dppclk_khz[i] = 0; 7470 state->dccg.pixclk_khz[i] = 0; 7471 state->dccg.dppclk_enable[i] = 0; 7472 if (i < 4) { 7473 state->dccg.dpstreamclk_enable[i] = 0; 7474 } 7475 } 7476 } 7477 7478 /* DSC clock state - only when actually using DSC */ 7479 for (i = 0; i < max_pipes; i++) { 7480 struct pipe_ctx *pipe_ctx = (i < dc->res_pool->pipe_count) ? &res_ctx->pipe_ctx[i] : NULL; 7481 if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->timing.dsc_cfg.num_slices_h > 0) { 7482 state->dccg.dscclk_khz[i] = 400000; /* Typical DSC clock frequency */ 7483 } else { 7484 state->dccg.dscclk_khz[i] = 0; 7485 } 7486 } 7487 7488 /* SYMCLK32 LE Control - only the essential HPO state for underflow analysis */ 7489 for (i = 0; i < 2; i++) { 7490 state->dccg.symclk32_le_enable[i] = 0; /* Default: disabled */ 7491 } 7492 7493 /* Check for active HPO usage that affects symclk32_le */ 7494 for (unsigned int pipe_idx = 0; pipe_idx < MAX_PIPES && pipe_idx < dc->res_pool->pipe_count; pipe_idx++) { 7495 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[pipe_idx]; 7496 if (!pipe_ctx->stream) 7497 continue; 7498 7499 /* HPO FRL (HDMI FRL) streams use symclk32_le */ 7500 if (pipe_ctx->stream_res.hpo_frl_stream_enc && pipe_ctx->link_res.hpo_frl_link_enc) { 7501 int hpo_le_inst = pipe_ctx->link_res.hpo_frl_link_enc->inst; 7502 if (hpo_le_inst >= 0 && hpo_le_inst < 2) { 7503 state->dccg.symclk32_le_enable[hpo_le_inst] = 1; 7504 } 7505 } 7506 } 7507 } 7508 7509 /* Capture essential DSC configuration for underflow analysis */ 7510 for (i = 0; i < max_pipes && i < dc->res_pool->pipe_count; i++) { 7511 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 7512 7513 if (pipe_ctx->stream && pipe_ctx->stream->timing.dsc_cfg.num_slices_h > 0) { 7514 /* DSC is enabled - capture essential configuration */ 7515 state->dsc[i].dsc_clock_enable = 1; 7516 7517 /* DSC configuration affecting bandwidth and timing */ 7518 struct dc_dsc_config *dsc_cfg = &pipe_ctx->stream->timing.dsc_cfg; 7519 state->dsc[i].dsc_num_slices_h = dsc_cfg->num_slices_h; 7520 state->dsc[i].dsc_num_slices_v = dsc_cfg->num_slices_v; 7521 state->dsc[i].dsc_bits_per_pixel = dsc_cfg->bits_per_pixel; 7522 7523 /* OPP pipe source for DSC forwarding */ 7524 if (pipe_ctx->stream_res.opp) { 7525 state->dsc[i].dscrm_dsc_forward_enable = 1; 7526 state->dsc[i].dscrm_dsc_opp_pipe_source = pipe_ctx->stream_res.opp->inst; 7527 } else { 7528 state->dsc[i].dscrm_dsc_forward_enable = 0; 7529 state->dsc[i].dscrm_dsc_opp_pipe_source = 0; 7530 } 7531 } else { 7532 /* DSC not enabled - clear all fields */ 7533 memset(&state->dsc[i], 0, sizeof(state->dsc[i])); 7534 } 7535 } 7536 7537 /* Capture MPC programming state - comprehensive register field coverage */ 7538 for (i = 0; i < max_pipes && i < dc->res_pool->pipe_count; i++) { 7539 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 7540 7541 if (pipe_ctx->plane_state && pipe_ctx->stream) { 7542 struct dc_plane_state *plane_state = pipe_ctx->plane_state; 7543 7544 /* MPCC blending tree and mode control - capture actual blend configuration */ 7545 state->mpc.mpcc_mode[i] = (plane_state->blend_tf.type != TF_TYPE_BYPASS) ? 1 : 0; 7546 state->mpc.mpcc_alpha_blend_mode[i] = plane_state->per_pixel_alpha ? 1 : 0; 7547 state->mpc.mpcc_alpha_multiplied_mode[i] = plane_state->pre_multiplied_alpha ? 1 : 0; 7548 state->mpc.mpcc_blnd_active_overlap_only[i] = 0; /* Default - no overlap restriction */ 7549 state->mpc.mpcc_global_alpha[i] = plane_state->global_alpha_value; 7550 state->mpc.mpcc_global_gain[i] = plane_state->global_alpha ? 255 : 0; 7551 state->mpc.mpcc_bg_bpc[i] = 8; /* Standard 8-bit background */ 7552 state->mpc.mpcc_bot_gain_mode[i] = 0; /* Standard gain mode */ 7553 7554 /* MPCC blending tree connections - capture tree topology */ 7555 if (pipe_ctx->bottom_pipe) { 7556 state->mpc.mpcc_bot_sel[i] = pipe_ctx->bottom_pipe->pipe_idx; 7557 } else { 7558 state->mpc.mpcc_bot_sel[i] = 0xF; /* No bottom connection */ 7559 } 7560 state->mpc.mpcc_top_sel[i] = pipe_ctx->pipe_idx; /* This pipe's DPP ID */ 7561 7562 /* MPCC output gamma control - capture gamma programming */ 7563 if (plane_state->gamma_correction.type != GAMMA_CS_TFM_1D && plane_state->gamma_correction.num_entries > 0) { 7564 state->mpc.mpcc_ogam_mode[i] = 1; /* Gamma enabled */ 7565 state->mpc.mpcc_ogam_select[i] = 0; /* Bank A selection */ 7566 state->mpc.mpcc_ogam_pwl_disable[i] = 0; /* PWL enabled */ 7567 } else { 7568 state->mpc.mpcc_ogam_mode[i] = 0; /* Bypass mode */ 7569 state->mpc.mpcc_ogam_select[i] = 0; 7570 state->mpc.mpcc_ogam_pwl_disable[i] = 1; /* PWL disabled */ 7571 } 7572 7573 /* MPCC pipe assignment and operational status */ 7574 if (pipe_ctx->stream_res.opp) { 7575 state->mpc.mpcc_opp_id[i] = pipe_ctx->stream_res.opp->inst; 7576 } else { 7577 state->mpc.mpcc_opp_id[i] = 0xF; /* No OPP assignment */ 7578 } 7579 7580 /* MPCC status indicators - active pipe state */ 7581 state->mpc.mpcc_idle[i] = 0; /* Active pipe - not idle */ 7582 state->mpc.mpcc_busy[i] = 1; /* Active pipe - busy processing */ 7583 7584 } else { 7585 /* Pipe not active - set disabled/idle state for all fields */ 7586 state->mpc.mpcc_mode[i] = 0; 7587 state->mpc.mpcc_alpha_blend_mode[i] = 0; 7588 state->mpc.mpcc_alpha_multiplied_mode[i] = 0; 7589 state->mpc.mpcc_blnd_active_overlap_only[i] = 0; 7590 state->mpc.mpcc_global_alpha[i] = 0; 7591 state->mpc.mpcc_global_gain[i] = 0; 7592 state->mpc.mpcc_bg_bpc[i] = 0; 7593 state->mpc.mpcc_bot_gain_mode[i] = 0; 7594 state->mpc.mpcc_bot_sel[i] = 0xF; /* No bottom connection */ 7595 state->mpc.mpcc_top_sel[i] = 0xF; /* No top connection */ 7596 state->mpc.mpcc_ogam_mode[i] = 0; /* Bypass */ 7597 state->mpc.mpcc_ogam_select[i] = 0; 7598 state->mpc.mpcc_ogam_pwl_disable[i] = 1; /* PWL disabled */ 7599 state->mpc.mpcc_opp_id[i] = 0xF; /* No OPP assignment */ 7600 state->mpc.mpcc_idle[i] = 1; /* Idle */ 7601 state->mpc.mpcc_busy[i] = 0; /* Not busy */ 7602 } 7603 } 7604 7605 /* Capture OPP programming state for each pipe - comprehensive register field coverage */ 7606 for (i = 0; i < max_pipes && i < dc->res_pool->pipe_count; i++) { 7607 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 7608 7609 if (!pipe_ctx->stream) 7610 continue; 7611 7612 if (pipe_ctx->stream_res.opp) { 7613 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 7614 7615 /* OPP Pipe Control */ 7616 state->opp[i].opp_pipe_clock_enable = 1; /* Active pipe has clock enabled */ 7617 7618 /* Display Pattern Generator (DPG) Control - 19 fields */ 7619 if (pipe_ctx->stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE) { 7620 state->opp[i].dpg_enable = 1; 7621 } else { 7622 /* Video mode - DPG disabled */ 7623 state->opp[i].dpg_enable = 0; 7624 } 7625 7626 /* Format Control (FMT) - 18 fields */ 7627 state->opp[i].fmt_pixel_encoding = timing->pixel_encoding; 7628 7629 /* Chroma subsampling mode based on pixel encoding */ 7630 if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) { 7631 state->opp[i].fmt_subsampling_mode = 1; /* 4:2:0 subsampling */ 7632 } else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { 7633 state->opp[i].fmt_subsampling_mode = 2; /* 4:2:2 subsampling */ 7634 } else { 7635 state->opp[i].fmt_subsampling_mode = 0; /* No subsampling (4:4:4) */ 7636 } 7637 7638 state->opp[i].fmt_cbcr_bit_reduction_bypass = (timing->pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 7639 state->opp[i].fmt_stereosync_override = (timing->timing_3d_format != TIMING_3D_FORMAT_NONE) ? 1 : 0; 7640 7641 /* Dithering control based on bit depth */ 7642 if (timing->display_color_depth < COLOR_DEPTH_121212) { 7643 state->opp[i].fmt_spatial_dither_frame_counter_max = 15; /* Typical frame counter max */ 7644 state->opp[i].fmt_spatial_dither_frame_counter_bit_swap = 0; /* No bit swapping */ 7645 state->opp[i].fmt_spatial_dither_enable = 1; 7646 state->opp[i].fmt_spatial_dither_mode = 0; /* Spatial dithering mode */ 7647 state->opp[i].fmt_spatial_dither_depth = timing->display_color_depth; 7648 state->opp[i].fmt_temporal_dither_enable = 0; /* Spatial dithering preferred */ 7649 } else { 7650 state->opp[i].fmt_spatial_dither_frame_counter_max = 0; 7651 state->opp[i].fmt_spatial_dither_frame_counter_bit_swap = 0; 7652 state->opp[i].fmt_spatial_dither_enable = 0; 7653 state->opp[i].fmt_spatial_dither_mode = 0; 7654 state->opp[i].fmt_spatial_dither_depth = 0; 7655 state->opp[i].fmt_temporal_dither_enable = 0; 7656 } 7657 7658 /* Truncation control for bit depth reduction */ 7659 if (timing->display_color_depth < COLOR_DEPTH_121212) { 7660 state->opp[i].fmt_truncate_enable = 1; 7661 state->opp[i].fmt_truncate_depth = timing->display_color_depth; 7662 state->opp[i].fmt_truncate_mode = 0; /* Round mode */ 7663 } else { 7664 state->opp[i].fmt_truncate_enable = 0; 7665 state->opp[i].fmt_truncate_depth = 0; 7666 state->opp[i].fmt_truncate_mode = 0; 7667 } 7668 7669 /* Data clamping control */ 7670 state->opp[i].fmt_clamp_data_enable = 1; /* Clamping typically enabled */ 7671 state->opp[i].fmt_clamp_color_format = timing->pixel_encoding; 7672 7673 /* Dynamic expansion for limited range content */ 7674 if (timing->pixel_encoding != PIXEL_ENCODING_RGB) { 7675 state->opp[i].fmt_dynamic_exp_enable = 1; /* YCbCr typically needs expansion */ 7676 state->opp[i].fmt_dynamic_exp_mode = 0; /* Standard expansion */ 7677 } else { 7678 state->opp[i].fmt_dynamic_exp_enable = 0; /* RGB typically full range */ 7679 state->opp[i].fmt_dynamic_exp_mode = 0; 7680 } 7681 7682 /* Legacy field for compatibility */ 7683 state->opp[i].fmt_bit_depth_control = timing->display_color_depth; 7684 7685 /* Output Buffer (OPPBUF) Control - 6 fields */ 7686 state->opp[i].oppbuf_active_width = timing->h_addressable; 7687 state->opp[i].oppbuf_pixel_repetition = 0; /* No pixel repetition by default */ 7688 7689 /* Multi-Stream Output (MSO) / ODM segmentation */ 7690 if (pipe_ctx->next_odm_pipe) { 7691 state->opp[i].oppbuf_display_segmentation = 1; /* Segmented display */ 7692 state->opp[i].oppbuf_overlap_pixel_num = 0; /* ODM overlap pixels */ 7693 } else { 7694 state->opp[i].oppbuf_display_segmentation = 0; /* Single segment */ 7695 state->opp[i].oppbuf_overlap_pixel_num = 0; 7696 } 7697 7698 /* 3D/Stereo control */ 7699 if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE) { 7700 state->opp[i].oppbuf_3d_vact_space1_size = 30; /* Typical stereo blanking */ 7701 state->opp[i].oppbuf_3d_vact_space2_size = 30; 7702 } else { 7703 state->opp[i].oppbuf_3d_vact_space1_size = 0; 7704 state->opp[i].oppbuf_3d_vact_space2_size = 0; 7705 } 7706 7707 /* DSC Forward Config - 3 fields */ 7708 if (timing->dsc_cfg.num_slices_h > 0) { 7709 state->opp[i].dscrm_dsc_forward_enable = 1; 7710 state->opp[i].dscrm_dsc_opp_pipe_source = pipe_ctx->stream_res.opp->inst; 7711 state->opp[i].dscrm_dsc_forward_enable_status = 1; /* Status follows enable */ 7712 } else { 7713 state->opp[i].dscrm_dsc_forward_enable = 0; 7714 state->opp[i].dscrm_dsc_opp_pipe_source = 0; 7715 state->opp[i].dscrm_dsc_forward_enable_status = 0; 7716 } 7717 } else { 7718 /* No OPP resource - set all fields to disabled state */ 7719 memset(&state->opp[i], 0, sizeof(state->opp[i])); 7720 } 7721 } 7722 7723 /* Capture OPTC programming state for each pipe - comprehensive register field coverage */ 7724 for (i = 0; i < max_pipes && i < dc->res_pool->pipe_count; i++) { 7725 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 7726 7727 if (!pipe_ctx->stream) 7728 continue; 7729 7730 if (pipe_ctx->stream_res.tg) { 7731 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 7732 7733 state->optc[i].otg_master_inst = pipe_ctx->stream_res.tg->inst; 7734 7735 /* OTG_CONTROL register - 5 fields */ 7736 state->optc[i].otg_master_enable = 1; /* Active stream */ 7737 state->optc[i].otg_disable_point_cntl = 0; /* Normal operation */ 7738 state->optc[i].otg_start_point_cntl = 0; /* Normal start */ 7739 state->optc[i].otg_field_number_cntl = (timing->flags.INTERLACE) ? 1 : 0; 7740 state->optc[i].otg_out_mux = 0; /* Direct output */ 7741 7742 /* OTG Horizontal Timing - 7 fields */ 7743 state->optc[i].otg_h_total = timing->h_total; 7744 state->optc[i].otg_h_blank_start = timing->h_addressable; 7745 state->optc[i].otg_h_blank_end = timing->h_total - timing->h_front_porch; 7746 state->optc[i].otg_h_sync_start = timing->h_addressable + timing->h_front_porch; 7747 state->optc[i].otg_h_sync_end = timing->h_addressable + timing->h_front_porch + timing->h_sync_width; 7748 state->optc[i].otg_h_sync_polarity = timing->flags.HSYNC_POSITIVE_POLARITY ? 0 : 1; 7749 state->optc[i].otg_h_timing_div_mode = (pipe_ctx->next_odm_pipe) ? 1 : 0; /* ODM divide mode */ 7750 7751 /* OTG Vertical Timing - 7 fields */ 7752 state->optc[i].otg_v_total = timing->v_total; 7753 state->optc[i].otg_v_blank_start = timing->v_addressable; 7754 state->optc[i].otg_v_blank_end = timing->v_total - timing->v_front_porch; 7755 state->optc[i].otg_v_sync_start = timing->v_addressable + timing->v_front_porch; 7756 state->optc[i].otg_v_sync_end = timing->v_addressable + timing->v_front_porch + timing->v_sync_width; 7757 state->optc[i].otg_v_sync_polarity = timing->flags.VSYNC_POSITIVE_POLARITY ? 0 : 1; 7758 state->optc[i].otg_v_sync_mode = 0; /* Normal sync mode */ 7759 7760 /* Initialize remaining core fields with appropriate defaults */ 7761 // TODO: Update logic for accurate vtotal min/max 7762 state->optc[i].otg_v_total_max = timing->v_total + 100; /* Typical DRR range */ 7763 state->optc[i].otg_v_total_min = timing->v_total - 50; 7764 state->optc[i].otg_v_total_mid = timing->v_total; 7765 7766 /* ODM configuration */ 7767 // TODO: Update logic to have complete ODM mappings (e.g. 3:1 and 4:1) stored in single pipe 7768 if (pipe_ctx->next_odm_pipe) { 7769 state->optc[i].optc_seg0_src_sel = pipe_ctx->stream_res.opp ? pipe_ctx->stream_res.opp->inst : 0; 7770 state->optc[i].optc_seg1_src_sel = pipe_ctx->next_odm_pipe->stream_res.opp ? pipe_ctx->next_odm_pipe->stream_res.opp->inst : 0; 7771 state->optc[i].optc_num_of_input_segment = 1; /* 2 segments - 1 */ 7772 } else { 7773 state->optc[i].optc_seg0_src_sel = pipe_ctx->stream_res.opp ? pipe_ctx->stream_res.opp->inst : 0; 7774 state->optc[i].optc_seg1_src_sel = 0; 7775 state->optc[i].optc_num_of_input_segment = 0; /* Single segment */ 7776 } 7777 7778 /* DSC configuration */ 7779 if (timing->dsc_cfg.num_slices_h > 0) { 7780 state->optc[i].optc_dsc_mode = 1; /* DSC enabled */ 7781 state->optc[i].optc_dsc_bytes_per_pixel = timing->dsc_cfg.bits_per_pixel / 16; /* Convert to bytes */ 7782 state->optc[i].optc_dsc_slice_width = timing->h_addressable / timing->dsc_cfg.num_slices_h; 7783 } else { 7784 state->optc[i].optc_dsc_mode = 0; 7785 state->optc[i].optc_dsc_bytes_per_pixel = 0; 7786 state->optc[i].optc_dsc_slice_width = 0; 7787 } 7788 7789 /* Essential control fields */ 7790 state->optc[i].otg_stereo_enable = (timing->timing_3d_format != TIMING_3D_FORMAT_NONE) ? 1 : 0; 7791 state->optc[i].otg_interlace_enable = timing->flags.INTERLACE ? 1 : 0; 7792 state->optc[i].otg_clock_enable = 1; /* OTG clock enabled */ 7793 state->optc[i].vtg0_enable = 1; /* VTG enabled for timing generation */ 7794 7795 /* Initialize other key fields to defaults */ 7796 state->optc[i].optc_input_pix_clk_en = 1; 7797 state->optc[i].optc_segment_width = (pipe_ctx->next_odm_pipe) ? (timing->h_addressable / 2) : timing->h_addressable; 7798 state->optc[i].otg_vready_offset = 1; 7799 state->optc[i].otg_vstartup_start = timing->v_addressable + 10; 7800 state->optc[i].otg_vupdate_offset = 0; 7801 state->optc[i].otg_vupdate_width = 5; 7802 } else { 7803 /* No timing generator resource - initialize all fields to 0 */ 7804 memset(&state->optc[i], 0, sizeof(state->optc[i])); 7805 } 7806 } 7807 7808 state->state_valid = true; 7809 return true; 7810 } 7811 7812 void dc_log_preos_dmcub_info(const struct dc *dc) 7813 { 7814 dc_dmub_srv_log_preos_dmcub_info(dc->ctx->dmub_srv); 7815 } 7816 7817 bool dc_get_qos_info(struct dc *dc, struct dc_qos_info *info) 7818 { 7819 const struct dc_clocks *clk = &dc->current_state->bw_ctx.bw.dcn.clk; 7820 struct dc_measured_memory_qos measured = {}; 7821 struct dc_requested_memory_qos requested = {}; 7822 7823 memset(info, 0, sizeof(*info)); 7824 7825 // Check if measurement function is available 7826 if (!dc->hwss.measure_memory_qos) { 7827 return false; 7828 } 7829 7830 dc->hwss.measure_memory_qos(dc, &measured); 7831 7832 info->actual_peak_bw_in_mbps = measured.peak_bw_mbps; 7833 info->actual_avg_bw_in_mbps = measured.avg_bw_mbps; 7834 info->actual_min_latency_in_ns = measured.min_latency_ns; 7835 info->actual_max_latency_in_ns = measured.max_latency_ns; 7836 info->actual_avg_latency_in_ns = measured.avg_latency_ns; 7837 info->dcn_bandwidth_ub_in_mbps = (uint32_t)(clk->fclk_khz / 1000 * 64); 7838 7839 if (dc->clk_mgr && dc->clk_mgr->funcs->get_requested_memory_qos) { 7840 dc->clk_mgr->funcs->get_requested_memory_qos(dc->clk_mgr, &requested); 7841 info->qos_bandwidth_lb_in_mbps = requested.bandwidth_lb_in_mbps; 7842 info->calculated_avg_bw_in_mbps = requested.calculated_avg_bw_in_mbps; 7843 info->qos_max_latency_ub_in_ns = requested.max_latency_ub_in_ns; 7844 info->qos_avg_latency_ub_in_ns = requested.avg_latency_ub_in_ns; 7845 info->qos_max_bw_budget_in_mbps = requested.max_bw_budget_in_mbps; 7846 } 7847 7848 return true; 7849 } 7850 7851 unsigned int dc_override_memory_bandwidth_request( 7852 struct dc *dc, 7853 unsigned int bw_mbps) 7854 { 7855 if (!dc->clk_mgr || !dc->clk_mgr->funcs) 7856 return 0; 7857 7858 return dc->clk_mgr->funcs->override_memory_bandwidth_request( 7859 dc->clk_mgr, bw_mbps * 1000) / 1000; 7860 } 7861 7862 enum update_v3_flow { 7863 UPDATE_V3_FLOW_INVALID, 7864 UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FAST, 7865 UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FULL, 7866 UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS, 7867 UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_NEW, 7868 UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_CURRENT, 7869 }; 7870 7871 struct dc_update_scratch_space { 7872 struct dc *dc; 7873 struct dc_surface_update *surface_updates; 7874 int surface_count; 7875 struct dc_stream_state *stream; 7876 struct dc_stream_update *stream_update; 7877 bool update_v3; 7878 bool do_clear_update_flags; 7879 enum surface_update_type update_type; 7880 struct dc_state *new_context; 7881 enum update_v3_flow flow; 7882 struct dc_state *backup_context; 7883 struct dc_state *intermediate_context; 7884 struct pipe_split_policy_backup intermediate_policy; 7885 struct dc_surface_update intermediate_updates[MAX_SURFACES]; 7886 int intermediate_count; 7887 }; 7888 7889 size_t dc_update_scratch_space_size(void) 7890 { 7891 return sizeof(struct dc_update_scratch_space); 7892 } 7893 7894 static bool update_planes_and_stream_prepare_v2( 7895 struct dc_update_scratch_space *scratch 7896 ) 7897 { 7898 // v2 is too tangled to break into stages, so just execute everything under lock 7899 dc_exit_ips_for_hw_access(scratch->dc); 7900 return update_planes_and_stream_v2( 7901 scratch->dc, 7902 scratch->surface_updates, 7903 scratch->surface_count, 7904 scratch->stream, 7905 scratch->stream_update 7906 ); 7907 } 7908 7909 static void update_planes_and_stream_execute_v2( 7910 const struct dc_update_scratch_space *scratch 7911 ) 7912 { 7913 // Nothing to do, see `update_planes_and_stream_prepare_v2` 7914 (void) scratch; 7915 } 7916 7917 static bool update_planes_and_stream_cleanup_v2( 7918 const struct dc_update_scratch_space *scratch 7919 ) 7920 { 7921 if (scratch->do_clear_update_flags) 7922 clear_update_flags(scratch->surface_updates, scratch->surface_count, scratch->stream); 7923 7924 return false; 7925 } 7926 7927 static void update_planes_and_stream_cleanup_v3_release_minimal( 7928 struct dc_update_scratch_space *scratch, 7929 bool backup 7930 ); 7931 7932 static bool update_planes_and_stream_prepare_v3_intermediate_seamless( 7933 struct dc_update_scratch_space *scratch 7934 ) 7935 { 7936 return is_pipe_topology_transition_seamless_with_intermediate_step( 7937 scratch->dc, 7938 scratch->dc->current_state, 7939 scratch->intermediate_context, 7940 scratch->new_context 7941 ); 7942 } 7943 7944 static void transition_countdown_init(struct dc *dc) 7945 { 7946 dc->check_config.transition_countdown_to_steady_state = 7947 dc->debug.num_fast_flips_to_steady_state_override ? 7948 dc->debug.num_fast_flips_to_steady_state_override : 7949 NUM_FAST_FLIPS_TO_STEADY_STATE; 7950 } 7951 7952 static bool update_planes_and_stream_prepare_v3( 7953 struct dc_update_scratch_space *scratch 7954 ) 7955 { 7956 if (scratch->flow == UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS) { 7957 return true; 7958 } 7959 ASSERT(scratch->flow == UPDATE_V3_FLOW_INVALID); 7960 dc_exit_ips_for_hw_access(scratch->dc); 7961 7962 /* HWSS path determination needs to be done prior to updating the surface and stream states. */ 7963 struct dc_fast_update fast_update[MAX_SURFACES] = { 0 }; 7964 7965 populate_fast_updates(fast_update, 7966 scratch->surface_updates, 7967 scratch->surface_count, 7968 scratch->stream_update); 7969 7970 const bool is_hwss_fast_path_only = 7971 fast_update_only(scratch->dc, 7972 fast_update, 7973 scratch->surface_updates, 7974 scratch->surface_count, 7975 scratch->stream_update, 7976 scratch->stream) && 7977 !scratch->dc->check_config.enable_legacy_fast_update; 7978 7979 if (!update_planes_and_stream_state( 7980 scratch->dc, 7981 scratch->surface_updates, 7982 scratch->surface_count, 7983 scratch->stream, 7984 scratch->stream_update, 7985 &scratch->update_type, 7986 &scratch->new_context 7987 )) { 7988 return false; 7989 } 7990 7991 if (scratch->new_context == scratch->dc->current_state) { 7992 ASSERT(scratch->update_type < UPDATE_TYPE_FULL); 7993 7994 scratch->flow = is_hwss_fast_path_only 7995 ? UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FAST 7996 : UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FULL; 7997 return true; 7998 } 7999 8000 ASSERT(scratch->update_type >= UPDATE_TYPE_FULL); 8001 8002 const bool seamless = scratch->dc->hwss.is_pipe_topology_transition_seamless( 8003 scratch->dc, 8004 scratch->dc->current_state, 8005 scratch->new_context 8006 ); 8007 if (seamless) { 8008 scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS; 8009 if (scratch->dc->check_config.deferred_transition_state) 8010 /* reset countdown as steady state not reached */ 8011 transition_countdown_init(scratch->dc); 8012 return true; 8013 } 8014 8015 if (!scratch->dc->debug.disable_deferred_minimal_transitions) { 8016 scratch->dc->check_config.deferred_transition_state = true; 8017 transition_countdown_init(scratch->dc); 8018 } 8019 8020 scratch->intermediate_context = create_minimal_transition_state( 8021 scratch->dc, 8022 scratch->new_context, 8023 &scratch->intermediate_policy 8024 ); 8025 if (scratch->intermediate_context) { 8026 if (update_planes_and_stream_prepare_v3_intermediate_seamless(scratch)) { 8027 scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_NEW; 8028 return true; 8029 } 8030 8031 update_planes_and_stream_cleanup_v3_release_minimal(scratch, false); 8032 } 8033 8034 scratch->backup_context = scratch->dc->current_state; 8035 restore_planes_and_stream_state(&scratch->dc->scratch.current_state, scratch->stream); 8036 dc_state_retain(scratch->backup_context); 8037 scratch->intermediate_context = create_minimal_transition_state( 8038 scratch->dc, 8039 scratch->backup_context, 8040 &scratch->intermediate_policy 8041 ); 8042 if (scratch->intermediate_context) { 8043 if (update_planes_and_stream_prepare_v3_intermediate_seamless(scratch)) { 8044 scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_CURRENT; 8045 scratch->intermediate_count = initialize_empty_surface_updates( 8046 scratch->stream, scratch->intermediate_updates 8047 ); 8048 return true; 8049 } 8050 8051 update_planes_and_stream_cleanup_v3_release_minimal(scratch, true); 8052 } 8053 8054 scratch->flow = UPDATE_V3_FLOW_INVALID; 8055 dc_state_release(scratch->backup_context); 8056 restore_planes_and_stream_state(&scratch->dc->scratch.new_state, scratch->stream); 8057 return false; 8058 } 8059 8060 static void update_planes_and_stream_execute_v3_commit( 8061 const struct dc_update_scratch_space *scratch, 8062 bool intermediate_update, 8063 bool intermediate_context, 8064 bool use_stream_update 8065 ) 8066 { 8067 commit_planes_for_stream( 8068 scratch->dc, 8069 intermediate_update ? scratch->intermediate_updates : scratch->surface_updates, 8070 intermediate_update ? scratch->intermediate_count : scratch->surface_count, 8071 scratch->stream, 8072 use_stream_update ? scratch->stream_update : NULL, 8073 intermediate_context ? UPDATE_TYPE_FULL : scratch->update_type, 8074 // `dc->current_state` only used in `NO_NEW_CONTEXT`, where it is equal to `new_context` 8075 intermediate_context ? scratch->intermediate_context : scratch->new_context 8076 ); 8077 } 8078 8079 static void update_planes_and_stream_execute_v3( 8080 const struct dc_update_scratch_space *scratch 8081 ) 8082 { 8083 switch (scratch->flow) { 8084 case UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FAST: 8085 commit_planes_for_stream_fast( 8086 scratch->dc, 8087 scratch->surface_updates, 8088 scratch->surface_count, 8089 scratch->stream, 8090 scratch->stream_update, 8091 scratch->update_type, 8092 scratch->new_context 8093 ); 8094 break; 8095 8096 case UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FULL: 8097 case UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS: 8098 update_planes_and_stream_execute_v3_commit(scratch, false, false, true); 8099 break; 8100 8101 case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_NEW: 8102 update_planes_and_stream_execute_v3_commit(scratch, false, true, 8103 scratch->dc->check_config.deferred_transition_state); 8104 break; 8105 8106 case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_CURRENT: 8107 update_planes_and_stream_execute_v3_commit(scratch, true, true, false); 8108 break; 8109 8110 case UPDATE_V3_FLOW_INVALID: 8111 default: 8112 ASSERT(false); 8113 } 8114 } 8115 8116 static void update_planes_and_stream_cleanup_v3_release_minimal( 8117 struct dc_update_scratch_space *scratch, 8118 bool backup 8119 ) 8120 { 8121 release_minimal_transition_state( 8122 scratch->dc, 8123 scratch->intermediate_context, 8124 backup ? scratch->backup_context : scratch->new_context, 8125 &scratch->intermediate_policy 8126 ); 8127 } 8128 8129 static void update_planes_and_stream_cleanup_v3_intermediate( 8130 struct dc_update_scratch_space *scratch, 8131 bool backup 8132 ) 8133 { 8134 swap_and_release_current_context(scratch->dc, scratch->intermediate_context, scratch->stream); 8135 dc_state_retain(scratch->dc->current_state); 8136 update_planes_and_stream_cleanup_v3_release_minimal(scratch, backup); 8137 } 8138 8139 static bool update_planes_and_stream_cleanup_v3( 8140 struct dc_update_scratch_space *scratch 8141 ) 8142 { 8143 switch (scratch->flow) { 8144 case UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FAST: 8145 case UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FULL: 8146 if (scratch->dc->check_config.transition_countdown_to_steady_state) 8147 scratch->dc->check_config.transition_countdown_to_steady_state--; 8148 break; 8149 8150 case UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS: 8151 swap_and_release_current_context(scratch->dc, scratch->new_context, scratch->stream); 8152 break; 8153 8154 case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_NEW: 8155 update_planes_and_stream_cleanup_v3_intermediate(scratch, false); 8156 if (scratch->dc->check_config.deferred_transition_state) { 8157 dc_state_release(scratch->new_context); 8158 } else { 8159 scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS; 8160 return true; 8161 } 8162 break; 8163 8164 case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_CURRENT: 8165 update_planes_and_stream_cleanup_v3_intermediate(scratch, true); 8166 dc_state_release(scratch->backup_context); 8167 restore_planes_and_stream_state(&scratch->dc->scratch.new_state, scratch->stream); 8168 scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS; 8169 return true; 8170 8171 case UPDATE_V3_FLOW_INVALID: 8172 default: 8173 ASSERT(false); 8174 } 8175 8176 if (scratch->do_clear_update_flags) 8177 clear_update_flags(scratch->surface_updates, scratch->surface_count, scratch->stream); 8178 8179 return false; 8180 } 8181 8182 struct dc_update_scratch_space *dc_update_planes_and_stream_init( 8183 struct dc *dc, 8184 struct dc_surface_update *surface_updates, 8185 int surface_count, 8186 struct dc_stream_state *stream, 8187 struct dc_stream_update *stream_update 8188 ) 8189 { 8190 const enum dce_version version = dc->ctx->dce_version; 8191 struct dc_update_scratch_space *scratch = stream->update_scratch; 8192 8193 *scratch = (struct dc_update_scratch_space){ 8194 .dc = dc, 8195 .surface_updates = surface_updates, 8196 .surface_count = surface_count, 8197 .stream = stream, 8198 .stream_update = stream_update, 8199 .update_v3 = version >= DCN_VERSION_4_01 || version == DCN_VERSION_3_2 || version == DCN_VERSION_3_21, 8200 .do_clear_update_flags = version >= DCN_VERSION_1_0, 8201 }; 8202 8203 return scratch; 8204 } 8205 8206 bool dc_update_planes_and_stream_prepare( 8207 struct dc_update_scratch_space *scratch 8208 ) 8209 { 8210 return scratch->update_v3 8211 ? update_planes_and_stream_prepare_v3(scratch) 8212 : update_planes_and_stream_prepare_v2(scratch); 8213 } 8214 8215 void dc_update_planes_and_stream_execute( 8216 const struct dc_update_scratch_space *scratch 8217 ) 8218 { 8219 scratch->update_v3 8220 ? update_planes_and_stream_execute_v3(scratch) 8221 : update_planes_and_stream_execute_v2(scratch); 8222 } 8223 8224 bool dc_update_planes_and_stream_cleanup( 8225 struct dc_update_scratch_space *scratch 8226 ) 8227 { 8228 return scratch->update_v3 8229 ? update_planes_and_stream_cleanup_v3(scratch) 8230 : update_planes_and_stream_cleanup_v2(scratch); 8231 } 8232 8233