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 "dcn30/dcn30_hubbub.h"
0028 #include "dcn31_hubbub.h"
0029 #include "dm_services.h"
0030 #include "reg_helper.h"
0031
0032
0033 #define CTX \
0034 hubbub2->base.ctx
0035 #define DC_LOGGER \
0036 hubbub2->base.ctx->logger
0037 #define REG(reg)\
0038 hubbub2->regs->reg
0039
0040 #undef FN
0041 #define FN(reg_name, field_name) \
0042 hubbub2->shifts->field_name, hubbub2->masks->field_name
0043
0044 #ifdef NUM_VMID
0045 #undef NUM_VMID
0046 #endif
0047 #define NUM_VMID 16
0048
0049 #define DCN31_CRB_SEGMENT_SIZE_KB 64
0050
0051 static void dcn31_init_crb(struct hubbub *hubbub)
0052 {
0053 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0054
0055 REG_GET(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT,
0056 &hubbub2->det0_size);
0057
0058 REG_GET(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT,
0059 &hubbub2->det1_size);
0060
0061 REG_GET(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT,
0062 &hubbub2->det2_size);
0063
0064 REG_GET(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT,
0065 &hubbub2->det3_size);
0066
0067 REG_GET(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT,
0068 &hubbub2->compbuf_size_segments);
0069
0070 REG_SET_2(COMPBUF_RESERVED_SPACE, 0,
0071 COMPBUF_RESERVED_SPACE_64B, hubbub2->pixel_chunk_size / 32,
0072 COMPBUF_RESERVED_SPACE_ZS, hubbub2->pixel_chunk_size / 128);
0073 REG_UPDATE(DCHUBBUB_DEBUG_CTRL_0, DET_DEPTH, 0x17F);
0074 }
0075
0076 static void dcn31_program_det_size(struct hubbub *hubbub, int hubp_inst, unsigned int det_buffer_size_in_kbyte)
0077 {
0078 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0079
0080 unsigned int det_size_segments = (det_buffer_size_in_kbyte + DCN31_CRB_SEGMENT_SIZE_KB - 1) / DCN31_CRB_SEGMENT_SIZE_KB;
0081
0082 switch (hubp_inst) {
0083 case 0:
0084 REG_UPDATE(DCHUBBUB_DET0_CTRL,
0085 DET0_SIZE, det_size_segments);
0086 hubbub2->det0_size = det_size_segments;
0087 break;
0088 case 1:
0089 REG_UPDATE(DCHUBBUB_DET1_CTRL,
0090 DET1_SIZE, det_size_segments);
0091 hubbub2->det1_size = det_size_segments;
0092 break;
0093 case 2:
0094 REG_UPDATE(DCHUBBUB_DET2_CTRL,
0095 DET2_SIZE, det_size_segments);
0096 hubbub2->det2_size = det_size_segments;
0097 break;
0098 case 3:
0099 REG_UPDATE(DCHUBBUB_DET3_CTRL,
0100 DET3_SIZE, det_size_segments);
0101 hubbub2->det3_size = det_size_segments;
0102 break;
0103 default:
0104 break;
0105 }
0106
0107 ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size
0108 + hubbub2->det3_size + hubbub2->compbuf_size_segments <= hubbub2->crb_size_segs);
0109 }
0110
0111 static void dcn31_program_compbuf_size(struct hubbub *hubbub, unsigned int compbuf_size_kb, bool safe_to_increase)
0112 {
0113 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0114 unsigned int compbuf_size_segments = (compbuf_size_kb + DCN31_CRB_SEGMENT_SIZE_KB - 1) / DCN31_CRB_SEGMENT_SIZE_KB;
0115
0116 if (safe_to_increase || compbuf_size_segments <= hubbub2->compbuf_size_segments) {
0117 if (compbuf_size_segments > hubbub2->compbuf_size_segments) {
0118 REG_WAIT(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, hubbub2->det0_size, 1, 100);
0119 REG_WAIT(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, hubbub2->det1_size, 1, 100);
0120 REG_WAIT(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, hubbub2->det2_size, 1, 100);
0121 REG_WAIT(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, hubbub2->det3_size, 1, 100);
0122 }
0123
0124 ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size
0125 + hubbub2->det3_size + compbuf_size_segments <= hubbub2->crb_size_segs);
0126 REG_UPDATE(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, compbuf_size_segments);
0127 hubbub2->compbuf_size_segments = compbuf_size_segments;
0128 ASSERT(REG_GET(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, &compbuf_size_segments) && !compbuf_size_segments);
0129 }
0130 }
0131
0132 static uint32_t convert_and_clamp(
0133 uint32_t wm_ns,
0134 uint32_t refclk_mhz,
0135 uint32_t clamp_value)
0136 {
0137 uint32_t ret_val = 0;
0138 ret_val = wm_ns * refclk_mhz;
0139 ret_val /= 1000;
0140
0141 if (ret_val > clamp_value) {
0142
0143 ASSERT(0);
0144 ret_val = clamp_value;
0145 }
0146
0147 return ret_val;
0148 }
0149
0150 static bool hubbub31_program_urgent_watermarks(
0151 struct hubbub *hubbub,
0152 struct dcn_watermark_set *watermarks,
0153 unsigned int refclk_mhz,
0154 bool safe_to_lower)
0155 {
0156 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0157 uint32_t prog_wm_value;
0158 bool wm_pending = false;
0159
0160
0161
0162 if (safe_to_lower || watermarks->a.urgent_ns > hubbub2->watermarks.a.urgent_ns) {
0163 hubbub2->watermarks.a.urgent_ns = watermarks->a.urgent_ns;
0164 prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns,
0165 refclk_mhz, 0x3fff);
0166 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0,
0167 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value);
0168
0169 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n"
0170 "HW register value = 0x%x\n",
0171 watermarks->a.urgent_ns, prog_wm_value);
0172 } else if (watermarks->a.urgent_ns < hubbub2->watermarks.a.urgent_ns)
0173 wm_pending = true;
0174
0175
0176 if (safe_to_lower || watermarks->a.frac_urg_bw_flip
0177 > hubbub2->watermarks.a.frac_urg_bw_flip) {
0178 hubbub2->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;
0179
0180 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0,
0181 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, watermarks->a.frac_urg_bw_flip);
0182 } else if (watermarks->a.frac_urg_bw_flip
0183 < hubbub2->watermarks.a.frac_urg_bw_flip)
0184 wm_pending = true;
0185
0186 if (safe_to_lower || watermarks->a.frac_urg_bw_nom
0187 > hubbub2->watermarks.a.frac_urg_bw_nom) {
0188 hubbub2->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;
0189
0190 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0,
0191 DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->a.frac_urg_bw_nom);
0192 } else if (watermarks->a.frac_urg_bw_nom
0193 < hubbub2->watermarks.a.frac_urg_bw_nom)
0194 wm_pending = true;
0195
0196 if (safe_to_lower || watermarks->a.urgent_latency_ns > hubbub2->watermarks.a.urgent_latency_ns) {
0197 hubbub2->watermarks.a.urgent_latency_ns = watermarks->a.urgent_latency_ns;
0198 prog_wm_value = convert_and_clamp(watermarks->a.urgent_latency_ns,
0199 refclk_mhz, 0x3fff);
0200 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0,
0201 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, prog_wm_value);
0202 } else if (watermarks->a.urgent_latency_ns < hubbub2->watermarks.a.urgent_latency_ns)
0203 wm_pending = true;
0204
0205
0206 if (safe_to_lower || watermarks->b.urgent_ns > hubbub2->watermarks.b.urgent_ns) {
0207 hubbub2->watermarks.b.urgent_ns = watermarks->b.urgent_ns;
0208 prog_wm_value = convert_and_clamp(watermarks->b.urgent_ns,
0209 refclk_mhz, 0x3fff);
0210 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0,
0211 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value);
0212
0213 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n"
0214 "HW register value = 0x%x\n",
0215 watermarks->b.urgent_ns, prog_wm_value);
0216 } else if (watermarks->b.urgent_ns < hubbub2->watermarks.b.urgent_ns)
0217 wm_pending = true;
0218
0219
0220 if (safe_to_lower || watermarks->b.frac_urg_bw_flip
0221 > hubbub2->watermarks.b.frac_urg_bw_flip) {
0222 hubbub2->watermarks.b.frac_urg_bw_flip = watermarks->b.frac_urg_bw_flip;
0223
0224 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0,
0225 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, watermarks->b.frac_urg_bw_flip);
0226 } else if (watermarks->b.frac_urg_bw_flip
0227 < hubbub2->watermarks.b.frac_urg_bw_flip)
0228 wm_pending = true;
0229
0230 if (safe_to_lower || watermarks->b.frac_urg_bw_nom
0231 > hubbub2->watermarks.b.frac_urg_bw_nom) {
0232 hubbub2->watermarks.b.frac_urg_bw_nom = watermarks->b.frac_urg_bw_nom;
0233
0234 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0,
0235 DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->b.frac_urg_bw_nom);
0236 } else if (watermarks->b.frac_urg_bw_nom
0237 < hubbub2->watermarks.b.frac_urg_bw_nom)
0238 wm_pending = true;
0239
0240 if (safe_to_lower || watermarks->b.urgent_latency_ns > hubbub2->watermarks.b.urgent_latency_ns) {
0241 hubbub2->watermarks.b.urgent_latency_ns = watermarks->b.urgent_latency_ns;
0242 prog_wm_value = convert_and_clamp(watermarks->b.urgent_latency_ns,
0243 refclk_mhz, 0x3fff);
0244 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0,
0245 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, prog_wm_value);
0246 } else if (watermarks->b.urgent_latency_ns < hubbub2->watermarks.b.urgent_latency_ns)
0247 wm_pending = true;
0248
0249
0250 if (safe_to_lower || watermarks->c.urgent_ns > hubbub2->watermarks.c.urgent_ns) {
0251 hubbub2->watermarks.c.urgent_ns = watermarks->c.urgent_ns;
0252 prog_wm_value = convert_and_clamp(watermarks->c.urgent_ns,
0253 refclk_mhz, 0x3fff);
0254 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0,
0255 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value);
0256
0257 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n"
0258 "HW register value = 0x%x\n",
0259 watermarks->c.urgent_ns, prog_wm_value);
0260 } else if (watermarks->c.urgent_ns < hubbub2->watermarks.c.urgent_ns)
0261 wm_pending = true;
0262
0263
0264 if (safe_to_lower || watermarks->c.frac_urg_bw_flip
0265 > hubbub2->watermarks.c.frac_urg_bw_flip) {
0266 hubbub2->watermarks.c.frac_urg_bw_flip = watermarks->c.frac_urg_bw_flip;
0267
0268 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, 0,
0269 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, watermarks->c.frac_urg_bw_flip);
0270 } else if (watermarks->c.frac_urg_bw_flip
0271 < hubbub2->watermarks.c.frac_urg_bw_flip)
0272 wm_pending = true;
0273
0274 if (safe_to_lower || watermarks->c.frac_urg_bw_nom
0275 > hubbub2->watermarks.c.frac_urg_bw_nom) {
0276 hubbub2->watermarks.c.frac_urg_bw_nom = watermarks->c.frac_urg_bw_nom;
0277
0278 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, 0,
0279 DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, watermarks->c.frac_urg_bw_nom);
0280 } else if (watermarks->c.frac_urg_bw_nom
0281 < hubbub2->watermarks.c.frac_urg_bw_nom)
0282 wm_pending = true;
0283
0284 if (safe_to_lower || watermarks->c.urgent_latency_ns > hubbub2->watermarks.c.urgent_latency_ns) {
0285 hubbub2->watermarks.c.urgent_latency_ns = watermarks->c.urgent_latency_ns;
0286 prog_wm_value = convert_and_clamp(watermarks->c.urgent_latency_ns,
0287 refclk_mhz, 0x3fff);
0288 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 0,
0289 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, prog_wm_value);
0290 } else if (watermarks->c.urgent_latency_ns < hubbub2->watermarks.c.urgent_latency_ns)
0291 wm_pending = true;
0292
0293
0294 if (safe_to_lower || watermarks->d.urgent_ns > hubbub2->watermarks.d.urgent_ns) {
0295 hubbub2->watermarks.d.urgent_ns = watermarks->d.urgent_ns;
0296 prog_wm_value = convert_and_clamp(watermarks->d.urgent_ns,
0297 refclk_mhz, 0x3fff);
0298 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0,
0299 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value);
0300
0301 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n"
0302 "HW register value = 0x%x\n",
0303 watermarks->d.urgent_ns, prog_wm_value);
0304 } else if (watermarks->d.urgent_ns < hubbub2->watermarks.d.urgent_ns)
0305 wm_pending = true;
0306
0307
0308 if (safe_to_lower || watermarks->d.frac_urg_bw_flip
0309 > hubbub2->watermarks.d.frac_urg_bw_flip) {
0310 hubbub2->watermarks.d.frac_urg_bw_flip = watermarks->d.frac_urg_bw_flip;
0311
0312 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, 0,
0313 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, watermarks->d.frac_urg_bw_flip);
0314 } else if (watermarks->d.frac_urg_bw_flip
0315 < hubbub2->watermarks.d.frac_urg_bw_flip)
0316 wm_pending = true;
0317
0318 if (safe_to_lower || watermarks->d.frac_urg_bw_nom
0319 > hubbub2->watermarks.d.frac_urg_bw_nom) {
0320 hubbub2->watermarks.d.frac_urg_bw_nom = watermarks->d.frac_urg_bw_nom;
0321
0322 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 0,
0323 DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, watermarks->d.frac_urg_bw_nom);
0324 } else if (watermarks->d.frac_urg_bw_nom
0325 < hubbub2->watermarks.d.frac_urg_bw_nom)
0326 wm_pending = true;
0327
0328 if (safe_to_lower || watermarks->d.urgent_latency_ns > hubbub2->watermarks.d.urgent_latency_ns) {
0329 hubbub2->watermarks.d.urgent_latency_ns = watermarks->d.urgent_latency_ns;
0330 prog_wm_value = convert_and_clamp(watermarks->d.urgent_latency_ns,
0331 refclk_mhz, 0x3fff);
0332 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0,
0333 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, prog_wm_value);
0334 } else if (watermarks->d.urgent_latency_ns < hubbub2->watermarks.d.urgent_latency_ns)
0335 wm_pending = true;
0336
0337 return wm_pending;
0338 }
0339
0340 static bool hubbub31_program_stutter_watermarks(
0341 struct hubbub *hubbub,
0342 struct dcn_watermark_set *watermarks,
0343 unsigned int refclk_mhz,
0344 bool safe_to_lower)
0345 {
0346 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0347 uint32_t prog_wm_value;
0348 bool wm_pending = false;
0349
0350
0351 if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
0352 > hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) {
0353 hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns =
0354 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns;
0355 prog_wm_value = convert_and_clamp(
0356 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns,
0357 refclk_mhz, 0xffff);
0358 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0,
0359 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value);
0360 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"
0361 "HW register value = 0x%x\n",
0362 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
0363 } else if (watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
0364 < hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns)
0365 wm_pending = true;
0366
0367 if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns
0368 > hubbub2->watermarks.a.cstate_pstate.cstate_exit_ns) {
0369 hubbub2->watermarks.a.cstate_pstate.cstate_exit_ns =
0370 watermarks->a.cstate_pstate.cstate_exit_ns;
0371 prog_wm_value = convert_and_clamp(
0372 watermarks->a.cstate_pstate.cstate_exit_ns,
0373 refclk_mhz, 0xffff);
0374 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0,
0375 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
0376 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"
0377 "HW register value = 0x%x\n",
0378 watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value);
0379 } else if (watermarks->a.cstate_pstate.cstate_exit_ns
0380 < hubbub2->watermarks.a.cstate_pstate.cstate_exit_ns)
0381 wm_pending = true;
0382
0383 if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns
0384 > hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns) {
0385 hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns =
0386 watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns;
0387 prog_wm_value = convert_and_clamp(
0388 watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns,
0389 refclk_mhz, 0xffff);
0390 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, 0,
0391 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, prog_wm_value);
0392 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_A calculated =%d\n"
0393 "HW register value = 0x%x\n",
0394 watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns, prog_wm_value);
0395 } else if (watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns
0396 < hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns)
0397 wm_pending = true;
0398
0399 if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_z8_ns
0400 > hubbub2->watermarks.a.cstate_pstate.cstate_exit_z8_ns) {
0401 hubbub2->watermarks.a.cstate_pstate.cstate_exit_z8_ns =
0402 watermarks->a.cstate_pstate.cstate_exit_z8_ns;
0403 prog_wm_value = convert_and_clamp(
0404 watermarks->a.cstate_pstate.cstate_exit_z8_ns,
0405 refclk_mhz, 0xffff);
0406 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, 0,
0407 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, prog_wm_value);
0408 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_A calculated =%d\n"
0409 "HW register value = 0x%x\n",
0410 watermarks->a.cstate_pstate.cstate_exit_z8_ns, prog_wm_value);
0411 } else if (watermarks->a.cstate_pstate.cstate_exit_z8_ns
0412 < hubbub2->watermarks.a.cstate_pstate.cstate_exit_z8_ns)
0413 wm_pending = true;
0414
0415
0416 if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
0417 > hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) {
0418 hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns =
0419 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns;
0420 prog_wm_value = convert_and_clamp(
0421 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns,
0422 refclk_mhz, 0xffff);
0423 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0,
0424 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value);
0425 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n"
0426 "HW register value = 0x%x\n",
0427 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
0428 } else if (watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
0429 < hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns)
0430 wm_pending = true;
0431
0432 if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns
0433 > hubbub2->watermarks.b.cstate_pstate.cstate_exit_ns) {
0434 hubbub2->watermarks.b.cstate_pstate.cstate_exit_ns =
0435 watermarks->b.cstate_pstate.cstate_exit_ns;
0436 prog_wm_value = convert_and_clamp(
0437 watermarks->b.cstate_pstate.cstate_exit_ns,
0438 refclk_mhz, 0xffff);
0439 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0,
0440 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value);
0441 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"
0442 "HW register value = 0x%x\n",
0443 watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value);
0444 } else if (watermarks->b.cstate_pstate.cstate_exit_ns
0445 < hubbub2->watermarks.b.cstate_pstate.cstate_exit_ns)
0446 wm_pending = true;
0447
0448 if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns
0449 > hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_z8_ns) {
0450 hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_z8_ns =
0451 watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns;
0452 prog_wm_value = convert_and_clamp(
0453 watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns,
0454 refclk_mhz, 0xffff);
0455 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, 0,
0456 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, prog_wm_value);
0457 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_B calculated =%d\n"
0458 "HW register value = 0x%x\n",
0459 watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns, prog_wm_value);
0460 } else if (watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns
0461 < hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_z8_ns)
0462 wm_pending = true;
0463
0464 if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_z8_ns
0465 > hubbub2->watermarks.b.cstate_pstate.cstate_exit_z8_ns) {
0466 hubbub2->watermarks.b.cstate_pstate.cstate_exit_z8_ns =
0467 watermarks->b.cstate_pstate.cstate_exit_z8_ns;
0468 prog_wm_value = convert_and_clamp(
0469 watermarks->b.cstate_pstate.cstate_exit_z8_ns,
0470 refclk_mhz, 0xffff);
0471 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, 0,
0472 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, prog_wm_value);
0473 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_B calculated =%d\n"
0474 "HW register value = 0x%x\n",
0475 watermarks->b.cstate_pstate.cstate_exit_z8_ns, prog_wm_value);
0476 } else if (watermarks->b.cstate_pstate.cstate_exit_z8_ns
0477 < hubbub2->watermarks.b.cstate_pstate.cstate_exit_z8_ns)
0478 wm_pending = true;
0479
0480
0481 if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
0482 > hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) {
0483 hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns =
0484 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns;
0485 prog_wm_value = convert_and_clamp(
0486 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns,
0487 refclk_mhz, 0xffff);
0488 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0,
0489 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value);
0490 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n"
0491 "HW register value = 0x%x\n",
0492 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
0493 } else if (watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
0494 < hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns)
0495 wm_pending = true;
0496
0497 if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns
0498 > hubbub2->watermarks.c.cstate_pstate.cstate_exit_ns) {
0499 hubbub2->watermarks.c.cstate_pstate.cstate_exit_ns =
0500 watermarks->c.cstate_pstate.cstate_exit_ns;
0501 prog_wm_value = convert_and_clamp(
0502 watermarks->c.cstate_pstate.cstate_exit_ns,
0503 refclk_mhz, 0xffff);
0504 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0,
0505 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value);
0506 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"
0507 "HW register value = 0x%x\n",
0508 watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value);
0509 } else if (watermarks->c.cstate_pstate.cstate_exit_ns
0510 < hubbub2->watermarks.c.cstate_pstate.cstate_exit_ns)
0511 wm_pending = true;
0512
0513 if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns
0514 > hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_z8_ns) {
0515 hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_z8_ns =
0516 watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns;
0517 prog_wm_value = convert_and_clamp(
0518 watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns,
0519 refclk_mhz, 0xffff);
0520 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, 0,
0521 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, prog_wm_value);
0522 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_C calculated =%d\n"
0523 "HW register value = 0x%x\n",
0524 watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns, prog_wm_value);
0525 } else if (watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns
0526 < hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_z8_ns)
0527 wm_pending = true;
0528
0529 if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_z8_ns
0530 > hubbub2->watermarks.c.cstate_pstate.cstate_exit_z8_ns) {
0531 hubbub2->watermarks.c.cstate_pstate.cstate_exit_z8_ns =
0532 watermarks->c.cstate_pstate.cstate_exit_z8_ns;
0533 prog_wm_value = convert_and_clamp(
0534 watermarks->c.cstate_pstate.cstate_exit_z8_ns,
0535 refclk_mhz, 0xffff);
0536 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, 0,
0537 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, prog_wm_value);
0538 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_C calculated =%d\n"
0539 "HW register value = 0x%x\n",
0540 watermarks->c.cstate_pstate.cstate_exit_z8_ns, prog_wm_value);
0541 } else if (watermarks->c.cstate_pstate.cstate_exit_z8_ns
0542 < hubbub2->watermarks.c.cstate_pstate.cstate_exit_z8_ns)
0543 wm_pending = true;
0544
0545
0546 if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
0547 > hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) {
0548 hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns =
0549 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns;
0550 prog_wm_value = convert_and_clamp(
0551 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns,
0552 refclk_mhz, 0xffff);
0553 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0,
0554 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value);
0555 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n"
0556 "HW register value = 0x%x\n",
0557 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
0558 } else if (watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
0559 < hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns)
0560 wm_pending = true;
0561
0562 if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns
0563 > hubbub2->watermarks.d.cstate_pstate.cstate_exit_ns) {
0564 hubbub2->watermarks.d.cstate_pstate.cstate_exit_ns =
0565 watermarks->d.cstate_pstate.cstate_exit_ns;
0566 prog_wm_value = convert_and_clamp(
0567 watermarks->d.cstate_pstate.cstate_exit_ns,
0568 refclk_mhz, 0xffff);
0569 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0,
0570 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value);
0571 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"
0572 "HW register value = 0x%x\n",
0573 watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value);
0574 } else if (watermarks->d.cstate_pstate.cstate_exit_ns
0575 < hubbub2->watermarks.d.cstate_pstate.cstate_exit_ns)
0576 wm_pending = true;
0577
0578 if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns
0579 > hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_z8_ns) {
0580 hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_z8_ns =
0581 watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns;
0582 prog_wm_value = convert_and_clamp(
0583 watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns,
0584 refclk_mhz, 0xffff);
0585 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, 0,
0586 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, prog_wm_value);
0587 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_D calculated =%d\n"
0588 "HW register value = 0x%x\n",
0589 watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns, prog_wm_value);
0590 } else if (watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns
0591 < hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_z8_ns)
0592 wm_pending = true;
0593
0594 if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_z8_ns
0595 > hubbub2->watermarks.d.cstate_pstate.cstate_exit_z8_ns) {
0596 hubbub2->watermarks.d.cstate_pstate.cstate_exit_z8_ns =
0597 watermarks->d.cstate_pstate.cstate_exit_z8_ns;
0598 prog_wm_value = convert_and_clamp(
0599 watermarks->d.cstate_pstate.cstate_exit_z8_ns,
0600 refclk_mhz, 0xffff);
0601 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, 0,
0602 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, prog_wm_value);
0603 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_D calculated =%d\n"
0604 "HW register value = 0x%x\n",
0605 watermarks->d.cstate_pstate.cstate_exit_z8_ns, prog_wm_value);
0606 } else if (watermarks->d.cstate_pstate.cstate_exit_z8_ns
0607 < hubbub2->watermarks.d.cstate_pstate.cstate_exit_z8_ns)
0608 wm_pending = true;
0609
0610 return wm_pending;
0611 }
0612
0613 static bool hubbub31_program_pstate_watermarks(
0614 struct hubbub *hubbub,
0615 struct dcn_watermark_set *watermarks,
0616 unsigned int refclk_mhz,
0617 bool safe_to_lower)
0618 {
0619 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0620 uint32_t prog_wm_value;
0621
0622 bool wm_pending = false;
0623
0624
0625 if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns
0626 > hubbub2->watermarks.a.cstate_pstate.pstate_change_ns) {
0627 hubbub2->watermarks.a.cstate_pstate.pstate_change_ns =
0628 watermarks->a.cstate_pstate.pstate_change_ns;
0629 prog_wm_value = convert_and_clamp(
0630 watermarks->a.cstate_pstate.pstate_change_ns,
0631 refclk_mhz, 0xffff);
0632 REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, 0,
0633 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value);
0634 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"
0635 "HW register value = 0x%x\n\n",
0636 watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value);
0637 } else if (watermarks->a.cstate_pstate.pstate_change_ns
0638 < hubbub2->watermarks.a.cstate_pstate.pstate_change_ns)
0639 wm_pending = true;
0640
0641
0642 if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns
0643 > hubbub2->watermarks.b.cstate_pstate.pstate_change_ns) {
0644 hubbub2->watermarks.b.cstate_pstate.pstate_change_ns =
0645 watermarks->b.cstate_pstate.pstate_change_ns;
0646 prog_wm_value = convert_and_clamp(
0647 watermarks->b.cstate_pstate.pstate_change_ns,
0648 refclk_mhz, 0xffff);
0649 REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, 0,
0650 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value);
0651 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n"
0652 "HW register value = 0x%x\n\n",
0653 watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value);
0654 } else if (watermarks->b.cstate_pstate.pstate_change_ns
0655 < hubbub2->watermarks.b.cstate_pstate.pstate_change_ns)
0656 wm_pending = false;
0657
0658
0659 if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns
0660 > hubbub2->watermarks.c.cstate_pstate.pstate_change_ns) {
0661 hubbub2->watermarks.c.cstate_pstate.pstate_change_ns =
0662 watermarks->c.cstate_pstate.pstate_change_ns;
0663 prog_wm_value = convert_and_clamp(
0664 watermarks->c.cstate_pstate.pstate_change_ns,
0665 refclk_mhz, 0xffff);
0666 REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, 0,
0667 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value);
0668 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n"
0669 "HW register value = 0x%x\n\n",
0670 watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value);
0671 } else if (watermarks->c.cstate_pstate.pstate_change_ns
0672 < hubbub2->watermarks.c.cstate_pstate.pstate_change_ns)
0673 wm_pending = true;
0674
0675
0676 if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns
0677 > hubbub2->watermarks.d.cstate_pstate.pstate_change_ns) {
0678 hubbub2->watermarks.d.cstate_pstate.pstate_change_ns =
0679 watermarks->d.cstate_pstate.pstate_change_ns;
0680 prog_wm_value = convert_and_clamp(
0681 watermarks->d.cstate_pstate.pstate_change_ns,
0682 refclk_mhz, 0xffff);
0683 REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, 0,
0684 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value);
0685 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n"
0686 "HW register value = 0x%x\n\n",
0687 watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value);
0688 } else if (watermarks->d.cstate_pstate.pstate_change_ns
0689 < hubbub2->watermarks.d.cstate_pstate.pstate_change_ns)
0690 wm_pending = true;
0691
0692 return wm_pending;
0693 }
0694
0695 static bool hubbub31_program_watermarks(
0696 struct hubbub *hubbub,
0697 struct dcn_watermark_set *watermarks,
0698 unsigned int refclk_mhz,
0699 bool safe_to_lower)
0700 {
0701 bool wm_pending = false;
0702
0703 if (hubbub31_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
0704 wm_pending = true;
0705
0706 if (hubbub31_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
0707 wm_pending = true;
0708
0709 if (hubbub31_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
0710 wm_pending = true;
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725
0726
0727
0728
0729
0730 hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
0731 return wm_pending;
0732 }
0733
0734 static void hubbub3_get_blk256_size(unsigned int *blk256_width, unsigned int *blk256_height,
0735 unsigned int bytes_per_element)
0736 {
0737
0738
0739 if (bytes_per_element == 1) {
0740 *blk256_width = 16;
0741 *blk256_height = 16;
0742 } else if (bytes_per_element == 2) {
0743 *blk256_width = 16;
0744 *blk256_height = 8;
0745 } else if (bytes_per_element == 4) {
0746 *blk256_width = 8;
0747 *blk256_height = 8;
0748 } else if (bytes_per_element == 8) {
0749 *blk256_width = 8;
0750 *blk256_height = 4;
0751 }
0752 }
0753
0754 static void hubbub31_det_request_size(
0755 unsigned int detile_buf_size,
0756 unsigned int height,
0757 unsigned int width,
0758 unsigned int bpe,
0759 bool *req128_horz_wc,
0760 bool *req128_vert_wc)
0761 {
0762 unsigned int blk256_height = 0;
0763 unsigned int blk256_width = 0;
0764 unsigned int swath_bytes_horz_wc, swath_bytes_vert_wc;
0765
0766 hubbub3_get_blk256_size(&blk256_width, &blk256_height, bpe);
0767
0768 swath_bytes_horz_wc = width * blk256_height * bpe;
0769 swath_bytes_vert_wc = height * blk256_width * bpe;
0770
0771 *req128_horz_wc = (2 * swath_bytes_horz_wc <= detile_buf_size) ?
0772 false :
0773 true;
0774
0775 *req128_vert_wc = (2 * swath_bytes_vert_wc <= detile_buf_size) ?
0776 false :
0777 true;
0778 }
0779
0780 static bool hubbub31_get_dcc_compression_cap(struct hubbub *hubbub,
0781 const struct dc_dcc_surface_param *input,
0782 struct dc_surface_dcc_cap *output)
0783 {
0784 struct dc *dc = hubbub->ctx->dc;
0785 enum dcc_control dcc_control;
0786 unsigned int bpe;
0787 enum segment_order segment_order_horz, segment_order_vert;
0788 bool req128_horz_wc, req128_vert_wc;
0789
0790 memset(output, 0, sizeof(*output));
0791
0792 if (dc->debug.disable_dcc == DCC_DISABLE)
0793 return false;
0794
0795 if (!hubbub->funcs->dcc_support_pixel_format(input->format,
0796 &bpe))
0797 return false;
0798
0799 if (!hubbub->funcs->dcc_support_swizzle(input->swizzle_mode, bpe,
0800 &segment_order_horz, &segment_order_vert))
0801 return false;
0802
0803 hubbub31_det_request_size(TO_DCN20_HUBBUB(hubbub)->detile_buf_size,
0804 input->surface_size.height, input->surface_size.width,
0805 bpe, &req128_horz_wc, &req128_vert_wc);
0806
0807 if (!req128_horz_wc && !req128_vert_wc) {
0808 dcc_control = dcc_control__256_256_xxx;
0809 } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) {
0810 if (!req128_horz_wc)
0811 dcc_control = dcc_control__256_256_xxx;
0812 else if (segment_order_horz == segment_order__contiguous)
0813 dcc_control = dcc_control__128_128_xxx;
0814 else
0815 dcc_control = dcc_control__256_64_64;
0816 } else if (input->scan == SCAN_DIRECTION_VERTICAL) {
0817 if (!req128_vert_wc)
0818 dcc_control = dcc_control__256_256_xxx;
0819 else if (segment_order_vert == segment_order__contiguous)
0820 dcc_control = dcc_control__128_128_xxx;
0821 else
0822 dcc_control = dcc_control__256_64_64;
0823 } else {
0824 if ((req128_horz_wc &&
0825 segment_order_horz == segment_order__non_contiguous) ||
0826 (req128_vert_wc &&
0827 segment_order_vert == segment_order__non_contiguous))
0828
0829 dcc_control = dcc_control__256_64_64;
0830 else
0831
0832
0833
0834 dcc_control = dcc_control__128_128_xxx;
0835 }
0836
0837
0838 if ((bpe == 2) && (input->swizzle_mode == DC_SW_64KB_R_X))
0839 dcc_control = dcc_control__128_128_xxx;
0840
0841 if (dc->debug.disable_dcc == DCC_HALF_REQ_DISALBE &&
0842 dcc_control != dcc_control__256_256_xxx)
0843 return false;
0844
0845 switch (dcc_control) {
0846 case dcc_control__256_256_xxx:
0847 output->grph.rgb.max_uncompressed_blk_size = 256;
0848 output->grph.rgb.max_compressed_blk_size = 256;
0849 output->grph.rgb.independent_64b_blks = false;
0850 output->grph.rgb.dcc_controls.dcc_256_256_unconstrained = 1;
0851 output->grph.rgb.dcc_controls.dcc_256_128_128 = 1;
0852 break;
0853 case dcc_control__128_128_xxx:
0854 output->grph.rgb.max_uncompressed_blk_size = 128;
0855 output->grph.rgb.max_compressed_blk_size = 128;
0856 output->grph.rgb.independent_64b_blks = false;
0857 output->grph.rgb.dcc_controls.dcc_128_128_uncontrained = 1;
0858 output->grph.rgb.dcc_controls.dcc_256_128_128 = 1;
0859 break;
0860 case dcc_control__256_64_64:
0861 output->grph.rgb.max_uncompressed_blk_size = 256;
0862 output->grph.rgb.max_compressed_blk_size = 64;
0863 output->grph.rgb.independent_64b_blks = true;
0864 output->grph.rgb.dcc_controls.dcc_256_64_64 = 1;
0865 break;
0866 case dcc_control__256_128_128:
0867 output->grph.rgb.max_uncompressed_blk_size = 256;
0868 output->grph.rgb.max_compressed_blk_size = 128;
0869 output->grph.rgb.independent_64b_blks = false;
0870 output->grph.rgb.dcc_controls.dcc_256_128_128 = 1;
0871 break;
0872 }
0873 output->capable = true;
0874 output->const_color_support = true;
0875
0876 return true;
0877 }
0878
0879 static int hubbub31_init_dchub_sys_ctx(struct hubbub *hubbub,
0880 struct dcn_hubbub_phys_addr_config *pa_config)
0881 {
0882 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0883 struct dcn_vmid_page_table_config phys_config;
0884
0885 REG_SET(DCN_VM_FB_LOCATION_BASE, 0,
0886 FB_BASE, pa_config->system_aperture.fb_base >> 24);
0887 REG_SET(DCN_VM_FB_LOCATION_TOP, 0,
0888 FB_TOP, pa_config->system_aperture.fb_top >> 24);
0889 REG_SET(DCN_VM_FB_OFFSET, 0,
0890 FB_OFFSET, pa_config->system_aperture.fb_offset >> 24);
0891 REG_SET(DCN_VM_AGP_BOT, 0,
0892 AGP_BOT, pa_config->system_aperture.agp_bot >> 24);
0893 REG_SET(DCN_VM_AGP_TOP, 0,
0894 AGP_TOP, pa_config->system_aperture.agp_top >> 24);
0895 REG_SET(DCN_VM_AGP_BASE, 0,
0896 AGP_BASE, pa_config->system_aperture.agp_base >> 24);
0897
0898 if (pa_config->gart_config.page_table_start_addr != pa_config->gart_config.page_table_end_addr) {
0899 phys_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr >> 12;
0900 phys_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr >> 12;
0901 phys_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr;
0902 phys_config.depth = 0;
0903 phys_config.block_size = 0;
0904
0905 dcn20_vmid_setup(&hubbub2->vmid[0], &phys_config);
0906
0907 dcn20_vmid_setup(&hubbub2->vmid[15], &phys_config);
0908 }
0909
0910 dcn21_dchvm_init(hubbub);
0911
0912 return NUM_VMID;
0913 }
0914
0915 static void hubbub31_get_dchub_ref_freq(struct hubbub *hubbub,
0916 unsigned int dccg_ref_freq_inKhz,
0917 unsigned int *dchub_ref_freq_inKhz)
0918 {
0919 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0920 uint32_t ref_div = 0;
0921 uint32_t ref_en = 0;
0922 unsigned int dc_refclk_khz = 24000;
0923
0924 REG_GET_2(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, &ref_div,
0925 DCHUBBUB_GLOBAL_TIMER_ENABLE, &ref_en);
0926
0927 if (ref_en) {
0928 if (ref_div == 2)
0929 *dchub_ref_freq_inKhz = dc_refclk_khz / 2;
0930 else
0931 *dchub_ref_freq_inKhz = dc_refclk_khz;
0932
0933
0934
0935
0936
0937
0938
0939 if (*dchub_ref_freq_inKhz < 20000 || *dchub_ref_freq_inKhz > 50000)
0940 ASSERT_CRITICAL(false);
0941
0942 return;
0943 } else {
0944 *dchub_ref_freq_inKhz = dc_refclk_khz;
0945
0946
0947 ASSERT_CRITICAL(false);
0948 return;
0949 }
0950 }
0951
0952 static bool hubbub31_verify_allow_pstate_change_high(struct hubbub *hubbub)
0953 {
0954 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0955
0956
0957
0958
0959
0960 const unsigned int pstate_wait_timeout_us = 100;
0961 const unsigned int pstate_wait_expected_timeout_us = 40;
0962
0963 static unsigned int max_sampled_pstate_wait_us;
0964 static bool forced_pstate_allow;
0965
0966 unsigned int debug_data = 0;
0967 unsigned int i;
0968
0969 if (forced_pstate_allow) {
0970
0971
0972
0973
0974 REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
0975 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 0,
0976 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 0);
0977 forced_pstate_allow = false;
0978 }
0979
0980 REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, hubbub2->debug_test_index_pstate);
0981
0982 for (i = 0; i < pstate_wait_timeout_us; i++) {
0983 debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA);
0984
0985
0986 if (debug_data & (1 << 26)) {
0987 if (i > pstate_wait_expected_timeout_us)
0988 DC_LOG_WARNING("pstate took longer than expected ~%dus\n", i);
0989 return true;
0990 }
0991 if (max_sampled_pstate_wait_us < i)
0992 max_sampled_pstate_wait_us = i;
0993
0994 udelay(1);
0995 }
0996
0997
0998
0999
1000 REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
1001 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 1,
1002 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1);
1003 forced_pstate_allow = true;
1004
1005 DC_LOG_WARNING("pstate TEST_DEBUG_DATA: 0x%X\n",
1006 debug_data);
1007
1008 return false;
1009 }
1010
1011 static const struct hubbub_funcs hubbub31_funcs = {
1012 .update_dchub = hubbub2_update_dchub,
1013 .init_dchub_sys_ctx = hubbub31_init_dchub_sys_ctx,
1014 .init_vm_ctx = hubbub2_init_vm_ctx,
1015 .dcc_support_swizzle = hubbub3_dcc_support_swizzle,
1016 .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format,
1017 .get_dcc_compression_cap = hubbub31_get_dcc_compression_cap,
1018 .wm_read_state = hubbub21_wm_read_state,
1019 .get_dchub_ref_freq = hubbub31_get_dchub_ref_freq,
1020 .program_watermarks = hubbub31_program_watermarks,
1021 .allow_self_refresh_control = hubbub1_allow_self_refresh_control,
1022 .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
1023 .verify_allow_pstate_change_high = hubbub31_verify_allow_pstate_change_high,
1024 .program_det_size = dcn31_program_det_size,
1025 .program_compbuf_size = dcn31_program_compbuf_size,
1026 .init_crb = dcn31_init_crb,
1027 .hubbub_read_state = hubbub2_read_state,
1028 };
1029
1030 void hubbub31_construct(struct dcn20_hubbub *hubbub31,
1031 struct dc_context *ctx,
1032 const struct dcn_hubbub_registers *hubbub_regs,
1033 const struct dcn_hubbub_shift *hubbub_shift,
1034 const struct dcn_hubbub_mask *hubbub_mask,
1035 int det_size_kb,
1036 int pixel_chunk_size_kb,
1037 int config_return_buffer_size_kb)
1038 {
1039
1040 hubbub3_construct(hubbub31, ctx, hubbub_regs, hubbub_shift, hubbub_mask);
1041 hubbub31->base.funcs = &hubbub31_funcs;
1042 hubbub31->detile_buf_size = det_size_kb * 1024;
1043 hubbub31->pixel_chunk_size = pixel_chunk_size_kb * 1024;
1044 hubbub31->crb_size_segs = config_return_buffer_size_kb / DCN31_CRB_SEGMENT_SIZE_KB;
1045
1046 hubbub31->debug_test_index_pstate = 0x6;
1047 }
1048