1/* $NetBSD: amdgpu_dc.c,v 1.4 2021/12/19 11:59:30 riastradh Exp $ */ 2 3/* 4 * Copyright 2015 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: AMD 25 */ 26 27#include <sys/cdefs.h> 28__KERNEL_RCSID(0, "$NetBSD: amdgpu_dc.c,v 1.4 2021/12/19 11:59:30 riastradh Exp $"); 29 30#include <linux/slab.h> 31#include <linux/mm.h> 32 33#include "dm_services.h" 34 35#include "dc.h" 36 37#include "core_status.h" 38#include "core_types.h" 39#include "hw_sequencer.h" 40#include "dce/dce_hwseq.h" 41 42#include "resource.h" 43 44#include "clk_mgr.h" 45#include "clock_source.h" 46#include "dc_bios_types.h" 47 48#include "bios_parser_interface.h" 49#include "include/irq_service_interface.h" 50#include "transform.h" 51#include "dmcu.h" 52#include "dpp.h" 53#include "timing_generator.h" 54#include "abm.h" 55#include "virtual/virtual_link_encoder.h" 56 57#include "link_hwss.h" 58#include "link_encoder.h" 59 60#include "dc_link_ddc.h" 61#include "dm_helpers.h" 62#include "mem_input.h" 63#include "hubp.h" 64 65#include "dc_link_dp.h" 66#include "dc_dmub_srv.h" 67 68#include "dsc.h" 69 70#include "vm_helper.h" 71 72#include "dce/dce_i2c.h" 73 74#define CTX \ 75 dc->ctx 76 77#define DC_LOGGER \ 78 dc->ctx->logger 79 80static const char DC_BUILD_ID[] = "production-build"; 81 82/** 83 * DOC: Overview 84 * 85 * DC is the OS-agnostic component of the amdgpu DC driver. 86 * 87 * DC maintains and validates a set of structs representing the state of the 88 * driver and writes that state to AMD hardware 89 * 90 * Main DC HW structs: 91 * 92 * struct dc - The central struct. One per driver. Created on driver load, 93 * destroyed on driver unload. 94 * 95 * struct dc_context - One per driver. 96 * Used as a backpointer by most other structs in dc. 97 * 98 * struct dc_link - One per connector (the physical DP, HDMI, miniDP, or eDP 99 * plugpoints). Created on driver load, destroyed on driver unload. 100 * 101 * struct dc_sink - One per display. Created on boot or hotplug. 102 * Destroyed on shutdown or hotunplug. A dc_link can have a local sink 103 * (the display directly attached). It may also have one or more remote 104 * sinks (in the Multi-Stream Transport case) 105 * 106 * struct resource_pool - One per driver. Represents the hw blocks not in the 107 * main pipeline. Not directly accessible by dm. 108 * 109 * Main dc state structs: 110 * 111 * These structs can be created and destroyed as needed. There is a full set of 112 * these structs in dc->current_state representing the currently programmed state. 113 * 114 * struct dc_state - The global DC state to track global state information, 115 * such as bandwidth values. 116 * 117 * struct dc_stream_state - Represents the hw configuration for the pipeline from 118 * a framebuffer to a display. Maps one-to-one with dc_sink. 119 * 120 * struct dc_plane_state - Represents a framebuffer. Each stream has at least one, 121 * and may have more in the Multi-Plane Overlay case. 122 * 123 * struct resource_context - Represents the programmable state of everything in 124 * the resource_pool. Not directly accessible by dm. 125 * 126 * struct pipe_ctx - A member of struct resource_context. Represents the 127 * internal hardware pipeline components. Each dc_plane_state has either 128 * one or two (in the pipe-split case). 129 */ 130 131/******************************************************************************* 132 * Private functions 133 ******************************************************************************/ 134 135static inline void elevate_update_type(enum surface_update_type *original, enum surface_update_type new) 136{ 137 if (new > *original) 138 *original = new; 139} 140 141static void destroy_links(struct dc *dc) 142{ 143 uint32_t i; 144 145 for (i = 0; i < dc->link_count; i++) { 146 if (NULL != dc->links[i]) 147 link_destroy(&dc->links[i]); 148 } 149} 150 151static bool create_links( 152 struct dc *dc, 153 uint32_t num_virtual_links) 154{ 155 int i; 156 int connectors_num; 157 struct dc_bios *bios = dc->ctx->dc_bios; 158 159 dc->link_count = 0; 160 161 connectors_num = bios->funcs->get_connectors_number(bios); 162 163 if (connectors_num > ENUM_ID_COUNT) { 164 dm_error( 165 "DC: Number of connectors %d exceeds maximum of %d!\n", 166 connectors_num, 167 ENUM_ID_COUNT); 168 return false; 169 } 170 171 dm_output_to_console( 172 "DC: %s: connectors_num: physical:%d, virtual:%d\n", 173 __func__, 174 connectors_num, 175 num_virtual_links); 176 177 for (i = 0; i < connectors_num; i++) { 178 struct link_init_data link_init_params = {0}; 179 struct dc_link *link; 180 181 link_init_params.ctx = dc->ctx; 182 /* next BIOS object table connector */ 183 link_init_params.connector_index = i; 184 link_init_params.link_index = dc->link_count; 185 link_init_params.dc = dc; 186 link = link_create(&link_init_params); 187 188 if (link) { 189 bool should_destory_link = false; 190 191 if (link->connector_signal == SIGNAL_TYPE_EDP) { 192 if (dc->config.edp_not_connected) 193 should_destory_link = true; 194 else if (dc->debug.remove_disconnect_edp) { 195 enum dc_connection_type type; 196 dc_link_detect_sink(link, &type); 197 if (type == dc_connection_none) 198 should_destory_link = true; 199 } 200 } 201 202 if (dc->config.force_enum_edp || !should_destory_link) { 203 dc->links[dc->link_count] = link; 204 link->dc = dc; 205 ++dc->link_count; 206 } else { 207 link_destroy(&link); 208 } 209 } 210 } 211 212 for (i = 0; i < num_virtual_links; i++) { 213 struct dc_link *link = kzalloc(sizeof(*link), GFP_KERNEL); 214 struct encoder_init_data enc_init = {0}; 215 216 if (link == NULL) { 217 BREAK_TO_DEBUGGER(); 218 goto failed_alloc; 219 } 220 221 link->link_index = dc->link_count; 222 dc->links[dc->link_count] = link; 223 dc->link_count++; 224 225 link->ctx = dc->ctx; 226 link->dc = dc; 227 link->connector_signal = SIGNAL_TYPE_VIRTUAL; 228 link->link_id.type = OBJECT_TYPE_CONNECTOR; 229 link->link_id.id = CONNECTOR_ID_VIRTUAL; 230 link->link_id.enum_id = ENUM_ID_1; 231 link->link_enc = kzalloc(sizeof(*link->link_enc), GFP_KERNEL); 232 233 if (!link->link_enc) { 234 BREAK_TO_DEBUGGER(); 235 goto failed_alloc; 236 } 237 238 link->link_status.dpcd_caps = &link->dpcd_caps; 239 240 enc_init.ctx = dc->ctx; 241 enc_init.channel = CHANNEL_ID_UNKNOWN; 242 enc_init.hpd_source = HPD_SOURCEID_UNKNOWN; 243 enc_init.transmitter = TRANSMITTER_UNKNOWN; 244 enc_init.connector = link->link_id; 245 enc_init.encoder.type = OBJECT_TYPE_ENCODER; 246 enc_init.encoder.id = ENCODER_ID_INTERNAL_VIRTUAL; 247 enc_init.encoder.enum_id = ENUM_ID_1; 248 virtual_link_encoder_construct(link->link_enc, &enc_init); 249 } 250 251 return true; 252 253failed_alloc: 254 return false; 255} 256 257static struct dc_perf_trace *dc_perf_trace_create(void) 258{ 259 return kzalloc(sizeof(struct dc_perf_trace), GFP_KERNEL); 260} 261 262static void dc_perf_trace_destroy(struct dc_perf_trace **perf_trace) 263{ 264 kfree(*perf_trace); 265 *perf_trace = NULL; 266} 267 268/** 269 ***************************************************************************** 270 * Function: dc_stream_adjust_vmin_vmax 271 * 272 * @brief 273 * Looks up the pipe context of dc_stream_state and updates the 274 * vertical_total_min and vertical_total_max of the DRR, Dynamic Refresh 275 * Rate, which is a power-saving feature that targets reducing panel 276 * refresh rate while the screen is static 277 * 278 * @param [in] dc: dc reference 279 * @param [in] stream: Initial dc stream state 280 * @param [in] adjust: Updated parameters for vertical_total_min and 281 * vertical_total_max 282 ***************************************************************************** 283 */ 284bool dc_stream_adjust_vmin_vmax(struct dc *dc, 285 struct dc_stream_state *stream, 286 struct dc_crtc_timing_adjust *adjust) 287{ 288 int i = 0; 289 bool ret = false; 290 291 for (i = 0; i < MAX_PIPES; i++) { 292 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 293 294 if (pipe->stream == stream && pipe->stream_res.tg) { 295 dc->hwss.set_drr(&pipe, 296 1, 297 adjust->v_total_min, 298 adjust->v_total_max, 299 adjust->v_total_mid, 300 adjust->v_total_mid_frame_num); 301 302 ret = true; 303 } 304 } 305 return ret; 306} 307 308bool dc_stream_get_crtc_position(struct dc *dc, 309 struct dc_stream_state **streams, int num_streams, 310 unsigned int *v_pos, unsigned int *nom_v_pos) 311{ 312 /* TODO: Support multiple streams */ 313 const struct dc_stream_state *stream = streams[0]; 314 int i = 0; 315 bool ret = false; 316 struct crtc_position position; 317 318 for (i = 0; i < MAX_PIPES; i++) { 319 struct pipe_ctx *pipe = 320 &dc->current_state->res_ctx.pipe_ctx[i]; 321 322 if (pipe->stream == stream && pipe->stream_res.stream_enc) { 323 dc->hwss.get_position(&pipe, 1, &position); 324 325 *v_pos = position.vertical_count; 326 *nom_v_pos = position.nominal_vcount; 327 ret = true; 328 } 329 } 330 return ret; 331} 332 333/** 334 * dc_stream_configure_crc() - Configure CRC capture for the given stream. 335 * @dc: DC Object 336 * @stream: The stream to configure CRC on. 337 * @enable: Enable CRC if true, disable otherwise. 338 * @continuous: Capture CRC on every frame if true. Otherwise, only capture 339 * once. 340 * 341 * By default, only CRC0 is configured, and the entire frame is used to 342 * calculate the crc. 343 */ 344bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream, 345 bool enable, bool continuous) 346{ 347 int i; 348 struct pipe_ctx *pipe; 349 struct crc_params param; 350 struct timing_generator *tg; 351 352 for (i = 0; i < MAX_PIPES; i++) { 353 pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 354 if (pipe->stream == stream) 355 break; 356 } 357 /* Stream not found */ 358 if (i == MAX_PIPES) 359 return false; 360 361 /* Always capture the full frame */ 362 param.windowa_x_start = 0; 363 param.windowa_y_start = 0; 364 param.windowa_x_end = pipe->stream->timing.h_addressable; 365 param.windowa_y_end = pipe->stream->timing.v_addressable; 366 param.windowb_x_start = 0; 367 param.windowb_y_start = 0; 368 param.windowb_x_end = pipe->stream->timing.h_addressable; 369 param.windowb_y_end = pipe->stream->timing.v_addressable; 370 371 /* Default to the union of both windows */ 372 param.selection = UNION_WINDOW_A_B; 373 param.continuous_mode = continuous; 374 param.enable = enable; 375 376 tg = pipe->stream_res.tg; 377 378 /* Only call if supported */ 379 if (tg->funcs->configure_crc) 380 return tg->funcs->configure_crc(tg, ¶m); 381 DC_LOG_WARNING("CRC capture not supported."); 382 return false; 383} 384 385/** 386 * dc_stream_get_crc() - Get CRC values for the given stream. 387 * @dc: DC object 388 * @stream: The DC stream state of the stream to get CRCs from. 389 * @r_cr, g_y, b_cb: CRC values for the three channels are stored here. 390 * 391 * dc_stream_configure_crc needs to be called beforehand to enable CRCs. 392 * Return false if stream is not found, or if CRCs are not enabled. 393 */ 394bool dc_stream_get_crc(struct dc *dc, struct dc_stream_state *stream, 395 uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb) 396{ 397 int i; 398 struct pipe_ctx *pipe; 399 struct timing_generator *tg; 400 401 for (i = 0; i < MAX_PIPES; i++) { 402 pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 403 if (pipe->stream == stream) 404 break; 405 } 406 /* Stream not found */ 407 if (i == MAX_PIPES) 408 return false; 409 410 tg = pipe->stream_res.tg; 411 412 if (tg->funcs->get_crc) 413 return tg->funcs->get_crc(tg, r_cr, g_y, b_cb); 414 DC_LOG_WARNING("CRC capture not supported."); 415 return false; 416} 417 418void dc_stream_set_dyn_expansion(struct dc *dc, struct dc_stream_state *stream, 419 enum dc_dynamic_expansion option) 420{ 421 /* OPP FMT dyn expansion updates*/ 422 int i = 0; 423 struct pipe_ctx *pipe_ctx; 424 425 for (i = 0; i < MAX_PIPES; i++) { 426 if (dc->current_state->res_ctx.pipe_ctx[i].stream 427 == stream) { 428 pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; 429 pipe_ctx->stream_res.opp->dyn_expansion = option; 430 pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( 431 pipe_ctx->stream_res.opp, 432 COLOR_SPACE_YCBCR601, 433 stream->timing.display_color_depth, 434 stream->signal); 435 } 436 } 437} 438 439void dc_stream_set_dither_option(struct dc_stream_state *stream, 440 enum dc_dither_option option) 441{ 442 struct bit_depth_reduction_params params; 443 struct dc_link *link = stream->link; 444 struct pipe_ctx *pipes = NULL; 445 int i; 446 447 for (i = 0; i < MAX_PIPES; i++) { 448 if (link->dc->current_state->res_ctx.pipe_ctx[i].stream == 449 stream) { 450 pipes = &link->dc->current_state->res_ctx.pipe_ctx[i]; 451 break; 452 } 453 } 454 455 if (!pipes) 456 return; 457 if (option > DITHER_OPTION_MAX) 458 return; 459 460 stream->dither_option = option; 461 462 memset(¶ms, 0, sizeof(params)); 463 resource_build_bit_depth_reduction_params(stream, ¶ms); 464 stream->bit_depth_params = params; 465 466 if (pipes->plane_res.xfm && 467 pipes->plane_res.xfm->funcs->transform_set_pixel_storage_depth) { 468 pipes->plane_res.xfm->funcs->transform_set_pixel_storage_depth( 469 pipes->plane_res.xfm, 470 pipes->plane_res.scl_data.lb_params.depth, 471 &stream->bit_depth_params); 472 } 473 474 pipes->stream_res.opp->funcs-> 475 opp_program_bit_depth_reduction(pipes->stream_res.opp, ¶ms); 476} 477 478bool dc_stream_set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream) 479{ 480 int i = 0; 481 bool ret = false; 482 struct pipe_ctx *pipes; 483 484 for (i = 0; i < MAX_PIPES; i++) { 485 if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) { 486 pipes = &dc->current_state->res_ctx.pipe_ctx[i]; 487 dc->hwss.program_gamut_remap(pipes); 488 ret = true; 489 } 490 } 491 492 return ret; 493} 494 495bool dc_stream_program_csc_matrix(struct dc *dc, struct dc_stream_state *stream) 496{ 497 int i = 0; 498 bool ret = false; 499 struct pipe_ctx *pipes; 500 501 for (i = 0; i < MAX_PIPES; i++) { 502 if (dc->current_state->res_ctx.pipe_ctx[i].stream 503 == stream) { 504 505 pipes = &dc->current_state->res_ctx.pipe_ctx[i]; 506 dc->hwss.program_output_csc(dc, 507 pipes, 508 stream->output_color_space, 509 stream->csc_color_matrix.matrix, 510 pipes->stream_res.opp->inst); 511 ret = true; 512 } 513 } 514 515 return ret; 516} 517 518void dc_stream_set_static_screen_params(struct dc *dc, 519 struct dc_stream_state **streams, 520 int num_streams, 521 const struct dc_static_screen_params *params) 522{ 523 int i = 0; 524 int j = 0; 525 struct pipe_ctx *pipes_affected[MAX_PIPES]; 526 int num_pipes_affected = 0; 527 528 for (i = 0; i < num_streams; i++) { 529 struct dc_stream_state *stream = streams[i]; 530 531 for (j = 0; j < MAX_PIPES; j++) { 532 if (dc->current_state->res_ctx.pipe_ctx[j].stream 533 == stream) { 534 pipes_affected[num_pipes_affected++] = 535 &dc->current_state->res_ctx.pipe_ctx[j]; 536 } 537 } 538 } 539 540 dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, params); 541} 542 543static void dc_destruct(struct dc *dc) 544{ 545 if (dc->current_state) { 546 dc_release_state(dc->current_state); 547 dc->current_state = NULL; 548 } 549 550 destroy_links(dc); 551 552 if (dc->clk_mgr) { 553 dc_destroy_clk_mgr(dc->clk_mgr); 554 dc->clk_mgr = NULL; 555 } 556 557 dc_destroy_resource_pool(dc); 558 559 if (dc->ctx->gpio_service) 560 dal_gpio_service_destroy(&dc->ctx->gpio_service); 561 562 if (dc->ctx->created_bios) 563 dal_bios_parser_destroy(&dc->ctx->dc_bios); 564 565 dc_perf_trace_destroy(&dc->ctx->perf_trace); 566 567 kfree(dc->ctx); 568 dc->ctx = NULL; 569 570 kfree(dc->bw_vbios); 571 dc->bw_vbios = NULL; 572 573 kfree(dc->bw_dceip); 574 dc->bw_dceip = NULL; 575 576#ifdef CONFIG_DRM_AMD_DC_DCN 577 kfree(dc->dcn_soc); 578 dc->dcn_soc = NULL; 579 580 kfree(dc->dcn_ip); 581 dc->dcn_ip = NULL; 582 583#endif 584 kfree(dc->vm_helper); 585 dc->vm_helper = NULL; 586 587} 588 589static bool dc_construct_ctx(struct dc *dc, 590 const struct dc_init_data *init_params) 591{ 592 struct dc_context *dc_ctx; 593 enum dce_version dc_version = DCE_VERSION_UNKNOWN; 594 595 dc_ctx = kzalloc(sizeof(*dc_ctx), GFP_KERNEL); 596 if (!dc_ctx) 597 return false; 598 599 dc_ctx->cgs_device = init_params->cgs_device; 600 dc_ctx->driver_context = init_params->driver; 601 dc_ctx->dc = dc; 602 dc_ctx->asic_id = init_params->asic_id; 603 dc_ctx->dc_sink_id_count = 0; 604 dc_ctx->dc_stream_id_count = 0; 605 dc_ctx->dce_environment = init_params->dce_environment; 606 607 /* Create logger */ 608 609 dc_version = resource_parse_asic_id(init_params->asic_id); 610 dc_ctx->dce_version = dc_version; 611 612 dc_ctx->perf_trace = dc_perf_trace_create(); 613 if (!dc_ctx->perf_trace) { 614 ASSERT_CRITICAL(false); 615 return false; 616 } 617 618 dc->ctx = dc_ctx; 619 620 return true; 621} 622 623static bool dc_construct(struct dc *dc, 624 const struct dc_init_data *init_params) 625{ 626 struct dc_context *dc_ctx; 627 struct bw_calcs_dceip *dc_dceip; 628 struct bw_calcs_vbios *dc_vbios; 629#ifdef CONFIG_DRM_AMD_DC_DCN 630 struct dcn_soc_bounding_box *dcn_soc; 631 struct dcn_ip_params *dcn_ip; 632#endif 633 634 dc->config = init_params->flags; 635 636 // Allocate memory for the vm_helper 637 dc->vm_helper = kzalloc(sizeof(struct vm_helper), GFP_KERNEL); 638 if (!dc->vm_helper) { 639 dm_error("%s: failed to create dc->vm_helper\n", __func__); 640 goto fail; 641 } 642 643 memcpy(&dc->bb_overrides, &init_params->bb_overrides, sizeof(dc->bb_overrides)); 644 645 dc_dceip = kzalloc(sizeof(*dc_dceip), GFP_KERNEL); 646 if (!dc_dceip) { 647 dm_error("%s: failed to create dceip\n", __func__); 648 goto fail; 649 } 650 651 dc->bw_dceip = dc_dceip; 652 653 dc_vbios = kzalloc(sizeof(*dc_vbios), GFP_KERNEL); 654 if (!dc_vbios) { 655 dm_error("%s: failed to create vbios\n", __func__); 656 goto fail; 657 } 658 659 dc->bw_vbios = dc_vbios; 660#ifdef CONFIG_DRM_AMD_DC_DCN 661 dcn_soc = kzalloc(sizeof(*dcn_soc), GFP_KERNEL); 662 if (!dcn_soc) { 663 dm_error("%s: failed to create dcn_soc\n", __func__); 664 goto fail; 665 } 666 667 dc->dcn_soc = dcn_soc; 668 669 dcn_ip = kzalloc(sizeof(*dcn_ip), GFP_KERNEL); 670 if (!dcn_ip) { 671 dm_error("%s: failed to create dcn_ip\n", __func__); 672 goto fail; 673 } 674 675 dc->dcn_ip = dcn_ip; 676 dc->soc_bounding_box = init_params->soc_bounding_box; 677#endif 678 679 if (!dc_construct_ctx(dc, init_params)) { 680 dm_error("%s: failed to create ctx\n", __func__); 681 goto fail; 682 } 683 684 dc_ctx = dc->ctx; 685 686 /* Resource should construct all asic specific resources. 687 * This should be the only place where we need to parse the asic id 688 */ 689 if (init_params->vbios_override) 690 dc_ctx->dc_bios = init_params->vbios_override; 691 else { 692 /* Create BIOS parser */ 693 struct bp_init_data bp_init_data; 694 695 bp_init_data.ctx = dc_ctx; 696 bp_init_data.bios = init_params->asic_id.atombios_base_address; 697 698 dc_ctx->dc_bios = dal_bios_parser_create( 699 &bp_init_data, dc_ctx->dce_version); 700 701 if (!dc_ctx->dc_bios) { 702 ASSERT_CRITICAL(false); 703 goto fail; 704 } 705 706 dc_ctx->created_bios = true; 707 } 708 709 710 711 /* Create GPIO service */ 712 dc_ctx->gpio_service = dal_gpio_service_create( 713 dc_ctx->dce_version, 714 dc_ctx->dce_environment, 715 dc_ctx); 716 717 if (!dc_ctx->gpio_service) { 718 ASSERT_CRITICAL(false); 719 goto fail; 720 } 721 722 dc->res_pool = dc_create_resource_pool(dc, init_params, dc_ctx->dce_version); 723 if (!dc->res_pool) 724 goto fail; 725 726 dc->clk_mgr = dc_clk_mgr_create(dc->ctx, dc->res_pool->pp_smu, dc->res_pool->dccg); 727 if (!dc->clk_mgr) 728 goto fail; 729 730 if (dc->res_pool->funcs->update_bw_bounding_box) 731 dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params); 732 733 /* Creation of current_state must occur after dc->dml 734 * is initialized in dc_create_resource_pool because 735 * on creation it copies the contents of dc->dml 736 */ 737 738 dc->current_state = dc_create_state(dc); 739 740 if (!dc->current_state) { 741 dm_error("%s: failed to create validate ctx\n", __func__); 742 goto fail; 743 } 744 745 dc_resource_state_construct(dc, dc->current_state); 746 747 if (!create_links(dc, init_params->num_virtual_links)) 748 goto fail; 749 750 return true; 751 752fail: 753 return false; 754} 755 756static bool disable_all_writeback_pipes_for_stream( 757 const struct dc *dc, 758 struct dc_stream_state *stream, 759 struct dc_state *context) 760{ 761 int i; 762 763 for (i = 0; i < stream->num_wb_info; i++) 764 stream->writeback_info[i].wb_enabled = false; 765 766 return true; 767} 768 769static void disable_dangling_plane(struct dc *dc, struct dc_state *context) 770{ 771 int i, j; 772 struct dc_state *dangling_context = dc_create_state(dc); 773 struct dc_state *current_ctx; 774 775 if (dangling_context == NULL) 776 return; 777 778 dc_resource_state_copy_construct(dc->current_state, dangling_context); 779 780 for (i = 0; i < dc->res_pool->pipe_count; i++) { 781 struct dc_stream_state *old_stream = 782 dc->current_state->res_ctx.pipe_ctx[i].stream; 783 bool should_disable = true; 784 785 for (j = 0; j < context->stream_count; j++) { 786 if (old_stream == context->streams[j]) { 787 should_disable = false; 788 break; 789 } 790 } 791 if (should_disable && old_stream) { 792 dc_rem_all_planes_for_stream(dc, old_stream, dangling_context); 793 disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context); 794 if (dc->hwss.apply_ctx_for_surface) 795 dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context); 796 } 797 if (dc->hwss.program_front_end_for_ctx) 798 dc->hwss.program_front_end_for_ctx(dc, dangling_context); 799 } 800 801 current_ctx = dc->current_state; 802 dc->current_state = dangling_context; 803 dc_release_state(current_ctx); 804} 805 806static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context) 807{ 808 int i; 809 int count = 0; 810 struct pipe_ctx *pipe; 811 PERF_TRACE(); 812 for (i = 0; i < MAX_PIPES; i++) { 813 pipe = &context->res_ctx.pipe_ctx[i]; 814 815 if (!pipe->plane_state) 816 continue; 817 818 /* Timeout 100 ms */ 819 while (count < 100000) { 820 /* Must set to false to start with, due to OR in update function */ 821 pipe->plane_state->status.is_flip_pending = false; 822 dc->hwss.update_pending_status(pipe); 823 if (!pipe->plane_state->status.is_flip_pending) 824 break; 825 udelay(1); 826 count++; 827 } 828 ASSERT(!pipe->plane_state->status.is_flip_pending); 829 } 830 PERF_TRACE(); 831} 832 833/******************************************************************************* 834 * Public functions 835 ******************************************************************************/ 836 837struct dc *dc_create(const struct dc_init_data *init_params) 838{ 839 struct dc *dc = kzalloc(sizeof(*dc), GFP_KERNEL); 840 unsigned int full_pipe_count; 841 842 if (NULL == dc) 843 goto alloc_fail; 844 845 if (init_params->dce_environment == DCE_ENV_VIRTUAL_HW) { 846 if (false == dc_construct_ctx(dc, init_params)) { 847 dc_destruct(dc); 848 goto construct_fail; 849 } 850 } else { 851 if (false == dc_construct(dc, init_params)) { 852 dc_destruct(dc); 853 goto construct_fail; 854 } 855 856 full_pipe_count = dc->res_pool->pipe_count; 857 if (dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE) 858 full_pipe_count--; 859 dc->caps.max_streams = min( 860 full_pipe_count, 861 dc->res_pool->stream_enc_count); 862 863 dc->optimize_seamless_boot_streams = 0; 864 dc->caps.max_links = dc->link_count; 865 dc->caps.max_audios = dc->res_pool->audio_count; 866 dc->caps.linear_pitch_alignment = 64; 867 868 dc->caps.max_dp_protocol_version = DP_VERSION_1_4; 869 870 if (dc->res_pool->dmcu != NULL) 871 dc->versions.dmcu_version = dc->res_pool->dmcu->dmcu_version; 872 } 873 874 /* Populate versioning information */ 875 dc->versions.dc_ver = DC_VER; 876 877 dc->build_id = DC_BUILD_ID; 878 879 DC_LOG_DC("Display Core initialized\n"); 880 881 882 883 return dc; 884 885construct_fail: 886 kfree(dc); 887 888alloc_fail: 889 return NULL; 890} 891 892void dc_hardware_init(struct dc *dc) 893{ 894 if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW) 895 dc->hwss.init_hw(dc); 896} 897 898void dc_init_callbacks(struct dc *dc, 899 const struct dc_callback_init *init_params) 900{ 901#ifdef CONFIG_DRM_AMD_DC_HDCP 902 dc->ctx->cp_psp = init_params->cp_psp; 903#endif 904} 905 906void dc_deinit_callbacks(struct dc *dc) 907{ 908#ifdef CONFIG_DRM_AMD_DC_HDCP 909 memset(&dc->ctx->cp_psp, 0, sizeof(dc->ctx->cp_psp)); 910#endif 911} 912 913void dc_destroy(struct dc **dc) 914{ 915 dc_destruct(*dc); 916 kfree(*dc); 917 *dc = NULL; 918} 919 920static void enable_timing_multisync( 921 struct dc *dc, 922 struct dc_state *ctx) 923{ 924 int i = 0, multisync_count = 0; 925 int pipe_count = dc->res_pool->pipe_count; 926 struct pipe_ctx *multisync_pipes[MAX_PIPES] = { NULL }; 927 928 for (i = 0; i < pipe_count; i++) { 929 if (!ctx->res_ctx.pipe_ctx[i].stream || 930 !ctx->res_ctx.pipe_ctx[i].stream->triggered_crtc_reset.enabled) 931 continue; 932 if (ctx->res_ctx.pipe_ctx[i].stream == ctx->res_ctx.pipe_ctx[i].stream->triggered_crtc_reset.event_source) 933 continue; 934 multisync_pipes[multisync_count] = &ctx->res_ctx.pipe_ctx[i]; 935 multisync_count++; 936 } 937 938 if (multisync_count > 0) { 939 dc->hwss.enable_per_frame_crtc_position_reset( 940 dc, multisync_count, multisync_pipes); 941 } 942} 943 944static void program_timing_sync( 945 struct dc *dc, 946 struct dc_state *ctx) 947{ 948 int i, j, k; 949 int group_index = 0; 950 int num_group = 0; 951 int pipe_count = dc->res_pool->pipe_count; 952 struct pipe_ctx *unsynced_pipes[MAX_PIPES] = { NULL }; 953 954 for (i = 0; i < pipe_count; i++) { 955 if (!ctx->res_ctx.pipe_ctx[i].stream || ctx->res_ctx.pipe_ctx[i].top_pipe) 956 continue; 957 958 unsynced_pipes[i] = &ctx->res_ctx.pipe_ctx[i]; 959 } 960 961 for (i = 0; i < pipe_count; i++) { 962 int group_size = 1; 963 struct pipe_ctx *pipe_set[MAX_PIPES]; 964 965 if (!unsynced_pipes[i]) 966 continue; 967 968 pipe_set[0] = unsynced_pipes[i]; 969 unsynced_pipes[i] = NULL; 970 971 /* Add tg to the set, search rest of the tg's for ones with 972 * same timing, add all tgs with same timing to the group 973 */ 974 for (j = i + 1; j < pipe_count; j++) { 975 if (!unsynced_pipes[j]) 976 continue; 977 978 if (resource_are_streams_timing_synchronizable( 979 unsynced_pipes[j]->stream, 980 pipe_set[0]->stream)) { 981 pipe_set[group_size] = unsynced_pipes[j]; 982 unsynced_pipes[j] = NULL; 983 group_size++; 984 } 985 } 986 987 /* set first pipe with plane as master */ 988 for (j = 0; j < group_size; j++) { 989 if (pipe_set[j]->plane_state) { 990 if (j == 0) 991 break; 992 993 swap(pipe_set[0], pipe_set[j]); 994 break; 995 } 996 } 997 998 999 for (k = 0; k < group_size; k++) { 1000 struct dc_stream_status *status = dc_stream_get_status_from_state(ctx, pipe_set[k]->stream); 1001 1002 status->timing_sync_info.group_id = num_group; 1003 status->timing_sync_info.group_size = group_size; 1004 if (k == 0) 1005 status->timing_sync_info.master = true; 1006 else 1007 status->timing_sync_info.master = false; 1008 1009 } 1010 /* remove any other pipes with plane as they have already been synced */ 1011 for (j = j + 1; j < group_size; j++) { 1012 if (pipe_set[j]->plane_state) { 1013 group_size--; 1014 pipe_set[j] = pipe_set[group_size]; 1015 j--; 1016 } 1017 } 1018 1019 if (group_size > 1) { 1020 dc->hwss.enable_timing_synchronization( 1021 dc, group_index, group_size, pipe_set); 1022 group_index++; 1023 } 1024 num_group++; 1025 } 1026} 1027 1028static bool context_changed( 1029 struct dc *dc, 1030 struct dc_state *context) 1031{ 1032 uint8_t i; 1033 1034 if (context->stream_count != dc->current_state->stream_count) 1035 return true; 1036 1037 for (i = 0; i < dc->current_state->stream_count; i++) { 1038 if (dc->current_state->streams[i] != context->streams[i]) 1039 return true; 1040 } 1041 1042 return false; 1043} 1044 1045bool dc_validate_seamless_boot_timing(const struct dc *dc, 1046 const struct dc_sink *sink, 1047 struct dc_crtc_timing *crtc_timing) 1048{ 1049 struct timing_generator *tg; 1050 struct stream_encoder *se = NULL; 1051 1052 struct dc_crtc_timing hw_crtc_timing = {0}; 1053 1054 struct dc_link *link = sink->link; 1055 unsigned int i, enc_inst, tg_inst = 0; 1056 1057 // Seamless port only support single DP and EDP so far 1058 if (sink->sink_signal != SIGNAL_TYPE_DISPLAY_PORT && 1059 sink->sink_signal != SIGNAL_TYPE_EDP) 1060 return false; 1061 1062 /* Check for enabled DIG to identify enabled display */ 1063 if (!link->link_enc->funcs->is_dig_enabled(link->link_enc)) 1064 return false; 1065 1066 enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc); 1067 1068 if (enc_inst == ENGINE_ID_UNKNOWN) 1069 return false; 1070 1071 for (i = 0; i < dc->res_pool->stream_enc_count; i++) { 1072 if (dc->res_pool->stream_enc[i]->id == enc_inst) { 1073 1074 se = dc->res_pool->stream_enc[i]; 1075 1076 tg_inst = dc->res_pool->stream_enc[i]->funcs->dig_source_otg( 1077 dc->res_pool->stream_enc[i]); 1078 break; 1079 } 1080 } 1081 1082 // tg_inst not found 1083 if (i == dc->res_pool->stream_enc_count) 1084 return false; 1085 1086 if (tg_inst >= dc->res_pool->timing_generator_count) 1087 return false; 1088 1089 tg = dc->res_pool->timing_generators[tg_inst]; 1090 1091 if (!tg->funcs->get_hw_timing) 1092 return false; 1093 1094 if (!tg->funcs->get_hw_timing(tg, &hw_crtc_timing)) 1095 return false; 1096 1097 if (crtc_timing->h_total != hw_crtc_timing.h_total) 1098 return false; 1099 1100 if (crtc_timing->h_border_left != hw_crtc_timing.h_border_left) 1101 return false; 1102 1103 if (crtc_timing->h_addressable != hw_crtc_timing.h_addressable) 1104 return false; 1105 1106 if (crtc_timing->h_border_right != hw_crtc_timing.h_border_right) 1107 return false; 1108 1109 if (crtc_timing->h_front_porch != hw_crtc_timing.h_front_porch) 1110 return false; 1111 1112 if (crtc_timing->h_sync_width != hw_crtc_timing.h_sync_width) 1113 return false; 1114 1115 if (crtc_timing->v_total != hw_crtc_timing.v_total) 1116 return false; 1117 1118 if (crtc_timing->v_border_top != hw_crtc_timing.v_border_top) 1119 return false; 1120 1121 if (crtc_timing->v_addressable != hw_crtc_timing.v_addressable) 1122 return false; 1123 1124 if (crtc_timing->v_border_bottom != hw_crtc_timing.v_border_bottom) 1125 return false; 1126 1127 if (crtc_timing->v_front_porch != hw_crtc_timing.v_front_porch) 1128 return false; 1129 1130 if (crtc_timing->v_sync_width != hw_crtc_timing.v_sync_width) 1131 return false; 1132 1133 if (dc_is_dp_signal(link->connector_signal)) { 1134 unsigned int pix_clk_100hz; 1135 1136 dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz( 1137 dc->res_pool->dp_clock_source, 1138 tg_inst, &pix_clk_100hz); 1139 1140 if (crtc_timing->pix_clk_100hz != pix_clk_100hz) 1141 return false; 1142 1143 if (!se->funcs->dp_get_pixel_format) 1144 return false; 1145 1146 if (!se->funcs->dp_get_pixel_format( 1147 se, 1148 &hw_crtc_timing.pixel_encoding, 1149 &hw_crtc_timing.display_color_depth)) 1150 return false; 1151 1152 if (hw_crtc_timing.display_color_depth != crtc_timing->display_color_depth) 1153 return false; 1154 1155 if (hw_crtc_timing.pixel_encoding != crtc_timing->pixel_encoding) 1156 return false; 1157 } 1158 1159 return true; 1160} 1161 1162bool dc_enable_stereo( 1163 struct dc *dc, 1164 struct dc_state *context, 1165 struct dc_stream_state *streams[], 1166 uint8_t stream_count) 1167{ 1168 bool ret = true; 1169 int i, j; 1170 struct pipe_ctx *pipe; 1171 1172 for (i = 0; i < MAX_PIPES; i++) { 1173 if (context != NULL) 1174 pipe = &context->res_ctx.pipe_ctx[i]; 1175 else 1176 pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 1177 for (j = 0 ; pipe && j < stream_count; j++) { 1178 if (streams[j] && streams[j] == pipe->stream && 1179 dc->hwss.setup_stereo) 1180 dc->hwss.setup_stereo(pipe, dc); 1181 } 1182 } 1183 1184 return ret; 1185} 1186 1187/* 1188 * Applies given context to HW and copy it into current context. 1189 * It's up to the user to release the src context afterwards. 1190 */ 1191static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *context) 1192{ 1193 struct dc_bios *dcb = dc->ctx->dc_bios; 1194 enum dc_status result = DC_ERROR_UNEXPECTED; 1195 struct pipe_ctx *pipe; 1196 int i, k, l; 1197 struct dc_stream_state *dc_streams[MAX_STREAMS] = {0}; 1198 1199 disable_dangling_plane(dc, context); 1200 1201 for (i = 0; i < context->stream_count; i++) 1202 dc_streams[i] = context->streams[i]; 1203 1204 if (!dcb->funcs->is_accelerated_mode(dcb)) 1205 dc->hwss.enable_accelerated_mode(dc, context); 1206 1207 for (i = 0; i < context->stream_count; i++) { 1208 if (context->streams[i]->apply_seamless_boot_optimization) 1209 dc->optimize_seamless_boot_streams++; 1210 } 1211 1212 if (dc->optimize_seamless_boot_streams == 0) 1213 dc->hwss.prepare_bandwidth(dc, context); 1214 1215 /* re-program planes for existing stream, in case we need to 1216 * free up plane resource for later use 1217 */ 1218 if (dc->hwss.apply_ctx_for_surface) 1219 for (i = 0; i < context->stream_count; i++) { 1220 if (context->streams[i]->mode_changed) 1221 continue; 1222 1223 dc->hwss.apply_ctx_for_surface( 1224 dc, context->streams[i], 1225 context->stream_status[i].plane_count, 1226 context); /* use new pipe config in new context */ 1227 } 1228 1229 /* Program hardware */ 1230 for (i = 0; i < dc->res_pool->pipe_count; i++) { 1231 pipe = &context->res_ctx.pipe_ctx[i]; 1232 dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); 1233 } 1234 1235 result = dc->hwss.apply_ctx_to_hw(dc, context); 1236 1237 if (result != DC_OK) 1238 return result; 1239 1240 if (context->stream_count > 1 && !dc->debug.disable_timing_sync) { 1241 enable_timing_multisync(dc, context); 1242 program_timing_sync(dc, context); 1243 } 1244 1245 /* Program all planes within new context*/ 1246 if (dc->hwss.program_front_end_for_ctx) 1247 dc->hwss.program_front_end_for_ctx(dc, context); 1248 for (i = 0; i < context->stream_count; i++) { 1249 const struct dc_link *link = context->streams[i]->link; 1250 1251 if (!context->streams[i]->mode_changed) 1252 continue; 1253 1254 if (dc->hwss.apply_ctx_for_surface) 1255 dc->hwss.apply_ctx_for_surface( 1256 dc, context->streams[i], 1257 context->stream_status[i].plane_count, 1258 context); 1259 1260 /* 1261 * enable stereo 1262 * TODO rework dc_enable_stereo call to work with validation sets? 1263 */ 1264 for (k = 0; k < MAX_PIPES; k++) { 1265 pipe = &context->res_ctx.pipe_ctx[k]; 1266 1267 for (l = 0 ; pipe && l < context->stream_count; l++) { 1268 if (context->streams[l] && 1269 context->streams[l] == pipe->stream && 1270 dc->hwss.setup_stereo) 1271 dc->hwss.setup_stereo(pipe, dc); 1272 } 1273 } 1274 1275 CONN_MSG_MODE(link, "{%dx%d, %dx%d@%dKhz}", 1276 context->streams[i]->timing.h_addressable, 1277 context->streams[i]->timing.v_addressable, 1278 context->streams[i]->timing.h_total, 1279 context->streams[i]->timing.v_total, 1280 context->streams[i]->timing.pix_clk_100hz / 10); 1281 } 1282 1283 dc_enable_stereo(dc, context, dc_streams, context->stream_count); 1284 1285 if (dc->optimize_seamless_boot_streams == 0) { 1286 /* Must wait for no flips to be pending before doing optimize bw */ 1287 wait_for_no_pipes_pending(dc, context); 1288 /* pplib is notified if disp_num changed */ 1289 dc->hwss.optimize_bandwidth(dc, context); 1290 } 1291 1292 for (i = 0; i < context->stream_count; i++) 1293 context->streams[i]->mode_changed = false; 1294 1295 dc_release_state(dc->current_state); 1296 1297 dc->current_state = context; 1298 1299 dc_retain_state(dc->current_state); 1300 1301 return result; 1302} 1303 1304bool dc_commit_state(struct dc *dc, struct dc_state *context) 1305{ 1306 enum dc_status result = DC_ERROR_UNEXPECTED; 1307 int i; 1308 1309 if (false == context_changed(dc, context)) 1310 return DC_OK; 1311 1312 DC_LOG_DC("%s: %d streams\n", 1313 __func__, context->stream_count); 1314 1315 for (i = 0; i < context->stream_count; i++) { 1316 struct dc_stream_state *stream = context->streams[i]; 1317 1318 dc_stream_log(dc, stream); 1319 } 1320 1321 result = dc_commit_state_no_check(dc, context); 1322 1323 return (result == DC_OK); 1324} 1325 1326bool dc_is_hw_initialized(struct dc *dc) 1327{ 1328 struct dc_bios *dcb = dc->ctx->dc_bios; 1329 return dcb->funcs->is_accelerated_mode(dcb); 1330} 1331 1332bool dc_post_update_surfaces_to_stream(struct dc *dc) 1333{ 1334 int i; 1335 struct dc_state *context = dc->current_state; 1336 1337 if (!dc->optimized_required || dc->optimize_seamless_boot_streams > 0) 1338 return true; 1339 1340 post_surface_trace(dc); 1341 1342 for (i = 0; i < dc->res_pool->pipe_count; i++) 1343 if (context->res_ctx.pipe_ctx[i].stream == NULL || 1344 context->res_ctx.pipe_ctx[i].plane_state == NULL) { 1345 context->res_ctx.pipe_ctx[i].pipe_idx = i; 1346 dc->hwss.disable_plane(dc, &context->res_ctx.pipe_ctx[i]); 1347 } 1348 1349 dc->optimized_required = false; 1350 1351 dc->hwss.optimize_bandwidth(dc, context); 1352 return true; 1353} 1354 1355struct dc_state *dc_create_state(struct dc *dc) 1356{ 1357 struct dc_state *context = kvzalloc(sizeof(struct dc_state), 1358 GFP_KERNEL); 1359 1360 if (!context) 1361 return NULL; 1362 /* Each context must have their own instance of VBA and in order to 1363 * initialize and obtain IP and SOC the base DML instance from DC is 1364 * initially copied into every context 1365 */ 1366#ifdef CONFIG_DRM_AMD_DC_DCN 1367 memcpy(&context->bw_ctx.dml, &dc->dml, sizeof(struct display_mode_lib)); 1368#endif 1369 1370 kref_init(&context->refcount); 1371 1372 return context; 1373} 1374 1375struct dc_state *dc_copy_state(struct dc_state *src_ctx) 1376{ 1377 int i, j; 1378 struct dc_state *new_ctx = kvmalloc(sizeof(struct dc_state), GFP_KERNEL); 1379 1380 if (!new_ctx) 1381 return NULL; 1382 memcpy(new_ctx, src_ctx, sizeof(struct dc_state)); 1383 1384 for (i = 0; i < MAX_PIPES; i++) { 1385 struct pipe_ctx *cur_pipe = &new_ctx->res_ctx.pipe_ctx[i]; 1386 1387 if (cur_pipe->top_pipe) 1388 cur_pipe->top_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; 1389 1390 if (cur_pipe->bottom_pipe) 1391 cur_pipe->bottom_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; 1392 1393 if (cur_pipe->prev_odm_pipe) 1394 cur_pipe->prev_odm_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx]; 1395 1396 if (cur_pipe->next_odm_pipe) 1397 cur_pipe->next_odm_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx]; 1398 1399 } 1400 1401 for (i = 0; i < new_ctx->stream_count; i++) { 1402 dc_stream_retain(new_ctx->streams[i]); 1403 for (j = 0; j < new_ctx->stream_status[i].plane_count; j++) 1404 dc_plane_state_retain( 1405 new_ctx->stream_status[i].plane_states[j]); 1406 } 1407 1408 kref_init(&new_ctx->refcount); 1409 1410 return new_ctx; 1411} 1412 1413void dc_retain_state(struct dc_state *context) 1414{ 1415 kref_get(&context->refcount); 1416} 1417 1418static void dc_state_free(struct kref *kref) 1419{ 1420 struct dc_state *context = container_of(kref, struct dc_state, refcount); 1421 dc_resource_state_destruct(context); 1422 kvfree(context); 1423} 1424 1425void dc_release_state(struct dc_state *context) 1426{ 1427 kref_put(&context->refcount, dc_state_free); 1428} 1429 1430bool dc_set_generic_gpio_for_stereo(bool enable, 1431 struct gpio_service *gpio_service) 1432{ 1433 enum gpio_result gpio_result = GPIO_RESULT_NON_SPECIFIC_ERROR; 1434 struct gpio_pin_info pin_info; 1435 struct gpio *generic; 1436 struct gpio_generic_mux_config *config = kzalloc(sizeof(struct gpio_generic_mux_config), 1437 GFP_KERNEL); 1438 1439 if (!config) 1440 return false; 1441 pin_info = dal_gpio_get_generic_pin_info(gpio_service, GPIO_ID_GENERIC, 0); 1442 1443 if (pin_info.mask == 0xFFFFFFFF || pin_info.offset == 0xFFFFFFFF) { 1444 kfree(config); 1445 return false; 1446 } else { 1447 generic = dal_gpio_service_create_generic_mux( 1448 gpio_service, 1449 pin_info.offset, 1450 pin_info.mask); 1451 } 1452 1453 if (!generic) { 1454 kfree(config); 1455 return false; 1456 } 1457 1458 gpio_result = dal_gpio_open(generic, GPIO_MODE_OUTPUT); 1459 1460 config->enable_output_from_mux = enable; 1461 config->mux_select = GPIO_SIGNAL_SOURCE_PASS_THROUGH_STEREO_SYNC; 1462 1463 if (gpio_result == GPIO_RESULT_OK) 1464 gpio_result = dal_mux_setup_config(generic, config); 1465 1466 if (gpio_result == GPIO_RESULT_OK) { 1467 dal_gpio_close(generic); 1468 dal_gpio_destroy_generic_mux(&generic); 1469 kfree(config); 1470 return true; 1471 } else { 1472 dal_gpio_close(generic); 1473 dal_gpio_destroy_generic_mux(&generic); 1474 kfree(config); 1475 return false; 1476 } 1477} 1478 1479static bool is_surface_in_context( 1480 const struct dc_state *context, 1481 const struct dc_plane_state *plane_state) 1482{ 1483 int j; 1484 1485 for (j = 0; j < MAX_PIPES; j++) { 1486 const struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 1487 1488 if (plane_state == pipe_ctx->plane_state) { 1489 return true; 1490 } 1491 } 1492 1493 return false; 1494} 1495 1496static enum surface_update_type get_plane_info_update_type(const struct dc_surface_update *u) 1497{ 1498 union surface_update_flags *update_flags = &u->surface->update_flags; 1499 enum surface_update_type update_type = UPDATE_TYPE_FAST; 1500 1501 if (!u->plane_info) 1502 return UPDATE_TYPE_FAST; 1503 1504 if (u->plane_info->color_space != u->surface->color_space) { 1505 update_flags->bits.color_space_change = 1; 1506 elevate_update_type(&update_type, UPDATE_TYPE_MED); 1507 } 1508 1509 if (u->plane_info->horizontal_mirror != u->surface->horizontal_mirror) { 1510 update_flags->bits.horizontal_mirror_change = 1; 1511 elevate_update_type(&update_type, UPDATE_TYPE_MED); 1512 } 1513 1514 if (u->plane_info->rotation != u->surface->rotation) { 1515 update_flags->bits.rotation_change = 1; 1516 elevate_update_type(&update_type, UPDATE_TYPE_FULL); 1517 } 1518 1519 if (u->plane_info->format != u->surface->format) { 1520 update_flags->bits.pixel_format_change = 1; 1521 elevate_update_type(&update_type, UPDATE_TYPE_FULL); 1522 } 1523 1524 if (u->plane_info->stereo_format != u->surface->stereo_format) { 1525 update_flags->bits.stereo_format_change = 1; 1526 elevate_update_type(&update_type, UPDATE_TYPE_FULL); 1527 } 1528 1529 if (u->plane_info->per_pixel_alpha != u->surface->per_pixel_alpha) { 1530 update_flags->bits.per_pixel_alpha_change = 1; 1531 elevate_update_type(&update_type, UPDATE_TYPE_MED); 1532 } 1533 1534 if (u->plane_info->global_alpha_value != u->surface->global_alpha_value) { 1535 update_flags->bits.global_alpha_change = 1; 1536 elevate_update_type(&update_type, UPDATE_TYPE_MED); 1537 } 1538 1539 if (u->plane_info->dcc.enable != u->surface->dcc.enable 1540 || u->plane_info->dcc.independent_64b_blks != u->surface->dcc.independent_64b_blks 1541 || u->plane_info->dcc.meta_pitch != u->surface->dcc.meta_pitch) { 1542 update_flags->bits.dcc_change = 1; 1543 elevate_update_type(&update_type, UPDATE_TYPE_MED); 1544 } 1545 1546 if (resource_pixel_format_to_bpp(u->plane_info->format) != 1547 resource_pixel_format_to_bpp(u->surface->format)) { 1548 /* different bytes per element will require full bandwidth 1549 * and DML calculation 1550 */ 1551 update_flags->bits.bpp_change = 1; 1552 elevate_update_type(&update_type, UPDATE_TYPE_FULL); 1553 } 1554 1555 if (u->plane_info->plane_size.surface_pitch != u->surface->plane_size.surface_pitch 1556 || u->plane_info->plane_size.chroma_pitch != u->surface->plane_size.chroma_pitch) { 1557 update_flags->bits.plane_size_change = 1; 1558 elevate_update_type(&update_type, UPDATE_TYPE_MED); 1559 } 1560 1561 1562 if (memcmp(&u->plane_info->tiling_info, &u->surface->tiling_info, 1563 sizeof(union dc_tiling_info)) != 0) { 1564 update_flags->bits.swizzle_change = 1; 1565 elevate_update_type(&update_type, UPDATE_TYPE_MED); 1566 1567 /* todo: below are HW dependent, we should add a hook to 1568 * DCE/N resource and validated there. 1569 */ 1570 if (u->plane_info->tiling_info.gfx9.swizzle != DC_SW_LINEAR) { 1571 /* swizzled mode requires RQ to be setup properly, 1572 * thus need to run DML to calculate RQ settings 1573 */ 1574 update_flags->bits.bandwidth_change = 1; 1575 elevate_update_type(&update_type, UPDATE_TYPE_FULL); 1576 } 1577 } 1578 1579 /* This should be UPDATE_TYPE_FAST if nothing has changed. */ 1580 return update_type; 1581} 1582 1583static enum surface_update_type get_scaling_info_update_type( 1584 const struct dc_surface_update *u) 1585{ 1586 union surface_update_flags *update_flags = &u->surface->update_flags; 1587 1588 if (!u->scaling_info) 1589 return UPDATE_TYPE_FAST; 1590 1591 if (u->scaling_info->clip_rect.width != u->surface->clip_rect.width 1592 || u->scaling_info->clip_rect.height != u->surface->clip_rect.height 1593 || u->scaling_info->dst_rect.width != u->surface->dst_rect.width 1594 || u->scaling_info->dst_rect.height != u->surface->dst_rect.height 1595 || u->scaling_info->scaling_quality.integer_scaling != 1596 u->surface->scaling_quality.integer_scaling 1597 ) { 1598 update_flags->bits.scaling_change = 1; 1599 1600 if ((u->scaling_info->dst_rect.width < u->surface->dst_rect.width 1601 || u->scaling_info->dst_rect.height < u->surface->dst_rect.height) 1602 && (u->scaling_info->dst_rect.width < u->surface->src_rect.width 1603 || u->scaling_info->dst_rect.height < u->surface->src_rect.height)) 1604 /* Making dst rect smaller requires a bandwidth change */ 1605 update_flags->bits.bandwidth_change = 1; 1606 } 1607 1608 if (u->scaling_info->src_rect.width != u->surface->src_rect.width 1609 || u->scaling_info->src_rect.height != u->surface->src_rect.height) { 1610 1611 update_flags->bits.scaling_change = 1; 1612 if (u->scaling_info->src_rect.width > u->surface->src_rect.width 1613 || u->scaling_info->src_rect.height > u->surface->src_rect.height) 1614 /* Making src rect bigger requires a bandwidth change */ 1615 update_flags->bits.clock_change = 1; 1616 } 1617 1618 if (u->scaling_info->src_rect.x != u->surface->src_rect.x 1619 || u->scaling_info->src_rect.y != u->surface->src_rect.y 1620 || u->scaling_info->clip_rect.x != u->surface->clip_rect.x 1621 || u->scaling_info->clip_rect.y != u->surface->clip_rect.y 1622 || u->scaling_info->dst_rect.x != u->surface->dst_rect.x 1623 || u->scaling_info->dst_rect.y != u->surface->dst_rect.y) 1624 update_flags->bits.position_change = 1; 1625 1626 if (update_flags->bits.clock_change 1627 || update_flags->bits.bandwidth_change 1628 || update_flags->bits.scaling_change) 1629 return UPDATE_TYPE_FULL; 1630 1631 if (update_flags->bits.position_change) 1632 return UPDATE_TYPE_MED; 1633 1634 return UPDATE_TYPE_FAST; 1635} 1636 1637static enum surface_update_type det_surface_update(const struct dc *dc, 1638 const struct dc_surface_update *u) 1639{ 1640 const struct dc_state *context = dc->current_state; 1641 enum surface_update_type type; 1642 enum surface_update_type overall_type = UPDATE_TYPE_FAST; 1643 union surface_update_flags *update_flags = &u->surface->update_flags; 1644 1645 if (u->flip_addr) 1646 update_flags->bits.addr_update = 1; 1647 1648 if (!is_surface_in_context(context, u->surface) || u->surface->force_full_update) { 1649 update_flags->raw = 0xFFFFFFFF; 1650 return UPDATE_TYPE_FULL; 1651 } 1652 1653 update_flags->raw = 0; // Reset all flags 1654 1655 type = get_plane_info_update_type(u); 1656 elevate_update_type(&overall_type, type); 1657 1658 type = get_scaling_info_update_type(u); 1659 elevate_update_type(&overall_type, type); 1660 1661 if (u->flip_addr) 1662 update_flags->bits.addr_update = 1; 1663 1664 if (u->in_transfer_func) 1665 update_flags->bits.in_transfer_func_change = 1; 1666 1667 if (u->input_csc_color_matrix) 1668 update_flags->bits.input_csc_change = 1; 1669 1670 if (u->coeff_reduction_factor) 1671 update_flags->bits.coeff_reduction_change = 1; 1672 1673 if (u->gamma) { 1674 enum surface_pixel_format format = SURFACE_PIXEL_FORMAT_GRPH_BEGIN; 1675 1676 if (u->plane_info) 1677 format = u->plane_info->format; 1678 else if (u->surface) 1679 format = u->surface->format; 1680 1681 if (dce_use_lut(format)) 1682 update_flags->bits.gamma_change = 1; 1683 } 1684 1685 if (u->hdr_mult.value) 1686 if (u->hdr_mult.value != u->surface->hdr_mult.value) { 1687 update_flags->bits.hdr_mult = 1; 1688 elevate_update_type(&overall_type, UPDATE_TYPE_MED); 1689 } 1690 1691 if (update_flags->bits.in_transfer_func_change) { 1692 type = UPDATE_TYPE_MED; 1693 elevate_update_type(&overall_type, type); 1694 } 1695 1696 if (update_flags->bits.input_csc_change 1697 || update_flags->bits.coeff_reduction_change 1698 || update_flags->bits.gamma_change) { 1699 type = UPDATE_TYPE_FULL; 1700 elevate_update_type(&overall_type, type); 1701 } 1702 1703 return overall_type; 1704} 1705 1706static enum surface_update_type check_update_surfaces_for_stream( 1707 struct dc *dc, 1708 struct dc_surface_update *updates, 1709 int surface_count, 1710 struct dc_stream_update *stream_update, 1711 const struct dc_stream_status *stream_status) 1712{ 1713 int i; 1714 enum surface_update_type overall_type = UPDATE_TYPE_FAST; 1715 1716 if (stream_status == NULL || stream_status->plane_count != surface_count) 1717 overall_type = UPDATE_TYPE_FULL; 1718 1719 /* some stream updates require passive update */ 1720 if (stream_update) { 1721 union stream_update_flags *su_flags = &stream_update->stream->update_flags; 1722 1723 if ((stream_update->src.height != 0 && stream_update->src.width != 0) || 1724 (stream_update->dst.height != 0 && stream_update->dst.width != 0) || 1725 stream_update->integer_scaling_update) 1726 su_flags->bits.scaling = 1; 1727 1728 if (stream_update->out_transfer_func) 1729 su_flags->bits.out_tf = 1; 1730 1731 if (stream_update->abm_level) 1732 su_flags->bits.abm_level = 1; 1733 1734 if (stream_update->dpms_off) 1735 su_flags->bits.dpms_off = 1; 1736 1737 if (stream_update->gamut_remap) 1738 su_flags->bits.gamut_remap = 1; 1739 1740 if (stream_update->wb_update) 1741 su_flags->bits.wb_update = 1; 1742 if (su_flags->raw != 0) 1743 overall_type = UPDATE_TYPE_FULL; 1744 1745 if (stream_update->output_csc_transform || stream_update->output_color_space) 1746 su_flags->bits.out_csc = 1; 1747 1748 if (stream_update->dsc_config) 1749 overall_type = UPDATE_TYPE_FULL; 1750 } 1751 1752 for (i = 0 ; i < surface_count; i++) { 1753 enum surface_update_type type = 1754 det_surface_update(dc, &updates[i]); 1755 1756 elevate_update_type(&overall_type, type); 1757 } 1758 1759 return overall_type; 1760} 1761 1762/** 1763 * dc_check_update_surfaces_for_stream() - Determine update type (fast, med, or full) 1764 * 1765 * See :c:type:`enum surface_update_type <surface_update_type>` for explanation of update types 1766 */ 1767enum surface_update_type dc_check_update_surfaces_for_stream( 1768 struct dc *dc, 1769 struct dc_surface_update *updates, 1770 int surface_count, 1771 struct dc_stream_update *stream_update, 1772 const struct dc_stream_status *stream_status) 1773{ 1774 int i; 1775 enum surface_update_type type; 1776 1777 if (stream_update) 1778 stream_update->stream->update_flags.raw = 0; 1779 for (i = 0; i < surface_count; i++) 1780 updates[i].surface->update_flags.raw = 0; 1781 1782 type = check_update_surfaces_for_stream(dc, updates, surface_count, stream_update, stream_status); 1783 if (type == UPDATE_TYPE_FULL) { 1784 if (stream_update) 1785 stream_update->stream->update_flags.raw = 0xFFFFFFFF; 1786 for (i = 0; i < surface_count; i++) 1787 updates[i].surface->update_flags.raw = 0xFFFFFFFF; 1788 } 1789 1790 if (type == UPDATE_TYPE_FAST) { 1791 // If there's an available clock comparator, we use that. 1792 if (dc->clk_mgr->funcs->are_clock_states_equal) { 1793 if (!dc->clk_mgr->funcs->are_clock_states_equal(&dc->clk_mgr->clks, &dc->current_state->bw_ctx.bw.dcn.clk)) 1794 dc->optimized_required = true; 1795 // Else we fallback to mem compare. 1796 } else if (memcmp(&dc->current_state->bw_ctx.bw.dcn.clk, &dc->clk_mgr->clks, offsetof(struct dc_clocks, prev_p_state_change_support)) != 0) { 1797 dc->optimized_required = true; 1798 } 1799 } 1800 1801 return type; 1802} 1803 1804static struct dc_stream_status *stream_get_status( 1805 struct dc_state *ctx, 1806 struct dc_stream_state *stream) 1807{ 1808 uint8_t i; 1809 1810 for (i = 0; i < ctx->stream_count; i++) { 1811 if (stream == ctx->streams[i]) { 1812 return &ctx->stream_status[i]; 1813 } 1814 } 1815 1816 return NULL; 1817} 1818 1819static const enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; 1820 1821static void copy_surface_update_to_plane( 1822 struct dc_plane_state *surface, 1823 struct dc_surface_update *srf_update) 1824{ 1825 if (srf_update->flip_addr) { 1826 surface->address = srf_update->flip_addr->address; 1827 surface->flip_immediate = 1828 srf_update->flip_addr->flip_immediate; 1829 surface->time.time_elapsed_in_us[surface->time.index] = 1830 srf_update->flip_addr->flip_timestamp_in_us - 1831 surface->time.prev_update_time_in_us; 1832 surface->time.prev_update_time_in_us = 1833 srf_update->flip_addr->flip_timestamp_in_us; 1834 surface->time.index++; 1835 if (surface->time.index >= DC_PLANE_UPDATE_TIMES_MAX) 1836 surface->time.index = 0; 1837 } 1838 1839 if (srf_update->scaling_info) { 1840 surface->scaling_quality = 1841 srf_update->scaling_info->scaling_quality; 1842 surface->dst_rect = 1843 srf_update->scaling_info->dst_rect; 1844 surface->src_rect = 1845 srf_update->scaling_info->src_rect; 1846 surface->clip_rect = 1847 srf_update->scaling_info->clip_rect; 1848 } 1849 1850 if (srf_update->plane_info) { 1851 surface->color_space = 1852 srf_update->plane_info->color_space; 1853 surface->format = 1854 srf_update->plane_info->format; 1855 surface->plane_size = 1856 srf_update->plane_info->plane_size; 1857 surface->rotation = 1858 srf_update->plane_info->rotation; 1859 surface->horizontal_mirror = 1860 srf_update->plane_info->horizontal_mirror; 1861 surface->stereo_format = 1862 srf_update->plane_info->stereo_format; 1863 surface->tiling_info = 1864 srf_update->plane_info->tiling_info; 1865 surface->visible = 1866 srf_update->plane_info->visible; 1867 surface->per_pixel_alpha = 1868 srf_update->plane_info->per_pixel_alpha; 1869 surface->global_alpha = 1870 srf_update->plane_info->global_alpha; 1871 surface->global_alpha_value = 1872 srf_update->plane_info->global_alpha_value; 1873 surface->dcc = 1874 srf_update->plane_info->dcc; 1875 surface->layer_index = 1876 srf_update->plane_info->layer_index; 1877 } 1878 1879 if (srf_update->gamma && 1880 (surface->gamma_correction != 1881 srf_update->gamma)) { 1882 memcpy(&surface->gamma_correction->entries, 1883 &srf_update->gamma->entries, 1884 sizeof(struct dc_gamma_entries)); 1885 surface->gamma_correction->is_identity = 1886 srf_update->gamma->is_identity; 1887 surface->gamma_correction->num_entries = 1888 srf_update->gamma->num_entries; 1889 surface->gamma_correction->type = 1890 srf_update->gamma->type; 1891 } 1892 1893 if (srf_update->in_transfer_func && 1894 (surface->in_transfer_func != 1895 srf_update->in_transfer_func)) { 1896 surface->in_transfer_func->sdr_ref_white_level = 1897 srf_update->in_transfer_func->sdr_ref_white_level; 1898 surface->in_transfer_func->tf = 1899 srf_update->in_transfer_func->tf; 1900 surface->in_transfer_func->type = 1901 srf_update->in_transfer_func->type; 1902 memcpy(&surface->in_transfer_func->tf_pts, 1903 &srf_update->in_transfer_func->tf_pts, 1904 sizeof(struct dc_transfer_func_distributed_points)); 1905 } 1906 1907 if (srf_update->func_shaper && 1908 (surface->in_shaper_func != 1909 srf_update->func_shaper)) 1910 memcpy(surface->in_shaper_func, srf_update->func_shaper, 1911 sizeof(*surface->in_shaper_func)); 1912 1913 if (srf_update->lut3d_func && 1914 (surface->lut3d_func != 1915 srf_update->lut3d_func)) 1916 memcpy(surface->lut3d_func, srf_update->lut3d_func, 1917 sizeof(*surface->lut3d_func)); 1918 1919 if (srf_update->hdr_mult.value) 1920 surface->hdr_mult = 1921 srf_update->hdr_mult; 1922 1923 if (srf_update->blend_tf && 1924 (surface->blend_tf != 1925 srf_update->blend_tf)) 1926 memcpy(surface->blend_tf, srf_update->blend_tf, 1927 sizeof(*surface->blend_tf)); 1928 1929 if (srf_update->input_csc_color_matrix) 1930 surface->input_csc_color_matrix = 1931 *srf_update->input_csc_color_matrix; 1932 1933 if (srf_update->coeff_reduction_factor) 1934 surface->coeff_reduction_factor = 1935 *srf_update->coeff_reduction_factor; 1936} 1937 1938static void copy_stream_update_to_stream(struct dc *dc, 1939 struct dc_state *context, 1940 struct dc_stream_state *stream, 1941 struct dc_stream_update *update) 1942{ 1943 struct dc_context *dc_ctx = dc->ctx; 1944 1945 if (update == NULL || stream == NULL) 1946 return; 1947 1948 if (update->src.height && update->src.width) 1949 stream->src = update->src; 1950 1951 if (update->dst.height && update->dst.width) 1952 stream->dst = update->dst; 1953 1954 if (update->out_transfer_func && 1955 stream->out_transfer_func != update->out_transfer_func) { 1956 stream->out_transfer_func->sdr_ref_white_level = 1957 update->out_transfer_func->sdr_ref_white_level; 1958 stream->out_transfer_func->tf = update->out_transfer_func->tf; 1959 stream->out_transfer_func->type = 1960 update->out_transfer_func->type; 1961 memcpy(&stream->out_transfer_func->tf_pts, 1962 &update->out_transfer_func->tf_pts, 1963 sizeof(struct dc_transfer_func_distributed_points)); 1964 } 1965 1966 if (update->hdr_static_metadata) 1967 stream->hdr_static_metadata = *update->hdr_static_metadata; 1968 1969 if (update->abm_level) 1970 stream->abm_level = *update->abm_level; 1971 1972 if (update->periodic_interrupt0) 1973 stream->periodic_interrupt0 = *update->periodic_interrupt0; 1974 1975 if (update->periodic_interrupt1) 1976 stream->periodic_interrupt1 = *update->periodic_interrupt1; 1977 1978 if (update->gamut_remap) 1979 stream->gamut_remap_matrix = *update->gamut_remap; 1980 1981 /* Note: this being updated after mode set is currently not a use case 1982 * however if it arises OCSC would need to be reprogrammed at the 1983 * minimum 1984 */ 1985 if (update->output_color_space) 1986 stream->output_color_space = *update->output_color_space; 1987 1988 if (update->output_csc_transform) 1989 stream->csc_color_matrix = *update->output_csc_transform; 1990 1991 if (update->vrr_infopacket) 1992 stream->vrr_infopacket = *update->vrr_infopacket; 1993 1994 if (update->dpms_off) 1995 stream->dpms_off = *update->dpms_off; 1996 1997 if (update->vsc_infopacket) 1998 stream->vsc_infopacket = *update->vsc_infopacket; 1999 2000 if (update->vsp_infopacket) 2001 stream->vsp_infopacket = *update->vsp_infopacket; 2002 2003 if (update->dither_option) 2004 stream->dither_option = *update->dither_option; 2005 /* update current stream with writeback info */ 2006 if (update->wb_update) { 2007 int i; 2008 2009 stream->num_wb_info = update->wb_update->num_wb_info; 2010 ASSERT(stream->num_wb_info <= MAX_DWB_PIPES); 2011 for (i = 0; i < stream->num_wb_info; i++) 2012 stream->writeback_info[i] = 2013 update->wb_update->writeback_info[i]; 2014 } 2015 if (update->dsc_config) { 2016 struct dc_dsc_config old_dsc_cfg = stream->timing.dsc_cfg; 2017 uint32_t old_dsc_enabled = stream->timing.flags.DSC; 2018 uint32_t enable_dsc = (update->dsc_config->num_slices_h != 0 && 2019 update->dsc_config->num_slices_v != 0); 2020 2021 /* Use temporarry context for validating new DSC config */ 2022 struct dc_state *dsc_validate_context = dc_create_state(dc); 2023 2024 if (dsc_validate_context) { 2025 dc_resource_state_copy_construct(dc->current_state, dsc_validate_context); 2026 2027 stream->timing.dsc_cfg = *update->dsc_config; 2028 stream->timing.flags.DSC = enable_dsc; 2029 if (!dc->res_pool->funcs->validate_bandwidth(dc, dsc_validate_context, true)) { 2030 stream->timing.dsc_cfg = old_dsc_cfg; 2031 stream->timing.flags.DSC = old_dsc_enabled; 2032 update->dsc_config = NULL; 2033 } 2034 2035 dc_release_state(dsc_validate_context); 2036 } else { 2037 DC_ERROR("Failed to allocate new validate context for DSC change\n"); 2038 update->dsc_config = NULL; 2039 } 2040 } 2041} 2042 2043static void commit_planes_do_stream_update(struct dc *dc, 2044 struct dc_stream_state *stream, 2045 struct dc_stream_update *stream_update, 2046 enum surface_update_type update_type, 2047 struct dc_state *context) 2048{ 2049 int j; 2050 bool should_program_abm; 2051 2052 // Stream updates 2053 for (j = 0; j < dc->res_pool->pipe_count; j++) { 2054 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 2055 2056 if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->stream == stream) { 2057 2058 if (stream_update->periodic_interrupt0 && 2059 dc->hwss.setup_periodic_interrupt) 2060 dc->hwss.setup_periodic_interrupt(dc, pipe_ctx, VLINE0); 2061 2062 if (stream_update->periodic_interrupt1 && 2063 dc->hwss.setup_periodic_interrupt) 2064 dc->hwss.setup_periodic_interrupt(dc, pipe_ctx, VLINE1); 2065 2066 if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) || 2067 stream_update->vrr_infopacket || 2068 stream_update->vsc_infopacket || 2069 stream_update->vsp_infopacket) { 2070 resource_build_info_frame(pipe_ctx); 2071 dc->hwss.update_info_frame(pipe_ctx); 2072 } 2073 2074 if (stream_update->hdr_static_metadata && 2075 stream->use_dynamic_meta && 2076 dc->hwss.set_dmdata_attributes && 2077 pipe_ctx->stream->dmdata_address.quad_part != 0) 2078 dc->hwss.set_dmdata_attributes(pipe_ctx); 2079 2080 if (stream_update->gamut_remap) 2081 dc_stream_set_gamut_remap(dc, stream); 2082 2083 if (stream_update->output_csc_transform) 2084 dc_stream_program_csc_matrix(dc, stream); 2085 2086 if (stream_update->dither_option) { 2087 struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe; 2088 resource_build_bit_depth_reduction_params(pipe_ctx->stream, 2089 &pipe_ctx->stream->bit_depth_params); 2090 pipe_ctx->stream_res.opp->funcs->opp_program_fmt(pipe_ctx->stream_res.opp, 2091 &stream->bit_depth_params, 2092 &stream->clamping); 2093 while (odm_pipe) { 2094 odm_pipe->stream_res.opp->funcs->opp_program_fmt(odm_pipe->stream_res.opp, 2095 &stream->bit_depth_params, 2096 &stream->clamping); 2097 odm_pipe = odm_pipe->next_odm_pipe; 2098 } 2099 } 2100 2101 if (stream_update->dsc_config && dc->hwss.pipe_control_lock_global) { 2102 dc->hwss.pipe_control_lock_global(dc, pipe_ctx, true); 2103 dp_update_dsc_config(pipe_ctx); 2104 dc->hwss.pipe_control_lock_global(dc, pipe_ctx, false); 2105 } 2106 /* Full fe update*/ 2107 if (update_type == UPDATE_TYPE_FAST) 2108 continue; 2109 2110 if (stream_update->dpms_off) { 2111 dc->hwss.pipe_control_lock(dc, pipe_ctx, true); 2112 2113 if (*stream_update->dpms_off) { 2114 core_link_disable_stream(pipe_ctx); 2115 /* for dpms, keep acquired resources*/ 2116 if (pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only) 2117 pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); 2118 2119 dc->hwss.optimize_bandwidth(dc, dc->current_state); 2120 } else { 2121 if (dc->optimize_seamless_boot_streams == 0) 2122 dc->hwss.prepare_bandwidth(dc, dc->current_state); 2123 2124 core_link_enable_stream(dc->current_state, pipe_ctx); 2125 } 2126 2127 dc->hwss.pipe_control_lock(dc, pipe_ctx, false); 2128 } 2129 2130 if (stream_update->abm_level && pipe_ctx->stream_res.abm) { 2131 should_program_abm = true; 2132 2133 // if otg funcs defined check if blanked before programming 2134 if (pipe_ctx->stream_res.tg->funcs->is_blanked) 2135 if (pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg)) 2136 should_program_abm = false; 2137 2138 if (should_program_abm) { 2139 if (*stream_update->abm_level == ABM_LEVEL_IMMEDIATE_DISABLE) { 2140 pipe_ctx->stream_res.abm->funcs->set_abm_immediate_disable(pipe_ctx->stream_res.abm); 2141 } else { 2142 pipe_ctx->stream_res.abm->funcs->set_abm_level( 2143 pipe_ctx->stream_res.abm, stream->abm_level); 2144 } 2145 } 2146 } 2147 } 2148 } 2149} 2150 2151static void commit_planes_for_stream(struct dc *dc, 2152 struct dc_surface_update *srf_updates, 2153 int surface_count, 2154 struct dc_stream_state *stream, 2155 struct dc_stream_update *stream_update, 2156 enum surface_update_type update_type, 2157 struct dc_state *context) 2158{ 2159 int i, j; 2160 struct pipe_ctx *top_pipe_to_program = NULL; 2161 2162 if (dc->optimize_seamless_boot_streams > 0 && surface_count > 0) { 2163 /* Optimize seamless boot flag keeps clocks and watermarks high until 2164 * first flip. After first flip, optimization is required to lower 2165 * bandwidth. Important to note that it is expected UEFI will 2166 * only light up a single display on POST, therefore we only expect 2167 * one stream with seamless boot flag set. 2168 */ 2169 if (stream->apply_seamless_boot_optimization) { 2170 stream->apply_seamless_boot_optimization = false; 2171 dc->optimize_seamless_boot_streams--; 2172 2173 if (dc->optimize_seamless_boot_streams == 0) 2174 dc->optimized_required = true; 2175 } 2176 } 2177 2178 if (update_type == UPDATE_TYPE_FULL && dc->optimize_seamless_boot_streams == 0) { 2179 dc->hwss.prepare_bandwidth(dc, context); 2180 context_clock_trace(dc, context); 2181 } 2182 2183 // Stream updates 2184 if (stream_update) 2185 commit_planes_do_stream_update(dc, stream, stream_update, update_type, context); 2186 2187 if (surface_count == 0) { 2188 /* 2189 * In case of turning off screen, no need to program front end a second time. 2190 * just return after program blank. 2191 */ 2192 if (dc->hwss.apply_ctx_for_surface) 2193 dc->hwss.apply_ctx_for_surface(dc, stream, 0, context); 2194 if (dc->hwss.program_front_end_for_ctx) 2195 dc->hwss.program_front_end_for_ctx(dc, context); 2196 2197 return; 2198 } 2199 2200 if (!IS_DIAG_DC(dc->ctx->dce_environment)) { 2201 for (i = 0; i < surface_count; i++) { 2202 struct dc_plane_state *plane_state = srf_updates[i].surface; 2203 /*set logical flag for lock/unlock use*/ 2204 for (j = 0; j < dc->res_pool->pipe_count; j++) { 2205 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 2206 if (!pipe_ctx->plane_state) 2207 continue; 2208 if (pipe_ctx->plane_state != plane_state) 2209 continue; 2210 plane_state->triplebuffer_flips = false; 2211 if (update_type == UPDATE_TYPE_FAST && 2212 dc->hwss.program_triplebuffer != NULL && 2213 !plane_state->flip_immediate && 2214 !dc->debug.disable_tri_buf) { 2215 /*triple buffer for VUpdate only*/ 2216 plane_state->triplebuffer_flips = true; 2217 } 2218 } 2219 } 2220 } 2221 2222 // Update Type FULL, Surface updates 2223 for (j = 0; j < dc->res_pool->pipe_count; j++) { 2224 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 2225 2226 if (!pipe_ctx->top_pipe && 2227 !pipe_ctx->prev_odm_pipe && 2228 pipe_ctx->stream && 2229 pipe_ctx->stream == stream) { 2230 struct dc_stream_status *stream_status = NULL; 2231 2232 top_pipe_to_program = pipe_ctx; 2233 2234 if (!pipe_ctx->plane_state) 2235 continue; 2236 2237 /* Full fe update*/ 2238 if (update_type == UPDATE_TYPE_FAST) 2239 continue; 2240 2241 ASSERT(!pipe_ctx->plane_state->triplebuffer_flips); 2242 2243 if (dc->hwss.program_triplebuffer != NULL && 2244 !dc->debug.disable_tri_buf) { 2245 /*turn off triple buffer for full update*/ 2246 dc->hwss.program_triplebuffer( 2247 dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips); 2248 } 2249 stream_status = 2250 stream_get_status(context, pipe_ctx->stream); 2251 2252 if (dc->hwss.apply_ctx_for_surface) 2253 dc->hwss.apply_ctx_for_surface( 2254 dc, pipe_ctx->stream, stream_status->plane_count, context); 2255 } 2256 } 2257 if (dc->hwss.program_front_end_for_ctx && update_type != UPDATE_TYPE_FAST) { 2258 dc->hwss.program_front_end_for_ctx(dc, context); 2259#ifdef CONFIG_DRM_AMD_DC_DCN 2260 if (dc->debug.validate_dml_output) { 2261 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2262 struct pipe_ctx cur_pipe = context->res_ctx.pipe_ctx[i]; 2263 if (cur_pipe.stream == NULL) 2264 continue; 2265 2266 cur_pipe.plane_res.hubp->funcs->validate_dml_output( 2267 cur_pipe.plane_res.hubp, dc->ctx, 2268 &context->res_ctx.pipe_ctx[i].rq_regs, 2269 &context->res_ctx.pipe_ctx[i].dlg_regs, 2270 &context->res_ctx.pipe_ctx[i].ttu_regs); 2271 } 2272 } 2273#endif 2274 } 2275 2276 // Update Type FAST, Surface updates 2277 if (update_type == UPDATE_TYPE_FAST) { 2278 /* Lock the top pipe while updating plane addrs, since freesync requires 2279 * plane addr update event triggers to be synchronized. 2280 * top_pipe_to_program is expected to never be NULL 2281 */ 2282 dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true); 2283 2284 if (dc->hwss.set_flip_control_gsl) 2285 for (i = 0; i < surface_count; i++) { 2286 struct dc_plane_state *plane_state = srf_updates[i].surface; 2287 2288 for (j = 0; j < dc->res_pool->pipe_count; j++) { 2289 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 2290 2291 if (pipe_ctx->stream != stream) 2292 continue; 2293 2294 if (pipe_ctx->plane_state != plane_state) 2295 continue; 2296 2297 // GSL has to be used for flip immediate 2298 dc->hwss.set_flip_control_gsl(pipe_ctx, 2299 plane_state->flip_immediate); 2300 } 2301 } 2302 /* Perform requested Updates */ 2303 for (i = 0; i < surface_count; i++) { 2304 struct dc_plane_state *plane_state = srf_updates[i].surface; 2305 2306 for (j = 0; j < dc->res_pool->pipe_count; j++) { 2307 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 2308 2309 if (pipe_ctx->stream != stream) 2310 continue; 2311 2312 if (pipe_ctx->plane_state != plane_state) 2313 continue; 2314 /*program triple buffer after lock based on flip type*/ 2315 if (dc->hwss.program_triplebuffer != NULL && 2316 !dc->debug.disable_tri_buf) { 2317 /*only enable triplebuffer for fast_update*/ 2318 dc->hwss.program_triplebuffer( 2319 dc, pipe_ctx, plane_state->triplebuffer_flips); 2320 } 2321 if (srf_updates[i].flip_addr) 2322 dc->hwss.update_plane_addr(dc, pipe_ctx); 2323 } 2324 } 2325 2326 dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); 2327 } 2328 2329 // Fire manual trigger only when bottom plane is flipped 2330 for (j = 0; j < dc->res_pool->pipe_count; j++) { 2331 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; 2332 2333 if (pipe_ctx->bottom_pipe || 2334 !pipe_ctx->stream || 2335 pipe_ctx->stream != stream || 2336 !pipe_ctx->plane_state->update_flags.bits.addr_update) 2337 continue; 2338 2339 if (pipe_ctx->stream_res.tg->funcs->program_manual_trigger) 2340 pipe_ctx->stream_res.tg->funcs->program_manual_trigger(pipe_ctx->stream_res.tg); 2341 } 2342} 2343 2344void dc_commit_updates_for_stream(struct dc *dc, 2345 struct dc_surface_update *srf_updates, 2346 int surface_count, 2347 struct dc_stream_state *stream, 2348 struct dc_stream_update *stream_update, 2349 struct dc_state *state) 2350{ 2351 const struct dc_stream_status *stream_status; 2352 enum surface_update_type update_type; 2353 struct dc_state *context; 2354 struct dc_context *dc_ctx = dc->ctx; 2355 int i; 2356 2357 stream_status = dc_stream_get_status(stream); 2358 context = dc->current_state; 2359 2360 update_type = dc_check_update_surfaces_for_stream( 2361 dc, srf_updates, surface_count, stream_update, stream_status); 2362 2363 if (update_type >= update_surface_trace_level) 2364 update_surface_trace(dc, srf_updates, surface_count); 2365 2366 2367 if (update_type >= UPDATE_TYPE_FULL) { 2368 2369 /* initialize scratch memory for building context */ 2370 context = dc_create_state(dc); 2371 if (context == NULL) { 2372 DC_ERROR("Failed to allocate new validate context!\n"); 2373 return; 2374 } 2375 2376 dc_resource_state_copy_construct(state, context); 2377 2378 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2379 struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i]; 2380 struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 2381 2382 if (new_pipe->plane_state && new_pipe->plane_state != old_pipe->plane_state) 2383 new_pipe->plane_state->force_full_update = true; 2384 } 2385 } 2386 2387 2388 for (i = 0; i < surface_count; i++) { 2389 struct dc_plane_state *surface = srf_updates[i].surface; 2390 2391 copy_surface_update_to_plane(surface, &srf_updates[i]); 2392 2393 } 2394 2395 copy_stream_update_to_stream(dc, context, stream, stream_update); 2396 2397 commit_planes_for_stream( 2398 dc, 2399 srf_updates, 2400 surface_count, 2401 stream, 2402 stream_update, 2403 update_type, 2404 context); 2405 /*update current_State*/ 2406 if (dc->current_state != context) { 2407 2408 struct dc_state *old = dc->current_state; 2409 2410 dc->current_state = context; 2411 dc_release_state(old); 2412 2413 for (i = 0; i < dc->res_pool->pipe_count; i++) { 2414 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 2415 2416 if (pipe_ctx->plane_state && pipe_ctx->stream == stream) 2417 pipe_ctx->plane_state->force_full_update = false; 2418 } 2419 } 2420 /*let's use current_state to update watermark etc*/ 2421 if (update_type >= UPDATE_TYPE_FULL) 2422 dc_post_update_surfaces_to_stream(dc); 2423 2424 return; 2425 2426} 2427 2428uint8_t dc_get_current_stream_count(struct dc *dc) 2429{ 2430 return dc->current_state->stream_count; 2431} 2432 2433struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i) 2434{ 2435 if (i < dc->current_state->stream_count) 2436 return dc->current_state->streams[i]; 2437 return NULL; 2438} 2439 2440enum dc_irq_source dc_interrupt_to_irq_source( 2441 struct dc *dc, 2442 uint32_t src_id, 2443 uint32_t ext_id) 2444{ 2445 return dal_irq_service_to_irq_source(dc->res_pool->irqs, src_id, ext_id); 2446} 2447 2448/** 2449 * dc_interrupt_set() - Enable/disable an AMD hw interrupt source 2450 */ 2451bool dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable) 2452{ 2453 2454 if (dc == NULL) 2455 return false; 2456 2457 return dal_irq_service_set(dc->res_pool->irqs, src, enable); 2458} 2459 2460void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src) 2461{ 2462 dal_irq_service_ack(dc->res_pool->irqs, src); 2463} 2464 2465void dc_set_power_state( 2466 struct dc *dc, 2467 enum dc_acpi_cm_power_state power_state) 2468{ 2469 struct kref refcount; 2470 struct display_mode_lib *dml; 2471 2472 switch (power_state) { 2473 case DC_ACPI_CM_POWER_STATE_D0: 2474 dc_resource_state_construct(dc, dc->current_state); 2475 2476 if (dc->ctx->dmub_srv) 2477 dc_dmub_srv_wait_phy_init(dc->ctx->dmub_srv); 2478 2479 dc->hwss.init_hw(dc); 2480 2481 if (dc->hwss.init_sys_ctx != NULL && 2482 dc->vm_pa_config.valid) { 2483 dc->hwss.init_sys_ctx(dc->hwseq, dc, &dc->vm_pa_config); 2484 } 2485 2486 break; 2487 default: 2488 ASSERT(dc->current_state->stream_count == 0); 2489 /* Zero out the current context so that on resume we start with 2490 * clean state, and dc hw programming optimizations will not 2491 * cause any trouble. 2492 */ 2493 dml = kzalloc(sizeof(struct display_mode_lib), 2494 GFP_KERNEL); 2495 2496 ASSERT(dml); 2497 if (!dml) 2498 return; 2499 2500 /* Preserve refcount */ 2501 refcount = dc->current_state->refcount; 2502 /* Preserve display mode lib */ 2503 memcpy(dml, &dc->current_state->bw_ctx.dml, sizeof(struct display_mode_lib)); 2504 2505 dc_resource_state_destruct(dc->current_state); 2506 memset(dc->current_state, 0, 2507 sizeof(*dc->current_state)); 2508 2509 dc->current_state->refcount = refcount; 2510 dc->current_state->bw_ctx.dml = *dml; 2511 2512 kfree(dml); 2513 2514 break; 2515 } 2516} 2517 2518void dc_resume(struct dc *dc) 2519{ 2520 2521 uint32_t i; 2522 2523 for (i = 0; i < dc->link_count; i++) 2524 core_link_resume(dc->links[i]); 2525} 2526 2527unsigned int dc_get_current_backlight_pwm(struct dc *dc) 2528{ 2529 struct abm *abm = dc->res_pool->abm; 2530 2531 if (abm) 2532 return abm->funcs->get_current_backlight(abm); 2533 2534 return 0; 2535} 2536 2537unsigned int dc_get_target_backlight_pwm(struct dc *dc) 2538{ 2539 struct abm *abm = dc->res_pool->abm; 2540 2541 if (abm) 2542 return abm->funcs->get_target_backlight(abm); 2543 2544 return 0; 2545} 2546 2547bool dc_is_dmcu_initialized(struct dc *dc) 2548{ 2549 struct dmcu *dmcu = dc->res_pool->dmcu; 2550 2551 if (dmcu) 2552 return dmcu->funcs->is_dmcu_initialized(dmcu); 2553 return false; 2554} 2555 2556bool dc_submit_i2c( 2557 struct dc *dc, 2558 uint32_t link_index, 2559 struct i2c_command *cmd) 2560{ 2561 2562 struct dc_link *link = dc->links[link_index]; 2563 struct ddc_service *ddc = link->ddc; 2564 return dce_i2c_submit_command( 2565 dc->res_pool, 2566 ddc->ddc_pin, 2567 cmd); 2568} 2569 2570bool dc_submit_i2c_oem( 2571 struct dc *dc, 2572 struct i2c_command *cmd) 2573{ 2574 struct ddc_service *ddc = dc->res_pool->oem_device; 2575 return dce_i2c_submit_command( 2576 dc->res_pool, 2577 ddc->ddc_pin, 2578 cmd); 2579} 2580 2581static bool link_add_remote_sink_helper(struct dc_link *dc_link, struct dc_sink *sink) 2582{ 2583 if (dc_link->sink_count >= MAX_SINKS_PER_LINK) { 2584 BREAK_TO_DEBUGGER(); 2585 return false; 2586 } 2587 2588 dc_sink_retain(sink); 2589 2590 dc_link->remote_sinks[dc_link->sink_count] = sink; 2591 dc_link->sink_count++; 2592 2593 return true; 2594} 2595 2596/** 2597 * dc_link_add_remote_sink() - Create a sink and attach it to an existing link 2598 * 2599 * EDID length is in bytes 2600 */ 2601struct dc_sink *dc_link_add_remote_sink( 2602 struct dc_link *link, 2603 const uint8_t *edid, 2604 int len, 2605 struct dc_sink_init_data *init_data) 2606{ 2607 struct dc_sink *dc_sink; 2608 enum dc_edid_status edid_status; 2609 2610 if (len > DC_MAX_EDID_BUFFER_SIZE) { 2611 dm_error("Max EDID buffer size breached!\n"); 2612 return NULL; 2613 } 2614 2615 if (!init_data) { 2616 BREAK_TO_DEBUGGER(); 2617 return NULL; 2618 } 2619 2620 if (!init_data->link) { 2621 BREAK_TO_DEBUGGER(); 2622 return NULL; 2623 } 2624 2625 dc_sink = dc_sink_create(init_data); 2626 2627 if (!dc_sink) 2628 return NULL; 2629 2630 memmove(dc_sink->dc_edid.raw_edid, edid, len); 2631 dc_sink->dc_edid.length = len; 2632 2633 if (!link_add_remote_sink_helper( 2634 link, 2635 dc_sink)) 2636 goto fail_add_sink; 2637 2638 edid_status = dm_helpers_parse_edid_caps( 2639 link->ctx, 2640 &dc_sink->dc_edid, 2641 &dc_sink->edid_caps); 2642 2643 /* 2644 * Treat device as no EDID device if EDID 2645 * parsing fails 2646 */ 2647 if (edid_status != EDID_OK) { 2648 dc_sink->dc_edid.length = 0; 2649 dm_error("Bad EDID, status%d!\n", edid_status); 2650 } 2651 2652 return dc_sink; 2653 2654fail_add_sink: 2655 dc_sink_release(dc_sink); 2656 return NULL; 2657} 2658 2659/** 2660 * dc_link_remove_remote_sink() - Remove a remote sink from a dc_link 2661 * 2662 * Note that this just removes the struct dc_sink - it doesn't 2663 * program hardware or alter other members of dc_link 2664 */ 2665void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) 2666{ 2667 int i; 2668 2669 if (!link->sink_count) { 2670 BREAK_TO_DEBUGGER(); 2671 return; 2672 } 2673 2674 for (i = 0; i < link->sink_count; i++) { 2675 if (link->remote_sinks[i] == sink) { 2676 dc_sink_release(sink); 2677 link->remote_sinks[i] = NULL; 2678 2679 /* shrink array to remove empty place */ 2680 while (i < link->sink_count - 1) { 2681 link->remote_sinks[i] = link->remote_sinks[i+1]; 2682 i++; 2683 } 2684 link->remote_sinks[i] = NULL; 2685 link->sink_count--; 2686 return; 2687 } 2688 } 2689} 2690 2691void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info) 2692{ 2693 info->displayClock = (unsigned int)state->bw_ctx.bw.dcn.clk.dispclk_khz; 2694 info->engineClock = (unsigned int)state->bw_ctx.bw.dcn.clk.dcfclk_khz; 2695 info->memoryClock = (unsigned int)state->bw_ctx.bw.dcn.clk.dramclk_khz; 2696 info->maxSupportedDppClock = (unsigned int)state->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz; 2697 info->dppClock = (unsigned int)state->bw_ctx.bw.dcn.clk.dppclk_khz; 2698 info->socClock = (unsigned int)state->bw_ctx.bw.dcn.clk.socclk_khz; 2699 info->dcfClockDeepSleep = (unsigned int)state->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz; 2700 info->fClock = (unsigned int)state->bw_ctx.bw.dcn.clk.fclk_khz; 2701 info->phyClock = (unsigned int)state->bw_ctx.bw.dcn.clk.phyclk_khz; 2702} 2703enum dc_status dc_set_clock(struct dc *dc, enum dc_clock_type clock_type, uint32_t clk_khz, uint32_t stepping) 2704{ 2705 if (dc->hwss.set_clock) 2706 return dc->hwss.set_clock(dc, clock_type, clk_khz, stepping); 2707 return DC_ERROR_UNEXPECTED; 2708} 2709void dc_get_clock(struct dc *dc, enum dc_clock_type clock_type, struct dc_clock_config *clock_cfg) 2710{ 2711 if (dc->hwss.get_clock) 2712 dc->hwss.get_clock(dc, clock_type, clock_cfg); 2713} 2714