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 "dcn32_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 #define DCN32_CRB_SEGMENT_SIZE_KB 64
0045
0046 static void dcn32_init_crb(struct hubbub *hubbub)
0047 {
0048 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0049
0050 REG_GET(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT,
0051 &hubbub2->det0_size);
0052
0053 REG_GET(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT,
0054 &hubbub2->det1_size);
0055
0056 REG_GET(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT,
0057 &hubbub2->det2_size);
0058
0059 REG_GET(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT,
0060 &hubbub2->det3_size);
0061
0062 REG_GET(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT,
0063 &hubbub2->compbuf_size_segments);
0064
0065 REG_SET_2(COMPBUF_RESERVED_SPACE, 0,
0066 COMPBUF_RESERVED_SPACE_64B, hubbub2->pixel_chunk_size / 32,
0067 COMPBUF_RESERVED_SPACE_ZS, hubbub2->pixel_chunk_size / 128);
0068 REG_UPDATE(DCHUBBUB_DEBUG_CTRL_0, DET_DEPTH, 0x47F);
0069 }
0070
0071 static void dcn32_program_det_size(struct hubbub *hubbub, int hubp_inst, unsigned int det_buffer_size_in_kbyte)
0072 {
0073 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0074
0075 unsigned int det_size_segments = (det_buffer_size_in_kbyte + DCN32_CRB_SEGMENT_SIZE_KB - 1) / DCN32_CRB_SEGMENT_SIZE_KB;
0076
0077 switch (hubp_inst) {
0078 case 0:
0079 REG_UPDATE(DCHUBBUB_DET0_CTRL,
0080 DET0_SIZE, det_size_segments);
0081 hubbub2->det0_size = det_size_segments;
0082 break;
0083 case 1:
0084 REG_UPDATE(DCHUBBUB_DET1_CTRL,
0085 DET1_SIZE, det_size_segments);
0086 hubbub2->det1_size = det_size_segments;
0087 break;
0088 case 2:
0089 REG_UPDATE(DCHUBBUB_DET2_CTRL,
0090 DET2_SIZE, det_size_segments);
0091 hubbub2->det2_size = det_size_segments;
0092 break;
0093 case 3:
0094 REG_UPDATE(DCHUBBUB_DET3_CTRL,
0095 DET3_SIZE, det_size_segments);
0096 hubbub2->det3_size = det_size_segments;
0097 break;
0098 default:
0099 break;
0100 }
0101 if (hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size
0102 + hubbub2->det3_size + hubbub2->compbuf_size_segments > hubbub2->crb_size_segs) {
0103
0104 DC_LOG_WARNING("CRB Config Warning: DET size (%d,%d,%d,%d) + Compbuf size (%d) > CRB segments (%d)\n",
0105 hubbub2->det0_size, hubbub2->det1_size, hubbub2->det2_size, hubbub2->det3_size,
0106 hubbub2->compbuf_size_segments, hubbub2->crb_size_segs);
0107 }
0108 }
0109
0110 static void dcn32_program_compbuf_size(struct hubbub *hubbub, unsigned int compbuf_size_kb, bool safe_to_increase)
0111 {
0112 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0113 unsigned int compbuf_size_segments = (compbuf_size_kb + DCN32_CRB_SEGMENT_SIZE_KB - 1) / DCN32_CRB_SEGMENT_SIZE_KB;
0114
0115 if (safe_to_increase || compbuf_size_segments <= hubbub2->compbuf_size_segments) {
0116 if (compbuf_size_segments > hubbub2->compbuf_size_segments) {
0117 REG_WAIT(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, hubbub2->det0_size, 1, 100);
0118 REG_WAIT(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, hubbub2->det1_size, 1, 100);
0119 REG_WAIT(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, hubbub2->det2_size, 1, 100);
0120 REG_WAIT(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, hubbub2->det3_size, 1, 100);
0121 }
0122
0123 ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size
0124 + hubbub2->det3_size + compbuf_size_segments <= hubbub2->crb_size_segs);
0125 REG_UPDATE(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, compbuf_size_segments);
0126 hubbub2->compbuf_size_segments = compbuf_size_segments;
0127 ASSERT(REG_GET(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, &compbuf_size_segments) && !compbuf_size_segments);
0128 }
0129 }
0130
0131 static uint32_t convert_and_clamp(
0132 uint32_t wm_ns,
0133 uint32_t refclk_mhz,
0134 uint32_t clamp_value)
0135 {
0136 uint32_t ret_val = 0;
0137 ret_val = wm_ns * refclk_mhz;
0138
0139 ret_val /= 1000;
0140
0141 if (ret_val > clamp_value)
0142 ret_val = clamp_value;
0143
0144 return ret_val;
0145 }
0146
0147 static bool hubbub32_program_urgent_watermarks(
0148 struct hubbub *hubbub,
0149 struct dcn_watermark_set *watermarks,
0150 unsigned int refclk_mhz,
0151 bool safe_to_lower)
0152 {
0153 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0154 uint32_t prog_wm_value;
0155 bool wm_pending = false;
0156
0157
0158
0159 if (safe_to_lower || watermarks->a.urgent_ns > hubbub2->watermarks.a.urgent_ns) {
0160 hubbub2->watermarks.a.urgent_ns = watermarks->a.urgent_ns;
0161 prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns,
0162 refclk_mhz, 0x3fff);
0163 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0,
0164 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value);
0165
0166 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n"
0167 "HW register value = 0x%x\n",
0168 watermarks->a.urgent_ns, prog_wm_value);
0169 } else if (watermarks->a.urgent_ns < hubbub2->watermarks.a.urgent_ns)
0170 wm_pending = true;
0171
0172
0173 if (safe_to_lower || watermarks->a.frac_urg_bw_flip
0174 > hubbub2->watermarks.a.frac_urg_bw_flip) {
0175 hubbub2->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;
0176
0177 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0,
0178 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, watermarks->a.frac_urg_bw_flip);
0179 } else if (watermarks->a.frac_urg_bw_flip
0180 < hubbub2->watermarks.a.frac_urg_bw_flip)
0181 wm_pending = true;
0182
0183 if (safe_to_lower || watermarks->a.frac_urg_bw_nom
0184 > hubbub2->watermarks.a.frac_urg_bw_nom) {
0185 hubbub2->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;
0186
0187 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0,
0188 DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->a.frac_urg_bw_nom);
0189 } else if (watermarks->a.frac_urg_bw_nom
0190 < hubbub2->watermarks.a.frac_urg_bw_nom)
0191 wm_pending = true;
0192
0193 if (safe_to_lower || watermarks->a.urgent_latency_ns > hubbub2->watermarks.a.urgent_latency_ns) {
0194 hubbub2->watermarks.a.urgent_latency_ns = watermarks->a.urgent_latency_ns;
0195 prog_wm_value = convert_and_clamp(watermarks->a.urgent_latency_ns,
0196 refclk_mhz, 0x3fff);
0197 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0,
0198 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, prog_wm_value);
0199 } else if (watermarks->a.urgent_latency_ns < hubbub2->watermarks.a.urgent_latency_ns)
0200 wm_pending = true;
0201
0202
0203 if (safe_to_lower || watermarks->b.urgent_ns > hubbub2->watermarks.b.urgent_ns) {
0204 hubbub2->watermarks.b.urgent_ns = watermarks->b.urgent_ns;
0205 prog_wm_value = convert_and_clamp(watermarks->b.urgent_ns,
0206 refclk_mhz, 0x3fff);
0207 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0,
0208 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value);
0209
0210 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n"
0211 "HW register value = 0x%x\n",
0212 watermarks->b.urgent_ns, prog_wm_value);
0213 } else if (watermarks->b.urgent_ns < hubbub2->watermarks.b.urgent_ns)
0214 wm_pending = true;
0215
0216
0217 if (safe_to_lower || watermarks->b.frac_urg_bw_flip
0218 > hubbub2->watermarks.b.frac_urg_bw_flip) {
0219 hubbub2->watermarks.b.frac_urg_bw_flip = watermarks->b.frac_urg_bw_flip;
0220
0221 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0,
0222 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, watermarks->b.frac_urg_bw_flip);
0223 } else if (watermarks->b.frac_urg_bw_flip
0224 < hubbub2->watermarks.b.frac_urg_bw_flip)
0225 wm_pending = true;
0226
0227 if (safe_to_lower || watermarks->b.frac_urg_bw_nom
0228 > hubbub2->watermarks.b.frac_urg_bw_nom) {
0229 hubbub2->watermarks.b.frac_urg_bw_nom = watermarks->b.frac_urg_bw_nom;
0230
0231 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0,
0232 DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->b.frac_urg_bw_nom);
0233 } else if (watermarks->b.frac_urg_bw_nom
0234 < hubbub2->watermarks.b.frac_urg_bw_nom)
0235 wm_pending = true;
0236
0237 if (safe_to_lower || watermarks->b.urgent_latency_ns > hubbub2->watermarks.b.urgent_latency_ns) {
0238 hubbub2->watermarks.b.urgent_latency_ns = watermarks->b.urgent_latency_ns;
0239 prog_wm_value = convert_and_clamp(watermarks->b.urgent_latency_ns,
0240 refclk_mhz, 0x3fff);
0241 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0,
0242 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, prog_wm_value);
0243 } else if (watermarks->b.urgent_latency_ns < hubbub2->watermarks.b.urgent_latency_ns)
0244 wm_pending = true;
0245
0246
0247 if (safe_to_lower || watermarks->c.urgent_ns > hubbub2->watermarks.c.urgent_ns) {
0248 hubbub2->watermarks.c.urgent_ns = watermarks->c.urgent_ns;
0249 prog_wm_value = convert_and_clamp(watermarks->c.urgent_ns,
0250 refclk_mhz, 0x3fff);
0251 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0,
0252 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value);
0253
0254 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n"
0255 "HW register value = 0x%x\n",
0256 watermarks->c.urgent_ns, prog_wm_value);
0257 } else if (watermarks->c.urgent_ns < hubbub2->watermarks.c.urgent_ns)
0258 wm_pending = true;
0259
0260
0261 if (safe_to_lower || watermarks->c.frac_urg_bw_flip
0262 > hubbub2->watermarks.c.frac_urg_bw_flip) {
0263 hubbub2->watermarks.c.frac_urg_bw_flip = watermarks->c.frac_urg_bw_flip;
0264
0265 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, 0,
0266 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, watermarks->c.frac_urg_bw_flip);
0267 } else if (watermarks->c.frac_urg_bw_flip
0268 < hubbub2->watermarks.c.frac_urg_bw_flip)
0269 wm_pending = true;
0270
0271 if (safe_to_lower || watermarks->c.frac_urg_bw_nom
0272 > hubbub2->watermarks.c.frac_urg_bw_nom) {
0273 hubbub2->watermarks.c.frac_urg_bw_nom = watermarks->c.frac_urg_bw_nom;
0274
0275 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, 0,
0276 DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, watermarks->c.frac_urg_bw_nom);
0277 } else if (watermarks->c.frac_urg_bw_nom
0278 < hubbub2->watermarks.c.frac_urg_bw_nom)
0279 wm_pending = true;
0280
0281 if (safe_to_lower || watermarks->c.urgent_latency_ns > hubbub2->watermarks.c.urgent_latency_ns) {
0282 hubbub2->watermarks.c.urgent_latency_ns = watermarks->c.urgent_latency_ns;
0283 prog_wm_value = convert_and_clamp(watermarks->c.urgent_latency_ns,
0284 refclk_mhz, 0x3fff);
0285 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 0,
0286 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, prog_wm_value);
0287 } else if (watermarks->c.urgent_latency_ns < hubbub2->watermarks.c.urgent_latency_ns)
0288 wm_pending = true;
0289
0290
0291 if (safe_to_lower || watermarks->d.urgent_ns > hubbub2->watermarks.d.urgent_ns) {
0292 hubbub2->watermarks.d.urgent_ns = watermarks->d.urgent_ns;
0293 prog_wm_value = convert_and_clamp(watermarks->d.urgent_ns,
0294 refclk_mhz, 0x3fff);
0295 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0,
0296 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value);
0297
0298 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n"
0299 "HW register value = 0x%x\n",
0300 watermarks->d.urgent_ns, prog_wm_value);
0301 } else if (watermarks->d.urgent_ns < hubbub2->watermarks.d.urgent_ns)
0302 wm_pending = true;
0303
0304
0305 if (safe_to_lower || watermarks->d.frac_urg_bw_flip
0306 > hubbub2->watermarks.d.frac_urg_bw_flip) {
0307 hubbub2->watermarks.d.frac_urg_bw_flip = watermarks->d.frac_urg_bw_flip;
0308
0309 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, 0,
0310 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, watermarks->d.frac_urg_bw_flip);
0311 } else if (watermarks->d.frac_urg_bw_flip
0312 < hubbub2->watermarks.d.frac_urg_bw_flip)
0313 wm_pending = true;
0314
0315 if (safe_to_lower || watermarks->d.frac_urg_bw_nom
0316 > hubbub2->watermarks.d.frac_urg_bw_nom) {
0317 hubbub2->watermarks.d.frac_urg_bw_nom = watermarks->d.frac_urg_bw_nom;
0318
0319 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 0,
0320 DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, watermarks->d.frac_urg_bw_nom);
0321 } else if (watermarks->d.frac_urg_bw_nom
0322 < hubbub2->watermarks.d.frac_urg_bw_nom)
0323 wm_pending = true;
0324
0325 if (safe_to_lower || watermarks->d.urgent_latency_ns > hubbub2->watermarks.d.urgent_latency_ns) {
0326 hubbub2->watermarks.d.urgent_latency_ns = watermarks->d.urgent_latency_ns;
0327 prog_wm_value = convert_and_clamp(watermarks->d.urgent_latency_ns,
0328 refclk_mhz, 0x3fff);
0329 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0,
0330 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, prog_wm_value);
0331 } else if (watermarks->d.urgent_latency_ns < hubbub2->watermarks.d.urgent_latency_ns)
0332 wm_pending = true;
0333
0334 return wm_pending;
0335 }
0336
0337 static bool hubbub32_program_stutter_watermarks(
0338 struct hubbub *hubbub,
0339 struct dcn_watermark_set *watermarks,
0340 unsigned int refclk_mhz,
0341 bool safe_to_lower)
0342 {
0343 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0344 uint32_t prog_wm_value;
0345 bool wm_pending = false;
0346
0347
0348 if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
0349 > hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) {
0350 hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns =
0351 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns;
0352 prog_wm_value = convert_and_clamp(
0353 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns,
0354 refclk_mhz, 0xffff);
0355 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0,
0356 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value);
0357 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"
0358 "HW register value = 0x%x\n",
0359 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
0360 } else if (watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
0361 < hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns)
0362 wm_pending = true;
0363
0364 if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns
0365 > hubbub2->watermarks.a.cstate_pstate.cstate_exit_ns) {
0366 hubbub2->watermarks.a.cstate_pstate.cstate_exit_ns =
0367 watermarks->a.cstate_pstate.cstate_exit_ns;
0368 prog_wm_value = convert_and_clamp(
0369 watermarks->a.cstate_pstate.cstate_exit_ns,
0370 refclk_mhz, 0xffff);
0371 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0,
0372 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
0373 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"
0374 "HW register value = 0x%x\n",
0375 watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value);
0376 } else if (watermarks->a.cstate_pstate.cstate_exit_ns
0377 < hubbub2->watermarks.a.cstate_pstate.cstate_exit_ns)
0378 wm_pending = true;
0379
0380
0381 if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
0382 > hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) {
0383 hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns =
0384 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns;
0385 prog_wm_value = convert_and_clamp(
0386 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns,
0387 refclk_mhz, 0xffff);
0388 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0,
0389 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value);
0390 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n"
0391 "HW register value = 0x%x\n",
0392 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
0393 } else if (watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
0394 < hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns)
0395 wm_pending = true;
0396
0397 if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns
0398 > hubbub2->watermarks.b.cstate_pstate.cstate_exit_ns) {
0399 hubbub2->watermarks.b.cstate_pstate.cstate_exit_ns =
0400 watermarks->b.cstate_pstate.cstate_exit_ns;
0401 prog_wm_value = convert_and_clamp(
0402 watermarks->b.cstate_pstate.cstate_exit_ns,
0403 refclk_mhz, 0xffff);
0404 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0,
0405 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value);
0406 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"
0407 "HW register value = 0x%x\n",
0408 watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value);
0409 } else if (watermarks->b.cstate_pstate.cstate_exit_ns
0410 < hubbub2->watermarks.b.cstate_pstate.cstate_exit_ns)
0411 wm_pending = true;
0412
0413
0414 if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
0415 > hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) {
0416 hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns =
0417 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns;
0418 prog_wm_value = convert_and_clamp(
0419 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns,
0420 refclk_mhz, 0xffff);
0421 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0,
0422 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value);
0423 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n"
0424 "HW register value = 0x%x\n",
0425 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
0426 } else if (watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
0427 < hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns)
0428 wm_pending = true;
0429
0430 if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns
0431 > hubbub2->watermarks.c.cstate_pstate.cstate_exit_ns) {
0432 hubbub2->watermarks.c.cstate_pstate.cstate_exit_ns =
0433 watermarks->c.cstate_pstate.cstate_exit_ns;
0434 prog_wm_value = convert_and_clamp(
0435 watermarks->c.cstate_pstate.cstate_exit_ns,
0436 refclk_mhz, 0xffff);
0437 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0,
0438 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value);
0439 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"
0440 "HW register value = 0x%x\n",
0441 watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value);
0442 } else if (watermarks->c.cstate_pstate.cstate_exit_ns
0443 < hubbub2->watermarks.c.cstate_pstate.cstate_exit_ns)
0444 wm_pending = true;
0445
0446
0447 if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
0448 > hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) {
0449 hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns =
0450 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns;
0451 prog_wm_value = convert_and_clamp(
0452 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns,
0453 refclk_mhz, 0xffff);
0454 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0,
0455 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value);
0456 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n"
0457 "HW register value = 0x%x\n",
0458 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
0459 } else if (watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
0460 < hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns)
0461 wm_pending = true;
0462
0463 if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns
0464 > hubbub2->watermarks.d.cstate_pstate.cstate_exit_ns) {
0465 hubbub2->watermarks.d.cstate_pstate.cstate_exit_ns =
0466 watermarks->d.cstate_pstate.cstate_exit_ns;
0467 prog_wm_value = convert_and_clamp(
0468 watermarks->d.cstate_pstate.cstate_exit_ns,
0469 refclk_mhz, 0xffff);
0470 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0,
0471 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value);
0472 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"
0473 "HW register value = 0x%x\n",
0474 watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value);
0475 } else if (watermarks->d.cstate_pstate.cstate_exit_ns
0476 < hubbub2->watermarks.d.cstate_pstate.cstate_exit_ns)
0477 wm_pending = true;
0478
0479 return wm_pending;
0480 }
0481
0482
0483 static bool hubbub32_program_pstate_watermarks(
0484 struct hubbub *hubbub,
0485 struct dcn_watermark_set *watermarks,
0486 unsigned int refclk_mhz,
0487 bool safe_to_lower)
0488 {
0489 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0490 uint32_t prog_wm_value;
0491
0492 bool wm_pending = false;
0493
0494
0495
0496 if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns
0497 > hubbub2->watermarks.a.cstate_pstate.pstate_change_ns) {
0498 hubbub2->watermarks.a.cstate_pstate.pstate_change_ns =
0499 watermarks->a.cstate_pstate.pstate_change_ns;
0500 prog_wm_value = convert_and_clamp(
0501 watermarks->a.cstate_pstate.pstate_change_ns,
0502 refclk_mhz, 0xffff);
0503 REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, 0,
0504 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, prog_wm_value);
0505 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"
0506 "HW register value = 0x%x\n\n",
0507 watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value);
0508 } else if (watermarks->a.cstate_pstate.pstate_change_ns
0509 < hubbub2->watermarks.a.cstate_pstate.pstate_change_ns)
0510 wm_pending = true;
0511
0512
0513 if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns
0514 > hubbub2->watermarks.b.cstate_pstate.pstate_change_ns) {
0515 hubbub2->watermarks.b.cstate_pstate.pstate_change_ns =
0516 watermarks->b.cstate_pstate.pstate_change_ns;
0517 prog_wm_value = convert_and_clamp(
0518 watermarks->b.cstate_pstate.pstate_change_ns,
0519 refclk_mhz, 0xffff);
0520 REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, 0,
0521 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, prog_wm_value);
0522 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n"
0523 "HW register value = 0x%x\n\n",
0524 watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value);
0525 } else if (watermarks->b.cstate_pstate.pstate_change_ns
0526 < hubbub2->watermarks.b.cstate_pstate.pstate_change_ns)
0527 wm_pending = true;
0528
0529
0530 if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns
0531 > hubbub2->watermarks.c.cstate_pstate.pstate_change_ns) {
0532 hubbub2->watermarks.c.cstate_pstate.pstate_change_ns =
0533 watermarks->c.cstate_pstate.pstate_change_ns;
0534 prog_wm_value = convert_and_clamp(
0535 watermarks->c.cstate_pstate.pstate_change_ns,
0536 refclk_mhz, 0xffff);
0537 REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, 0,
0538 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, prog_wm_value);
0539 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n"
0540 "HW register value = 0x%x\n\n",
0541 watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value);
0542 } else if (watermarks->c.cstate_pstate.pstate_change_ns
0543 < hubbub2->watermarks.c.cstate_pstate.pstate_change_ns)
0544 wm_pending = true;
0545
0546
0547 if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns
0548 > hubbub2->watermarks.d.cstate_pstate.pstate_change_ns) {
0549 hubbub2->watermarks.d.cstate_pstate.pstate_change_ns =
0550 watermarks->d.cstate_pstate.pstate_change_ns;
0551 prog_wm_value = convert_and_clamp(
0552 watermarks->d.cstate_pstate.pstate_change_ns,
0553 refclk_mhz, 0xffff);
0554 REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, 0,
0555 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, prog_wm_value);
0556 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n"
0557 "HW register value = 0x%x\n\n",
0558 watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value);
0559 } else if (watermarks->d.cstate_pstate.pstate_change_ns
0560 < hubbub2->watermarks.d.cstate_pstate.pstate_change_ns)
0561 wm_pending = true;
0562
0563
0564
0565 if (safe_to_lower || watermarks->a.cstate_pstate.fclk_pstate_change_ns
0566 > hubbub2->watermarks.a.cstate_pstate.fclk_pstate_change_ns) {
0567 hubbub2->watermarks.a.cstate_pstate.fclk_pstate_change_ns =
0568 watermarks->a.cstate_pstate.fclk_pstate_change_ns;
0569 prog_wm_value = convert_and_clamp(
0570 watermarks->a.cstate_pstate.fclk_pstate_change_ns,
0571 refclk_mhz, 0xffff);
0572 REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, 0,
0573 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, prog_wm_value);
0574 DC_LOG_BANDWIDTH_CALCS("FCLK_CHANGE_WATERMARK_A calculated =%d\n"
0575 "HW register value = 0x%x\n\n",
0576 watermarks->a.cstate_pstate.fclk_pstate_change_ns, prog_wm_value);
0577 } else if (watermarks->a.cstate_pstate.fclk_pstate_change_ns
0578 < hubbub2->watermarks.a.cstate_pstate.fclk_pstate_change_ns)
0579 wm_pending = true;
0580
0581
0582 if (safe_to_lower || watermarks->b.cstate_pstate.fclk_pstate_change_ns
0583 > hubbub2->watermarks.b.cstate_pstate.fclk_pstate_change_ns) {
0584 hubbub2->watermarks.b.cstate_pstate.fclk_pstate_change_ns =
0585 watermarks->b.cstate_pstate.fclk_pstate_change_ns;
0586 prog_wm_value = convert_and_clamp(
0587 watermarks->b.cstate_pstate.fclk_pstate_change_ns,
0588 refclk_mhz, 0xffff);
0589 REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, 0,
0590 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, prog_wm_value);
0591 DC_LOG_BANDWIDTH_CALCS("FCLK_CHANGE_WATERMARK_B calculated =%d\n"
0592 "HW register value = 0x%x\n\n",
0593 watermarks->b.cstate_pstate.fclk_pstate_change_ns, prog_wm_value);
0594 } else if (watermarks->b.cstate_pstate.fclk_pstate_change_ns
0595 < hubbub2->watermarks.b.cstate_pstate.fclk_pstate_change_ns)
0596 wm_pending = true;
0597
0598
0599 if (safe_to_lower || watermarks->c.cstate_pstate.fclk_pstate_change_ns
0600 > hubbub2->watermarks.c.cstate_pstate.fclk_pstate_change_ns) {
0601 hubbub2->watermarks.c.cstate_pstate.fclk_pstate_change_ns =
0602 watermarks->c.cstate_pstate.fclk_pstate_change_ns;
0603 prog_wm_value = convert_and_clamp(
0604 watermarks->c.cstate_pstate.fclk_pstate_change_ns,
0605 refclk_mhz, 0xffff);
0606 REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, 0,
0607 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, prog_wm_value);
0608 DC_LOG_BANDWIDTH_CALCS("FCLK_CHANGE_WATERMARK_C calculated =%d\n"
0609 "HW register value = 0x%x\n\n",
0610 watermarks->c.cstate_pstate.fclk_pstate_change_ns, prog_wm_value);
0611 } else if (watermarks->c.cstate_pstate.fclk_pstate_change_ns
0612 < hubbub2->watermarks.c.cstate_pstate.fclk_pstate_change_ns)
0613 wm_pending = true;
0614
0615
0616 if (safe_to_lower || watermarks->d.cstate_pstate.fclk_pstate_change_ns
0617 > hubbub2->watermarks.d.cstate_pstate.fclk_pstate_change_ns) {
0618 hubbub2->watermarks.d.cstate_pstate.fclk_pstate_change_ns =
0619 watermarks->d.cstate_pstate.fclk_pstate_change_ns;
0620 prog_wm_value = convert_and_clamp(
0621 watermarks->d.cstate_pstate.fclk_pstate_change_ns,
0622 refclk_mhz, 0xffff);
0623 REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, 0,
0624 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, prog_wm_value);
0625 DC_LOG_BANDWIDTH_CALCS("FCLK_CHANGE_WATERMARK_D calculated =%d\n"
0626 "HW register value = 0x%x\n\n",
0627 watermarks->d.cstate_pstate.fclk_pstate_change_ns, prog_wm_value);
0628 } else if (watermarks->d.cstate_pstate.fclk_pstate_change_ns
0629 < hubbub2->watermarks.d.cstate_pstate.fclk_pstate_change_ns)
0630 wm_pending = true;
0631
0632 return wm_pending;
0633 }
0634
0635
0636 static bool hubbub32_program_usr_watermarks(
0637 struct hubbub *hubbub,
0638 struct dcn_watermark_set *watermarks,
0639 unsigned int refclk_mhz,
0640 bool safe_to_lower)
0641 {
0642 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0643 uint32_t prog_wm_value;
0644
0645 bool wm_pending = false;
0646
0647
0648 if (safe_to_lower || watermarks->a.usr_retraining_ns
0649 > hubbub2->watermarks.a.usr_retraining_ns) {
0650 hubbub2->watermarks.a.usr_retraining_ns = watermarks->a.usr_retraining_ns;
0651 prog_wm_value = convert_and_clamp(
0652 watermarks->a.usr_retraining_ns,
0653 refclk_mhz, 0x3fff);
0654 REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, 0,
0655 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, prog_wm_value);
0656 DC_LOG_BANDWIDTH_CALCS("USR_RETRAINING_WATERMARK_A calculated =%d\n"
0657 "HW register value = 0x%x\n\n",
0658 watermarks->a.usr_retraining_ns, prog_wm_value);
0659 } else if (watermarks->a.usr_retraining_ns
0660 < hubbub2->watermarks.a.usr_retraining_ns)
0661 wm_pending = true;
0662
0663
0664 if (safe_to_lower || watermarks->b.usr_retraining_ns
0665 > hubbub2->watermarks.b.usr_retraining_ns) {
0666 hubbub2->watermarks.b.usr_retraining_ns = watermarks->b.usr_retraining_ns;
0667 prog_wm_value = convert_and_clamp(
0668 watermarks->b.usr_retraining_ns,
0669 refclk_mhz, 0x3fff);
0670 REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, 0,
0671 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, prog_wm_value);
0672 DC_LOG_BANDWIDTH_CALCS("USR_RETRAINING_WATERMARK_B calculated =%d\n"
0673 "HW register value = 0x%x\n\n",
0674 watermarks->b.usr_retraining_ns, prog_wm_value);
0675 } else if (watermarks->b.usr_retraining_ns
0676 < hubbub2->watermarks.b.usr_retraining_ns)
0677 wm_pending = true;
0678
0679
0680 if (safe_to_lower || watermarks->c.usr_retraining_ns
0681 > hubbub2->watermarks.c.usr_retraining_ns) {
0682 hubbub2->watermarks.c.usr_retraining_ns =
0683 watermarks->c.usr_retraining_ns;
0684 prog_wm_value = convert_and_clamp(
0685 watermarks->c.usr_retraining_ns,
0686 refclk_mhz, 0x3fff);
0687 REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, 0,
0688 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, prog_wm_value);
0689 DC_LOG_BANDWIDTH_CALCS("USR_RETRAINING_WATERMARK_C calculated =%d\n"
0690 "HW register value = 0x%x\n\n",
0691 watermarks->c.usr_retraining_ns, prog_wm_value);
0692 } else if (watermarks->c.usr_retraining_ns
0693 < hubbub2->watermarks.c.usr_retraining_ns)
0694 wm_pending = true;
0695
0696
0697 if (safe_to_lower || watermarks->d.usr_retraining_ns
0698 > hubbub2->watermarks.d.usr_retraining_ns) {
0699 hubbub2->watermarks.d.usr_retraining_ns =
0700 watermarks->d.usr_retraining_ns;
0701 prog_wm_value = convert_and_clamp(
0702 watermarks->d.usr_retraining_ns,
0703 refclk_mhz, 0x3fff);
0704 REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, 0,
0705 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, prog_wm_value);
0706 DC_LOG_BANDWIDTH_CALCS("USR_RETRAINING_WATERMARK_D calculated =%d\n"
0707 "HW register value = 0x%x\n\n",
0708 watermarks->d.usr_retraining_ns, prog_wm_value);
0709 } else if (watermarks->d.usr_retraining_ns
0710 < hubbub2->watermarks.d.usr_retraining_ns)
0711 wm_pending = true;
0712
0713 return wm_pending;
0714 }
0715
0716 void hubbub32_force_usr_retraining_allow(struct hubbub *hubbub, bool allow)
0717 {
0718 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0719
0720
0721
0722
0723
0724
0725 REG_UPDATE_2(DCHUBBUB_ARB_USR_RETRAINING_CNTL,
0726 DCHUBBUB_ARB_ALLOW_USR_RETRAINING_FORCE_VALUE, allow,
0727 DCHUBBUB_ARB_ALLOW_USR_RETRAINING_FORCE_ENABLE, allow);
0728 }
0729
0730 static bool hubbub32_program_watermarks(
0731 struct hubbub *hubbub,
0732 struct dcn_watermark_set *watermarks,
0733 unsigned int refclk_mhz,
0734 bool safe_to_lower)
0735 {
0736 bool wm_pending = false;
0737
0738 if (hubbub32_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
0739 wm_pending = true;
0740
0741 if (hubbub32_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
0742 wm_pending = true;
0743
0744 if (hubbub32_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
0745 wm_pending = true;
0746
0747 if (hubbub32_program_usr_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
0748 wm_pending = true;
0749
0750
0751
0752
0753
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768 hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
0769
0770 hubbub32_force_usr_retraining_allow(hubbub, hubbub->ctx->dc->debug.force_usr_allow);
0771
0772 return wm_pending;
0773 }
0774
0775
0776 void hubbub32_init_watermarks(struct hubbub *hubbub)
0777 {
0778 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0779 uint32_t reg;
0780
0781 reg = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A);
0782 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, reg);
0783 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, reg);
0784 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, reg);
0785
0786 reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A);
0787 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, reg);
0788 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, reg);
0789 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, reg);
0790
0791 reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A);
0792 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, reg);
0793 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, reg);
0794 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, reg);
0795
0796 reg = REG_READ(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A);
0797 REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, reg);
0798 REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, reg);
0799 REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, reg);
0800
0801 reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A);
0802 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, reg);
0803 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, reg);
0804 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, reg);
0805
0806 reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A);
0807 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, reg);
0808 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, reg);
0809 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, reg);
0810
0811 reg = REG_READ(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A);
0812 REG_WRITE(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, reg);
0813 REG_WRITE(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, reg);
0814 REG_WRITE(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, reg);
0815
0816 reg = REG_READ(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A);
0817 REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, reg);
0818 REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, reg);
0819 REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, reg);
0820
0821 reg = REG_READ(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A);
0822 REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, reg);
0823 REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, reg);
0824 REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, reg);
0825 }
0826
0827 void hubbub32_wm_read_state(struct hubbub *hubbub,
0828 struct dcn_hubbub_wm *wm)
0829 {
0830 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0831 struct dcn_hubbub_wm_set *s;
0832
0833 memset(wm, 0, sizeof(struct dcn_hubbub_wm));
0834
0835 s = &wm->sets[0];
0836 s->wm_set = 0;
0837 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A,
0838 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, &s->data_urgent);
0839
0840 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A,
0841 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, &s->sr_enter);
0842
0843 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A,
0844 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, &s->sr_exit);
0845
0846 REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A,
0847 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, &s->dram_clk_chanage);
0848
0849 REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A,
0850 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, &s->usr_retrain);
0851
0852 REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A,
0853 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, &s->fclk_pstate_change);
0854
0855 s = &wm->sets[1];
0856 s->wm_set = 1;
0857 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B,
0858 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, &s->data_urgent);
0859
0860 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B,
0861 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, &s->sr_enter);
0862
0863 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B,
0864 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, &s->sr_exit);
0865
0866 REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B,
0867 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, &s->dram_clk_chanage);
0868
0869 REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B,
0870 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, &s->usr_retrain);
0871
0872 REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B,
0873 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, &s->fclk_pstate_change);
0874
0875 s = &wm->sets[2];
0876 s->wm_set = 2;
0877 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C,
0878 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, &s->data_urgent);
0879
0880 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C,
0881 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, &s->sr_enter);
0882
0883 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C,
0884 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, &s->sr_exit);
0885
0886 REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C,
0887 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, &s->dram_clk_chanage);
0888
0889 REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C,
0890 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, &s->usr_retrain);
0891
0892 REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C,
0893 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, &s->fclk_pstate_change);
0894
0895 s = &wm->sets[3];
0896 s->wm_set = 3;
0897 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D,
0898 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, &s->data_urgent);
0899
0900 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D,
0901 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, &s->sr_enter);
0902
0903 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D,
0904 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, &s->sr_exit);
0905
0906 REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D,
0907 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, &s->dram_clk_chanage);
0908
0909 REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D,
0910 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, &s->usr_retrain);
0911
0912 REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D,
0913 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, &s->fclk_pstate_change);
0914 }
0915
0916 void hubbub32_force_wm_propagate_to_pipes(struct hubbub *hubbub)
0917 {
0918 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
0919 uint32_t refclk_mhz = hubbub->ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000;
0920 uint32_t prog_wm_value = convert_and_clamp(hubbub2->watermarks.a.urgent_ns,
0921 refclk_mhz, 0x3fff);
0922
0923 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0,
0924 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value);
0925 }
0926
0927 static const struct hubbub_funcs hubbub32_funcs = {
0928 .update_dchub = hubbub2_update_dchub,
0929 .init_dchub_sys_ctx = hubbub3_init_dchub_sys_ctx,
0930 .init_vm_ctx = hubbub2_init_vm_ctx,
0931 .dcc_support_swizzle = hubbub3_dcc_support_swizzle,
0932 .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format,
0933 .get_dcc_compression_cap = hubbub3_get_dcc_compression_cap,
0934 .wm_read_state = hubbub32_wm_read_state,
0935 .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,
0936 .program_watermarks = hubbub32_program_watermarks,
0937 .allow_self_refresh_control = hubbub1_allow_self_refresh_control,
0938 .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
0939 .force_wm_propagate_to_pipes = hubbub32_force_wm_propagate_to_pipes,
0940 .force_pstate_change_control = hubbub3_force_pstate_change_control,
0941 .init_watermarks = hubbub32_init_watermarks,
0942 .program_det_size = dcn32_program_det_size,
0943 .program_compbuf_size = dcn32_program_compbuf_size,
0944 .init_crb = dcn32_init_crb,
0945 .hubbub_read_state = hubbub2_read_state,
0946 .force_usr_retraining_allow = hubbub32_force_usr_retraining_allow,
0947 };
0948
0949 void hubbub32_construct(struct dcn20_hubbub *hubbub2,
0950 struct dc_context *ctx,
0951 const struct dcn_hubbub_registers *hubbub_regs,
0952 const struct dcn_hubbub_shift *hubbub_shift,
0953 const struct dcn_hubbub_mask *hubbub_mask,
0954 int det_size_kb,
0955 int pixel_chunk_size_kb,
0956 int config_return_buffer_size_kb)
0957 {
0958 hubbub2->base.ctx = ctx;
0959 hubbub2->base.funcs = &hubbub32_funcs;
0960 hubbub2->regs = hubbub_regs;
0961 hubbub2->shifts = hubbub_shift;
0962 hubbub2->masks = hubbub_mask;
0963
0964 hubbub2->debug_test_index_pstate = 0xB;
0965 hubbub2->detile_buf_size = det_size_kb * 1024;
0966 hubbub2->pixel_chunk_size = pixel_chunk_size_kb * 1024;
0967 hubbub2->crb_size_segs = config_return_buffer_size_kb / DCN32_CRB_SEGMENT_SIZE_KB;
0968 }