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 26 27 #include "dcn20_hubbub.h" 28 #include "reg_helper.h" 29 30 #define REG(reg)\ 31 hubbub1->regs->reg 32 33 #define CTX \ 34 hubbub1->base.ctx 35 36 #undef FN 37 #define FN(reg_name, field_name) \ 38 hubbub1->shifts->field_name, hubbub1->masks->field_name 39 40 #define REG(reg)\ 41 hubbub1->regs->reg 42 43 #define CTX \ 44 hubbub1->base.ctx 45 46 #undef FN 47 #define FN(reg_name, field_name) \ 48 hubbub1->shifts->field_name, hubbub1->masks->field_name 49 50 #ifdef NUM_VMID 51 #undef NUM_VMID 52 #endif 53 #define NUM_VMID 16 54 55 bool hubbub2_dcc_support_swizzle( 56 enum swizzle_mode_values swizzle, 57 unsigned int bytes_per_element, 58 enum segment_order *segment_order_horz, 59 enum segment_order *segment_order_vert) 60 { 61 bool standard_swizzle = false; 62 bool display_swizzle = false; 63 bool render_swizzle = false; 64 65 switch (swizzle) { 66 case DC_SW_4KB_S: 67 case DC_SW_64KB_S: 68 case DC_SW_VAR_S: 69 case DC_SW_4KB_S_X: 70 case DC_SW_64KB_S_X: 71 case DC_SW_VAR_S_X: 72 standard_swizzle = true; 73 break; 74 case DC_SW_64KB_R_X: 75 render_swizzle = true; 76 break; 77 case DC_SW_4KB_D: 78 case DC_SW_64KB_D: 79 case DC_SW_VAR_D: 80 case DC_SW_4KB_D_X: 81 case DC_SW_64KB_D_X: 82 case DC_SW_VAR_D_X: 83 display_swizzle = true; 84 break; 85 default: 86 break; 87 } 88 89 if (standard_swizzle) { 90 if (bytes_per_element == 1) { 91 *segment_order_horz = segment_order__contiguous; 92 *segment_order_vert = segment_order__na; 93 return true; 94 } 95 if (bytes_per_element == 2) { 96 *segment_order_horz = segment_order__non_contiguous; 97 *segment_order_vert = segment_order__contiguous; 98 return true; 99 } 100 if (bytes_per_element == 4) { 101 *segment_order_horz = segment_order__non_contiguous; 102 *segment_order_vert = segment_order__contiguous; 103 return true; 104 } 105 if (bytes_per_element == 8) { 106 *segment_order_horz = segment_order__na; 107 *segment_order_vert = segment_order__contiguous; 108 return true; 109 } 110 } 111 if (render_swizzle) { 112 if (bytes_per_element == 2) { 113 *segment_order_horz = segment_order__contiguous; 114 *segment_order_vert = segment_order__contiguous; 115 return true; 116 } 117 if (bytes_per_element == 4) { 118 *segment_order_horz = segment_order__non_contiguous; 119 *segment_order_vert = segment_order__contiguous; 120 return true; 121 } 122 if (bytes_per_element == 8) { 123 *segment_order_horz = segment_order__contiguous; 124 *segment_order_vert = segment_order__non_contiguous; 125 return true; 126 } 127 } 128 if (display_swizzle && bytes_per_element == 8) { 129 *segment_order_horz = segment_order__contiguous; 130 *segment_order_vert = segment_order__non_contiguous; 131 return true; 132 } 133 134 return false; 135 } 136 137 bool hubbub2_dcc_support_pixel_format( 138 enum surface_pixel_format format, 139 unsigned int *bytes_per_element) 140 { 141 /* DML: get_bytes_per_element */ 142 switch (format) { 143 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 144 case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 145 *bytes_per_element = 2; 146 return true; 147 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 148 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 149 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 150 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 151 case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX: 152 case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX: 153 case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT: 154 case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT: 155 *bytes_per_element = 4; 156 return true; 157 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 158 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 159 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 160 *bytes_per_element = 8; 161 return true; 162 default: 163 return false; 164 } 165 } 166 167 static void hubbub2_get_blk256_size(unsigned int *blk256_width, unsigned int *blk256_height, 168 unsigned int bytes_per_element) 169 { 170 /* copied from DML. might want to refactor DML to leverage from DML */ 171 /* DML : get_blk256_size */ 172 if (bytes_per_element == 1) { 173 *blk256_width = 16; 174 *blk256_height = 16; 175 } else if (bytes_per_element == 2) { 176 *blk256_width = 16; 177 *blk256_height = 8; 178 } else if (bytes_per_element == 4) { 179 *blk256_width = 8; 180 *blk256_height = 8; 181 } else if (bytes_per_element == 8) { 182 *blk256_width = 8; 183 *blk256_height = 4; 184 } 185 } 186 187 static void hubbub2_det_request_size( 188 unsigned int height, 189 unsigned int width, 190 unsigned int bpe, 191 bool *req128_horz_wc, 192 bool *req128_vert_wc) 193 { 194 unsigned int detile_buf_size = 164 * 1024; /* 164KB for DCN1.0 */ 195 196 unsigned int blk256_height = 0; 197 unsigned int blk256_width = 0; 198 unsigned int swath_bytes_horz_wc, swath_bytes_vert_wc; 199 200 hubbub2_get_blk256_size(&blk256_width, &blk256_height, bpe); 201 202 swath_bytes_horz_wc = width * blk256_height * bpe; 203 swath_bytes_vert_wc = height * blk256_width * bpe; 204 205 *req128_horz_wc = (2 * swath_bytes_horz_wc <= detile_buf_size) ? 206 false : /* full 256B request */ 207 true; /* half 128b request */ 208 209 *req128_vert_wc = (2 * swath_bytes_vert_wc <= detile_buf_size) ? 210 false : /* full 256B request */ 211 true; /* half 128b request */ 212 } 213 214 bool hubbub2_get_dcc_compression_cap(struct hubbub *hubbub, 215 const struct dc_dcc_surface_param *input, 216 struct dc_surface_dcc_cap *output) 217 { 218 struct dc *dc = hubbub->ctx->dc; 219 /* implement section 1.6.2.1 of DCN1_Programming_Guide.docx */ 220 enum dcc_control dcc_control; 221 unsigned int bpe; 222 enum segment_order segment_order_horz, segment_order_vert; 223 bool req128_horz_wc, req128_vert_wc; 224 225 memset(output, 0, sizeof(*output)); 226 227 if (dc->debug.disable_dcc == DCC_DISABLE) 228 return false; 229 230 if (!hubbub->funcs->dcc_support_pixel_format(input->format, 231 &bpe)) 232 return false; 233 234 if (!hubbub->funcs->dcc_support_swizzle(input->swizzle_mode, bpe, 235 &segment_order_horz, &segment_order_vert)) 236 return false; 237 238 hubbub2_det_request_size(input->surface_size.height, input->surface_size.width, 239 bpe, &req128_horz_wc, &req128_vert_wc); 240 241 if (!req128_horz_wc && !req128_vert_wc) { 242 dcc_control = dcc_control__256_256_xxx; 243 } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) { 244 if (!req128_horz_wc) 245 dcc_control = dcc_control__256_256_xxx; 246 else if (segment_order_horz == segment_order__contiguous) 247 dcc_control = dcc_control__128_128_xxx; 248 else 249 dcc_control = dcc_control__256_64_64; 250 } else if (input->scan == SCAN_DIRECTION_VERTICAL) { 251 if (!req128_vert_wc) 252 dcc_control = dcc_control__256_256_xxx; 253 else if (segment_order_vert == segment_order__contiguous) 254 dcc_control = dcc_control__128_128_xxx; 255 else 256 dcc_control = dcc_control__256_64_64; 257 } else { 258 if ((req128_horz_wc && 259 segment_order_horz == segment_order__non_contiguous) || 260 (req128_vert_wc && 261 segment_order_vert == segment_order__non_contiguous)) 262 /* access_dir not known, must use most constraining */ 263 dcc_control = dcc_control__256_64_64; 264 else 265 /* reg128 is true for either horz and vert 266 * but segment_order is contiguous 267 */ 268 dcc_control = dcc_control__128_128_xxx; 269 } 270 271 /* Exception for 64KB_R_X */ 272 if ((bpe == 2) && (input->swizzle_mode == DC_SW_64KB_R_X)) 273 dcc_control = dcc_control__128_128_xxx; 274 275 if (dc->debug.disable_dcc == DCC_HALF_REQ_DISALBE && 276 dcc_control != dcc_control__256_256_xxx) 277 return false; 278 279 switch (dcc_control) { 280 case dcc_control__256_256_xxx: 281 output->grph.rgb.max_uncompressed_blk_size = 256; 282 output->grph.rgb.max_compressed_blk_size = 256; 283 output->grph.rgb.independent_64b_blks = false; 284 break; 285 case dcc_control__128_128_xxx: 286 output->grph.rgb.max_uncompressed_blk_size = 128; 287 output->grph.rgb.max_compressed_blk_size = 128; 288 output->grph.rgb.independent_64b_blks = false; 289 break; 290 case dcc_control__256_64_64: 291 output->grph.rgb.max_uncompressed_blk_size = 256; 292 output->grph.rgb.max_compressed_blk_size = 64; 293 output->grph.rgb.independent_64b_blks = true; 294 break; 295 } 296 output->capable = true; 297 output->const_color_support = true; 298 299 return true; 300 } 301 302 static enum dcn_hubbub_page_table_depth page_table_depth_to_hw(unsigned int page_table_depth) 303 { 304 enum dcn_hubbub_page_table_depth depth = 0; 305 306 switch (page_table_depth) { 307 case 1: 308 depth = DCN_PAGE_TABLE_DEPTH_1_LEVEL; 309 break; 310 case 2: 311 depth = DCN_PAGE_TABLE_DEPTH_2_LEVEL; 312 break; 313 case 3: 314 depth = DCN_PAGE_TABLE_DEPTH_3_LEVEL; 315 break; 316 case 4: 317 depth = DCN_PAGE_TABLE_DEPTH_4_LEVEL; 318 break; 319 default: 320 ASSERT(false); 321 break; 322 } 323 324 return depth; 325 } 326 327 static enum dcn_hubbub_page_table_block_size page_table_block_size_to_hw(unsigned int page_table_block_size) 328 { 329 enum dcn_hubbub_page_table_block_size block_size = 0; 330 331 switch (page_table_block_size) { 332 case 4096: 333 block_size = DCN_PAGE_TABLE_BLOCK_SIZE_4KB; 334 break; 335 case 65536: 336 block_size = DCN_PAGE_TABLE_BLOCK_SIZE_64KB; 337 break; 338 default: 339 ASSERT(false); 340 break; 341 } 342 343 return block_size; 344 } 345 346 void hubbub2_init_vm_ctx(struct hubbub *hubbub, 347 struct dcn_hubbub_virt_addr_config *va_config, 348 int vmid) 349 { 350 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); 351 struct dcn_vmid_page_table_config virt_config; 352 353 virt_config.page_table_start_addr = va_config->page_table_start_addr >> 12; 354 virt_config.page_table_end_addr = va_config->page_table_end_addr >> 12; 355 virt_config.depth = page_table_depth_to_hw(va_config->page_table_depth); 356 virt_config.block_size = page_table_block_size_to_hw(va_config->page_table_block_size); 357 virt_config.page_table_base_addr = va_config->page_table_base_addr; 358 359 dcn20_vmid_setup(&hubbub1->vmid[vmid], &virt_config); 360 } 361 362 int hubbub2_init_dchub_sys_ctx(struct hubbub *hubbub, 363 struct dcn_hubbub_phys_addr_config *pa_config) 364 { 365 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); 366 struct dcn_vmid_page_table_config phys_config; 367 368 REG_SET(DCN_VM_FB_LOCATION_BASE, 0, 369 FB_BASE, pa_config->system_aperture.fb_base); 370 REG_SET(DCN_VM_FB_LOCATION_TOP, 0, 371 FB_TOP, pa_config->system_aperture.fb_top); 372 REG_SET(DCN_VM_FB_OFFSET, 0, 373 FB_OFFSET, pa_config->system_aperture.fb_offset); 374 REG_SET(DCN_VM_AGP_BOT, 0, 375 AGP_BOT, pa_config->system_aperture.agp_bot); 376 REG_SET(DCN_VM_AGP_TOP, 0, 377 AGP_TOP, pa_config->system_aperture.agp_top); 378 REG_SET(DCN_VM_AGP_BASE, 0, 379 AGP_BASE, pa_config->system_aperture.agp_base); 380 381 if (pa_config->gart_config.page_table_start_addr != pa_config->gart_config.page_table_end_addr) { 382 phys_config.depth = 1; 383 phys_config.block_size = 4096; 384 phys_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr >> 12; 385 phys_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr >> 12; 386 phys_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr; 387 388 // Init VMID 0 based on PA config 389 dcn20_vmid_setup(&hubbub1->vmid[0], &phys_config); 390 } 391 392 return NUM_VMID; 393 } 394 395 void hubbub2_update_dchub(struct hubbub *hubbub, 396 struct dchub_init_data *dh_data) 397 { 398 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); 399 400 if (REG(DCHUBBUB_SDPIF_FB_TOP) == 0) { 401 ASSERT(false); 402 /*should not come here*/ 403 return; 404 } 405 /* TODO: port code from dal2 */ 406 switch (dh_data->fb_mode) { 407 case FRAME_BUFFER_MODE_ZFB_ONLY: 408 /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ 409 REG_UPDATE(DCHUBBUB_SDPIF_FB_TOP, 410 SDPIF_FB_TOP, 0); 411 412 REG_UPDATE(DCHUBBUB_SDPIF_FB_BASE, 413 SDPIF_FB_BASE, 0x0FFFF); 414 415 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, 416 SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); 417 418 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, 419 SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); 420 421 REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, 422 SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + 423 dh_data->zfb_size_in_byte - 1) >> 22); 424 break; 425 case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: 426 /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ 427 428 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, 429 SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); 430 431 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, 432 SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); 433 434 REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, 435 SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + 436 dh_data->zfb_size_in_byte - 1) >> 22); 437 break; 438 case FRAME_BUFFER_MODE_LOCAL_ONLY: 439 /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ 440 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, 441 SDPIF_AGP_BASE, 0); 442 443 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, 444 SDPIF_AGP_BOT, 0X03FFFF); 445 446 REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, 447 SDPIF_AGP_TOP, 0); 448 break; 449 default: 450 break; 451 } 452 453 dh_data->dchub_initialzied = true; 454 dh_data->dchub_info_valid = false; 455 } 456 457 void hubbub2_wm_read_state(struct hubbub *hubbub, 458 struct dcn_hubbub_wm *wm) 459 { 460 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); 461 462 struct dcn_hubbub_wm_set *s; 463 464 memset(wm, 0, sizeof(struct dcn_hubbub_wm)); 465 466 s = &wm->sets[0]; 467 s->wm_set = 0; 468 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A); 469 if (REG(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A)) 470 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A); 471 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A)) { 472 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A); 473 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A); 474 } 475 s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A); 476 477 s = &wm->sets[1]; 478 s->wm_set = 1; 479 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B); 480 if (REG(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B)) 481 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B); 482 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B)) { 483 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B); 484 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B); 485 } 486 s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B); 487 488 s = &wm->sets[2]; 489 s->wm_set = 2; 490 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C); 491 if (REG(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C)) 492 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C); 493 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C)) { 494 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C); 495 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C); 496 } 497 s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C); 498 499 s = &wm->sets[3]; 500 s->wm_set = 3; 501 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D); 502 if (REG(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D)) 503 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D); 504 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D)) { 505 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D); 506 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D); 507 } 508 s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D); 509 } 510 511 void hubbub2_get_dchub_ref_freq(struct hubbub *hubbub, 512 unsigned int dccg_ref_freq_inKhz, 513 unsigned int *dchub_ref_freq_inKhz) 514 { 515 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); 516 uint32_t ref_div = 0; 517 uint32_t ref_en = 0; 518 519 REG_GET_2(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, &ref_div, 520 DCHUBBUB_GLOBAL_TIMER_ENABLE, &ref_en); 521 522 if (ref_en) { 523 if (ref_div == 2) 524 *dchub_ref_freq_inKhz = dccg_ref_freq_inKhz / 2; 525 else 526 *dchub_ref_freq_inKhz = dccg_ref_freq_inKhz; 527 528 // DC hub reference frequency must be around 50Mhz, otherwise there may be 529 // overflow/underflow issues when doing HUBBUB programming 530 if (*dchub_ref_freq_inKhz < 40000 || *dchub_ref_freq_inKhz > 60000) 531 ASSERT_CRITICAL(false); 532 533 return; 534 } else { 535 *dchub_ref_freq_inKhz = dccg_ref_freq_inKhz; 536 537 // HUBBUB global timer must be enabled. 538 ASSERT_CRITICAL(false); 539 return; 540 } 541 } 542 543 static void hubbub2_program_watermarks( 544 struct hubbub *hubbub, 545 struct dcn_watermark_set *watermarks, 546 unsigned int refclk_mhz, 547 bool safe_to_lower) 548 { 549 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); 550 /* 551 * Need to clamp to max of the register values (i.e. no wrap) 552 * for dcn1, all wm registers are 21-bit wide 553 */ 554 hubbub1_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); 555 hubbub1_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); 556 hubbub1_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); 557 558 REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0, 559 DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); 560 REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 180); 561 562 hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); 563 } 564 565 static const struct hubbub_funcs hubbub2_funcs = { 566 .update_dchub = hubbub2_update_dchub, 567 .init_dchub_sys_ctx = hubbub2_init_dchub_sys_ctx, 568 .init_vm_ctx = hubbub2_init_vm_ctx, 569 .dcc_support_swizzle = hubbub2_dcc_support_swizzle, 570 .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format, 571 .get_dcc_compression_cap = hubbub2_get_dcc_compression_cap, 572 .wm_read_state = hubbub2_wm_read_state, 573 .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq, 574 .program_watermarks = hubbub2_program_watermarks, 575 }; 576 577 void hubbub2_construct(struct dcn20_hubbub *hubbub, 578 struct dc_context *ctx, 579 const struct dcn_hubbub_registers *hubbub_regs, 580 const struct dcn_hubbub_shift *hubbub_shift, 581 const struct dcn_hubbub_mask *hubbub_mask) 582 { 583 hubbub->base.ctx = ctx; 584 585 hubbub->base.funcs = &hubbub2_funcs; 586 587 hubbub->regs = hubbub_regs; 588 hubbub->shifts = hubbub_shift; 589 hubbub->masks = hubbub_mask; 590 591 hubbub->debug_test_index_pstate = 0xB; 592 } 593