693 lines · c
1/*2 * Copyright 2016 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26 27#include "dcn20_hubbub.h"28#include "reg_helper.h"29#include "clk_mgr.h"30 31#define REG(reg)\32 hubbub1->regs->reg33 34#define CTX \35 hubbub1->base.ctx36 37#undef FN38#define FN(reg_name, field_name) \39 hubbub1->shifts->field_name, hubbub1->masks->field_name40 41#define REG(reg)\42 hubbub1->regs->reg43 44#define CTX \45 hubbub1->base.ctx46 47#undef FN48#define FN(reg_name, field_name) \49 hubbub1->shifts->field_name, hubbub1->masks->field_name50 51#ifdef NUM_VMID52#undef NUM_VMID53#endif54#define NUM_VMID 1655 56bool hubbub2_dcc_support_swizzle(57 enum swizzle_mode_values swizzle,58 unsigned int bytes_per_element,59 enum segment_order *segment_order_horz,60 enum segment_order *segment_order_vert)61{62 bool standard_swizzle = false;63 bool display_swizzle = false;64 bool render_swizzle = false;65 66 switch (swizzle) {67 case DC_SW_4KB_S:68 case DC_SW_64KB_S:69 case DC_SW_VAR_S:70 case DC_SW_4KB_S_X:71 case DC_SW_64KB_S_X:72 case DC_SW_VAR_S_X:73 standard_swizzle = true;74 break;75 case DC_SW_64KB_R_X:76 render_swizzle = true;77 break;78 case DC_SW_4KB_D:79 case DC_SW_64KB_D:80 case DC_SW_VAR_D:81 case DC_SW_4KB_D_X:82 case DC_SW_64KB_D_X:83 case DC_SW_VAR_D_X:84 display_swizzle = true;85 break;86 default:87 break;88 }89 90 if (standard_swizzle) {91 if (bytes_per_element == 1) {92 *segment_order_horz = segment_order__contiguous;93 *segment_order_vert = segment_order__na;94 return true;95 }96 if (bytes_per_element == 2) {97 *segment_order_horz = segment_order__non_contiguous;98 *segment_order_vert = segment_order__contiguous;99 return true;100 }101 if (bytes_per_element == 4) {102 *segment_order_horz = segment_order__non_contiguous;103 *segment_order_vert = segment_order__contiguous;104 return true;105 }106 if (bytes_per_element == 8) {107 *segment_order_horz = segment_order__na;108 *segment_order_vert = segment_order__contiguous;109 return true;110 }111 }112 if (render_swizzle) {113 if (bytes_per_element == 2) {114 *segment_order_horz = segment_order__contiguous;115 *segment_order_vert = segment_order__contiguous;116 return true;117 }118 if (bytes_per_element == 4) {119 *segment_order_horz = segment_order__non_contiguous;120 *segment_order_vert = segment_order__contiguous;121 return true;122 }123 if (bytes_per_element == 8) {124 *segment_order_horz = segment_order__contiguous;125 *segment_order_vert = segment_order__non_contiguous;126 return true;127 }128 }129 if (display_swizzle && bytes_per_element == 8) {130 *segment_order_horz = segment_order__contiguous;131 *segment_order_vert = segment_order__non_contiguous;132 return true;133 }134 135 return false;136}137 138bool hubbub2_dcc_support_pixel_format(139 enum surface_pixel_format format,140 unsigned int *bytes_per_element)141{142 /* DML: get_bytes_per_element */143 switch (format) {144 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:145 case SURFACE_PIXEL_FORMAT_GRPH_RGB565:146 *bytes_per_element = 2;147 return true;148 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:149 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:150 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:151 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:152 case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX:153 case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX:154 case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT:155 case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT:156 case SURFACE_PIXEL_FORMAT_GRPH_RGBE:157 case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:158 *bytes_per_element = 4;159 return true;160 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:161 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:162 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:163 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:164 *bytes_per_element = 8;165 return true;166 default:167 return false;168 }169}170 171static void hubbub2_get_blk256_size(unsigned int *blk256_width, unsigned int *blk256_height,172 unsigned int bytes_per_element)173{174 /* copied from DML. might want to refactor DML to leverage from DML */175 /* DML : get_blk256_size */176 if (bytes_per_element == 1) {177 *blk256_width = 16;178 *blk256_height = 16;179 } else if (bytes_per_element == 2) {180 *blk256_width = 16;181 *blk256_height = 8;182 } else if (bytes_per_element == 4) {183 *blk256_width = 8;184 *blk256_height = 8;185 } else if (bytes_per_element == 8) {186 *blk256_width = 8;187 *blk256_height = 4;188 }189}190 191static void hubbub2_det_request_size(192 unsigned int detile_buf_size,193 unsigned int height,194 unsigned int width,195 unsigned int bpe,196 bool *req128_horz_wc,197 bool *req128_vert_wc)198{199 unsigned int blk256_height = 0;200 unsigned int blk256_width = 0;201 unsigned int swath_bytes_horz_wc, swath_bytes_vert_wc;202 203 hubbub2_get_blk256_size(&blk256_width, &blk256_height, bpe);204 205 swath_bytes_horz_wc = width * blk256_height * bpe;206 swath_bytes_vert_wc = height * blk256_width * bpe;207 208 *req128_horz_wc = (2 * swath_bytes_horz_wc <= detile_buf_size) ?209 false : /* full 256B request */210 true; /* half 128b request */211 212 *req128_vert_wc = (2 * swath_bytes_vert_wc <= detile_buf_size) ?213 false : /* full 256B request */214 true; /* half 128b request */215}216 217bool hubbub2_get_dcc_compression_cap(struct hubbub *hubbub,218 const struct dc_dcc_surface_param *input,219 struct dc_surface_dcc_cap *output)220{221 struct dc *dc = hubbub->ctx->dc;222 /* implement section 1.6.2.1 of DCN1_Programming_Guide.docx */223 enum dcc_control dcc_control;224 unsigned int bpe;225 enum segment_order segment_order_horz, segment_order_vert;226 bool req128_horz_wc, req128_vert_wc;227 228 memset(output, 0, sizeof(*output));229 230 if (dc->debug.disable_dcc == DCC_DISABLE)231 return false;232 233 if (!hubbub->funcs->dcc_support_pixel_format(input->format,234 &bpe))235 return false;236 237 if (!hubbub->funcs->dcc_support_swizzle(input->swizzle_mode, bpe,238 &segment_order_horz, &segment_order_vert))239 return false;240 241 hubbub2_det_request_size(TO_DCN20_HUBBUB(hubbub)->detile_buf_size,242 input->surface_size.height, input->surface_size.width,243 bpe, &req128_horz_wc, &req128_vert_wc);244 245 if (!req128_horz_wc && !req128_vert_wc) {246 dcc_control = dcc_control__256_256_xxx;247 } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) {248 if (!req128_horz_wc)249 dcc_control = dcc_control__256_256_xxx;250 else if (segment_order_horz == segment_order__contiguous)251 dcc_control = dcc_control__128_128_xxx;252 else253 dcc_control = dcc_control__256_64_64;254 } else if (input->scan == SCAN_DIRECTION_VERTICAL) {255 if (!req128_vert_wc)256 dcc_control = dcc_control__256_256_xxx;257 else if (segment_order_vert == segment_order__contiguous)258 dcc_control = dcc_control__128_128_xxx;259 else260 dcc_control = dcc_control__256_64_64;261 } else {262 if ((req128_horz_wc &&263 segment_order_horz == segment_order__non_contiguous) ||264 (req128_vert_wc &&265 segment_order_vert == segment_order__non_contiguous))266 /* access_dir not known, must use most constraining */267 dcc_control = dcc_control__256_64_64;268 else269 /* reg128 is true for either horz and vert270 * but segment_order is contiguous271 */272 dcc_control = dcc_control__128_128_xxx;273 }274 275 /* Exception for 64KB_R_X */276 if ((bpe == 2) && (input->swizzle_mode == DC_SW_64KB_R_X))277 dcc_control = dcc_control__128_128_xxx;278 279 if (dc->debug.disable_dcc == DCC_HALF_REQ_DISALBE &&280 dcc_control != dcc_control__256_256_xxx)281 return false;282 283 switch (dcc_control) {284 case dcc_control__256_256_xxx:285 output->grph.rgb.max_uncompressed_blk_size = 256;286 output->grph.rgb.max_compressed_blk_size = 256;287 output->grph.rgb.independent_64b_blks = false;288 break;289 case dcc_control__128_128_xxx:290 output->grph.rgb.max_uncompressed_blk_size = 128;291 output->grph.rgb.max_compressed_blk_size = 128;292 output->grph.rgb.independent_64b_blks = false;293 break;294 case dcc_control__256_64_64:295 output->grph.rgb.max_uncompressed_blk_size = 256;296 output->grph.rgb.max_compressed_blk_size = 64;297 output->grph.rgb.independent_64b_blks = true;298 break;299 default:300 ASSERT(false);301 break;302 }303 output->capable = true;304 output->const_color_support = true;305 306 return true;307}308 309static enum dcn_hubbub_page_table_depth page_table_depth_to_hw(unsigned int page_table_depth)310{311 enum dcn_hubbub_page_table_depth depth = 0;312 313 switch (page_table_depth) {314 case 1:315 depth = DCN_PAGE_TABLE_DEPTH_1_LEVEL;316 break;317 case 2:318 depth = DCN_PAGE_TABLE_DEPTH_2_LEVEL;319 break;320 case 3:321 depth = DCN_PAGE_TABLE_DEPTH_3_LEVEL;322 break;323 case 4:324 depth = DCN_PAGE_TABLE_DEPTH_4_LEVEL;325 break;326 default:327 ASSERT(false);328 break;329 }330 331 return depth;332}333 334static enum dcn_hubbub_page_table_block_size page_table_block_size_to_hw(unsigned int page_table_block_size)335{336 enum dcn_hubbub_page_table_block_size block_size = 0;337 338 switch (page_table_block_size) {339 case 4096:340 block_size = DCN_PAGE_TABLE_BLOCK_SIZE_4KB;341 break;342 case 8192:343 block_size = DCN_PAGE_TABLE_BLOCK_SIZE_8KB;344 break;345 case 16384:346 block_size = DCN_PAGE_TABLE_BLOCK_SIZE_16KB;347 break;348 case 32768:349 block_size = DCN_PAGE_TABLE_BLOCK_SIZE_32KB;350 break;351 case 65536:352 block_size = DCN_PAGE_TABLE_BLOCK_SIZE_64KB;353 break;354 case 131072:355 block_size = DCN_PAGE_TABLE_BLOCK_SIZE_128KB;356 break;357 case 262144:358 block_size = DCN_PAGE_TABLE_BLOCK_SIZE_256KB;359 break;360 case 524288:361 block_size = DCN_PAGE_TABLE_BLOCK_SIZE_512KB;362 break;363 case 1048576:364 block_size = DCN_PAGE_TABLE_BLOCK_SIZE_1024KB;365 break;366 case 2097152:367 block_size = DCN_PAGE_TABLE_BLOCK_SIZE_2048KB;368 break;369 default:370 ASSERT(false);371 block_size = DCN_PAGE_TABLE_BLOCK_SIZE_4KB;372 break;373 }374 375 return block_size;376}377 378void hubbub2_init_vm_ctx(struct hubbub *hubbub,379 struct dcn_hubbub_virt_addr_config *va_config,380 int vmid)381{382 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);383 struct dcn_vmid_page_table_config virt_config;384 385 virt_config.page_table_start_addr = va_config->page_table_start_addr >> 12;386 virt_config.page_table_end_addr = va_config->page_table_end_addr >> 12;387 virt_config.depth = page_table_depth_to_hw(va_config->page_table_depth);388 virt_config.block_size = page_table_block_size_to_hw(va_config->page_table_block_size);389 virt_config.page_table_base_addr = va_config->page_table_base_addr;390 391 dcn20_vmid_setup(&hubbub1->vmid[vmid], &virt_config);392}393 394int hubbub2_init_dchub_sys_ctx(struct hubbub *hubbub,395 struct dcn_hubbub_phys_addr_config *pa_config)396{397 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);398 struct dcn_vmid_page_table_config phys_config;399 400 REG_SET(DCN_VM_FB_LOCATION_BASE, 0,401 FB_BASE, pa_config->system_aperture.fb_base >> 24);402 REG_SET(DCN_VM_FB_LOCATION_TOP, 0,403 FB_TOP, pa_config->system_aperture.fb_top >> 24);404 REG_SET(DCN_VM_FB_OFFSET, 0,405 FB_OFFSET, pa_config->system_aperture.fb_offset >> 24);406 REG_SET(DCN_VM_AGP_BOT, 0,407 AGP_BOT, pa_config->system_aperture.agp_bot >> 24);408 REG_SET(DCN_VM_AGP_TOP, 0,409 AGP_TOP, pa_config->system_aperture.agp_top >> 24);410 REG_SET(DCN_VM_AGP_BASE, 0,411 AGP_BASE, pa_config->system_aperture.agp_base >> 24);412 413 REG_SET(DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_MSB, 0,414 DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_MSB, (pa_config->page_table_default_page_addr >> 44) & 0xF);415 REG_SET(DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB, 0,416 DCN_VM_PROTECTION_FAULT_DEFAULT_ADDR_LSB, (pa_config->page_table_default_page_addr >> 12) & 0xFFFFFFFF);417 418 if (pa_config->gart_config.page_table_start_addr != pa_config->gart_config.page_table_end_addr) {419 phys_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr >> 12;420 phys_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr >> 12;421 phys_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr;422 phys_config.depth = 0;423 phys_config.block_size = 0;424 // Init VMID 0 based on PA config425 dcn20_vmid_setup(&hubbub1->vmid[0], &phys_config);426 }427 428 return NUM_VMID;429}430 431void hubbub2_update_dchub(struct hubbub *hubbub,432 struct dchub_init_data *dh_data)433{434 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);435 436 if (REG(DCN_VM_FB_LOCATION_TOP) == 0)437 return;438 439 switch (dh_data->fb_mode) {440 case FRAME_BUFFER_MODE_ZFB_ONLY:441 /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/442 REG_UPDATE(DCN_VM_FB_LOCATION_TOP,443 FB_TOP, 0);444 445 REG_UPDATE(DCN_VM_FB_LOCATION_BASE,446 FB_BASE, 0xFFFFFF);447 448 /*This field defines the 24 MSBs, bits [47:24] of the 48 bit AGP Base*/449 REG_UPDATE(DCN_VM_AGP_BASE,450 AGP_BASE, dh_data->zfb_phys_addr_base >> 24);451 452 /*This field defines the bottom range of the AGP aperture and represents the 24*/453 /*MSBs, bits [47:24] of the 48 address bits*/454 REG_UPDATE(DCN_VM_AGP_BOT,455 AGP_BOT, dh_data->zfb_mc_base_addr >> 24);456 457 /*This field defines the top range of the AGP aperture and represents the 24*/458 /*MSBs, bits [47:24] of the 48 address bits*/459 REG_UPDATE(DCN_VM_AGP_TOP,460 AGP_TOP, (dh_data->zfb_mc_base_addr +461 dh_data->zfb_size_in_byte - 1) >> 24);462 break;463 case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL:464 /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/465 466 /*This field defines the 24 MSBs, bits [47:24] of the 48 bit AGP Base*/467 REG_UPDATE(DCN_VM_AGP_BASE,468 AGP_BASE, dh_data->zfb_phys_addr_base >> 24);469 470 /*This field defines the bottom range of the AGP aperture and represents the 24*/471 /*MSBs, bits [47:24] of the 48 address bits*/472 REG_UPDATE(DCN_VM_AGP_BOT,473 AGP_BOT, dh_data->zfb_mc_base_addr >> 24);474 475 /*This field defines the top range of the AGP aperture and represents the 24*/476 /*MSBs, bits [47:24] of the 48 address bits*/477 REG_UPDATE(DCN_VM_AGP_TOP,478 AGP_TOP, (dh_data->zfb_mc_base_addr +479 dh_data->zfb_size_in_byte - 1) >> 24);480 break;481 case FRAME_BUFFER_MODE_LOCAL_ONLY:482 /*Should not touch FB LOCATION (should be done by VBIOS)*/483 484 /*This field defines the 24 MSBs, bits [47:24] of the 48 bit AGP Base*/485 REG_UPDATE(DCN_VM_AGP_BASE,486 AGP_BASE, 0);487 488 /*This field defines the bottom range of the AGP aperture and represents the 24*/489 /*MSBs, bits [47:24] of the 48 address bits*/490 REG_UPDATE(DCN_VM_AGP_BOT,491 AGP_BOT, 0xFFFFFF);492 493 /*This field defines the top range of the AGP aperture and represents the 24*/494 /*MSBs, bits [47:24] of the 48 address bits*/495 REG_UPDATE(DCN_VM_AGP_TOP,496 AGP_TOP, 0);497 break;498 default:499 break;500 }501 502 dh_data->dchub_initialzied = true;503 dh_data->dchub_info_valid = false;504}505 506void hubbub2_wm_read_state(struct hubbub *hubbub,507 struct dcn_hubbub_wm *wm)508{509 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);510 511 struct dcn_hubbub_wm_set *s;512 513 memset(wm, 0, sizeof(struct dcn_hubbub_wm));514 515 s = &wm->sets[0];516 s->wm_set = 0;517 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A);518 if (REG(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A))519 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A);520 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A)) {521 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A);522 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A);523 }524 s->dram_clk_change = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A);525 526 s = &wm->sets[1];527 s->wm_set = 1;528 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B);529 if (REG(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B))530 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B);531 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B)) {532 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B);533 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B);534 }535 s->dram_clk_change = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B);536 537 s = &wm->sets[2];538 s->wm_set = 2;539 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C);540 if (REG(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C))541 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C);542 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C)) {543 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C);544 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C);545 }546 s->dram_clk_change = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C);547 548 s = &wm->sets[3];549 s->wm_set = 3;550 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D);551 if (REG(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D))552 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D);553 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D)) {554 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D);555 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D);556 }557 s->dram_clk_change = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D);558}559 560void hubbub2_get_dchub_ref_freq(struct hubbub *hubbub,561 unsigned int dccg_ref_freq_inKhz,562 unsigned int *dchub_ref_freq_inKhz)563{564 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);565 uint32_t ref_div = 0;566 uint32_t ref_en = 0;567 568 REG_GET_2(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, &ref_div,569 DCHUBBUB_GLOBAL_TIMER_ENABLE, &ref_en);570 571 if (ref_en) {572 if (ref_div == 2)573 *dchub_ref_freq_inKhz = dccg_ref_freq_inKhz / 2;574 else575 *dchub_ref_freq_inKhz = dccg_ref_freq_inKhz;576 577 // DC hub reference frequency must be around 50Mhz, otherwise there may be578 // overflow/underflow issues when doing HUBBUB programming579 if (*dchub_ref_freq_inKhz < 40000 || *dchub_ref_freq_inKhz > 60000)580 ASSERT_CRITICAL(false);581 582 return;583 } else {584 *dchub_ref_freq_inKhz = dccg_ref_freq_inKhz;585 586 // HUBBUB global timer must be enabled.587 ASSERT_CRITICAL(false);588 return;589 }590}591 592static bool hubbub2_program_watermarks(593 struct hubbub *hubbub,594 union dcn_watermark_set *watermarks,595 unsigned int refclk_mhz,596 bool safe_to_lower)597{598 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);599 bool wm_pending = false;600 /*601 * Need to clamp to max of the register values (i.e. no wrap)602 * for dcn1, all wm registers are 21-bit wide603 */604 if (hubbub1_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))605 wm_pending = true;606 607 if (hubbub1_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))608 wm_pending = true;609 610 /*611 * There's a special case when going from p-state support to p-state unsupported612 * here we are going to LOWER watermarks to go to dummy p-state only, but this has613 * to be done prepare_bandwidth, not optimize614 */615 if (hubbub1->base.ctx->dc->clk_mgr->clks.prev_p_state_change_support == true &&616 hubbub1->base.ctx->dc->clk_mgr->clks.p_state_change_support == false)617 safe_to_lower = true;618 619 if (hubbub1_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))620 wm_pending = true;621 622 REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0,623 DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);624 REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 180);625 626 hubbub->funcs->allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);627 return wm_pending;628}629 630void hubbub2_read_state(struct hubbub *hubbub, struct dcn_hubbub_state *hubbub_state)631{632 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);633 634 if (REG(DCN_VM_FAULT_ADDR_MSB))635 hubbub_state->vm_fault_addr_msb = REG_READ(DCN_VM_FAULT_ADDR_MSB);636 637 if (REG(DCN_VM_FAULT_ADDR_LSB))638 hubbub_state->vm_fault_addr_msb = REG_READ(DCN_VM_FAULT_ADDR_LSB);639 640 if (REG(DCN_VM_FAULT_CNTL))641 REG_GET(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_MODE, &hubbub_state->vm_error_mode);642 643 if (REG(DCN_VM_FAULT_STATUS)) {644 REG_GET(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_STATUS, &hubbub_state->vm_error_status);645 REG_GET(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, &hubbub_state->vm_error_vmid);646 REG_GET(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, &hubbub_state->vm_error_pipe);647 }648 649 if (REG(DCHUBBUB_TEST_DEBUG_INDEX) && REG(DCHUBBUB_TEST_DEBUG_DATA)) {650 REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, 0x6);651 hubbub_state->test_debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA);652 }653 654 if (REG(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL))655 hubbub_state->watermark_change_cntl = REG_READ(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL);656 657 if (REG(DCHUBBUB_ARB_DRAM_STATE_CNTL))658 hubbub_state->dram_state_cntl = REG_READ(DCHUBBUB_ARB_DRAM_STATE_CNTL);659}660 661static const struct hubbub_funcs hubbub2_funcs = {662 .update_dchub = hubbub2_update_dchub,663 .init_dchub_sys_ctx = hubbub2_init_dchub_sys_ctx,664 .init_vm_ctx = hubbub2_init_vm_ctx,665 .dcc_support_swizzle = hubbub2_dcc_support_swizzle,666 .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format,667 .get_dcc_compression_cap = hubbub2_get_dcc_compression_cap,668 .wm_read_state = hubbub2_wm_read_state,669 .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,670 .program_watermarks = hubbub2_program_watermarks,671 .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,672 .allow_self_refresh_control = hubbub1_allow_self_refresh_control,673 .hubbub_read_state = hubbub2_read_state,674};675 676void hubbub2_construct(struct dcn20_hubbub *hubbub,677 struct dc_context *ctx,678 const struct dcn_hubbub_registers *hubbub_regs,679 const struct dcn_hubbub_shift *hubbub_shift,680 const struct dcn_hubbub_mask *hubbub_mask)681{682 hubbub->base.ctx = ctx;683 684 hubbub->base.funcs = &hubbub2_funcs;685 686 hubbub->regs = hubbub_regs;687 hubbub->shifts = hubbub_shift;688 hubbub->masks = hubbub_mask;689 690 hubbub->debug_test_index_pstate = 0xB;691 hubbub->detile_buf_size = 164 * 1024; /* 164KB for DCN2.0 */692}693