0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #include "dm_services.h"
0028 #include "reg_helper.h"
0029 #include "dcn30_hubbub.h"
0030
0031
0032 #define CTX \
0033 hubbub1->base.ctx
0034 #define DC_LOGGER \
0035 hubbub1->base.ctx->logger
0036 #define REG(reg)\
0037 hubbub1->regs->reg
0038
0039 #undef FN
0040 #define FN(reg_name, field_name) \
0041 hubbub1->shifts->field_name, hubbub1->masks->field_name
0042
0043 #ifdef NUM_VMID
0044 #undef NUM_VMID
0045 #endif
0046 #define NUM_VMID 16
0047
0048
0049 static uint32_t convert_and_clamp(
0050 uint32_t wm_ns,
0051 uint32_t refclk_mhz,
0052 uint32_t clamp_value)
0053 {
0054 uint32_t ret_val = 0;
0055 ret_val = wm_ns * refclk_mhz;
0056 ret_val /= 1000;
0057
0058 if (ret_val > clamp_value)
0059 ret_val = clamp_value;
0060
0061 return ret_val;
0062 }
0063
0064 int hubbub3_init_dchub_sys_ctx(struct hubbub *hubbub,
0065 struct dcn_hubbub_phys_addr_config *pa_config)
0066 {
0067 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
0068 struct dcn_vmid_page_table_config phys_config;
0069
0070 REG_SET(DCN_VM_FB_LOCATION_BASE, 0,
0071 FB_BASE, pa_config->system_aperture.fb_base >> 24);
0072 REG_SET(DCN_VM_FB_LOCATION_TOP, 0,
0073 FB_TOP, pa_config->system_aperture.fb_top >> 24);
0074 REG_SET(DCN_VM_FB_OFFSET, 0,
0075 FB_OFFSET, pa_config->system_aperture.fb_offset >> 24);
0076 REG_SET(DCN_VM_AGP_BOT, 0,
0077 AGP_BOT, pa_config->system_aperture.agp_bot >> 24);
0078 REG_SET(DCN_VM_AGP_TOP, 0,
0079 AGP_TOP, pa_config->system_aperture.agp_top >> 24);
0080 REG_SET(DCN_VM_AGP_BASE, 0,
0081 AGP_BASE, pa_config->system_aperture.agp_base >> 24);
0082
0083 if (pa_config->gart_config.page_table_start_addr != pa_config->gart_config.page_table_end_addr) {
0084 phys_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr >> 12;
0085 phys_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr >> 12;
0086 phys_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr;
0087 phys_config.depth = 0;
0088 phys_config.block_size = 0;
0089
0090 dcn20_vmid_setup(&hubbub1->vmid[0], &phys_config);
0091 }
0092
0093 return NUM_VMID;
0094 }
0095
0096 bool hubbub3_program_watermarks(
0097 struct hubbub *hubbub,
0098 struct dcn_watermark_set *watermarks,
0099 unsigned int refclk_mhz,
0100 bool safe_to_lower)
0101 {
0102 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
0103 bool wm_pending = false;
0104
0105 if (hubbub21_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
0106 wm_pending = true;
0107
0108 if (hubbub21_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
0109 wm_pending = true;
0110
0111 if (hubbub21_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
0112 wm_pending = true;
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127 REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0,
0128 DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
0129 REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND,
0130 DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF);
0131
0132 hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
0133
0134 return wm_pending;
0135 }
0136
0137 bool hubbub3_dcc_support_swizzle(
0138 enum swizzle_mode_values swizzle,
0139 unsigned int bytes_per_element,
0140 enum segment_order *segment_order_horz,
0141 enum segment_order *segment_order_vert)
0142 {
0143 bool standard_swizzle = false;
0144 bool display_swizzle = false;
0145 bool render_swizzle = false;
0146
0147 switch (swizzle) {
0148 case DC_SW_4KB_S:
0149 case DC_SW_64KB_S:
0150 case DC_SW_VAR_S:
0151 case DC_SW_4KB_S_X:
0152 case DC_SW_64KB_S_X:
0153 case DC_SW_VAR_S_X:
0154 standard_swizzle = true;
0155 break;
0156 case DC_SW_4KB_R:
0157 case DC_SW_64KB_R:
0158 case DC_SW_VAR_R:
0159 case DC_SW_4KB_R_X:
0160 case DC_SW_64KB_R_X:
0161 case DC_SW_VAR_R_X:
0162 render_swizzle = true;
0163 break;
0164 case DC_SW_4KB_D:
0165 case DC_SW_64KB_D:
0166 case DC_SW_VAR_D:
0167 case DC_SW_4KB_D_X:
0168 case DC_SW_64KB_D_X:
0169 case DC_SW_VAR_D_X:
0170 display_swizzle = true;
0171 break;
0172 default:
0173 break;
0174 }
0175
0176 if (standard_swizzle) {
0177 if (bytes_per_element == 1) {
0178 *segment_order_horz = segment_order__contiguous;
0179 *segment_order_vert = segment_order__na;
0180 return true;
0181 }
0182 if (bytes_per_element == 2) {
0183 *segment_order_horz = segment_order__non_contiguous;
0184 *segment_order_vert = segment_order__contiguous;
0185 return true;
0186 }
0187 if (bytes_per_element == 4) {
0188 *segment_order_horz = segment_order__non_contiguous;
0189 *segment_order_vert = segment_order__contiguous;
0190 return true;
0191 }
0192 if (bytes_per_element == 8) {
0193 *segment_order_horz = segment_order__na;
0194 *segment_order_vert = segment_order__contiguous;
0195 return true;
0196 }
0197 }
0198 if (render_swizzle) {
0199 if (bytes_per_element == 1) {
0200 *segment_order_horz = segment_order__contiguous;
0201 *segment_order_vert = segment_order__na;
0202 return true;
0203 }
0204 if (bytes_per_element == 2) {
0205 *segment_order_horz = segment_order__non_contiguous;
0206 *segment_order_vert = segment_order__contiguous;
0207 return true;
0208 }
0209 if (bytes_per_element == 4) {
0210 *segment_order_horz = segment_order__contiguous;
0211 *segment_order_vert = segment_order__non_contiguous;
0212 return true;
0213 }
0214 if (bytes_per_element == 8) {
0215 *segment_order_horz = segment_order__contiguous;
0216 *segment_order_vert = segment_order__non_contiguous;
0217 return true;
0218 }
0219 }
0220 if (display_swizzle && bytes_per_element == 8) {
0221 *segment_order_horz = segment_order__contiguous;
0222 *segment_order_vert = segment_order__non_contiguous;
0223 return true;
0224 }
0225
0226 return false;
0227 }
0228
0229 static void hubbub3_get_blk256_size(unsigned int *blk256_width, unsigned int *blk256_height,
0230 unsigned int bytes_per_element)
0231 {
0232
0233
0234 if (bytes_per_element == 1) {
0235 *blk256_width = 16;
0236 *blk256_height = 16;
0237 } else if (bytes_per_element == 2) {
0238 *blk256_width = 16;
0239 *blk256_height = 8;
0240 } else if (bytes_per_element == 4) {
0241 *blk256_width = 8;
0242 *blk256_height = 8;
0243 } else if (bytes_per_element == 8) {
0244 *blk256_width = 8;
0245 *blk256_height = 4;
0246 }
0247 }
0248
0249 static void hubbub3_det_request_size(
0250 unsigned int detile_buf_size,
0251 unsigned int height,
0252 unsigned int width,
0253 unsigned int bpe,
0254 bool *req128_horz_wc,
0255 bool *req128_vert_wc)
0256 {
0257 unsigned int blk256_height = 0;
0258 unsigned int blk256_width = 0;
0259 unsigned int swath_bytes_horz_wc, swath_bytes_vert_wc;
0260
0261 hubbub3_get_blk256_size(&blk256_width, &blk256_height, bpe);
0262
0263 swath_bytes_horz_wc = width * blk256_height * bpe;
0264 swath_bytes_vert_wc = height * blk256_width * bpe;
0265
0266 *req128_horz_wc = (2 * swath_bytes_horz_wc <= detile_buf_size) ?
0267 false :
0268 true;
0269
0270 *req128_vert_wc = (2 * swath_bytes_vert_wc <= detile_buf_size) ?
0271 false :
0272 true;
0273 }
0274
0275 bool hubbub3_get_dcc_compression_cap(struct hubbub *hubbub,
0276 const struct dc_dcc_surface_param *input,
0277 struct dc_surface_dcc_cap *output)
0278 {
0279 struct dc *dc = hubbub->ctx->dc;
0280
0281 enum dcc_control dcc_control;
0282 unsigned int bpe;
0283 enum segment_order segment_order_horz, segment_order_vert;
0284 bool req128_horz_wc, req128_vert_wc;
0285
0286 memset(output, 0, sizeof(*output));
0287
0288 if (dc->debug.disable_dcc == DCC_DISABLE)
0289 return false;
0290
0291 if (!hubbub->funcs->dcc_support_pixel_format(input->format,
0292 &bpe))
0293 return false;
0294
0295 if (!hubbub->funcs->dcc_support_swizzle(input->swizzle_mode, bpe,
0296 &segment_order_horz, &segment_order_vert))
0297 return false;
0298
0299 hubbub3_det_request_size(TO_DCN20_HUBBUB(hubbub)->detile_buf_size,
0300 input->surface_size.height, input->surface_size.width,
0301 bpe, &req128_horz_wc, &req128_vert_wc);
0302
0303 if (!req128_horz_wc && !req128_vert_wc) {
0304 dcc_control = dcc_control__256_256_xxx;
0305 } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) {
0306 if (!req128_horz_wc)
0307 dcc_control = dcc_control__256_256_xxx;
0308 else if (segment_order_horz == segment_order__contiguous)
0309 dcc_control = dcc_control__128_128_xxx;
0310 else
0311 dcc_control = dcc_control__256_64_64;
0312 } else if (input->scan == SCAN_DIRECTION_VERTICAL) {
0313 if (!req128_vert_wc)
0314 dcc_control = dcc_control__256_256_xxx;
0315 else if (segment_order_vert == segment_order__contiguous)
0316 dcc_control = dcc_control__128_128_xxx;
0317 else
0318 dcc_control = dcc_control__256_64_64;
0319 } else {
0320 if ((req128_horz_wc &&
0321 segment_order_horz == segment_order__non_contiguous) ||
0322 (req128_vert_wc &&
0323 segment_order_vert == segment_order__non_contiguous))
0324
0325 dcc_control = dcc_control__256_64_64;
0326 else
0327
0328
0329
0330 dcc_control = dcc_control__128_128_xxx;
0331 }
0332
0333
0334 if ((bpe == 2) && (input->swizzle_mode == DC_SW_64KB_R_X))
0335 dcc_control = dcc_control__128_128_xxx;
0336
0337 if (dc->debug.disable_dcc == DCC_HALF_REQ_DISALBE &&
0338 dcc_control != dcc_control__256_256_xxx)
0339 return false;
0340
0341 switch (dcc_control) {
0342 case dcc_control__256_256_xxx:
0343 output->grph.rgb.max_uncompressed_blk_size = 256;
0344 output->grph.rgb.max_compressed_blk_size = 256;
0345 output->grph.rgb.independent_64b_blks = false;
0346 output->grph.rgb.dcc_controls.dcc_256_256_unconstrained = 1;
0347 output->grph.rgb.dcc_controls.dcc_256_128_128 = 1;
0348 break;
0349 case dcc_control__128_128_xxx:
0350 output->grph.rgb.max_uncompressed_blk_size = 128;
0351 output->grph.rgb.max_compressed_blk_size = 128;
0352 output->grph.rgb.independent_64b_blks = false;
0353 output->grph.rgb.dcc_controls.dcc_128_128_uncontrained = 1;
0354 output->grph.rgb.dcc_controls.dcc_256_128_128 = 1;
0355 break;
0356 case dcc_control__256_64_64:
0357 output->grph.rgb.max_uncompressed_blk_size = 256;
0358 output->grph.rgb.max_compressed_blk_size = 64;
0359 output->grph.rgb.independent_64b_blks = true;
0360 output->grph.rgb.dcc_controls.dcc_256_64_64 = 1;
0361 break;
0362 case dcc_control__256_128_128:
0363 output->grph.rgb.max_uncompressed_blk_size = 256;
0364 output->grph.rgb.max_compressed_blk_size = 128;
0365 output->grph.rgb.independent_64b_blks = false;
0366 output->grph.rgb.dcc_controls.dcc_256_128_128 = 1;
0367 break;
0368 }
0369 output->capable = true;
0370 output->const_color_support = true;
0371
0372 return true;
0373 }
0374
0375 void hubbub3_force_wm_propagate_to_pipes(struct hubbub *hubbub)
0376 {
0377 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
0378 uint32_t refclk_mhz = hubbub->ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000;
0379 uint32_t prog_wm_value = convert_and_clamp(hubbub1->watermarks.a.urgent_ns,
0380 refclk_mhz, 0x1fffff);
0381
0382 REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0,
0383 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value,
0384 DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_A, prog_wm_value);
0385 }
0386
0387 void hubbub3_force_pstate_change_control(struct hubbub *hubbub,
0388 bool force, bool allow)
0389 {
0390 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
0391
0392 REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
0393 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, allow,
0394 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, force);
0395 }
0396
0397
0398 void hubbub3_init_watermarks(struct hubbub *hubbub)
0399 {
0400 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
0401 uint32_t reg;
0402
0403 reg = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A);
0404 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, reg);
0405 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, reg);
0406 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, reg);
0407
0408 reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A);
0409 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, reg);
0410 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, reg);
0411 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, reg);
0412
0413 reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A);
0414 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, reg);
0415 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, reg);
0416 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, reg);
0417
0418 reg = REG_READ(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A);
0419 REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, reg);
0420 REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, reg);
0421 REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, reg);
0422
0423 reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A);
0424 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, reg);
0425 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, reg);
0426 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, reg);
0427
0428 reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A);
0429 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, reg);
0430 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, reg);
0431 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, reg);
0432
0433 reg = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A);
0434 REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, reg);
0435 REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, reg);
0436 REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, reg);
0437 }
0438
0439 static const struct hubbub_funcs hubbub30_funcs = {
0440 .update_dchub = hubbub2_update_dchub,
0441 .init_dchub_sys_ctx = hubbub3_init_dchub_sys_ctx,
0442 .init_vm_ctx = hubbub2_init_vm_ctx,
0443 .dcc_support_swizzle = hubbub3_dcc_support_swizzle,
0444 .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format,
0445 .get_dcc_compression_cap = hubbub3_get_dcc_compression_cap,
0446 .wm_read_state = hubbub21_wm_read_state,
0447 .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,
0448 .program_watermarks = hubbub3_program_watermarks,
0449 .allow_self_refresh_control = hubbub1_allow_self_refresh_control,
0450 .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
0451 .verify_allow_pstate_change_high = hubbub1_verify_allow_pstate_change_high,
0452 .force_wm_propagate_to_pipes = hubbub3_force_wm_propagate_to_pipes,
0453 .force_pstate_change_control = hubbub3_force_pstate_change_control,
0454 .init_watermarks = hubbub3_init_watermarks,
0455 .hubbub_read_state = hubbub2_read_state,
0456 };
0457
0458 void hubbub3_construct(struct dcn20_hubbub *hubbub3,
0459 struct dc_context *ctx,
0460 const struct dcn_hubbub_registers *hubbub_regs,
0461 const struct dcn_hubbub_shift *hubbub_shift,
0462 const struct dcn_hubbub_mask *hubbub_mask)
0463 {
0464 hubbub3->base.ctx = ctx;
0465 hubbub3->base.funcs = &hubbub30_funcs;
0466 hubbub3->regs = hubbub_regs;
0467 hubbub3->shifts = hubbub_shift;
0468 hubbub3->masks = hubbub_mask;
0469
0470 hubbub3->debug_test_index_pstate = 0xB;
0471 hubbub3->detile_buf_size = 184 * 1024;
0472 }
0473