1 /* 2 * Copyright 2012-15 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: AMD 23 * 24 */ 25 26 #include "dm_services.h" 27 28 #include "link_encoder.h" 29 #include "stream_encoder.h" 30 31 #include "resource.h" 32 #include "dce110/dce110_resource.h" 33 34 #include "include/irq_service_interface.h" 35 #include "dce/dce_audio.h" 36 #include "dce110/dce110_timing_generator.h" 37 #include "irq/dce110/irq_service_dce110.h" 38 #include "dce110/dce110_timing_generator_v.h" 39 #include "dce/dce_link_encoder.h" 40 #include "dce/dce_stream_encoder.h" 41 #include "dce110/dce110_mem_input.h" 42 #include "dce110/dce110_mem_input_v.h" 43 #include "dce/dce_ipp.h" 44 #include "dce/dce_transform.h" 45 #include "dce110/dce110_transform_v.h" 46 #include "dce/dce_opp.h" 47 #include "dce110/dce110_opp_v.h" 48 #include "dce/dce_clocks.h" 49 #include "dce/dce_clock_source.h" 50 #include "dce/dce_hwseq.h" 51 #include "dce110/dce110_hw_sequencer.h" 52 #include "dce/dce_abm.h" 53 #include "dce/dce_dmcu.h" 54 55 #include "reg_helper.h" 56 57 #include "dce/dce_11_0_d.h" 58 #include "dce/dce_11_0_sh_mask.h" 59 60 #ifndef mmMC_HUB_RDREQ_DMIF_LIMIT 61 #include "gmc/gmc_8_2_d.h" 62 #include "gmc/gmc_8_2_sh_mask.h" 63 #endif 64 65 #ifndef mmDP_DPHY_INTERNAL_CTRL 66 #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 67 #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 68 #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7 69 #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7 70 #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7 71 #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7 72 #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7 73 #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7 74 #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7 75 #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7 76 #endif 77 78 #ifndef mmBIOS_SCRATCH_2 79 #define mmBIOS_SCRATCH_2 0x05CB 80 #define mmBIOS_SCRATCH_6 0x05CF 81 #endif 82 83 #ifndef mmDP_DPHY_BS_SR_SWAP_CNTL 84 #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC 85 #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC 86 #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC 87 #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC 88 #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC 89 #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC 90 #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC 91 #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC 92 #endif 93 94 #ifndef mmDP_DPHY_FAST_TRAINING 95 #define mmDP_DPHY_FAST_TRAINING 0x4ABC 96 #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC 97 #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC 98 #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC 99 #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC 100 #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC 101 #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC 102 #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC 103 #endif 104 105 #ifndef DPHY_RX_FAST_TRAINING_CAPABLE 106 #define DPHY_RX_FAST_TRAINING_CAPABLE 0x1 107 #endif 108 109 static const struct dce110_timing_generator_offsets dce110_tg_offsets[] = { 110 { 111 .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), 112 .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), 113 }, 114 { 115 .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), 116 .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), 117 }, 118 { 119 .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), 120 .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), 121 }, 122 { 123 .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), 124 .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), 125 }, 126 { 127 .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), 128 .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), 129 }, 130 { 131 .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), 132 .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), 133 } 134 }; 135 136 static const struct dce110_mem_input_reg_offsets dce110_mi_reg_offsets[] = { 137 { 138 .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), 139 .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL 140 - mmDPG_WATERMARK_MASK_CONTROL), 141 .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL 142 - mmPIPE0_DMIF_BUFFER_CONTROL), 143 }, 144 { 145 .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), 146 .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL 147 - mmDPG_WATERMARK_MASK_CONTROL), 148 .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL 149 - mmPIPE0_DMIF_BUFFER_CONTROL), 150 }, 151 { 152 .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), 153 .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL 154 - mmDPG_WATERMARK_MASK_CONTROL), 155 .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL 156 - mmPIPE0_DMIF_BUFFER_CONTROL), 157 } 158 }; 159 160 /* set register offset */ 161 #define SR(reg_name)\ 162 .reg_name = mm ## reg_name 163 164 /* set register offset with instance */ 165 #define SRI(reg_name, block, id)\ 166 .reg_name = mm ## block ## id ## _ ## reg_name 167 168 static const struct dce_disp_clk_registers disp_clk_regs = { 169 CLK_COMMON_REG_LIST_DCE_BASE() 170 }; 171 172 static const struct dce_disp_clk_shift disp_clk_shift = { 173 CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) 174 }; 175 176 static const struct dce_disp_clk_mask disp_clk_mask = { 177 CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) 178 }; 179 180 static const struct dce_dmcu_registers dmcu_regs = { 181 DMCU_DCE110_COMMON_REG_LIST() 182 }; 183 184 static const struct dce_dmcu_shift dmcu_shift = { 185 DMCU_MASK_SH_LIST_DCE110(__SHIFT) 186 }; 187 188 static const struct dce_dmcu_mask dmcu_mask = { 189 DMCU_MASK_SH_LIST_DCE110(_MASK) 190 }; 191 192 static const struct dce_abm_registers abm_regs = { 193 ABM_DCE110_COMMON_REG_LIST() 194 }; 195 196 static const struct dce_abm_shift abm_shift = { 197 ABM_MASK_SH_LIST_DCE110(__SHIFT) 198 }; 199 200 static const struct dce_abm_mask abm_mask = { 201 ABM_MASK_SH_LIST_DCE110(_MASK) 202 }; 203 204 #define ipp_regs(id)\ 205 [id] = {\ 206 IPP_DCE110_REG_LIST_DCE_BASE(id)\ 207 } 208 209 static const struct dce_ipp_registers ipp_regs[] = { 210 ipp_regs(0), 211 ipp_regs(1), 212 ipp_regs(2) 213 }; 214 215 static const struct dce_ipp_shift ipp_shift = { 216 IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) 217 }; 218 219 static const struct dce_ipp_mask ipp_mask = { 220 IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) 221 }; 222 223 #define transform_regs(id)\ 224 [id] = {\ 225 XFM_COMMON_REG_LIST_DCE110(id)\ 226 } 227 228 static const struct dce_transform_registers xfm_regs[] = { 229 transform_regs(0), 230 transform_regs(1), 231 transform_regs(2) 232 }; 233 234 static const struct dce_transform_shift xfm_shift = { 235 XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT) 236 }; 237 238 static const struct dce_transform_mask xfm_mask = { 239 XFM_COMMON_MASK_SH_LIST_DCE110(_MASK) 240 }; 241 242 #define aux_regs(id)\ 243 [id] = {\ 244 AUX_REG_LIST(id)\ 245 } 246 247 static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { 248 aux_regs(0), 249 aux_regs(1), 250 aux_regs(2), 251 aux_regs(3), 252 aux_regs(4), 253 aux_regs(5) 254 }; 255 256 #define hpd_regs(id)\ 257 [id] = {\ 258 HPD_REG_LIST(id)\ 259 } 260 261 static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { 262 hpd_regs(0), 263 hpd_regs(1), 264 hpd_regs(2), 265 hpd_regs(3), 266 hpd_regs(4), 267 hpd_regs(5) 268 }; 269 270 271 #define link_regs(id)\ 272 [id] = {\ 273 LE_DCE110_REG_LIST(id)\ 274 } 275 276 static const struct dce110_link_enc_registers link_enc_regs[] = { 277 link_regs(0), 278 link_regs(1), 279 link_regs(2), 280 link_regs(3), 281 link_regs(4), 282 link_regs(5), 283 link_regs(6), 284 }; 285 286 #define stream_enc_regs(id)\ 287 [id] = {\ 288 SE_COMMON_REG_LIST(id),\ 289 .TMDS_CNTL = 0,\ 290 } 291 292 static const struct dce110_stream_enc_registers stream_enc_regs[] = { 293 stream_enc_regs(0), 294 stream_enc_regs(1), 295 stream_enc_regs(2) 296 }; 297 298 static const struct dce_stream_encoder_shift se_shift = { 299 SE_COMMON_MASK_SH_LIST_DCE110(__SHIFT) 300 }; 301 302 static const struct dce_stream_encoder_mask se_mask = { 303 SE_COMMON_MASK_SH_LIST_DCE110(_MASK) 304 }; 305 306 #define opp_regs(id)\ 307 [id] = {\ 308 OPP_DCE_110_REG_LIST(id),\ 309 } 310 311 static const struct dce_opp_registers opp_regs[] = { 312 opp_regs(0), 313 opp_regs(1), 314 opp_regs(2), 315 opp_regs(3), 316 opp_regs(4), 317 opp_regs(5) 318 }; 319 320 static const struct dce_opp_shift opp_shift = { 321 OPP_COMMON_MASK_SH_LIST_DCE_110(__SHIFT) 322 }; 323 324 static const struct dce_opp_mask opp_mask = { 325 OPP_COMMON_MASK_SH_LIST_DCE_110(_MASK) 326 }; 327 328 #define audio_regs(id)\ 329 [id] = {\ 330 AUD_COMMON_REG_LIST(id)\ 331 } 332 333 static const struct dce_audio_registers audio_regs[] = { 334 audio_regs(0), 335 audio_regs(1), 336 audio_regs(2), 337 audio_regs(3), 338 audio_regs(4), 339 audio_regs(5), 340 audio_regs(6), 341 }; 342 343 static const struct dce_audio_shift audio_shift = { 344 AUD_COMMON_MASK_SH_LIST(__SHIFT) 345 }; 346 347 static const struct dce_aduio_mask audio_mask = { 348 AUD_COMMON_MASK_SH_LIST(_MASK) 349 }; 350 351 /* AG TBD Needs to be reduced back to 3 pipes once dce10 hw sequencer implemented. */ 352 353 354 #define clk_src_regs(id)\ 355 [id] = {\ 356 CS_COMMON_REG_LIST_DCE_100_110(id),\ 357 } 358 359 static const struct dce110_clk_src_regs clk_src_regs[] = { 360 clk_src_regs(0), 361 clk_src_regs(1), 362 clk_src_regs(2) 363 }; 364 365 static const struct dce110_clk_src_shift cs_shift = { 366 CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) 367 }; 368 369 static const struct dce110_clk_src_mask cs_mask = { 370 CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) 371 }; 372 373 static const struct bios_registers bios_regs = { 374 .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 375 }; 376 377 static const struct resource_caps carrizo_resource_cap = { 378 .num_timing_generator = 3, 379 .num_video_plane = 1, 380 .num_audio = 3, 381 .num_stream_encoder = 3, 382 .num_pll = 2, 383 }; 384 385 static const struct resource_caps stoney_resource_cap = { 386 .num_timing_generator = 2, 387 .num_video_plane = 1, 388 .num_audio = 3, 389 .num_stream_encoder = 3, 390 .num_pll = 2, 391 }; 392 393 #define CTX ctx 394 #define REG(reg) mm ## reg 395 396 #ifndef mmCC_DC_HDMI_STRAPS 397 #define mmCC_DC_HDMI_STRAPS 0x4819 398 #define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 399 #define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 400 #define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 401 #define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 402 #endif 403 404 static void read_dce_straps( 405 struct dc_context *ctx, 406 struct resource_straps *straps) 407 { 408 REG_GET_2(CC_DC_HDMI_STRAPS, 409 HDMI_DISABLE, &straps->hdmi_disable, 410 AUDIO_STREAM_NUMBER, &straps->audio_stream_number); 411 412 REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); 413 } 414 415 static struct audio *create_audio( 416 struct dc_context *ctx, unsigned int inst) 417 { 418 return dce_audio_create(ctx, inst, 419 &audio_regs[inst], &audio_shift, &audio_mask); 420 } 421 422 static struct timing_generator *dce110_timing_generator_create( 423 struct dc_context *ctx, 424 uint32_t instance, 425 const struct dce110_timing_generator_offsets *offsets) 426 { 427 struct dce110_timing_generator *tg110 = 428 dm_alloc(sizeof(struct dce110_timing_generator)); 429 430 if (!tg110) 431 return NULL; 432 433 if (dce110_timing_generator_construct(tg110, ctx, instance, offsets)) 434 return &tg110->base; 435 436 BREAK_TO_DEBUGGER(); 437 dm_free(tg110); 438 return NULL; 439 } 440 441 static struct stream_encoder *dce110_stream_encoder_create( 442 enum engine_id eng_id, 443 struct dc_context *ctx) 444 { 445 struct dce110_stream_encoder *enc110 = 446 dm_alloc(sizeof(struct dce110_stream_encoder)); 447 448 if (!enc110) 449 return NULL; 450 451 if (dce110_stream_encoder_construct( 452 enc110, ctx, ctx->dc_bios, eng_id, 453 &stream_enc_regs[eng_id], &se_shift, &se_mask)) 454 return &enc110->base; 455 456 BREAK_TO_DEBUGGER(); 457 dm_free(enc110); 458 return NULL; 459 } 460 461 #define SRII(reg_name, block, id)\ 462 .reg_name[id] = mm ## block ## id ## _ ## reg_name 463 464 static const struct dce_hwseq_registers hwseq_stoney_reg = { 465 HWSEQ_ST_REG_LIST() 466 }; 467 468 static const struct dce_hwseq_registers hwseq_cz_reg = { 469 HWSEQ_CZ_REG_LIST() 470 }; 471 472 static const struct dce_hwseq_shift hwseq_shift = { 473 HWSEQ_DCE11_MASK_SH_LIST(__SHIFT), 474 }; 475 476 static const struct dce_hwseq_mask hwseq_mask = { 477 HWSEQ_DCE11_MASK_SH_LIST(_MASK), 478 }; 479 480 static struct dce_hwseq *dce110_hwseq_create( 481 struct dc_context *ctx) 482 { 483 struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); 484 485 if (hws) { 486 hws->ctx = ctx; 487 hws->regs = ASIC_REV_IS_STONEY(ctx->asic_id.hw_internal_rev) ? 488 &hwseq_stoney_reg : &hwseq_cz_reg; 489 hws->shifts = &hwseq_shift; 490 hws->masks = &hwseq_mask; 491 hws->wa.blnd_crtc_trigger = true; 492 } 493 return hws; 494 } 495 496 static const struct resource_create_funcs res_create_funcs = { 497 .read_dce_straps = read_dce_straps, 498 .create_audio = create_audio, 499 .create_stream_encoder = dce110_stream_encoder_create, 500 .create_hwseq = dce110_hwseq_create, 501 }; 502 503 #define mi_inst_regs(id) { \ 504 MI_DCE11_REG_LIST(id), \ 505 .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ 506 } 507 static const struct dce_mem_input_registers mi_regs[] = { 508 mi_inst_regs(0), 509 mi_inst_regs(1), 510 mi_inst_regs(2), 511 }; 512 513 static const struct dce_mem_input_shift mi_shifts = { 514 MI_DCE11_MASK_SH_LIST(__SHIFT), 515 .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT 516 }; 517 518 static const struct dce_mem_input_mask mi_masks = { 519 MI_DCE11_MASK_SH_LIST(_MASK), 520 .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK 521 }; 522 523 static struct mem_input *dce110_mem_input_create( 524 struct dc_context *ctx, 525 uint32_t inst, 526 const struct dce110_mem_input_reg_offsets *offset) 527 { 528 struct dce110_mem_input *mem_input110 = 529 dm_alloc(sizeof(struct dce110_mem_input)); 530 531 if (!mem_input110) 532 return NULL; 533 534 if (dce110_mem_input_construct(mem_input110, ctx, inst, offset)) { 535 struct mem_input *mi = &mem_input110->base; 536 537 mi->regs = &mi_regs[inst]; 538 mi->shifts = &mi_shifts; 539 mi->masks = &mi_masks; 540 mi->wa.single_head_rdreq_dmif_limit = 3; 541 return mi; 542 } 543 544 BREAK_TO_DEBUGGER(); 545 dm_free(mem_input110); 546 return NULL; 547 } 548 549 static void dce110_transform_destroy(struct transform **xfm) 550 { 551 dm_free(TO_DCE_TRANSFORM(*xfm)); 552 *xfm = NULL; 553 } 554 555 static struct transform *dce110_transform_create( 556 struct dc_context *ctx, 557 uint32_t inst) 558 { 559 struct dce_transform *transform = 560 dm_alloc(sizeof(struct dce_transform)); 561 562 if (!transform) 563 return NULL; 564 565 if (dce_transform_construct(transform, ctx, inst, 566 &xfm_regs[inst], &xfm_shift, &xfm_mask)) 567 return &transform->base; 568 569 BREAK_TO_DEBUGGER(); 570 dm_free(transform); 571 return NULL; 572 } 573 574 static struct input_pixel_processor *dce110_ipp_create( 575 struct dc_context *ctx, uint32_t inst) 576 { 577 struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); 578 579 if (!ipp) { 580 BREAK_TO_DEBUGGER(); 581 return NULL; 582 } 583 584 dce_ipp_construct(ipp, ctx, inst, 585 &ipp_regs[inst], &ipp_shift, &ipp_mask); 586 return &ipp->base; 587 } 588 589 static const struct encoder_feature_support link_enc_feature = { 590 .max_hdmi_deep_color = COLOR_DEPTH_121212, 591 .max_hdmi_pixel_clock = 594000, 592 .flags.bits.IS_HBR2_CAPABLE = true, 593 .flags.bits.IS_TPS3_CAPABLE = true, 594 .flags.bits.IS_YCBCR_CAPABLE = true 595 }; 596 597 struct link_encoder *dce110_link_encoder_create( 598 const struct encoder_init_data *enc_init_data) 599 { 600 struct dce110_link_encoder *enc110 = 601 dm_alloc(sizeof(struct dce110_link_encoder)); 602 603 if (!enc110) 604 return NULL; 605 606 if (dce110_link_encoder_construct( 607 enc110, 608 enc_init_data, 609 &link_enc_feature, 610 &link_enc_regs[enc_init_data->transmitter], 611 &link_enc_aux_regs[enc_init_data->channel - 1], 612 &link_enc_hpd_regs[enc_init_data->hpd_source])) { 613 614 return &enc110->base; 615 } 616 617 BREAK_TO_DEBUGGER(); 618 dm_free(enc110); 619 return NULL; 620 } 621 622 static struct output_pixel_processor *dce110_opp_create( 623 struct dc_context *ctx, 624 uint32_t inst) 625 { 626 struct dce110_opp *opp = 627 dm_alloc(sizeof(struct dce110_opp)); 628 629 if (!opp) 630 return NULL; 631 632 if (dce110_opp_construct(opp, 633 ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) 634 return &opp->base; 635 636 BREAK_TO_DEBUGGER(); 637 dm_free(opp); 638 return NULL; 639 } 640 641 struct clock_source *dce110_clock_source_create( 642 struct dc_context *ctx, 643 struct dc_bios *bios, 644 enum clock_source_id id, 645 const struct dce110_clk_src_regs *regs, 646 bool dp_clk_src) 647 { 648 struct dce110_clk_src *clk_src = 649 dm_alloc(sizeof(struct dce110_clk_src)); 650 651 if (!clk_src) 652 return NULL; 653 654 if (dce110_clk_src_construct(clk_src, ctx, bios, id, 655 regs, &cs_shift, &cs_mask)) { 656 clk_src->base.dp_clk_src = dp_clk_src; 657 return &clk_src->base; 658 } 659 660 BREAK_TO_DEBUGGER(); 661 return NULL; 662 } 663 664 void dce110_clock_source_destroy(struct clock_source **clk_src) 665 { 666 struct dce110_clk_src *dce110_clk_src; 667 668 if (!clk_src) 669 return; 670 671 dce110_clk_src = TO_DCE110_CLK_SRC(*clk_src); 672 673 if (dce110_clk_src->dp_ss_params) 674 dm_free(dce110_clk_src->dp_ss_params); 675 676 if (dce110_clk_src->hdmi_ss_params) 677 dm_free(dce110_clk_src->hdmi_ss_params); 678 679 if (dce110_clk_src->dvi_ss_params) 680 dm_free(dce110_clk_src->dvi_ss_params); 681 682 dm_free(dce110_clk_src); 683 *clk_src = NULL; 684 } 685 686 static void destruct(struct dce110_resource_pool *pool) 687 { 688 unsigned int i; 689 690 for (i = 0; i < pool->base.pipe_count; i++) { 691 if (pool->base.opps[i] != NULL) 692 dce110_opp_destroy(&pool->base.opps[i]); 693 694 if (pool->base.transforms[i] != NULL) 695 dce110_transform_destroy(&pool->base.transforms[i]); 696 697 if (pool->base.ipps[i] != NULL) 698 dce_ipp_destroy(&pool->base.ipps[i]); 699 700 if (pool->base.mis[i] != NULL) { 701 dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); 702 pool->base.mis[i] = NULL; 703 } 704 705 if (pool->base.timing_generators[i] != NULL) { 706 dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); 707 pool->base.timing_generators[i] = NULL; 708 } 709 } 710 711 for (i = 0; i < pool->base.stream_enc_count; i++) { 712 if (pool->base.stream_enc[i] != NULL) 713 dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); 714 } 715 716 for (i = 0; i < pool->base.clk_src_count; i++) { 717 if (pool->base.clock_sources[i] != NULL) { 718 dce110_clock_source_destroy(&pool->base.clock_sources[i]); 719 } 720 } 721 722 if (pool->base.dp_clock_source != NULL) 723 dce110_clock_source_destroy(&pool->base.dp_clock_source); 724 725 for (i = 0; i < pool->base.audio_count; i++) { 726 if (pool->base.audios[i] != NULL) { 727 dce_aud_destroy(&pool->base.audios[i]); 728 } 729 } 730 731 if (pool->base.abm != NULL) 732 dce_abm_destroy(&pool->base.abm); 733 734 if (pool->base.dmcu != NULL) 735 dce_dmcu_destroy(&pool->base.dmcu); 736 737 if (pool->base.display_clock != NULL) 738 dce_disp_clk_destroy(&pool->base.display_clock); 739 740 if (pool->base.irqs != NULL) { 741 dal_irq_service_destroy(&pool->base.irqs); 742 } 743 } 744 745 746 static void get_pixel_clock_parameters( 747 const struct pipe_ctx *pipe_ctx, 748 struct pixel_clk_params *pixel_clk_params) 749 { 750 const struct core_stream *stream = pipe_ctx->stream; 751 752 /*TODO: is this halved for YCbCr 420? in that case we might want to move 753 * the pixel clock normalization for hdmi up to here instead of doing it 754 * in pll_adjust_pix_clk 755 */ 756 pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz; 757 pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id; 758 pixel_clk_params->signal_type = pipe_ctx->stream->signal; 759 pixel_clk_params->controller_id = pipe_ctx->pipe_idx + 1; 760 /* TODO: un-hardcode*/ 761 pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * 762 LINK_RATE_REF_FREQ_IN_KHZ; 763 pixel_clk_params->flags.ENABLE_SS = 0; 764 pixel_clk_params->color_depth = 765 stream->public.timing.display_color_depth; 766 pixel_clk_params->flags.DISPLAY_BLANKED = 1; 767 pixel_clk_params->flags.SUPPORT_YCBCR420 = (stream->public.timing.pixel_encoding == 768 PIXEL_ENCODING_YCBCR420); 769 pixel_clk_params->pixel_encoding = stream->public.timing.pixel_encoding; 770 if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) { 771 pixel_clk_params->color_depth = COLOR_DEPTH_888; 772 } 773 if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { 774 pixel_clk_params->requested_pix_clk = pixel_clk_params->requested_pix_clk / 2; 775 } 776 } 777 778 enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) 779 { 780 get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->pix_clk_params); 781 pipe_ctx->clock_source->funcs->get_pix_clk_dividers( 782 pipe_ctx->clock_source, 783 &pipe_ctx->pix_clk_params, 784 &pipe_ctx->pll_settings); 785 resource_build_bit_depth_reduction_params(pipe_ctx->stream, 786 &pipe_ctx->stream->bit_depth_params); 787 pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->public.timing.pixel_encoding; 788 789 return DC_OK; 790 } 791 792 static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigned int underlay_idx) 793 { 794 if (pipe_ctx->pipe_idx != underlay_idx) 795 return true; 796 if (!pipe_ctx->surface) 797 return false; 798 if (pipe_ctx->surface->public.format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) 799 return false; 800 return true; 801 } 802 803 static enum dc_status validate_mapped_resource( 804 const struct core_dc *dc, 805 struct validate_context *context) 806 { 807 enum dc_status status = DC_OK; 808 uint8_t i, j; 809 810 for (i = 0; i < context->stream_count; i++) { 811 struct core_stream *stream = context->streams[i]; 812 struct core_link *link = stream->sink->link; 813 814 if (resource_is_stream_unchanged(dc->current_context, stream)) 815 continue; 816 817 for (j = 0; j < MAX_PIPES; j++) { 818 struct pipe_ctx *pipe_ctx = 819 &context->res_ctx.pipe_ctx[j]; 820 821 if (context->res_ctx.pipe_ctx[j].stream != stream) 822 continue; 823 824 if (!is_surface_pixel_format_supported(pipe_ctx, 825 dc->res_pool->underlay_pipe_index)) 826 return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; 827 828 if (!pipe_ctx->tg->funcs->validate_timing( 829 pipe_ctx->tg, &stream->public.timing)) 830 return DC_FAIL_CONTROLLER_VALIDATE; 831 832 status = dce110_resource_build_pipe_hw_param(pipe_ctx); 833 834 if (status != DC_OK) 835 return status; 836 837 if (!link->link_enc->funcs->validate_output_with_stream( 838 link->link_enc, 839 pipe_ctx)) 840 return DC_FAIL_ENC_VALIDATE; 841 842 /* TODO: validate audio ASIC caps, encoder */ 843 844 status = dc_link_validate_mode_timing(stream, 845 link, 846 &stream->public.timing); 847 848 if (status != DC_OK) 849 return status; 850 851 resource_build_info_frame(pipe_ctx); 852 853 /* do not need to validate non root pipes */ 854 break; 855 } 856 } 857 858 return DC_OK; 859 } 860 861 bool dce110_validate_bandwidth( 862 const struct core_dc *dc, 863 struct validate_context *context) 864 { 865 bool result = false; 866 867 dm_logger_write( 868 dc->ctx->logger, LOG_BANDWIDTH_CALCS, 869 "%s: start", 870 __func__); 871 872 if (bw_calcs( 873 dc->ctx, 874 &dc->bw_dceip, 875 &dc->bw_vbios, 876 context->res_ctx.pipe_ctx, 877 dc->res_pool->pipe_count, 878 &context->bw_results)) 879 result = true; 880 context->dispclk_khz = context->bw_results.dispclk_khz; 881 882 if (!result) 883 dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, 884 "%s: %dx%d@%d Bandwidth validation failed!\n", 885 __func__, 886 context->streams[0]->public.timing.h_addressable, 887 context->streams[0]->public.timing.v_addressable, 888 context->streams[0]->public.timing.pix_clk_khz); 889 890 if (memcmp(&dc->current_context->bw_results, 891 &context->bw_results, sizeof(context->bw_results))) { 892 struct log_entry log_entry; 893 dm_logger_open( 894 dc->ctx->logger, 895 &log_entry, 896 LOG_BANDWIDTH_CALCS); 897 dm_logger_append(&log_entry, "%s: finish,\n" 898 "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" 899 "stutMark_b: %d stutMark_a: %d\n", 900 __func__, 901 context->bw_results.nbp_state_change_wm_ns[0].b_mark, 902 context->bw_results.nbp_state_change_wm_ns[0].a_mark, 903 context->bw_results.urgent_wm_ns[0].b_mark, 904 context->bw_results.urgent_wm_ns[0].a_mark, 905 context->bw_results.stutter_exit_wm_ns[0].b_mark, 906 context->bw_results.stutter_exit_wm_ns[0].a_mark); 907 dm_logger_append(&log_entry, 908 "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" 909 "stutMark_b: %d stutMark_a: %d\n", 910 context->bw_results.nbp_state_change_wm_ns[1].b_mark, 911 context->bw_results.nbp_state_change_wm_ns[1].a_mark, 912 context->bw_results.urgent_wm_ns[1].b_mark, 913 context->bw_results.urgent_wm_ns[1].a_mark, 914 context->bw_results.stutter_exit_wm_ns[1].b_mark, 915 context->bw_results.stutter_exit_wm_ns[1].a_mark); 916 dm_logger_append(&log_entry, 917 "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" 918 "stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n", 919 context->bw_results.nbp_state_change_wm_ns[2].b_mark, 920 context->bw_results.nbp_state_change_wm_ns[2].a_mark, 921 context->bw_results.urgent_wm_ns[2].b_mark, 922 context->bw_results.urgent_wm_ns[2].a_mark, 923 context->bw_results.stutter_exit_wm_ns[2].b_mark, 924 context->bw_results.stutter_exit_wm_ns[2].a_mark, 925 context->bw_results.stutter_mode_enable); 926 dm_logger_append(&log_entry, 927 "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n" 928 "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %d\n", 929 context->bw_results.cpuc_state_change_enable, 930 context->bw_results.cpup_state_change_enable, 931 context->bw_results.nbp_state_change_enable, 932 context->bw_results.all_displays_in_sync, 933 context->bw_results.dispclk_khz, 934 context->bw_results.required_sclk, 935 context->bw_results.required_sclk_deep_sleep, 936 context->bw_results.required_yclk, 937 context->bw_results.blackout_recovery_time_us); 938 dm_logger_close(&log_entry); 939 } 940 return result; 941 } 942 943 static bool dce110_validate_surface_sets( 944 const struct dc_validation_set set[], 945 int set_count) 946 { 947 int i; 948 949 for (i = 0; i < set_count; i++) { 950 if (set[i].surface_count == 0) 951 continue; 952 953 if (set[i].surface_count > 2) 954 return false; 955 956 if (set[i].surfaces[0]->format 957 >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) 958 return false; 959 960 if (set[i].surface_count == 2) { 961 if (set[i].surfaces[1]->format 962 < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) 963 return false; 964 if (set[i].surfaces[1]->src_rect.width > 1920 965 || set[i].surfaces[1]->src_rect.height > 1080) 966 return false; 967 968 if (set[i].stream->timing.pixel_encoding != PIXEL_ENCODING_RGB) 969 return false; 970 } 971 } 972 973 return true; 974 } 975 976 enum dc_status dce110_validate_with_context( 977 const struct core_dc *dc, 978 const struct dc_validation_set set[], 979 int set_count, 980 struct validate_context *context) 981 { 982 struct dc_context *dc_ctx = dc->ctx; 983 enum dc_status result = DC_ERROR_UNEXPECTED; 984 int i; 985 986 if (!dce110_validate_surface_sets(set, set_count)) 987 return DC_FAIL_SURFACE_VALIDATE; 988 989 for (i = 0; i < set_count; i++) { 990 context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); 991 dc_stream_retain(&context->streams[i]->public); 992 context->stream_count++; 993 } 994 995 result = resource_map_pool_resources(dc, context); 996 997 if (result == DC_OK) 998 result = resource_map_clock_resources(dc, context); 999 1000 if (!resource_validate_attach_surfaces(set, set_count, 1001 dc->current_context, context, dc->res_pool)) { 1002 DC_ERROR("Failed to attach surface to stream!\n"); 1003 return DC_FAIL_ATTACH_SURFACES; 1004 } 1005 1006 if (result == DC_OK) 1007 result = validate_mapped_resource(dc, context); 1008 1009 if (result == DC_OK) 1010 result = resource_build_scaling_params_for_context(dc, context); 1011 1012 if (result == DC_OK) 1013 if (!dce110_validate_bandwidth(dc, context)) 1014 result = DC_FAIL_BANDWIDTH_VALIDATE; 1015 1016 return result; 1017 } 1018 1019 enum dc_status dce110_validate_guaranteed( 1020 const struct core_dc *dc, 1021 const struct dc_stream *dc_stream, 1022 struct validate_context *context) 1023 { 1024 enum dc_status result = DC_ERROR_UNEXPECTED; 1025 1026 context->streams[0] = DC_STREAM_TO_CORE(dc_stream); 1027 dc_stream_retain(&context->streams[0]->public); 1028 context->stream_count++; 1029 1030 result = resource_map_pool_resources(dc, context); 1031 1032 if (result == DC_OK) 1033 result = resource_map_clock_resources(dc, context); 1034 1035 if (result == DC_OK) 1036 result = validate_mapped_resource(dc, context); 1037 1038 if (result == DC_OK) { 1039 validate_guaranteed_copy_streams( 1040 context, dc->public.caps.max_streams); 1041 result = resource_build_scaling_params_for_context(dc, context); 1042 } 1043 1044 if (result == DC_OK) 1045 if (!dce110_validate_bandwidth(dc, context)) 1046 result = DC_FAIL_BANDWIDTH_VALIDATE; 1047 1048 return result; 1049 } 1050 1051 static struct pipe_ctx *dce110_acquire_underlay( 1052 struct validate_context *context, 1053 const struct resource_pool *pool, 1054 struct core_stream *stream) 1055 { 1056 struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); 1057 struct resource_context *res_ctx = &context->res_ctx; 1058 unsigned int underlay_idx = pool->underlay_pipe_index; 1059 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[underlay_idx]; 1060 1061 if (res_ctx->pipe_ctx[underlay_idx].stream) 1062 return NULL; 1063 1064 pipe_ctx->tg = pool->timing_generators[underlay_idx]; 1065 pipe_ctx->mi = pool->mis[underlay_idx]; 1066 /*pipe_ctx->ipp = res_ctx->pool->ipps[underlay_idx];*/ 1067 pipe_ctx->xfm = pool->transforms[underlay_idx]; 1068 pipe_ctx->opp = pool->opps[underlay_idx]; 1069 pipe_ctx->dis_clk = pool->display_clock; 1070 pipe_ctx->pipe_idx = underlay_idx; 1071 1072 pipe_ctx->stream = stream; 1073 1074 if (!dc->current_context->res_ctx.pipe_ctx[underlay_idx].stream) { 1075 struct tg_color black_color = {0}; 1076 struct dc_bios *dcb = dc->ctx->dc_bios; 1077 1078 dc->hwss.enable_display_power_gating( 1079 dc, 1080 pipe_ctx->pipe_idx, 1081 dcb, PIPE_GATING_CONTROL_DISABLE); 1082 1083 /* 1084 * This is for powering on underlay, so crtc does not 1085 * need to be enabled 1086 */ 1087 1088 pipe_ctx->tg->funcs->program_timing(pipe_ctx->tg, 1089 &stream->public.timing, 1090 false); 1091 1092 pipe_ctx->tg->funcs->enable_advanced_request( 1093 pipe_ctx->tg, 1094 true, 1095 &stream->public.timing); 1096 1097 pipe_ctx->mi->funcs->allocate_mem_input(pipe_ctx->mi, 1098 stream->public.timing.h_total, 1099 stream->public.timing.v_total, 1100 stream->public.timing.pix_clk_khz, 1101 context->stream_count); 1102 1103 color_space_to_black_color(dc, 1104 COLOR_SPACE_YCBCR601, &black_color); 1105 pipe_ctx->tg->funcs->set_blank_color( 1106 pipe_ctx->tg, 1107 &black_color); 1108 } 1109 1110 return pipe_ctx; 1111 } 1112 1113 static void dce110_destroy_resource_pool(struct resource_pool **pool) 1114 { 1115 struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); 1116 1117 destruct(dce110_pool); 1118 dm_free(dce110_pool); 1119 *pool = NULL; 1120 } 1121 1122 1123 static const struct resource_funcs dce110_res_pool_funcs = { 1124 .destroy = dce110_destroy_resource_pool, 1125 .link_enc_create = dce110_link_encoder_create, 1126 .validate_with_context = dce110_validate_with_context, 1127 .validate_guaranteed = dce110_validate_guaranteed, 1128 .validate_bandwidth = dce110_validate_bandwidth, 1129 .acquire_idle_pipe_for_layer = dce110_acquire_underlay, 1130 }; 1131 1132 static bool underlay_create(struct dc_context *ctx, struct resource_pool *pool) 1133 { 1134 struct dce110_timing_generator *dce110_tgv = dm_alloc(sizeof (*dce110_tgv)); 1135 struct dce_transform *dce110_xfmv = dm_alloc(sizeof (*dce110_xfmv)); 1136 struct dce110_mem_input *dce110_miv = dm_alloc(sizeof (*dce110_miv)); 1137 struct dce110_opp *dce110_oppv = dm_alloc(sizeof (*dce110_oppv)); 1138 1139 if ((dce110_tgv == NULL) || 1140 (dce110_xfmv == NULL) || 1141 (dce110_miv == NULL) || 1142 (dce110_oppv == NULL)) 1143 return false; 1144 1145 if (!dce110_opp_v_construct(dce110_oppv, ctx)) 1146 return false; 1147 1148 dce110_timing_generator_v_construct(dce110_tgv, ctx); 1149 dce110_mem_input_v_construct(dce110_miv, ctx); 1150 dce110_transform_v_construct(dce110_xfmv, ctx); 1151 1152 pool->opps[pool->pipe_count] = &dce110_oppv->base; 1153 pool->timing_generators[pool->pipe_count] = &dce110_tgv->base; 1154 pool->mis[pool->pipe_count] = &dce110_miv->base; 1155 pool->transforms[pool->pipe_count] = &dce110_xfmv->base; 1156 pool->pipe_count++; 1157 1158 /* update the public caps to indicate an underlay is available */ 1159 ctx->dc->caps.max_slave_planes = 1; 1160 ctx->dc->caps.max_slave_planes = 1; 1161 1162 return true; 1163 } 1164 1165 static void bw_calcs_data_update_from_pplib(struct core_dc *dc) 1166 { 1167 struct dm_pp_clock_levels clks = {0}; 1168 1169 /*do system clock*/ 1170 dm_pp_get_clock_levels_by_type( 1171 dc->ctx, 1172 DM_PP_CLOCK_TYPE_ENGINE_CLK, 1173 &clks); 1174 /* convert all the clock fro kHz to fix point mHz */ 1175 dc->bw_vbios.high_sclk = bw_frc_to_fixed( 1176 clks.clocks_in_khz[clks.num_levels-1], 1000); 1177 dc->bw_vbios.mid1_sclk = bw_frc_to_fixed( 1178 clks.clocks_in_khz[clks.num_levels/8], 1000); 1179 dc->bw_vbios.mid2_sclk = bw_frc_to_fixed( 1180 clks.clocks_in_khz[clks.num_levels*2/8], 1000); 1181 dc->bw_vbios.mid3_sclk = bw_frc_to_fixed( 1182 clks.clocks_in_khz[clks.num_levels*3/8], 1000); 1183 dc->bw_vbios.mid4_sclk = bw_frc_to_fixed( 1184 clks.clocks_in_khz[clks.num_levels*4/8], 1000); 1185 dc->bw_vbios.mid5_sclk = bw_frc_to_fixed( 1186 clks.clocks_in_khz[clks.num_levels*5/8], 1000); 1187 dc->bw_vbios.mid6_sclk = bw_frc_to_fixed( 1188 clks.clocks_in_khz[clks.num_levels*6/8], 1000); 1189 dc->bw_vbios.low_sclk = bw_frc_to_fixed( 1190 clks.clocks_in_khz[0], 1000); 1191 dc->sclk_lvls = clks; 1192 1193 /*do display clock*/ 1194 dm_pp_get_clock_levels_by_type( 1195 dc->ctx, 1196 DM_PP_CLOCK_TYPE_DISPLAY_CLK, 1197 &clks); 1198 dc->bw_vbios.high_voltage_max_dispclk = bw_frc_to_fixed( 1199 clks.clocks_in_khz[clks.num_levels-1], 1000); 1200 dc->bw_vbios.mid_voltage_max_dispclk = bw_frc_to_fixed( 1201 clks.clocks_in_khz[clks.num_levels>>1], 1000); 1202 dc->bw_vbios.low_voltage_max_dispclk = bw_frc_to_fixed( 1203 clks.clocks_in_khz[0], 1000); 1204 1205 /*do memory clock*/ 1206 dm_pp_get_clock_levels_by_type( 1207 dc->ctx, 1208 DM_PP_CLOCK_TYPE_MEMORY_CLK, 1209 &clks); 1210 1211 dc->bw_vbios.low_yclk = bw_frc_to_fixed( 1212 clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER, 1000); 1213 dc->bw_vbios.mid_yclk = bw_frc_to_fixed( 1214 clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER, 1215 1000); 1216 dc->bw_vbios.high_yclk = bw_frc_to_fixed( 1217 clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER, 1218 1000); 1219 } 1220 1221 const struct resource_caps *dce110_resource_cap( 1222 struct hw_asic_id *asic_id) 1223 { 1224 if (ASIC_REV_IS_STONEY(asic_id->hw_internal_rev)) 1225 return &stoney_resource_cap; 1226 else 1227 return &carrizo_resource_cap; 1228 } 1229 1230 static bool construct( 1231 uint8_t num_virtual_links, 1232 struct core_dc *dc, 1233 struct dce110_resource_pool *pool, 1234 struct hw_asic_id asic_id) 1235 { 1236 unsigned int i; 1237 struct dc_context *ctx = dc->ctx; 1238 struct firmware_info info; 1239 struct dc_bios *bp; 1240 struct dm_pp_static_clock_info static_clk_info = {0}; 1241 1242 ctx->dc_bios->regs = &bios_regs; 1243 1244 pool->base.res_cap = dce110_resource_cap(&ctx->asic_id); 1245 pool->base.funcs = &dce110_res_pool_funcs; 1246 1247 /************************************************* 1248 * Resource + asic cap harcoding * 1249 *************************************************/ 1250 1251 pool->base.pipe_count = pool->base.res_cap->num_timing_generator; 1252 pool->base.underlay_pipe_index = pool->base.pipe_count; 1253 1254 dc->public.caps.max_downscale_ratio = 150; 1255 dc->public.caps.i2c_speed_in_khz = 100; 1256 dc->public.caps.max_cursor_size = 128; 1257 1258 /************************************************* 1259 * Create resources * 1260 *************************************************/ 1261 1262 bp = ctx->dc_bios; 1263 1264 if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) && 1265 info.external_clock_source_frequency_for_dp != 0) { 1266 pool->base.dp_clock_source = 1267 dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); 1268 1269 pool->base.clock_sources[0] = 1270 dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, 1271 &clk_src_regs[0], false); 1272 pool->base.clock_sources[1] = 1273 dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, 1274 &clk_src_regs[1], false); 1275 1276 pool->base.clk_src_count = 2; 1277 1278 /* TODO: find out if CZ support 3 PLLs */ 1279 } 1280 1281 if (pool->base.dp_clock_source == NULL) { 1282 dm_error("DC: failed to create dp clock source!\n"); 1283 BREAK_TO_DEBUGGER(); 1284 goto res_create_fail; 1285 } 1286 1287 for (i = 0; i < pool->base.clk_src_count; i++) { 1288 if (pool->base.clock_sources[i] == NULL) { 1289 dm_error("DC: failed to create clock sources!\n"); 1290 BREAK_TO_DEBUGGER(); 1291 goto res_create_fail; 1292 } 1293 } 1294 1295 pool->base.display_clock = dce110_disp_clk_create(ctx, 1296 &disp_clk_regs, 1297 &disp_clk_shift, 1298 &disp_clk_mask); 1299 if (pool->base.display_clock == NULL) { 1300 dm_error("DC: failed to create display clock!\n"); 1301 BREAK_TO_DEBUGGER(); 1302 goto res_create_fail; 1303 } 1304 1305 pool->base.dmcu = dce_dmcu_create(ctx, 1306 &dmcu_regs, 1307 &dmcu_shift, 1308 &dmcu_mask); 1309 if (pool->base.dmcu == NULL) { 1310 dm_error("DC: failed to create dmcu!\n"); 1311 BREAK_TO_DEBUGGER(); 1312 goto res_create_fail; 1313 } 1314 1315 pool->base.abm = dce_abm_create(ctx, 1316 &abm_regs, 1317 &abm_shift, 1318 &abm_mask); 1319 if (pool->base.abm == NULL) { 1320 dm_error("DC: failed to create abm!\n"); 1321 BREAK_TO_DEBUGGER(); 1322 goto res_create_fail; 1323 } 1324 1325 /* get static clock information for PPLIB or firmware, save 1326 * max_clock_state 1327 */ 1328 if (dm_pp_get_static_clocks(ctx, &static_clk_info)) 1329 pool->base.display_clock->max_clks_state = 1330 static_clk_info.max_clocks_state; 1331 1332 { 1333 struct irq_service_init_data init_data; 1334 init_data.ctx = dc->ctx; 1335 pool->base.irqs = dal_irq_service_dce110_create(&init_data); 1336 if (!pool->base.irqs) 1337 goto res_create_fail; 1338 } 1339 1340 for (i = 0; i < pool->base.pipe_count; i++) { 1341 pool->base.timing_generators[i] = dce110_timing_generator_create( 1342 ctx, i, &dce110_tg_offsets[i]); 1343 if (pool->base.timing_generators[i] == NULL) { 1344 BREAK_TO_DEBUGGER(); 1345 dm_error("DC: failed to create tg!\n"); 1346 goto res_create_fail; 1347 } 1348 1349 pool->base.mis[i] = dce110_mem_input_create(ctx, i, 1350 &dce110_mi_reg_offsets[i]); 1351 if (pool->base.mis[i] == NULL) { 1352 BREAK_TO_DEBUGGER(); 1353 dm_error( 1354 "DC: failed to create memory input!\n"); 1355 goto res_create_fail; 1356 } 1357 1358 pool->base.ipps[i] = dce110_ipp_create(ctx, i); 1359 if (pool->base.ipps[i] == NULL) { 1360 BREAK_TO_DEBUGGER(); 1361 dm_error( 1362 "DC: failed to create input pixel processor!\n"); 1363 goto res_create_fail; 1364 } 1365 1366 pool->base.transforms[i] = dce110_transform_create(ctx, i); 1367 if (pool->base.transforms[i] == NULL) { 1368 BREAK_TO_DEBUGGER(); 1369 dm_error( 1370 "DC: failed to create transform!\n"); 1371 goto res_create_fail; 1372 } 1373 1374 pool->base.opps[i] = dce110_opp_create(ctx, i); 1375 if (pool->base.opps[i] == NULL) { 1376 BREAK_TO_DEBUGGER(); 1377 dm_error( 1378 "DC: failed to create output pixel processor!\n"); 1379 goto res_create_fail; 1380 } 1381 } 1382 1383 if (!underlay_create(ctx, &pool->base)) 1384 goto res_create_fail; 1385 1386 if (!resource_construct(num_virtual_links, dc, &pool->base, 1387 &res_create_funcs)) 1388 goto res_create_fail; 1389 1390 /* Create hardware sequencer */ 1391 if (!dce110_hw_sequencer_construct(dc)) 1392 goto res_create_fail; 1393 1394 dc->public.caps.max_surfaces = pool->base.pipe_count; 1395 1396 bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); 1397 1398 bw_calcs_data_update_from_pplib(dc); 1399 1400 return true; 1401 1402 res_create_fail: 1403 destruct(pool); 1404 return false; 1405 } 1406 1407 struct resource_pool *dce110_create_resource_pool( 1408 uint8_t num_virtual_links, 1409 struct core_dc *dc, 1410 struct hw_asic_id asic_id) 1411 { 1412 struct dce110_resource_pool *pool = 1413 dm_alloc(sizeof(struct dce110_resource_pool)); 1414 1415 if (!pool) 1416 return NULL; 1417 1418 if (construct(num_virtual_links, dc, pool, asic_id)) 1419 return &pool->base; 1420 1421 BREAK_TO_DEBUGGER(); 1422 return NULL; 1423 } 1424