root/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dcn20_enable_power_gating_plane
  2. dcn20_dccg_init
  3. dcn20_display_init
  4. dcn20_disable_vga
  5. dcn20_program_tripleBuffer
  6. dcn20_init_blank
  7. dcn20_dsc_pg_control
  8. dcn20_dpp_pg_control
  9. dcn20_hubp_pg_control
  10. dcn20_plane_atomic_disable
  11. dcn20_disable_plane
  12. dcn20_enable_stream_timing
  13. dcn20_program_output_csc
  14. dcn20_set_output_transfer_func
  15. dcn20_set_blend_lut
  16. dcn20_set_shaper_3dlut
  17. dcn20_set_input_transfer_func
  18. dcn20_update_odm
  19. dcn20_blank_pixel_data
  20. dcn20_power_on_plane
  21. dcn20_enable_plane
  22. dcn20_program_pipe
  23. dcn20_program_all_pipe_in_tree
  24. dcn20_pipe_control_lock_global
  25. dcn20_pipe_control_lock
  26. dcn20_apply_ctx_for_surface
  27. dcn20_prepare_bandwidth
  28. dcn20_optimize_bandwidth
  29. dcn20_update_bandwidth
  30. dcn20_enable_writeback
  31. dcn20_disable_writeback
  32. dcn20_hwss_wait_for_blank_complete
  33. dcn20_dmdata_status_done
  34. dcn20_disable_stream_gating
  35. dcn20_enable_stream_gating
  36. dcn20_set_dmdata_attributes
  37. dcn20_disable_stream
  38. dcn20_init_vm_ctx
  39. dcn20_init_sys_ctx
  40. patch_address_for_sbs_tb_stereo
  41. dcn20_update_plane_addr
  42. dcn20_unblank_stream
  43. dcn20_setup_vupdate_interrupt
  44. dcn20_reset_back_end_for_pipe
  45. dcn20_reset_hw_ctx_wrap
  46. dcn20_update_mpcc
  47. find_free_gsl_group
  48. dcn20_setup_gsl_group_as_lock
  49. dcn20_set_flip_control_gsl
  50. dcn20_enable_stream
  51. dcn20_program_dmdata_engine
  52. dcn20_fpga_init_hw
  53. dcn20_hw_sequencer_construct

   1 /*
   2  * Copyright 2016 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 <linux/delay.h>
  26 
  27 #include "dm_services.h"
  28 #include "dm_helpers.h"
  29 #include "core_types.h"
  30 #include "resource.h"
  31 #include "dcn20/dcn20_resource.h"
  32 #include "dce110/dce110_hw_sequencer.h"
  33 #include "dcn10/dcn10_hw_sequencer.h"
  34 #include "dcn20_hwseq.h"
  35 #include "dce/dce_hwseq.h"
  36 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
  37 #include "dcn20/dcn20_dsc.h"
  38 #endif
  39 #include "abm.h"
  40 #include "clk_mgr.h"
  41 #include "dmcu.h"
  42 #include "hubp.h"
  43 #include "timing_generator.h"
  44 #include "opp.h"
  45 #include "ipp.h"
  46 #include "mpc.h"
  47 #include "mcif_wb.h"
  48 #include "reg_helper.h"
  49 #include "dcn10/dcn10_cm_common.h"
  50 #include "dcn10/dcn10_hubbub.h"
  51 #include "dcn10/dcn10_optc.h"
  52 #include "dc_link_dp.h"
  53 #include "vm_helper.h"
  54 #include "dccg.h"
  55 
  56 #define DC_LOGGER_INIT(logger)
  57 
  58 #define CTX \
  59         hws->ctx
  60 #define REG(reg)\
  61         hws->regs->reg
  62 
  63 #undef FN
  64 #define FN(reg_name, field_name) \
  65         hws->shifts->field_name, hws->masks->field_name
  66 
  67 static void dcn20_enable_power_gating_plane(
  68         struct dce_hwseq *hws,
  69         bool enable)
  70 {
  71         bool force_on = 1; /* disable power gating */
  72 
  73         if (enable)
  74                 force_on = 0;
  75 
  76         /* DCHUBP0/1/2/3/4/5 */
  77         REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on);
  78         REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on);
  79         REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on);
  80         REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on);
  81         if (REG(DOMAIN8_PG_CONFIG))
  82                 REG_UPDATE(DOMAIN8_PG_CONFIG, DOMAIN8_POWER_FORCEON, force_on);
  83         if (REG(DOMAIN10_PG_CONFIG))
  84                 REG_UPDATE(DOMAIN10_PG_CONFIG, DOMAIN8_POWER_FORCEON, force_on);
  85 
  86         /* DPP0/1/2/3/4/5 */
  87         REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on);
  88         REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on);
  89         REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on);
  90         REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on);
  91         if (REG(DOMAIN9_PG_CONFIG))
  92                 REG_UPDATE(DOMAIN9_PG_CONFIG, DOMAIN9_POWER_FORCEON, force_on);
  93         if (REG(DOMAIN11_PG_CONFIG))
  94                 REG_UPDATE(DOMAIN11_PG_CONFIG, DOMAIN9_POWER_FORCEON, force_on);
  95 
  96         /* DCS0/1/2/3/4/5 */
  97         REG_UPDATE(DOMAIN16_PG_CONFIG, DOMAIN16_POWER_FORCEON, force_on);
  98         REG_UPDATE(DOMAIN17_PG_CONFIG, DOMAIN17_POWER_FORCEON, force_on);
  99         REG_UPDATE(DOMAIN18_PG_CONFIG, DOMAIN18_POWER_FORCEON, force_on);
 100         if (REG(DOMAIN19_PG_CONFIG))
 101                 REG_UPDATE(DOMAIN19_PG_CONFIG, DOMAIN19_POWER_FORCEON, force_on);
 102         if (REG(DOMAIN20_PG_CONFIG))
 103                 REG_UPDATE(DOMAIN20_PG_CONFIG, DOMAIN20_POWER_FORCEON, force_on);
 104         if (REG(DOMAIN21_PG_CONFIG))
 105                 REG_UPDATE(DOMAIN21_PG_CONFIG, DOMAIN21_POWER_FORCEON, force_on);
 106 }
 107 
 108 void dcn20_dccg_init(struct dce_hwseq *hws)
 109 {
 110         /*
 111          * set MICROSECOND_TIME_BASE_DIV
 112          * 100Mhz refclk -> 0x120264
 113          * 27Mhz refclk -> 0x12021b
 114          * 48Mhz refclk -> 0x120230
 115          *
 116          */
 117         REG_WRITE(MICROSECOND_TIME_BASE_DIV, 0x120264);
 118 
 119         /*
 120          * set MILLISECOND_TIME_BASE_DIV
 121          * 100Mhz refclk -> 0x1186a0
 122          * 27Mhz refclk -> 0x106978
 123          * 48Mhz refclk -> 0x10bb80
 124          *
 125          */
 126         REG_WRITE(MILLISECOND_TIME_BASE_DIV, 0x1186a0);
 127 
 128         /* This value is dependent on the hardware pipeline delay so set once per SOC */
 129         REG_WRITE(DISPCLK_FREQ_CHANGE_CNTL, 0x801003c);
 130 }
 131 void dcn20_display_init(struct dc *dc)
 132 {
 133         struct dce_hwseq *hws = dc->hwseq;
 134 
 135         /* RBBMIF
 136          * disable RBBMIF timeout detection for all clients
 137          * Ensure RBBMIF does not drop register accesses due to the per-client timeout
 138          */
 139         REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF);
 140         REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF);
 141 
 142         /* DCCG */
 143         dcn20_dccg_init(hws);
 144 
 145         REG_UPDATE(DC_MEM_GLOBAL_PWR_REQ_CNTL, DC_MEM_GLOBAL_PWR_REQ_DIS, 0);
 146 
 147         /* DCHUB/MMHUBBUB
 148          * set global timer refclk divider
 149          * 100Mhz refclk -> 2
 150          * 27Mhz refclk ->  1
 151          * 48Mhz refclk ->  1
 152          */
 153         REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2);
 154         REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
 155         REG_WRITE(REFCLK_CNTL, 0);
 156 
 157         /* OPTC
 158          * OTG_CONTROL.OTG_DISABLE_POINT_CNTL = 0x3; will be set during optc2_enable_crtc
 159          */
 160 
 161         /* AZ
 162          * default value is 0x64 for 100Mhz ref clock, if the ref clock is 100Mhz, no need to program this regiser,
 163          * if not, it should be programmed according to the ref clock
 164          */
 165         REG_UPDATE(AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, 0x64);
 166         /* Enable controller clock gating */
 167         REG_WRITE(AZALIA_CONTROLLER_CLOCK_GATING, 0x1);
 168 }
 169 
 170 void dcn20_disable_vga(
 171         struct dce_hwseq *hws)
 172 {
 173         REG_WRITE(D1VGA_CONTROL, 0);
 174         REG_WRITE(D2VGA_CONTROL, 0);
 175         REG_WRITE(D3VGA_CONTROL, 0);
 176         REG_WRITE(D4VGA_CONTROL, 0);
 177         REG_WRITE(D5VGA_CONTROL, 0);
 178         REG_WRITE(D6VGA_CONTROL, 0);
 179 }
 180 
 181 void dcn20_program_tripleBuffer(
 182         const struct dc *dc,
 183         struct pipe_ctx *pipe_ctx,
 184         bool enableTripleBuffer)
 185 {
 186         if (pipe_ctx->plane_res.hubp && pipe_ctx->plane_res.hubp->funcs) {
 187                 pipe_ctx->plane_res.hubp->funcs->hubp_enable_tripleBuffer(
 188                         pipe_ctx->plane_res.hubp,
 189                         enableTripleBuffer);
 190         }
 191 }
 192 
 193 /* Blank pixel data during initialization */
 194 void dcn20_init_blank(
 195                 struct dc *dc,
 196                 struct timing_generator *tg)
 197 {
 198         enum dc_color_space color_space;
 199         struct tg_color black_color = {0};
 200         struct output_pixel_processor *opp = NULL;
 201         struct output_pixel_processor *bottom_opp = NULL;
 202         uint32_t num_opps, opp_id_src0, opp_id_src1;
 203         uint32_t otg_active_width, otg_active_height;
 204 
 205         /* program opp dpg blank color */
 206         color_space = COLOR_SPACE_SRGB;
 207         color_space_to_black_color(dc, color_space, &black_color);
 208 
 209         /* get the OTG active size */
 210         tg->funcs->get_otg_active_size(tg,
 211                         &otg_active_width,
 212                         &otg_active_height);
 213 
 214         /* get the OPTC source */
 215         tg->funcs->get_optc_source(tg, &num_opps, &opp_id_src0, &opp_id_src1);
 216         ASSERT(opp_id_src0 < dc->res_pool->res_cap->num_opp);
 217         opp = dc->res_pool->opps[opp_id_src0];
 218 
 219         if (num_opps == 2) {
 220                 otg_active_width = otg_active_width / 2;
 221                 ASSERT(opp_id_src1 < dc->res_pool->res_cap->num_opp);
 222                 bottom_opp = dc->res_pool->opps[opp_id_src1];
 223         }
 224 
 225         opp->funcs->opp_set_disp_pattern_generator(
 226                         opp,
 227                         CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR,
 228                         COLOR_DEPTH_UNDEFINED,
 229                         &black_color,
 230                         otg_active_width,
 231                         otg_active_height);
 232 
 233         if (num_opps == 2) {
 234                 bottom_opp->funcs->opp_set_disp_pattern_generator(
 235                                 bottom_opp,
 236                                 CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR,
 237                                 COLOR_DEPTH_UNDEFINED,
 238                                 &black_color,
 239                                 otg_active_width,
 240                                 otg_active_height);
 241         }
 242 
 243         dcn20_hwss_wait_for_blank_complete(opp);
 244 }
 245 
 246 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
 247 static void dcn20_dsc_pg_control(
 248                 struct dce_hwseq *hws,
 249                 unsigned int dsc_inst,
 250                 bool power_on)
 251 {
 252         uint32_t power_gate = power_on ? 0 : 1;
 253         uint32_t pwr_status = power_on ? 0 : 2;
 254         uint32_t org_ip_request_cntl = 0;
 255 
 256         if (hws->ctx->dc->debug.disable_dsc_power_gate)
 257                 return;
 258 
 259         if (REG(DOMAIN16_PG_CONFIG) == 0)
 260                 return;
 261 
 262         REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
 263         if (org_ip_request_cntl == 0)
 264                 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
 265 
 266         switch (dsc_inst) {
 267         case 0: /* DSC0 */
 268                 REG_UPDATE(DOMAIN16_PG_CONFIG,
 269                                 DOMAIN16_POWER_GATE, power_gate);
 270 
 271                 REG_WAIT(DOMAIN16_PG_STATUS,
 272                                 DOMAIN16_PGFSM_PWR_STATUS, pwr_status,
 273                                 1, 1000);
 274                 break;
 275         case 1: /* DSC1 */
 276                 REG_UPDATE(DOMAIN17_PG_CONFIG,
 277                                 DOMAIN17_POWER_GATE, power_gate);
 278 
 279                 REG_WAIT(DOMAIN17_PG_STATUS,
 280                                 DOMAIN17_PGFSM_PWR_STATUS, pwr_status,
 281                                 1, 1000);
 282                 break;
 283         case 2: /* DSC2 */
 284                 REG_UPDATE(DOMAIN18_PG_CONFIG,
 285                                 DOMAIN18_POWER_GATE, power_gate);
 286 
 287                 REG_WAIT(DOMAIN18_PG_STATUS,
 288                                 DOMAIN18_PGFSM_PWR_STATUS, pwr_status,
 289                                 1, 1000);
 290                 break;
 291         case 3: /* DSC3 */
 292                 REG_UPDATE(DOMAIN19_PG_CONFIG,
 293                                 DOMAIN19_POWER_GATE, power_gate);
 294 
 295                 REG_WAIT(DOMAIN19_PG_STATUS,
 296                                 DOMAIN19_PGFSM_PWR_STATUS, pwr_status,
 297                                 1, 1000);
 298                 break;
 299         case 4: /* DSC4 */
 300                 REG_UPDATE(DOMAIN20_PG_CONFIG,
 301                                 DOMAIN20_POWER_GATE, power_gate);
 302 
 303                 REG_WAIT(DOMAIN20_PG_STATUS,
 304                                 DOMAIN20_PGFSM_PWR_STATUS, pwr_status,
 305                                 1, 1000);
 306                 break;
 307         case 5: /* DSC5 */
 308                 REG_UPDATE(DOMAIN21_PG_CONFIG,
 309                                 DOMAIN21_POWER_GATE, power_gate);
 310 
 311                 REG_WAIT(DOMAIN21_PG_STATUS,
 312                                 DOMAIN21_PGFSM_PWR_STATUS, pwr_status,
 313                                 1, 1000);
 314                 break;
 315         default:
 316                 BREAK_TO_DEBUGGER();
 317                 break;
 318         }
 319 
 320         if (org_ip_request_cntl == 0)
 321                 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
 322 }
 323 #endif
 324 
 325 static void dcn20_dpp_pg_control(
 326                 struct dce_hwseq *hws,
 327                 unsigned int dpp_inst,
 328                 bool power_on)
 329 {
 330         uint32_t power_gate = power_on ? 0 : 1;
 331         uint32_t pwr_status = power_on ? 0 : 2;
 332 
 333         if (hws->ctx->dc->debug.disable_dpp_power_gate)
 334                 return;
 335         if (REG(DOMAIN1_PG_CONFIG) == 0)
 336                 return;
 337 
 338         switch (dpp_inst) {
 339         case 0: /* DPP0 */
 340                 REG_UPDATE(DOMAIN1_PG_CONFIG,
 341                                 DOMAIN1_POWER_GATE, power_gate);
 342 
 343                 REG_WAIT(DOMAIN1_PG_STATUS,
 344                                 DOMAIN1_PGFSM_PWR_STATUS, pwr_status,
 345                                 1, 1000);
 346                 break;
 347         case 1: /* DPP1 */
 348                 REG_UPDATE(DOMAIN3_PG_CONFIG,
 349                                 DOMAIN3_POWER_GATE, power_gate);
 350 
 351                 REG_WAIT(DOMAIN3_PG_STATUS,
 352                                 DOMAIN3_PGFSM_PWR_STATUS, pwr_status,
 353                                 1, 1000);
 354                 break;
 355         case 2: /* DPP2 */
 356                 REG_UPDATE(DOMAIN5_PG_CONFIG,
 357                                 DOMAIN5_POWER_GATE, power_gate);
 358 
 359                 REG_WAIT(DOMAIN5_PG_STATUS,
 360                                 DOMAIN5_PGFSM_PWR_STATUS, pwr_status,
 361                                 1, 1000);
 362                 break;
 363         case 3: /* DPP3 */
 364                 REG_UPDATE(DOMAIN7_PG_CONFIG,
 365                                 DOMAIN7_POWER_GATE, power_gate);
 366 
 367                 REG_WAIT(DOMAIN7_PG_STATUS,
 368                                 DOMAIN7_PGFSM_PWR_STATUS, pwr_status,
 369                                 1, 1000);
 370                 break;
 371         case 4: /* DPP4 */
 372                 REG_UPDATE(DOMAIN9_PG_CONFIG,
 373                                 DOMAIN9_POWER_GATE, power_gate);
 374 
 375                 REG_WAIT(DOMAIN9_PG_STATUS,
 376                                 DOMAIN9_PGFSM_PWR_STATUS, pwr_status,
 377                                 1, 1000);
 378                 break;
 379         case 5: /* DPP5 */
 380                 /*
 381                  * Do not power gate DPP5, should be left at HW default, power on permanently.
 382                  * PG on Pipe5 is De-featured, attempting to put it to PG state may result in hard
 383                  * reset.
 384                  * REG_UPDATE(DOMAIN11_PG_CONFIG,
 385                  *              DOMAIN11_POWER_GATE, power_gate);
 386                  *
 387                  * REG_WAIT(DOMAIN11_PG_STATUS,
 388                  *              DOMAIN11_PGFSM_PWR_STATUS, pwr_status,
 389                  *              1, 1000);
 390                  */
 391                 break;
 392         default:
 393                 BREAK_TO_DEBUGGER();
 394                 break;
 395         }
 396 }
 397 
 398 
 399 static void dcn20_hubp_pg_control(
 400                 struct dce_hwseq *hws,
 401                 unsigned int hubp_inst,
 402                 bool power_on)
 403 {
 404         uint32_t power_gate = power_on ? 0 : 1;
 405         uint32_t pwr_status = power_on ? 0 : 2;
 406 
 407         if (hws->ctx->dc->debug.disable_hubp_power_gate)
 408                 return;
 409         if (REG(DOMAIN0_PG_CONFIG) == 0)
 410                 return;
 411 
 412         switch (hubp_inst) {
 413         case 0: /* DCHUBP0 */
 414                 REG_UPDATE(DOMAIN0_PG_CONFIG,
 415                                 DOMAIN0_POWER_GATE, power_gate);
 416 
 417                 REG_WAIT(DOMAIN0_PG_STATUS,
 418                                 DOMAIN0_PGFSM_PWR_STATUS, pwr_status,
 419                                 1, 1000);
 420                 break;
 421         case 1: /* DCHUBP1 */
 422                 REG_UPDATE(DOMAIN2_PG_CONFIG,
 423                                 DOMAIN2_POWER_GATE, power_gate);
 424 
 425                 REG_WAIT(DOMAIN2_PG_STATUS,
 426                                 DOMAIN2_PGFSM_PWR_STATUS, pwr_status,
 427                                 1, 1000);
 428                 break;
 429         case 2: /* DCHUBP2 */
 430                 REG_UPDATE(DOMAIN4_PG_CONFIG,
 431                                 DOMAIN4_POWER_GATE, power_gate);
 432 
 433                 REG_WAIT(DOMAIN4_PG_STATUS,
 434                                 DOMAIN4_PGFSM_PWR_STATUS, pwr_status,
 435                                 1, 1000);
 436                 break;
 437         case 3: /* DCHUBP3 */
 438                 REG_UPDATE(DOMAIN6_PG_CONFIG,
 439                                 DOMAIN6_POWER_GATE, power_gate);
 440 
 441                 REG_WAIT(DOMAIN6_PG_STATUS,
 442                                 DOMAIN6_PGFSM_PWR_STATUS, pwr_status,
 443                                 1, 1000);
 444                 break;
 445         case 4: /* DCHUBP4 */
 446                 REG_UPDATE(DOMAIN8_PG_CONFIG,
 447                                 DOMAIN8_POWER_GATE, power_gate);
 448 
 449                 REG_WAIT(DOMAIN8_PG_STATUS,
 450                                 DOMAIN8_PGFSM_PWR_STATUS, pwr_status,
 451                                 1, 1000);
 452                 break;
 453         case 5: /* DCHUBP5 */
 454                 /*
 455                  * Do not power gate DCHUB5, should be left at HW default, power on permanently.
 456                  * PG on Pipe5 is De-featured, attempting to put it to PG state may result in hard
 457                  * reset.
 458                  * REG_UPDATE(DOMAIN10_PG_CONFIG,
 459                  *              DOMAIN10_POWER_GATE, power_gate);
 460                  *
 461                  * REG_WAIT(DOMAIN10_PG_STATUS,
 462                  *              DOMAIN10_PGFSM_PWR_STATUS, pwr_status,
 463                  *              1, 1000);
 464                  */
 465                 break;
 466         default:
 467                 BREAK_TO_DEBUGGER();
 468                 break;
 469         }
 470 }
 471 
 472 
 473 /* disable HW used by plane.
 474  * note:  cannot disable until disconnect is complete
 475  */
 476 static void dcn20_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
 477 {
 478         struct hubp *hubp = pipe_ctx->plane_res.hubp;
 479         struct dpp *dpp = pipe_ctx->plane_res.dpp;
 480 
 481         dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx);
 482 
 483         /* In flip immediate with pipe splitting case GSL is used for
 484          * synchronization so we must disable it when the plane is disabled.
 485          */
 486         if (pipe_ctx->stream_res.gsl_group != 0)
 487                 dcn20_setup_gsl_group_as_lock(dc, pipe_ctx, false);
 488 
 489         dc->hwss.set_flip_control_gsl(pipe_ctx, false);
 490 
 491         hubp->funcs->hubp_clk_cntl(hubp, false);
 492 
 493         dpp->funcs->dpp_dppclk_control(dpp, false, false);
 494 
 495         hubp->power_gated = true;
 496 
 497         dc->hwss.plane_atomic_power_down(dc,
 498                         pipe_ctx->plane_res.dpp,
 499                         pipe_ctx->plane_res.hubp);
 500 
 501         pipe_ctx->stream = NULL;
 502         memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res));
 503         memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res));
 504         pipe_ctx->top_pipe = NULL;
 505         pipe_ctx->bottom_pipe = NULL;
 506         pipe_ctx->plane_state = NULL;
 507 }
 508 
 509 
 510 void dcn20_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
 511 {
 512         DC_LOGGER_INIT(dc->ctx->logger);
 513 
 514         if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated)
 515                 return;
 516 
 517         dcn20_plane_atomic_disable(dc, pipe_ctx);
 518 
 519         DC_LOG_DC("Power down front end %d\n",
 520                                         pipe_ctx->pipe_idx);
 521 }
 522 
 523 enum dc_status dcn20_enable_stream_timing(
 524                 struct pipe_ctx *pipe_ctx,
 525                 struct dc_state *context,
 526                 struct dc *dc)
 527 {
 528         struct dc_stream_state *stream = pipe_ctx->stream;
 529         struct drr_params params = {0};
 530         unsigned int event_triggers = 0;
 531         struct pipe_ctx *odm_pipe;
 532         int opp_cnt = 1;
 533         int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst };
 534 
 535         /* by upper caller loop, pipe0 is parent pipe and be called first.
 536          * back end is set up by for pipe0. Other children pipe share back end
 537          * with pipe 0. No program is needed.
 538          */
 539         if (pipe_ctx->top_pipe != NULL)
 540                 return DC_OK;
 541 
 542         /* TODO check if timing_changed, disable stream if timing changed */
 543 
 544         for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
 545                 opp_inst[opp_cnt] = odm_pipe->stream_res.opp->inst;
 546                 opp_cnt++;
 547         }
 548 
 549         if (opp_cnt > 1)
 550                 pipe_ctx->stream_res.tg->funcs->set_odm_combine(
 551                                 pipe_ctx->stream_res.tg,
 552                                 opp_inst, opp_cnt,
 553                                 &pipe_ctx->stream->timing);
 554 
 555         /* HW program guide assume display already disable
 556          * by unplug sequence. OTG assume stop.
 557          */
 558         pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, true);
 559 
 560         if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
 561                         pipe_ctx->clock_source,
 562                         &pipe_ctx->stream_res.pix_clk_params,
 563                         &pipe_ctx->pll_settings)) {
 564                 BREAK_TO_DEBUGGER();
 565                 return DC_ERROR_UNEXPECTED;
 566         }
 567 
 568         pipe_ctx->stream_res.tg->funcs->program_timing(
 569                         pipe_ctx->stream_res.tg,
 570                         &stream->timing,
 571                         pipe_ctx->pipe_dlg_param.vready_offset,
 572                         pipe_ctx->pipe_dlg_param.vstartup_start,
 573                         pipe_ctx->pipe_dlg_param.vupdate_offset,
 574                         pipe_ctx->pipe_dlg_param.vupdate_width,
 575                         pipe_ctx->stream->signal,
 576                         true);
 577 
 578         for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
 579                 odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control(
 580                                 odm_pipe->stream_res.opp,
 581                                 true);
 582 
 583         pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
 584                         pipe_ctx->stream_res.opp,
 585                         true);
 586 
 587         dc->hwss.blank_pixel_data(dc, pipe_ctx, true);
 588 
 589         /* VTG is  within DCHUB command block. DCFCLK is always on */
 590         if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) {
 591                 BREAK_TO_DEBUGGER();
 592                 return DC_ERROR_UNEXPECTED;
 593         }
 594 
 595         dcn20_hwss_wait_for_blank_complete(pipe_ctx->stream_res.opp);
 596 
 597         params.vertical_total_min = stream->adjust.v_total_min;
 598         params.vertical_total_max = stream->adjust.v_total_max;
 599         params.vertical_total_mid = stream->adjust.v_total_mid;
 600         params.vertical_total_mid_frame_num = stream->adjust.v_total_mid_frame_num;
 601         if (pipe_ctx->stream_res.tg->funcs->set_drr)
 602                 pipe_ctx->stream_res.tg->funcs->set_drr(
 603                         pipe_ctx->stream_res.tg, &params);
 604 
 605         // DRR should set trigger event to monitor surface update event
 606         if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0)
 607                 event_triggers = 0x80;
 608         if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control)
 609                 pipe_ctx->stream_res.tg->funcs->set_static_screen_control(
 610                                 pipe_ctx->stream_res.tg, event_triggers);
 611 
 612         /* TODO program crtc source select for non-virtual signal*/
 613         /* TODO program FMT */
 614         /* TODO setup link_enc */
 615         /* TODO set stream attributes */
 616         /* TODO program audio */
 617         /* TODO enable stream if timing changed */
 618         /* TODO unblank stream if DP */
 619 
 620         return DC_OK;
 621 }
 622 
 623 void dcn20_program_output_csc(struct dc *dc,
 624                 struct pipe_ctx *pipe_ctx,
 625                 enum dc_color_space colorspace,
 626                 uint16_t *matrix,
 627                 int opp_id)
 628 {
 629         struct mpc *mpc = dc->res_pool->mpc;
 630         enum mpc_output_csc_mode ocsc_mode = MPC_OUTPUT_CSC_COEF_A;
 631         int mpcc_id = pipe_ctx->plane_res.hubp->inst;
 632 
 633         if (mpc->funcs->power_on_mpc_mem_pwr)
 634                 mpc->funcs->power_on_mpc_mem_pwr(mpc, mpcc_id, true);
 635 
 636         if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
 637                 if (mpc->funcs->set_output_csc != NULL)
 638                         mpc->funcs->set_output_csc(mpc,
 639                                         opp_id,
 640                                         matrix,
 641                                         ocsc_mode);
 642         } else {
 643                 if (mpc->funcs->set_ocsc_default != NULL)
 644                         mpc->funcs->set_ocsc_default(mpc,
 645                                         opp_id,
 646                                         colorspace,
 647                                         ocsc_mode);
 648         }
 649 }
 650 
 651 bool dcn20_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
 652                                 const struct dc_stream_state *stream)
 653 {
 654         int mpcc_id = pipe_ctx->plane_res.hubp->inst;
 655         struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
 656         struct pwl_params *params = NULL;
 657         /*
 658          * program OGAM only for the top pipe
 659          * if there is a pipe split then fix diagnostic is required:
 660          * how to pass OGAM parameter for stream.
 661          * if programming for all pipes is required then remove condition
 662          * pipe_ctx->top_pipe == NULL ,but then fix the diagnostic.
 663          */
 664         if (mpc->funcs->power_on_mpc_mem_pwr)
 665                 mpc->funcs->power_on_mpc_mem_pwr(mpc, mpcc_id, true);
 666         if (pipe_ctx->top_pipe == NULL
 667                         && mpc->funcs->set_output_gamma && stream->out_transfer_func) {
 668                 if (stream->out_transfer_func->type == TF_TYPE_HWPWL)
 669                         params = &stream->out_transfer_func->pwl;
 670                 else if (pipe_ctx->stream->out_transfer_func->type ==
 671                         TF_TYPE_DISTRIBUTED_POINTS &&
 672                         cm_helper_translate_curve_to_hw_format(
 673                         stream->out_transfer_func,
 674                         &mpc->blender_params, false))
 675                         params = &mpc->blender_params;
 676                 /*
 677                  * there is no ROM
 678                  */
 679                 if (stream->out_transfer_func->type == TF_TYPE_PREDEFINED)
 680                         BREAK_TO_DEBUGGER();
 681         }
 682         /*
 683          * if above if is not executed then 'params' equal to 0 and set in bypass
 684          */
 685         mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
 686 
 687         return true;
 688 }
 689 
 690 static bool dcn20_set_blend_lut(
 691         struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state)
 692 {
 693         struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
 694         bool result = true;
 695         struct pwl_params *blend_lut = NULL;
 696 
 697         if (plane_state->blend_tf) {
 698                 if (plane_state->blend_tf->type == TF_TYPE_HWPWL)
 699                         blend_lut = &plane_state->blend_tf->pwl;
 700                 else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) {
 701                         cm_helper_translate_curve_to_hw_format(
 702                                         plane_state->blend_tf,
 703                                         &dpp_base->regamma_params, false);
 704                         blend_lut = &dpp_base->regamma_params;
 705                 }
 706         }
 707         result = dpp_base->funcs->dpp_program_blnd_lut(dpp_base, blend_lut);
 708 
 709         return result;
 710 }
 711 
 712 static bool dcn20_set_shaper_3dlut(
 713         struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state)
 714 {
 715         struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
 716         bool result = true;
 717         struct pwl_params *shaper_lut = NULL;
 718 
 719         if (plane_state->in_shaper_func) {
 720                 if (plane_state->in_shaper_func->type == TF_TYPE_HWPWL)
 721                         shaper_lut = &plane_state->in_shaper_func->pwl;
 722                 else if (plane_state->in_shaper_func->type == TF_TYPE_DISTRIBUTED_POINTS) {
 723                         cm_helper_translate_curve_to_hw_format(
 724                                         plane_state->in_shaper_func,
 725                                         &dpp_base->shaper_params, true);
 726                         shaper_lut = &dpp_base->shaper_params;
 727                 }
 728         }
 729 
 730         result = dpp_base->funcs->dpp_program_shaper_lut(dpp_base, shaper_lut);
 731         if (plane_state->lut3d_func &&
 732                 plane_state->lut3d_func->state.bits.initialized == 1)
 733                 result = dpp_base->funcs->dpp_program_3dlut(dpp_base,
 734                                                                 &plane_state->lut3d_func->lut_3d);
 735         else
 736                 result = dpp_base->funcs->dpp_program_3dlut(dpp_base, NULL);
 737 
 738         if (plane_state->lut3d_func &&
 739                 plane_state->lut3d_func->state.bits.initialized == 1 &&
 740                 plane_state->lut3d_func->hdr_multiplier != 0)
 741                 dpp_base->funcs->dpp_set_hdr_multiplier(dpp_base,
 742                                 plane_state->lut3d_func->hdr_multiplier);
 743         else
 744                 dpp_base->funcs->dpp_set_hdr_multiplier(dpp_base, 0x1f000);
 745 
 746         return result;
 747 }
 748 
 749 bool dcn20_set_input_transfer_func(struct pipe_ctx *pipe_ctx,
 750                                           const struct dc_plane_state *plane_state)
 751 {
 752         struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
 753         const struct dc_transfer_func *tf = NULL;
 754         bool result = true;
 755         bool use_degamma_ram = false;
 756 
 757         if (dpp_base == NULL || plane_state == NULL)
 758                 return false;
 759 
 760         dcn20_set_shaper_3dlut(pipe_ctx, plane_state);
 761         dcn20_set_blend_lut(pipe_ctx, plane_state);
 762 
 763         if (plane_state->in_transfer_func)
 764                 tf = plane_state->in_transfer_func;
 765 
 766 
 767         if (tf == NULL) {
 768                 dpp_base->funcs->dpp_set_degamma(dpp_base,
 769                                 IPP_DEGAMMA_MODE_BYPASS);
 770                 return true;
 771         }
 772 
 773         if (tf->type == TF_TYPE_HWPWL || tf->type == TF_TYPE_DISTRIBUTED_POINTS)
 774                 use_degamma_ram = true;
 775 
 776         if (use_degamma_ram == true) {
 777                 if (tf->type == TF_TYPE_HWPWL)
 778                         dpp_base->funcs->dpp_program_degamma_pwl(dpp_base,
 779                                         &tf->pwl);
 780                 else if (tf->type == TF_TYPE_DISTRIBUTED_POINTS) {
 781                         cm_helper_translate_curve_to_degamma_hw_format(tf,
 782                                         &dpp_base->degamma_params);
 783                         dpp_base->funcs->dpp_program_degamma_pwl(dpp_base,
 784                                 &dpp_base->degamma_params);
 785                 }
 786                 return true;
 787         }
 788         /* handle here the optimized cases when de-gamma ROM could be used.
 789          *
 790          */
 791         if (tf->type == TF_TYPE_PREDEFINED) {
 792                 switch (tf->tf) {
 793                 case TRANSFER_FUNCTION_SRGB:
 794                         dpp_base->funcs->dpp_set_degamma(dpp_base,
 795                                         IPP_DEGAMMA_MODE_HW_sRGB);
 796                         break;
 797                 case TRANSFER_FUNCTION_BT709:
 798                         dpp_base->funcs->dpp_set_degamma(dpp_base,
 799                                         IPP_DEGAMMA_MODE_HW_xvYCC);
 800                         break;
 801                 case TRANSFER_FUNCTION_LINEAR:
 802                         dpp_base->funcs->dpp_set_degamma(dpp_base,
 803                                         IPP_DEGAMMA_MODE_BYPASS);
 804                         break;
 805                 case TRANSFER_FUNCTION_PQ:
 806                 default:
 807                         result = false;
 808                         break;
 809                 }
 810         } else if (tf->type == TF_TYPE_BYPASS)
 811                 dpp_base->funcs->dpp_set_degamma(dpp_base,
 812                                 IPP_DEGAMMA_MODE_BYPASS);
 813         else {
 814                 /*
 815                  * if we are here, we did not handle correctly.
 816                  * fix is required for this use case
 817                  */
 818                 BREAK_TO_DEBUGGER();
 819                 dpp_base->funcs->dpp_set_degamma(dpp_base,
 820                                 IPP_DEGAMMA_MODE_BYPASS);
 821         }
 822 
 823         return result;
 824 }
 825 
 826 static void dcn20_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
 827 {
 828         struct pipe_ctx *odm_pipe;
 829         int opp_cnt = 1;
 830         int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst };
 831 
 832         for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
 833                 opp_inst[opp_cnt] = odm_pipe->stream_res.opp->inst;
 834                 opp_cnt++;
 835         }
 836 
 837         if (opp_cnt > 1)
 838                 pipe_ctx->stream_res.tg->funcs->set_odm_combine(
 839                                 pipe_ctx->stream_res.tg,
 840                                 opp_inst, opp_cnt,
 841                                 &pipe_ctx->stream->timing);
 842         else
 843                 pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
 844                                 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
 845 }
 846 
 847 void dcn20_blank_pixel_data(
 848                 struct dc *dc,
 849                 struct pipe_ctx *pipe_ctx,
 850                 bool blank)
 851 {
 852         struct tg_color black_color = {0};
 853         struct stream_resource *stream_res = &pipe_ctx->stream_res;
 854         struct dc_stream_state *stream = pipe_ctx->stream;
 855         enum dc_color_space color_space = stream->output_color_space;
 856         enum controller_dp_test_pattern test_pattern = CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR;
 857         struct pipe_ctx *odm_pipe;
 858         int odm_cnt = 1;
 859 
 860         int width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
 861         int height = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
 862 
 863         /* get opp dpg blank color */
 864         color_space_to_black_color(dc, color_space, &black_color);
 865 
 866         for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
 867                 odm_cnt++;
 868 
 869         width = width / odm_cnt;
 870 
 871         if (blank) {
 872                 if (stream_res->abm)
 873                         stream_res->abm->funcs->set_abm_immediate_disable(stream_res->abm);
 874 
 875                 if (dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE)
 876                         test_pattern = CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
 877         } else {
 878                 test_pattern = CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
 879         }
 880 
 881         stream_res->opp->funcs->opp_set_disp_pattern_generator(
 882                         stream_res->opp,
 883                         test_pattern,
 884                         stream->timing.display_color_depth,
 885                         &black_color,
 886                         width,
 887                         height);
 888 
 889         for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
 890                 odm_pipe->stream_res.opp->funcs->opp_set_disp_pattern_generator(
 891                                 odm_pipe->stream_res.opp,
 892                                 dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE && blank ?
 893                                                 CONTROLLER_DP_TEST_PATTERN_COLORRAMP : test_pattern,
 894                                 stream->timing.display_color_depth,
 895                                 &black_color,
 896                                 width,
 897                                 height);
 898         }
 899 
 900         if (!blank)
 901                 if (stream_res->abm) {
 902                         stream_res->abm->funcs->set_pipe(stream_res->abm, stream_res->tg->inst + 1);
 903                         stream_res->abm->funcs->set_abm_level(stream_res->abm, stream->abm_level);
 904                 }
 905 }
 906 
 907 
 908 static void dcn20_power_on_plane(
 909         struct dce_hwseq *hws,
 910         struct pipe_ctx *pipe_ctx)
 911 {
 912         DC_LOGGER_INIT(hws->ctx->logger);
 913         if (REG(DC_IP_REQUEST_CNTL)) {
 914                 REG_SET(DC_IP_REQUEST_CNTL, 0,
 915                                 IP_REQUEST_EN, 1);
 916                 dcn20_dpp_pg_control(hws, pipe_ctx->plane_res.dpp->inst, true);
 917                 dcn20_hubp_pg_control(hws, pipe_ctx->plane_res.hubp->inst, true);
 918                 REG_SET(DC_IP_REQUEST_CNTL, 0,
 919                                 IP_REQUEST_EN, 0);
 920                 DC_LOG_DEBUG(
 921                                 "Un-gated front end for pipe %d\n", pipe_ctx->plane_res.hubp->inst);
 922         }
 923 }
 924 
 925 void dcn20_enable_plane(
 926         struct dc *dc,
 927         struct pipe_ctx *pipe_ctx,
 928         struct dc_state *context)
 929 {
 930         //if (dc->debug.sanity_checks) {
 931         //      dcn10_verify_allow_pstate_change_high(dc);
 932         //}
 933         dcn20_power_on_plane(dc->hwseq, pipe_ctx);
 934 
 935         /* enable DCFCLK current DCHUB */
 936         pipe_ctx->plane_res.hubp->funcs->hubp_clk_cntl(pipe_ctx->plane_res.hubp, true);
 937 
 938         /* initialize HUBP on power up */
 939         pipe_ctx->plane_res.hubp->funcs->hubp_init(pipe_ctx->plane_res.hubp);
 940 
 941         /* make sure OPP_PIPE_CLOCK_EN = 1 */
 942         pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
 943                         pipe_ctx->stream_res.opp,
 944                         true);
 945 
 946 /* TODO: enable/disable in dm as per update type.
 947         if (plane_state) {
 948                 DC_LOG_DC(dc->ctx->logger,
 949                                 "Pipe:%d 0x%x: addr hi:0x%x, "
 950                                 "addr low:0x%x, "
 951                                 "src: %d, %d, %d,"
 952                                 " %d; dst: %d, %d, %d, %d;\n",
 953                                 pipe_ctx->pipe_idx,
 954                                 plane_state,
 955                                 plane_state->address.grph.addr.high_part,
 956                                 plane_state->address.grph.addr.low_part,
 957                                 plane_state->src_rect.x,
 958                                 plane_state->src_rect.y,
 959                                 plane_state->src_rect.width,
 960                                 plane_state->src_rect.height,
 961                                 plane_state->dst_rect.x,
 962                                 plane_state->dst_rect.y,
 963                                 plane_state->dst_rect.width,
 964                                 plane_state->dst_rect.height);
 965 
 966                 DC_LOG_DC(dc->ctx->logger,
 967                                 "Pipe %d: width, height, x, y         format:%d\n"
 968                                 "viewport:%d, %d, %d, %d\n"
 969                                 "recout:  %d, %d, %d, %d\n",
 970                                 pipe_ctx->pipe_idx,
 971                                 plane_state->format,
 972                                 pipe_ctx->plane_res.scl_data.viewport.width,
 973                                 pipe_ctx->plane_res.scl_data.viewport.height,
 974                                 pipe_ctx->plane_res.scl_data.viewport.x,
 975                                 pipe_ctx->plane_res.scl_data.viewport.y,
 976                                 pipe_ctx->plane_res.scl_data.recout.width,
 977                                 pipe_ctx->plane_res.scl_data.recout.height,
 978                                 pipe_ctx->plane_res.scl_data.recout.x,
 979                                 pipe_ctx->plane_res.scl_data.recout.y);
 980                 print_rq_dlg_ttu(dc, pipe_ctx);
 981         }
 982 */
 983         if (dc->vm_pa_config.valid) {
 984                 struct vm_system_aperture_param apt;
 985 
 986                 apt.sys_default.quad_part = 0;
 987 
 988                 apt.sys_low.quad_part = dc->vm_pa_config.system_aperture.start_addr;
 989                 apt.sys_high.quad_part = dc->vm_pa_config.system_aperture.end_addr;
 990 
 991                 // Program system aperture settings
 992                 pipe_ctx->plane_res.hubp->funcs->hubp_set_vm_system_aperture_settings(pipe_ctx->plane_res.hubp, &apt);
 993         }
 994 
 995 //      if (dc->debug.sanity_checks) {
 996 //              dcn10_verify_allow_pstate_change_high(dc);
 997 //      }
 998 }
 999 
1000 
1001 static void dcn20_program_pipe(
1002                 struct dc *dc,
1003                 struct pipe_ctx *pipe_ctx,
1004                 struct dc_state *context)
1005 {
1006         pipe_ctx->plane_state->update_flags.bits.full_update =
1007                         context->commit_hints.full_update_needed ? 1 : pipe_ctx->plane_state->update_flags.bits.full_update;
1008 
1009         if (pipe_ctx->plane_state->update_flags.bits.full_update)
1010                 dcn20_enable_plane(dc, pipe_ctx, context);
1011 
1012         update_dchubp_dpp(dc, pipe_ctx, context);
1013 
1014         set_hdr_multiplier(pipe_ctx);
1015 
1016         if (pipe_ctx->plane_state->update_flags.bits.full_update ||
1017                         pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
1018                         pipe_ctx->plane_state->update_flags.bits.gamma_change)
1019                 dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state);
1020 
1021         /* dcn10_translate_regamma_to_hw_format takes 750us to finish
1022          * only do gamma programming for full update.
1023          * TODO: This can be further optimized/cleaned up
1024          * Always call this for now since it does memcmp inside before
1025          * doing heavy calculation and programming
1026          */
1027         if (pipe_ctx->plane_state->update_flags.bits.full_update)
1028                 dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream);
1029 }
1030 
1031 static void dcn20_program_all_pipe_in_tree(
1032                 struct dc *dc,
1033                 struct pipe_ctx *pipe_ctx,
1034                 struct dc_state *context)
1035 {
1036         if (pipe_ctx->top_pipe == NULL && !pipe_ctx->prev_odm_pipe) {
1037                 bool blank = !is_pipe_tree_visible(pipe_ctx);
1038 
1039                 pipe_ctx->stream_res.tg->funcs->program_global_sync(
1040                                 pipe_ctx->stream_res.tg,
1041                                 pipe_ctx->pipe_dlg_param.vready_offset,
1042                                 pipe_ctx->pipe_dlg_param.vstartup_start,
1043                                 pipe_ctx->pipe_dlg_param.vupdate_offset,
1044                                 pipe_ctx->pipe_dlg_param.vupdate_width);
1045 
1046                 pipe_ctx->stream_res.tg->funcs->set_vtg_params(
1047                                 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
1048 
1049                 dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
1050 
1051                 if (dc->hwss.update_odm)
1052                         dc->hwss.update_odm(dc, context, pipe_ctx);
1053         }
1054 
1055         if (pipe_ctx->plane_state != NULL)
1056                 dcn20_program_pipe(dc, pipe_ctx, context);
1057 
1058         if (pipe_ctx->bottom_pipe != NULL) {
1059                 ASSERT(pipe_ctx->bottom_pipe != pipe_ctx);
1060                 dcn20_program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context);
1061         } else if (pipe_ctx->next_odm_pipe != NULL) {
1062                 ASSERT(pipe_ctx->next_odm_pipe != pipe_ctx);
1063                 dcn20_program_all_pipe_in_tree(dc, pipe_ctx->next_odm_pipe, context);
1064         }
1065 }
1066 
1067 void dcn20_pipe_control_lock_global(
1068                 struct dc *dc,
1069                 struct pipe_ctx *pipe,
1070                 bool lock)
1071 {
1072         if (lock) {
1073                 pipe->stream_res.tg->funcs->lock_doublebuffer_enable(
1074                                 pipe->stream_res.tg);
1075                 pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
1076         } else {
1077                 pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
1078                 pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
1079                                 CRTC_STATE_VACTIVE);
1080                 pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
1081                                 CRTC_STATE_VBLANK);
1082                 pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
1083                                 CRTC_STATE_VACTIVE);
1084                 pipe->stream_res.tg->funcs->lock_doublebuffer_disable(
1085                                 pipe->stream_res.tg);
1086         }
1087 }
1088 
1089 void dcn20_pipe_control_lock(
1090         struct dc *dc,
1091         struct pipe_ctx *pipe,
1092         bool lock)
1093 {
1094         bool flip_immediate = false;
1095 
1096         /* use TG master update lock to lock everything on the TG
1097          * therefore only top pipe need to lock
1098          */
1099         if (pipe->top_pipe)
1100                 return;
1101 
1102         if (pipe->plane_state != NULL)
1103                 flip_immediate = pipe->plane_state->flip_immediate;
1104 
1105         if (flip_immediate && lock) {
1106                 const int TIMEOUT_FOR_FLIP_PENDING = 100000;
1107                 int i;
1108 
1109                 for (i = 0; i < TIMEOUT_FOR_FLIP_PENDING; ++i) {
1110                         if (!pipe->plane_res.hubp->funcs->hubp_is_flip_pending(pipe->plane_res.hubp))
1111                                 break;
1112                         udelay(1);
1113                 }
1114 
1115                 if (pipe->bottom_pipe != NULL) {
1116                         for (i = 0; i < TIMEOUT_FOR_FLIP_PENDING; ++i) {
1117                                 if (!pipe->bottom_pipe->plane_res.hubp->funcs->hubp_is_flip_pending(pipe->bottom_pipe->plane_res.hubp))
1118                                         break;
1119                                 udelay(1);
1120                         }
1121                 }
1122         }
1123 
1124         /* In flip immediate and pipe splitting case, we need to use GSL
1125          * for synchronization. Only do setup on locking and on flip type change.
1126          */
1127         if (lock && pipe->bottom_pipe != NULL)
1128                 if ((flip_immediate && pipe->stream_res.gsl_group == 0) ||
1129                     (!flip_immediate && pipe->stream_res.gsl_group > 0))
1130                         dcn20_setup_gsl_group_as_lock(dc, pipe, flip_immediate);
1131 
1132         if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) {
1133                 if (lock)
1134                         pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg);
1135                 else
1136                         pipe->stream_res.tg->funcs->triplebuffer_unlock(pipe->stream_res.tg);
1137         } else {
1138                 if (lock)
1139                         pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
1140                 else
1141                         pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
1142         }
1143 }
1144 
1145 static void dcn20_apply_ctx_for_surface(
1146                 struct dc *dc,
1147                 const struct dc_stream_state *stream,
1148                 int num_planes,
1149                 struct dc_state *context)
1150 {
1151         const unsigned int TIMEOUT_FOR_PIPE_ENABLE_MS = 100;
1152         int i;
1153         struct timing_generator *tg;
1154         bool removed_pipe[6] = { false };
1155         bool interdependent_update = false;
1156         struct pipe_ctx *top_pipe_to_program =
1157                         find_top_pipe_for_stream(dc, context, stream);
1158         struct pipe_ctx *prev_top_pipe_to_program =
1159                         find_top_pipe_for_stream(dc, dc->current_state, stream);
1160         DC_LOGGER_INIT(dc->ctx->logger);
1161 
1162         if (!top_pipe_to_program)
1163                 return;
1164 
1165         /* Carry over GSL groups in case the context is changing. */
1166         for (i = 0; i < dc->res_pool->pipe_count; i++) {
1167                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1168                 struct pipe_ctx *old_pipe_ctx =
1169                         &dc->current_state->res_ctx.pipe_ctx[i];
1170 
1171                 if (pipe_ctx->stream == stream &&
1172                     pipe_ctx->stream == old_pipe_ctx->stream)
1173                         pipe_ctx->stream_res.gsl_group =
1174                                 old_pipe_ctx->stream_res.gsl_group;
1175         }
1176 
1177         tg = top_pipe_to_program->stream_res.tg;
1178 
1179         interdependent_update = top_pipe_to_program->plane_state &&
1180                 top_pipe_to_program->plane_state->update_flags.bits.full_update;
1181 
1182         if (interdependent_update)
1183                 lock_all_pipes(dc, context, true);
1184         else
1185                 dcn20_pipe_control_lock(dc, top_pipe_to_program, true);
1186 
1187         if (num_planes == 0) {
1188                 /* OTG blank before remove all front end */
1189                 dc->hwss.blank_pixel_data(dc, top_pipe_to_program, true);
1190         }
1191 
1192         /* Disconnect unused mpcc */
1193         for (i = 0; i < dc->res_pool->pipe_count; i++) {
1194                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1195                 struct pipe_ctx *old_pipe_ctx =
1196                                 &dc->current_state->res_ctx.pipe_ctx[i];
1197                 /*
1198                  * Powergate reused pipes that are not powergated
1199                  * fairly hacky right now, using opp_id as indicator
1200                  * TODO: After move dc_post to dc_update, this will
1201                  * be removed.
1202                  */
1203                 if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) {
1204                         if (old_pipe_ctx->stream_res.tg == tg &&
1205                             old_pipe_ctx->plane_res.hubp &&
1206                             old_pipe_ctx->plane_res.hubp->opp_id != OPP_ID_INVALID)
1207                                 dc->hwss.disable_plane(dc, old_pipe_ctx);
1208                 }
1209 
1210                 if ((!pipe_ctx->plane_state ||
1211                      pipe_ctx->stream_res.tg != old_pipe_ctx->stream_res.tg) &&
1212                      old_pipe_ctx->plane_state &&
1213                      old_pipe_ctx->stream_res.tg == tg) {
1214 
1215                         dc->hwss.plane_atomic_disconnect(dc, old_pipe_ctx);
1216                         removed_pipe[i] = true;
1217 
1218                         DC_LOG_DC("Reset mpcc for pipe %d\n",
1219                                         old_pipe_ctx->pipe_idx);
1220                 }
1221         }
1222 
1223         if (num_planes > 0)
1224                 dcn20_program_all_pipe_in_tree(dc, top_pipe_to_program, context);
1225 
1226         /* Program secondary blending tree and writeback pipes */
1227         if ((stream->num_wb_info > 0) && (dc->hwss.program_all_writeback_pipes_in_tree))
1228                 dc->hwss.program_all_writeback_pipes_in_tree(dc, stream, context);
1229 
1230         if (interdependent_update)
1231                 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1232                         struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1233 
1234                         /* Skip inactive pipes and ones already updated */
1235                         if (!pipe_ctx->stream || pipe_ctx->stream == stream ||
1236                             !pipe_ctx->plane_state || !tg->funcs->is_tg_enabled(tg))
1237                                 continue;
1238 
1239                         pipe_ctx->plane_res.hubp->funcs->hubp_setup_interdependent(
1240                                 pipe_ctx->plane_res.hubp,
1241                                 &pipe_ctx->dlg_regs,
1242                                 &pipe_ctx->ttu_regs);
1243                 }
1244 
1245         if (interdependent_update)
1246                 lock_all_pipes(dc, context, false);
1247         else
1248                 dcn20_pipe_control_lock(dc, top_pipe_to_program, false);
1249 
1250         for (i = 0; i < dc->res_pool->pipe_count; i++)
1251                 if (removed_pipe[i])
1252                         dcn20_disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
1253 
1254         /*
1255          * If we are enabling a pipe, we need to wait for pending clear as this is a critical
1256          * part of the enable operation otherwise, DM may request an immediate flip which
1257          * will cause HW to perform an "immediate enable" (as opposed to "vsync enable") which
1258          * is unsupported on DCN.
1259          */
1260         i = 0;
1261         if (num_planes > 0 && top_pipe_to_program &&
1262                         (prev_top_pipe_to_program == NULL || prev_top_pipe_to_program->plane_state == NULL)) {
1263                 while (i < TIMEOUT_FOR_PIPE_ENABLE_MS &&
1264                                 top_pipe_to_program->plane_res.hubp->funcs->hubp_is_flip_pending(top_pipe_to_program->plane_res.hubp)) {
1265                         i += 1;
1266                         msleep(1);
1267                 }
1268         }
1269 }
1270 
1271 
1272 void dcn20_prepare_bandwidth(
1273                 struct dc *dc,
1274                 struct dc_state *context)
1275 {
1276         struct hubbub *hubbub = dc->res_pool->hubbub;
1277 
1278         dc->clk_mgr->funcs->update_clocks(
1279                         dc->clk_mgr,
1280                         context,
1281                         false);
1282 
1283         /* program dchubbub watermarks */
1284         hubbub->funcs->program_watermarks(hubbub,
1285                                         &context->bw_ctx.bw.dcn.watermarks,
1286                                         dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
1287                                         false);
1288 }
1289 
1290 void dcn20_optimize_bandwidth(
1291                 struct dc *dc,
1292                 struct dc_state *context)
1293 {
1294         struct hubbub *hubbub = dc->res_pool->hubbub;
1295 
1296         /* program dchubbub watermarks */
1297         hubbub->funcs->program_watermarks(hubbub,
1298                                         &context->bw_ctx.bw.dcn.watermarks,
1299                                         dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
1300                                         true);
1301 
1302         dc->clk_mgr->funcs->update_clocks(
1303                         dc->clk_mgr,
1304                         context,
1305                         true);
1306 }
1307 
1308 bool dcn20_update_bandwidth(
1309                 struct dc *dc,
1310                 struct dc_state *context)
1311 {
1312         int i;
1313 
1314         /* recalculate DML parameters */
1315         if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false))
1316                 return false;
1317 
1318         /* apply updated bandwidth parameters */
1319         dc->hwss.prepare_bandwidth(dc, context);
1320 
1321         /* update hubp configs for all pipes */
1322         for (i = 0; i < dc->res_pool->pipe_count; i++) {
1323                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1324 
1325                 if (pipe_ctx->plane_state == NULL)
1326                         continue;
1327 
1328                 if (pipe_ctx->top_pipe == NULL) {
1329                         bool blank = !is_pipe_tree_visible(pipe_ctx);
1330 
1331                         pipe_ctx->stream_res.tg->funcs->program_global_sync(
1332                                         pipe_ctx->stream_res.tg,
1333                                         pipe_ctx->pipe_dlg_param.vready_offset,
1334                                         pipe_ctx->pipe_dlg_param.vstartup_start,
1335                                         pipe_ctx->pipe_dlg_param.vupdate_offset,
1336                                         pipe_ctx->pipe_dlg_param.vupdate_width);
1337 
1338                         pipe_ctx->stream_res.tg->funcs->set_vtg_params(
1339                                         pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
1340                         if (pipe_ctx->prev_odm_pipe == NULL)
1341                                 dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
1342                 }
1343 
1344                 pipe_ctx->plane_res.hubp->funcs->hubp_setup(
1345                                 pipe_ctx->plane_res.hubp,
1346                                         &pipe_ctx->dlg_regs,
1347                                         &pipe_ctx->ttu_regs,
1348                                         &pipe_ctx->rq_regs,
1349                                         &pipe_ctx->pipe_dlg_param);
1350         }
1351 
1352         return true;
1353 }
1354 
1355 static void dcn20_enable_writeback(
1356                 struct dc *dc,
1357                 const struct dc_stream_status *stream_status,
1358                 struct dc_writeback_info *wb_info,
1359                 struct dc_state *context)
1360 {
1361         struct dwbc *dwb;
1362         struct mcif_wb *mcif_wb;
1363         struct timing_generator *optc;
1364 
1365         ASSERT(wb_info->dwb_pipe_inst < MAX_DWB_PIPES);
1366         ASSERT(wb_info->wb_enabled);
1367         dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
1368         mcif_wb = dc->res_pool->mcif_wb[wb_info->dwb_pipe_inst];
1369 
1370         /* set the OPTC source mux */
1371         ASSERT(stream_status->primary_otg_inst < MAX_PIPES);
1372         optc = dc->res_pool->timing_generators[stream_status->primary_otg_inst];
1373         optc->funcs->set_dwb_source(optc, wb_info->dwb_pipe_inst);
1374         /* set MCIF_WB buffer and arbitration configuration */
1375         mcif_wb->funcs->config_mcif_buf(mcif_wb, &wb_info->mcif_buf_params, wb_info->dwb_params.dest_height);
1376         mcif_wb->funcs->config_mcif_arb(mcif_wb, &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[wb_info->dwb_pipe_inst]);
1377         /* Enable MCIF_WB */
1378         mcif_wb->funcs->enable_mcif(mcif_wb);
1379         /* Enable DWB */
1380         dwb->funcs->enable(dwb, &wb_info->dwb_params);
1381         /* TODO: add sequence to enable/disable warmup */
1382 }
1383 
1384 void dcn20_disable_writeback(
1385                 struct dc *dc,
1386                 unsigned int dwb_pipe_inst)
1387 {
1388         struct dwbc *dwb;
1389         struct mcif_wb *mcif_wb;
1390 
1391         ASSERT(dwb_pipe_inst < MAX_DWB_PIPES);
1392         dwb = dc->res_pool->dwbc[dwb_pipe_inst];
1393         mcif_wb = dc->res_pool->mcif_wb[dwb_pipe_inst];
1394 
1395         dwb->funcs->disable(dwb);
1396         mcif_wb->funcs->disable_mcif(mcif_wb);
1397 }
1398 
1399 bool dcn20_hwss_wait_for_blank_complete(
1400                 struct output_pixel_processor *opp)
1401 {
1402         int counter;
1403 
1404         for (counter = 0; counter < 1000; counter++) {
1405                 if (opp->funcs->dpg_is_blanked(opp))
1406                         break;
1407 
1408                 udelay(100);
1409         }
1410 
1411         if (counter == 1000) {
1412                 dm_error("DC: failed to blank crtc!\n");
1413                 return false;
1414         }
1415 
1416         return true;
1417 }
1418 
1419 bool dcn20_dmdata_status_done(struct pipe_ctx *pipe_ctx)
1420 {
1421         struct hubp *hubp = pipe_ctx->plane_res.hubp;
1422 
1423         if (!hubp)
1424                 return false;
1425         return hubp->funcs->dmdata_status_done(hubp);
1426 }
1427 
1428 static void dcn20_disable_stream_gating(struct dc *dc, struct pipe_ctx *pipe_ctx)
1429 {
1430 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
1431         struct dce_hwseq *hws = dc->hwseq;
1432 
1433         if (pipe_ctx->stream_res.dsc) {
1434                 struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
1435 
1436                 dcn20_dsc_pg_control(hws, pipe_ctx->stream_res.dsc->inst, true);
1437                 while (odm_pipe) {
1438                         dcn20_dsc_pg_control(hws, odm_pipe->stream_res.dsc->inst, true);
1439                         odm_pipe = odm_pipe->next_odm_pipe;
1440                 }
1441         }
1442 #endif
1443 }
1444 
1445 static void dcn20_enable_stream_gating(struct dc *dc, struct pipe_ctx *pipe_ctx)
1446 {
1447 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
1448         struct dce_hwseq *hws = dc->hwseq;
1449 
1450         if (pipe_ctx->stream_res.dsc) {
1451                 struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
1452 
1453                 dcn20_dsc_pg_control(hws, pipe_ctx->stream_res.dsc->inst, false);
1454                 while (odm_pipe) {
1455                         dcn20_dsc_pg_control(hws, odm_pipe->stream_res.dsc->inst, false);
1456                         odm_pipe = odm_pipe->next_odm_pipe;
1457                 }
1458         }
1459 #endif
1460 }
1461 
1462 void dcn20_set_dmdata_attributes(struct pipe_ctx *pipe_ctx)
1463 {
1464         struct dc_dmdata_attributes attr = { 0 };
1465         struct hubp *hubp = pipe_ctx->plane_res.hubp;
1466 
1467         attr.dmdata_mode = DMDATA_HW_MODE;
1468         attr.dmdata_size =
1469                 dc_is_hdmi_signal(pipe_ctx->stream->signal) ? 32 : 36;
1470         attr.address.quad_part =
1471                         pipe_ctx->stream->dmdata_address.quad_part;
1472         attr.dmdata_dl_delta = 0;
1473         attr.dmdata_qos_mode = 0;
1474         attr.dmdata_qos_level = 0;
1475         attr.dmdata_repeat = 1; /* always repeat */
1476         attr.dmdata_updated = 1;
1477         attr.dmdata_sw_data = NULL;
1478 
1479         hubp->funcs->dmdata_set_attributes(hubp, &attr);
1480 }
1481 
1482 void dcn20_disable_stream(struct pipe_ctx *pipe_ctx)
1483 {
1484         dce110_disable_stream(pipe_ctx);
1485 }
1486 
1487 static void dcn20_init_vm_ctx(
1488                 struct dce_hwseq *hws,
1489                 struct dc *dc,
1490                 struct dc_virtual_addr_space_config *va_config,
1491                 int vmid)
1492 {
1493         struct dcn_hubbub_virt_addr_config config;
1494 
1495         if (vmid == 0) {
1496                 ASSERT(0); /* VMID cannot be 0 for vm context */
1497                 return;
1498         }
1499 
1500         config.page_table_start_addr = va_config->page_table_start_addr;
1501         config.page_table_end_addr = va_config->page_table_end_addr;
1502         config.page_table_block_size = va_config->page_table_block_size_in_bytes;
1503         config.page_table_depth = va_config->page_table_depth;
1504         config.page_table_base_addr = va_config->page_table_base_addr;
1505 
1506         dc->res_pool->hubbub->funcs->init_vm_ctx(dc->res_pool->hubbub, &config, vmid);
1507 }
1508 
1509 static int dcn20_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config)
1510 {
1511         struct dcn_hubbub_phys_addr_config config;
1512 
1513         config.system_aperture.fb_top = pa_config->system_aperture.fb_top;
1514         config.system_aperture.fb_offset = pa_config->system_aperture.fb_offset;
1515         config.system_aperture.fb_base = pa_config->system_aperture.fb_base;
1516         config.system_aperture.agp_top = pa_config->system_aperture.agp_top;
1517         config.system_aperture.agp_bot = pa_config->system_aperture.agp_bot;
1518         config.system_aperture.agp_base = pa_config->system_aperture.agp_base;
1519         config.gart_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr;
1520         config.gart_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr;
1521         config.gart_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr;
1522         config.page_table_default_page_addr = pa_config->page_table_default_page_addr;
1523 
1524         return dc->res_pool->hubbub->funcs->init_dchub_sys_ctx(dc->res_pool->hubbub, &config);
1525 }
1526 
1527 static bool patch_address_for_sbs_tb_stereo(
1528                 struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr)
1529 {
1530         struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1531         bool sec_split = pipe_ctx->top_pipe &&
1532                         pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state;
1533         if (sec_split && plane_state->address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
1534                         (pipe_ctx->stream->timing.timing_3d_format ==
1535                         TIMING_3D_FORMAT_SIDE_BY_SIDE ||
1536                         pipe_ctx->stream->timing.timing_3d_format ==
1537                         TIMING_3D_FORMAT_TOP_AND_BOTTOM)) {
1538                 *addr = plane_state->address.grph_stereo.left_addr;
1539                 plane_state->address.grph_stereo.left_addr =
1540                                 plane_state->address.grph_stereo.right_addr;
1541                 return true;
1542         }
1543 
1544         if (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_NONE &&
1545                         plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO) {
1546                 plane_state->address.type = PLN_ADDR_TYPE_GRPH_STEREO;
1547                 plane_state->address.grph_stereo.right_addr =
1548                                 plane_state->address.grph_stereo.left_addr;
1549         }
1550         return false;
1551 }
1552 
1553 
1554 static void dcn20_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx)
1555 {
1556         bool addr_patched = false;
1557         PHYSICAL_ADDRESS_LOC addr;
1558         struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1559 
1560         if (plane_state == NULL)
1561                 return;
1562 
1563         addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr);
1564 
1565         // Call Helper to track VMID use
1566         vm_helper_mark_vmid_used(dc->vm_helper, plane_state->address.vmid, pipe_ctx->plane_res.hubp->inst);
1567 
1568         pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr(
1569                         pipe_ctx->plane_res.hubp,
1570                         &plane_state->address,
1571                         plane_state->flip_immediate);
1572 
1573         plane_state->status.requested_address = plane_state->address;
1574 
1575         if (plane_state->flip_immediate)
1576                 plane_state->status.current_address = plane_state->address;
1577 
1578         if (addr_patched)
1579                 pipe_ctx->plane_state->address.grph_stereo.left_addr = addr;
1580 }
1581 
1582 void dcn20_unblank_stream(struct pipe_ctx *pipe_ctx,
1583                 struct dc_link_settings *link_settings)
1584 {
1585         struct encoder_unblank_param params = { { 0 } };
1586         struct dc_stream_state *stream = pipe_ctx->stream;
1587         struct dc_link *link = stream->link;
1588         struct pipe_ctx *odm_pipe;
1589 
1590         params.opp_cnt = 1;
1591         for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
1592                 params.opp_cnt++;
1593         }
1594         /* only 3 items below are used by unblank */
1595         params.timing = pipe_ctx->stream->timing;
1596 
1597         params.link_settings.link_rate = link_settings->link_rate;
1598 
1599         if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
1600                 if (optc1_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1)
1601                         params.timing.pix_clk_100hz /= 2;
1602                 pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine(
1603                                 pipe_ctx->stream_res.stream_enc, params.opp_cnt > 1);
1604                 pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, &params);
1605         }
1606 
1607         if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
1608                 link->dc->hwss.edp_backlight_control(link, true);
1609         }
1610 }
1611 
1612 void dcn20_setup_vupdate_interrupt(struct pipe_ctx *pipe_ctx)
1613 {
1614         struct timing_generator *tg = pipe_ctx->stream_res.tg;
1615         int start_line = get_vupdate_offset_from_vsync(pipe_ctx);
1616 
1617         if (start_line < 0)
1618                 start_line = 0;
1619 
1620         if (tg->funcs->setup_vertical_interrupt2)
1621                 tg->funcs->setup_vertical_interrupt2(tg, start_line);
1622 }
1623 
1624 static void dcn20_reset_back_end_for_pipe(
1625                 struct dc *dc,
1626                 struct pipe_ctx *pipe_ctx,
1627                 struct dc_state *context)
1628 {
1629         int i;
1630         DC_LOGGER_INIT(dc->ctx->logger);
1631         if (pipe_ctx->stream_res.stream_enc == NULL) {
1632                 pipe_ctx->stream = NULL;
1633                 return;
1634         }
1635 
1636         if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
1637                 /* DPMS may already disable */
1638                 if (!pipe_ctx->stream->dpms_off)
1639                         core_link_disable_stream(pipe_ctx);
1640                 else if (pipe_ctx->stream_res.audio)
1641                         dc->hwss.disable_audio_stream(pipe_ctx);
1642 
1643                 /* free acquired resources */
1644                 if (pipe_ctx->stream_res.audio) {
1645                         /*disable az_endpoint*/
1646                         pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
1647 
1648                         /*free audio*/
1649                         if (dc->caps.dynamic_audio == true) {
1650                                 /*we have to dynamic arbitrate the audio endpoints*/
1651                                 /*we free the resource, need reset is_audio_acquired*/
1652                                 update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
1653                                                 pipe_ctx->stream_res.audio, false);
1654                                 pipe_ctx->stream_res.audio = NULL;
1655                         }
1656                 }
1657         }
1658 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
1659         else if (pipe_ctx->stream_res.dsc) {
1660                 dp_set_dsc_enable(pipe_ctx, false);
1661         }
1662 #endif
1663 
1664         /* by upper caller loop, parent pipe: pipe0, will be reset last.
1665          * back end share by all pipes and will be disable only when disable
1666          * parent pipe.
1667          */
1668         if (pipe_ctx->top_pipe == NULL) {
1669                 pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
1670 
1671                 pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
1672                 if (pipe_ctx->stream_res.tg->funcs->set_odm_bypass)
1673                         pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
1674                                         pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
1675 
1676                 if (pipe_ctx->stream_res.tg->funcs->set_drr)
1677                         pipe_ctx->stream_res.tg->funcs->set_drr(
1678                                         pipe_ctx->stream_res.tg, NULL);
1679         }
1680 
1681         for (i = 0; i < dc->res_pool->pipe_count; i++)
1682                 if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx)
1683                         break;
1684 
1685         if (i == dc->res_pool->pipe_count)
1686                 return;
1687 
1688         pipe_ctx->stream = NULL;
1689         DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n",
1690                                         pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst);
1691 }
1692 
1693 static void dcn20_reset_hw_ctx_wrap(
1694                 struct dc *dc,
1695                 struct dc_state *context)
1696 {
1697         int i;
1698 
1699         /* Reset Back End*/
1700         for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
1701                 struct pipe_ctx *pipe_ctx_old =
1702                         &dc->current_state->res_ctx.pipe_ctx[i];
1703                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1704 
1705                 if (!pipe_ctx_old->stream)
1706                         continue;
1707 
1708                 if (pipe_ctx_old->top_pipe || pipe_ctx_old->prev_odm_pipe)
1709                         continue;
1710 
1711                 if (!pipe_ctx->stream ||
1712                                 pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
1713                         struct clock_source *old_clk = pipe_ctx_old->clock_source;
1714 
1715                         dcn20_reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state);
1716                         if (dc->hwss.enable_stream_gating)
1717                                 dc->hwss.enable_stream_gating(dc, pipe_ctx);
1718                         if (old_clk)
1719                                 old_clk->funcs->cs_power_down(old_clk);
1720                 }
1721         }
1722 }
1723 
1724 static void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
1725 {
1726         struct hubp *hubp = pipe_ctx->plane_res.hubp;
1727         struct mpcc_blnd_cfg blnd_cfg = { {0} };
1728         bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha;
1729         int mpcc_id;
1730         struct mpcc *new_mpcc;
1731         struct mpc *mpc = dc->res_pool->mpc;
1732         struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params);
1733 
1734         // input to MPCC is always RGB, by default leave black_color at 0
1735         if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR) {
1736                 dcn10_get_hdr_visual_confirm_color(
1737                                 pipe_ctx, &blnd_cfg.black_color);
1738         } else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) {
1739                 dcn10_get_surface_visual_confirm_color(
1740                                 pipe_ctx, &blnd_cfg.black_color);
1741         }
1742 
1743         if (per_pixel_alpha)
1744                 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
1745         else
1746                 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
1747 
1748         blnd_cfg.overlap_only = false;
1749         blnd_cfg.global_gain = 0xff;
1750 
1751         if (pipe_ctx->plane_state->global_alpha)
1752                 blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value;
1753         else
1754                 blnd_cfg.global_alpha = 0xff;
1755 
1756         blnd_cfg.background_color_bpc = 4;
1757         blnd_cfg.bottom_gain_mode = 0;
1758         blnd_cfg.top_gain = 0x1f000;
1759         blnd_cfg.bottom_inside_gain = 0x1f000;
1760         blnd_cfg.bottom_outside_gain = 0x1f000;
1761         blnd_cfg.pre_multiplied_alpha = per_pixel_alpha;
1762 
1763         /*
1764          * TODO: remove hack
1765          * Note: currently there is a bug in init_hw such that
1766          * on resume from hibernate, BIOS sets up MPCC0, and
1767          * we do mpcc_remove but the mpcc cannot go to idle
1768          * after remove. This cause us to pick mpcc1 here,
1769          * which causes a pstate hang for yet unknown reason.
1770          */
1771         mpcc_id = hubp->inst;
1772 
1773         /* If there is no full update, don't need to touch MPC tree*/
1774         if (!pipe_ctx->plane_state->update_flags.bits.full_update) {
1775                 mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id);
1776                 return;
1777         }
1778 
1779         /* check if this MPCC is already being used */
1780         new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id);
1781         /* remove MPCC if being used */
1782         if (new_mpcc != NULL)
1783                 mpc->funcs->remove_mpcc(mpc, mpc_tree_params, new_mpcc);
1784         else
1785                 if (dc->debug.sanity_checks)
1786                         mpc->funcs->assert_mpcc_idle_before_connect(
1787                                         dc->res_pool->mpc, mpcc_id);
1788 
1789         /* Call MPC to insert new plane */
1790         new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc,
1791                         mpc_tree_params,
1792                         &blnd_cfg,
1793                         NULL,
1794                         NULL,
1795                         hubp->inst,
1796                         mpcc_id);
1797 
1798         ASSERT(new_mpcc != NULL);
1799         hubp->opp_id = pipe_ctx->stream_res.opp->inst;
1800         hubp->mpcc_id = mpcc_id;
1801 }
1802 
1803 static int find_free_gsl_group(const struct dc *dc)
1804 {
1805         if (dc->res_pool->gsl_groups.gsl_0 == 0)
1806                 return 1;
1807         if (dc->res_pool->gsl_groups.gsl_1 == 0)
1808                 return 2;
1809         if (dc->res_pool->gsl_groups.gsl_2 == 0)
1810                 return 3;
1811 
1812         return 0;
1813 }
1814 
1815 /* NOTE: This is not a generic setup_gsl function (hence the suffix as_lock)
1816  * This is only used to lock pipes in pipe splitting case with immediate flip
1817  * Ordinary MPC/OTG locks suppress VUPDATE which doesn't help with immediate,
1818  * so we get tearing with freesync since we cannot flip multiple pipes
1819  * atomically.
1820  * We use GSL for this:
1821  * - immediate flip: find first available GSL group if not already assigned
1822  *                   program gsl with that group, set current OTG as master
1823  *                   and always us 0x4 = AND of flip_ready from all pipes
1824  * - vsync flip: disable GSL if used
1825  *
1826  * Groups in stream_res are stored as +1 from HW registers, i.e.
1827  * gsl_0 <=> pipe_ctx->stream_res.gsl_group == 1
1828  * Using a magic value like -1 would require tracking all inits/resets
1829  */
1830 void dcn20_setup_gsl_group_as_lock(
1831                 const struct dc *dc,
1832                 struct pipe_ctx *pipe_ctx,
1833                 bool enable)
1834 {
1835         struct gsl_params gsl;
1836         int group_idx;
1837 
1838         memset(&gsl, 0, sizeof(struct gsl_params));
1839 
1840         if (enable) {
1841                 /* return if group already assigned since GSL was set up
1842                  * for vsync flip, we would unassign so it can't be "left over"
1843                  */
1844                 if (pipe_ctx->stream_res.gsl_group > 0)
1845                         return;
1846 
1847                 group_idx = find_free_gsl_group(dc);
1848                 ASSERT(group_idx != 0);
1849                 pipe_ctx->stream_res.gsl_group = group_idx;
1850 
1851                 /* set gsl group reg field and mark resource used */
1852                 switch (group_idx) {
1853                 case 1:
1854                         gsl.gsl0_en = 1;
1855                         dc->res_pool->gsl_groups.gsl_0 = 1;
1856                         break;
1857                 case 2:
1858                         gsl.gsl1_en = 1;
1859                         dc->res_pool->gsl_groups.gsl_1 = 1;
1860                         break;
1861                 case 3:
1862                         gsl.gsl2_en = 1;
1863                         dc->res_pool->gsl_groups.gsl_2 = 1;
1864                         break;
1865                 default:
1866                         BREAK_TO_DEBUGGER();
1867                         return; // invalid case
1868                 }
1869                 gsl.gsl_master_en = 1;
1870         } else {
1871                 group_idx = pipe_ctx->stream_res.gsl_group;
1872                 if (group_idx == 0)
1873                         return; // if not in use, just return
1874 
1875                 pipe_ctx->stream_res.gsl_group = 0;
1876 
1877                 /* unset gsl group reg field and mark resource free */
1878                 switch (group_idx) {
1879                 case 1:
1880                         gsl.gsl0_en = 0;
1881                         dc->res_pool->gsl_groups.gsl_0 = 0;
1882                         break;
1883                 case 2:
1884                         gsl.gsl1_en = 0;
1885                         dc->res_pool->gsl_groups.gsl_1 = 0;
1886                         break;
1887                 case 3:
1888                         gsl.gsl2_en = 0;
1889                         dc->res_pool->gsl_groups.gsl_2 = 0;
1890                         break;
1891                 default:
1892                         BREAK_TO_DEBUGGER();
1893                         return;
1894                 }
1895                 gsl.gsl_master_en = 0;
1896         }
1897 
1898         /* at this point we want to program whether it's to enable or disable */
1899         if (pipe_ctx->stream_res.tg->funcs->set_gsl != NULL &&
1900                 pipe_ctx->stream_res.tg->funcs->set_gsl_source_select != NULL) {
1901                 pipe_ctx->stream_res.tg->funcs->set_gsl(
1902                         pipe_ctx->stream_res.tg,
1903                         &gsl);
1904 
1905                 pipe_ctx->stream_res.tg->funcs->set_gsl_source_select(
1906                         pipe_ctx->stream_res.tg, group_idx,     enable ? 4 : 0);
1907         } else
1908                 BREAK_TO_DEBUGGER();
1909 }
1910 
1911 static void dcn20_set_flip_control_gsl(
1912                 struct pipe_ctx *pipe_ctx,
1913                 bool flip_immediate)
1914 {
1915         if (pipe_ctx && pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_control_surface_gsl)
1916                 pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_control_surface_gsl(
1917                                 pipe_ctx->plane_res.hubp, flip_immediate);
1918 
1919 }
1920 
1921 static void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
1922 {
1923         enum dc_lane_count lane_count =
1924                 pipe_ctx->stream->link->cur_link_settings.lane_count;
1925 
1926         struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
1927         struct dc_link *link = pipe_ctx->stream->link;
1928 
1929         uint32_t active_total_with_borders;
1930         uint32_t early_control = 0;
1931         struct timing_generator *tg = pipe_ctx->stream_res.tg;
1932 
1933         /* For MST, there are multiply stream go to only one link.
1934          * connect DIG back_end to front_end while enable_stream and
1935          * disconnect them during disable_stream
1936          * BY this, it is logic clean to separate stream and link
1937          */
1938         link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
1939                                                     pipe_ctx->stream_res.stream_enc->id, true);
1940 
1941         if (link->dc->hwss.program_dmdata_engine)
1942                 link->dc->hwss.program_dmdata_engine(pipe_ctx);
1943 
1944         link->dc->hwss.update_info_frame(pipe_ctx);
1945 
1946         /* enable early control to avoid corruption on DP monitor*/
1947         active_total_with_borders =
1948                         timing->h_addressable
1949                                 + timing->h_border_left
1950                                 + timing->h_border_right;
1951 
1952         if (lane_count != 0)
1953                 early_control = active_total_with_borders % lane_count;
1954 
1955         if (early_control == 0)
1956                 early_control = lane_count;
1957 
1958         tg->funcs->set_early_control(tg, early_control);
1959 
1960         /* enable audio only within mode set */
1961         if (pipe_ctx->stream_res.audio != NULL) {
1962                 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1963                         pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
1964         }
1965 }
1966 
1967 static void dcn20_program_dmdata_engine(struct pipe_ctx *pipe_ctx)
1968 {
1969         struct dc_stream_state    *stream     = pipe_ctx->stream;
1970         struct hubp               *hubp       = pipe_ctx->plane_res.hubp;
1971         bool                       enable     = false;
1972         struct stream_encoder     *stream_enc = pipe_ctx->stream_res.stream_enc;
1973         enum dynamic_metadata_mode mode       = dc_is_dp_signal(stream->signal)
1974                                                         ? dmdata_dp
1975                                                         : dmdata_hdmi;
1976 
1977         /* if using dynamic meta, don't set up generic infopackets */
1978         if (pipe_ctx->stream->dmdata_address.quad_part != 0) {
1979                 pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false;
1980                 enable = true;
1981         }
1982 
1983         if (!hubp)
1984                 return;
1985 
1986         if (!stream_enc || !stream_enc->funcs->set_dynamic_metadata)
1987                 return;
1988 
1989         stream_enc->funcs->set_dynamic_metadata(stream_enc, enable,
1990                                                 hubp->inst, mode);
1991 }
1992 
1993 static void dcn20_fpga_init_hw(struct dc *dc)
1994 {
1995         int i, j;
1996         struct dce_hwseq *hws = dc->hwseq;
1997         struct resource_pool *res_pool = dc->res_pool;
1998         struct dc_state  *context = dc->current_state;
1999 
2000         if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
2001                 dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
2002 
2003         // Initialize the dccg
2004         if (res_pool->dccg->funcs->dccg_init)
2005                 res_pool->dccg->funcs->dccg_init(res_pool->dccg);
2006 
2007         //Enable ability to power gate / don't force power on permanently
2008         dc->hwss.enable_power_gating_plane(hws, true);
2009 
2010         // Specific to FPGA dccg and registers
2011         REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF);
2012         REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF);
2013 
2014         dcn20_dccg_init(hws);
2015 
2016         REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2);
2017         REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
2018         if (REG(REFCLK_CNTL))
2019                 REG_WRITE(REFCLK_CNTL, 0);
2020         //
2021 
2022 
2023         /* Blank pixel data with OPP DPG */
2024         for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
2025                 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2026 
2027                 if (tg->funcs->is_tg_enabled(tg))
2028                         dcn20_init_blank(dc, tg);
2029         }
2030 
2031         for (i = 0; i < res_pool->timing_generator_count; i++) {
2032                 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2033 
2034                 if (tg->funcs->is_tg_enabled(tg))
2035                         tg->funcs->lock(tg);
2036         }
2037 
2038         for (i = 0; i < dc->res_pool->pipe_count; i++) {
2039                 struct dpp *dpp = res_pool->dpps[i];
2040 
2041                 dpp->funcs->dpp_reset(dpp);
2042         }
2043 
2044         /* Reset all MPCC muxes */
2045         res_pool->mpc->funcs->mpc_init(res_pool->mpc);
2046 
2047         /* initialize OPP mpc_tree parameter */
2048         for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) {
2049                 res_pool->opps[i]->mpc_tree_params.opp_id = res_pool->opps[i]->inst;
2050                 res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
2051                 for (j = 0; j < MAX_PIPES; j++)
2052                         res_pool->opps[i]->mpcc_disconnect_pending[j] = false;
2053         }
2054 
2055         for (i = 0; i < dc->res_pool->pipe_count; i++) {
2056                 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2057                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2058                 struct hubp *hubp = dc->res_pool->hubps[i];
2059                 struct dpp *dpp = dc->res_pool->dpps[i];
2060 
2061                 pipe_ctx->stream_res.tg = tg;
2062                 pipe_ctx->pipe_idx = i;
2063 
2064                 pipe_ctx->plane_res.hubp = hubp;
2065                 pipe_ctx->plane_res.dpp = dpp;
2066                 pipe_ctx->plane_res.mpcc_inst = dpp->inst;
2067                 hubp->mpcc_id = dpp->inst;
2068                 hubp->opp_id = OPP_ID_INVALID;
2069                 hubp->power_gated = false;
2070                 pipe_ctx->stream_res.opp = NULL;
2071 
2072                 hubp->funcs->hubp_init(hubp);
2073 
2074                 //dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst;
2075                 //dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
2076                 dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
2077                 pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
2078                 /*to do*/
2079                 hwss1_plane_atomic_disconnect(dc, pipe_ctx);
2080         }
2081 
2082         /* initialize DWB pointer to MCIF_WB */
2083         for (i = 0; i < res_pool->res_cap->num_dwb; i++)
2084                 res_pool->dwbc[i]->mcif = res_pool->mcif_wb[i];
2085 
2086         for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
2087                 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2088 
2089                 if (tg->funcs->is_tg_enabled(tg))
2090                         tg->funcs->unlock(tg);
2091         }
2092 
2093         for (i = 0; i < dc->res_pool->pipe_count; i++) {
2094                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2095 
2096                 dc->hwss.disable_plane(dc, pipe_ctx);
2097 
2098                 pipe_ctx->stream_res.tg = NULL;
2099                 pipe_ctx->plane_res.hubp = NULL;
2100         }
2101 
2102         for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
2103                 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2104 
2105                 tg->funcs->tg_init(tg);
2106         }
2107 }
2108 
2109 void dcn20_hw_sequencer_construct(struct dc *dc)
2110 {
2111         dcn10_hw_sequencer_construct(dc);
2112         dc->hwss.unblank_stream = dcn20_unblank_stream;
2113         dc->hwss.update_plane_addr = dcn20_update_plane_addr;
2114         dc->hwss.enable_stream_timing = dcn20_enable_stream_timing;
2115         dc->hwss.program_triplebuffer = dcn20_program_tripleBuffer;
2116         dc->hwss.set_input_transfer_func = dcn20_set_input_transfer_func;
2117         dc->hwss.set_output_transfer_func = dcn20_set_output_transfer_func;
2118         dc->hwss.apply_ctx_for_surface = dcn20_apply_ctx_for_surface;
2119         dc->hwss.pipe_control_lock = dcn20_pipe_control_lock;
2120         dc->hwss.pipe_control_lock_global = dcn20_pipe_control_lock_global;
2121         dc->hwss.optimize_bandwidth = dcn20_optimize_bandwidth;
2122         dc->hwss.prepare_bandwidth = dcn20_prepare_bandwidth;
2123         dc->hwss.update_bandwidth = dcn20_update_bandwidth;
2124         dc->hwss.enable_writeback = dcn20_enable_writeback;
2125         dc->hwss.disable_writeback = dcn20_disable_writeback;
2126         dc->hwss.program_output_csc = dcn20_program_output_csc;
2127         dc->hwss.update_odm = dcn20_update_odm;
2128         dc->hwss.blank_pixel_data = dcn20_blank_pixel_data;
2129         dc->hwss.dmdata_status_done = dcn20_dmdata_status_done;
2130         dc->hwss.program_dmdata_engine = dcn20_program_dmdata_engine;
2131         dc->hwss.enable_stream = dcn20_enable_stream;
2132         dc->hwss.disable_stream = dcn20_disable_stream;
2133         dc->hwss.init_sys_ctx = dcn20_init_sys_ctx;
2134         dc->hwss.init_vm_ctx = dcn20_init_vm_ctx;
2135         dc->hwss.disable_stream_gating = dcn20_disable_stream_gating;
2136         dc->hwss.enable_stream_gating = dcn20_enable_stream_gating;
2137         dc->hwss.setup_vupdate_interrupt = dcn20_setup_vupdate_interrupt;
2138         dc->hwss.reset_hw_ctx_wrap = dcn20_reset_hw_ctx_wrap;
2139         dc->hwss.update_mpcc = dcn20_update_mpcc;
2140         dc->hwss.set_flip_control_gsl = dcn20_set_flip_control_gsl;
2141         dc->hwss.init_blank = dcn20_init_blank;
2142         dc->hwss.disable_plane = dcn20_disable_plane;
2143         dc->hwss.plane_atomic_disable = dcn20_plane_atomic_disable;
2144         dc->hwss.enable_power_gating_plane = dcn20_enable_power_gating_plane;
2145         dc->hwss.dpp_pg_control = dcn20_dpp_pg_control;
2146         dc->hwss.hubp_pg_control = dcn20_hubp_pg_control;
2147 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
2148         dc->hwss.dsc_pg_control = dcn20_dsc_pg_control;
2149 #else
2150         dc->hwss.dsc_pg_control = NULL;
2151 #endif
2152         dc->hwss.disable_vga = dcn20_disable_vga;
2153 
2154         if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
2155                 dc->hwss.init_hw = dcn20_fpga_init_hw;
2156                 dc->hwss.init_pipes = NULL;
2157         }
2158 
2159 
2160 }

/* [<][>][^][v][top][bottom][index][help] */