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 #include <linux/delay.h>
0026 #include "dm_services.h"
0027 #include "dcn20/dcn20_hubbub.h"
0028 #include "dcn21_hubbub.h"
0029 #include "reg_helper.h"
0030
0031 #define REG(reg)\
0032 hubbub1->regs->reg
0033 #define DC_LOGGER \
0034 hubbub1->base.ctx->logger
0035 #define CTX \
0036 hubbub1->base.ctx
0037
0038 #undef FN
0039 #define FN(reg_name, field_name) \
0040 hubbub1->shifts->field_name, hubbub1->masks->field_name
0041
0042 #define REG(reg)\
0043 hubbub1->regs->reg
0044
0045 #define CTX \
0046 hubbub1->base.ctx
0047
0048 #undef FN
0049 #define FN(reg_name, field_name) \
0050 hubbub1->shifts->field_name, hubbub1->masks->field_name
0051
0052 static uint32_t convert_and_clamp(
0053 uint32_t wm_ns,
0054 uint32_t refclk_mhz,
0055 uint32_t clamp_value)
0056 {
0057 uint32_t ret_val = 0;
0058 ret_val = wm_ns * refclk_mhz;
0059 ret_val /= 1000;
0060
0061 if (ret_val > clamp_value)
0062 ret_val = clamp_value;
0063
0064 return ret_val;
0065 }
0066
0067 void dcn21_dchvm_init(struct hubbub *hubbub)
0068 {
0069 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
0070 uint32_t riommu_active, prefetch_done;
0071 int i;
0072
0073 REG_GET(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, &prefetch_done);
0074
0075 if (prefetch_done) {
0076 hubbub->riommu_active = true;
0077 return;
0078 }
0079
0080 REG_UPDATE(DCHVM_CTRL0, HOSTVM_INIT_REQ, 1);
0081
0082
0083 for (i = 0; i < 100; i++) {
0084 REG_GET(DCHVM_RIOMMU_STAT0, RIOMMU_ACTIVE, &riommu_active);
0085
0086 if (riommu_active)
0087 break;
0088 else
0089 udelay(5);
0090 }
0091
0092 if (riommu_active) {
0093
0094 REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, 1);
0095
0096
0097 REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, 1);
0098
0099
0100 REG_UPDATE_4(DCHVM_CLK_CTRL,
0101 HVM_DISPCLK_R_GATE_DIS, 0,
0102 HVM_DISPCLK_G_GATE_DIS, 0,
0103 HVM_DCFCLK_R_GATE_DIS, 0,
0104 HVM_DCFCLK_G_GATE_DIS, 0);
0105
0106
0107 REG_WAIT(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, 1, 5, 100);
0108
0109 hubbub->riommu_active = true;
0110 }
0111 }
0112
0113 int hubbub21_init_dchub(struct hubbub *hubbub,
0114 struct dcn_hubbub_phys_addr_config *pa_config)
0115 {
0116 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
0117 struct dcn_vmid_page_table_config phys_config;
0118
0119 REG_SET(DCN_VM_FB_LOCATION_BASE, 0,
0120 FB_BASE, pa_config->system_aperture.fb_base >> 24);
0121 REG_SET(DCN_VM_FB_LOCATION_TOP, 0,
0122 FB_TOP, pa_config->system_aperture.fb_top >> 24);
0123 REG_SET(DCN_VM_FB_OFFSET, 0,
0124 FB_OFFSET, pa_config->system_aperture.fb_offset >> 24);
0125 REG_SET(DCN_VM_AGP_BOT, 0,
0126 AGP_BOT, pa_config->system_aperture.agp_bot >> 24);
0127 REG_SET(DCN_VM_AGP_TOP, 0,
0128 AGP_TOP, pa_config->system_aperture.agp_top >> 24);
0129 REG_SET(DCN_VM_AGP_BASE, 0,
0130 AGP_BASE, pa_config->system_aperture.agp_base >> 24);
0131
0132 if (pa_config->gart_config.page_table_start_addr != pa_config->gart_config.page_table_end_addr) {
0133 phys_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr >> 12;
0134 phys_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr >> 12;
0135 phys_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr | 1;
0136 phys_config.depth = 0;
0137 phys_config.block_size = 0;
0138
0139 dcn20_vmid_setup(&hubbub1->vmid[0], &phys_config);
0140 }
0141
0142 dcn21_dchvm_init(hubbub);
0143
0144 return hubbub1->num_vmid;
0145 }
0146
0147 bool hubbub21_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 *hubbub1 = 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 > hubbub1->watermarks.a.urgent_ns) {
0160 hubbub1->watermarks.a.urgent_ns = watermarks->a.urgent_ns;
0161 prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns,
0162 refclk_mhz, 0x1fffff);
0163 REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0,
0164 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value,
0165 DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_A, prog_wm_value);
0166
0167 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n"
0168 "HW register value = 0x%x\n",
0169 watermarks->a.urgent_ns, prog_wm_value);
0170 } else if (watermarks->a.urgent_ns < hubbub1->watermarks.a.urgent_ns)
0171 wm_pending = true;
0172
0173
0174 if (safe_to_lower || watermarks->a.frac_urg_bw_flip
0175 > hubbub1->watermarks.a.frac_urg_bw_flip) {
0176 hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;
0177
0178 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0,
0179 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, watermarks->a.frac_urg_bw_flip);
0180 } else if (watermarks->a.frac_urg_bw_flip
0181 < hubbub1->watermarks.a.frac_urg_bw_flip)
0182 wm_pending = true;
0183
0184 if (safe_to_lower || watermarks->a.frac_urg_bw_nom
0185 > hubbub1->watermarks.a.frac_urg_bw_nom) {
0186 hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;
0187
0188 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0,
0189 DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->a.frac_urg_bw_nom);
0190 } else if (watermarks->a.frac_urg_bw_nom
0191 < hubbub1->watermarks.a.frac_urg_bw_nom)
0192 wm_pending = true;
0193
0194 if (safe_to_lower || watermarks->a.urgent_latency_ns > hubbub1->watermarks.a.urgent_latency_ns) {
0195 hubbub1->watermarks.a.urgent_latency_ns = watermarks->a.urgent_latency_ns;
0196 prog_wm_value = convert_and_clamp(watermarks->a.urgent_latency_ns,
0197 refclk_mhz, 0x1fffff);
0198 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0,
0199 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, prog_wm_value);
0200 } else if (watermarks->a.urgent_latency_ns < hubbub1->watermarks.a.urgent_latency_ns)
0201 wm_pending = true;
0202
0203
0204 if (safe_to_lower || watermarks->b.urgent_ns > hubbub1->watermarks.b.urgent_ns) {
0205 hubbub1->watermarks.b.urgent_ns = watermarks->b.urgent_ns;
0206 prog_wm_value = convert_and_clamp(watermarks->b.urgent_ns,
0207 refclk_mhz, 0x1fffff);
0208 REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0,
0209 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value,
0210 DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_B, prog_wm_value);
0211
0212 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n"
0213 "HW register value = 0x%x\n",
0214 watermarks->b.urgent_ns, prog_wm_value);
0215 } else if (watermarks->b.urgent_ns < hubbub1->watermarks.b.urgent_ns)
0216 wm_pending = true;
0217
0218
0219 if (safe_to_lower || watermarks->a.frac_urg_bw_flip
0220 > hubbub1->watermarks.a.frac_urg_bw_flip) {
0221 hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;
0222
0223 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0,
0224 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, watermarks->a.frac_urg_bw_flip);
0225 } else if (watermarks->a.frac_urg_bw_flip
0226 < hubbub1->watermarks.a.frac_urg_bw_flip)
0227 wm_pending = true;
0228
0229 if (safe_to_lower || watermarks->a.frac_urg_bw_nom
0230 > hubbub1->watermarks.a.frac_urg_bw_nom) {
0231 hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;
0232
0233 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0,
0234 DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->a.frac_urg_bw_nom);
0235 } else if (watermarks->a.frac_urg_bw_nom
0236 < hubbub1->watermarks.a.frac_urg_bw_nom)
0237 wm_pending = true;
0238
0239 if (safe_to_lower || watermarks->b.urgent_latency_ns > hubbub1->watermarks.b.urgent_latency_ns) {
0240 hubbub1->watermarks.b.urgent_latency_ns = watermarks->b.urgent_latency_ns;
0241 prog_wm_value = convert_and_clamp(watermarks->b.urgent_latency_ns,
0242 refclk_mhz, 0x1fffff);
0243 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0,
0244 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, prog_wm_value);
0245 } else if (watermarks->b.urgent_latency_ns < hubbub1->watermarks.b.urgent_latency_ns)
0246 wm_pending = true;
0247
0248
0249 if (safe_to_lower || watermarks->c.urgent_ns > hubbub1->watermarks.c.urgent_ns) {
0250 hubbub1->watermarks.c.urgent_ns = watermarks->c.urgent_ns;
0251 prog_wm_value = convert_and_clamp(watermarks->c.urgent_ns,
0252 refclk_mhz, 0x1fffff);
0253 REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0,
0254 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value,
0255 DCHUBBUB_ARB_VM_ROW_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 < hubbub1->watermarks.c.urgent_ns)
0261 wm_pending = true;
0262
0263
0264 if (safe_to_lower || watermarks->a.frac_urg_bw_flip
0265 > hubbub1->watermarks.a.frac_urg_bw_flip) {
0266 hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.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->a.frac_urg_bw_flip);
0270 } else if (watermarks->a.frac_urg_bw_flip
0271 < hubbub1->watermarks.a.frac_urg_bw_flip)
0272 wm_pending = true;
0273
0274 if (safe_to_lower || watermarks->a.frac_urg_bw_nom
0275 > hubbub1->watermarks.a.frac_urg_bw_nom) {
0276 hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.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->a.frac_urg_bw_nom);
0280 } else if (watermarks->a.frac_urg_bw_nom
0281 < hubbub1->watermarks.a.frac_urg_bw_nom)
0282 wm_pending = true;
0283
0284 if (safe_to_lower || watermarks->c.urgent_latency_ns > hubbub1->watermarks.c.urgent_latency_ns) {
0285 hubbub1->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, 0x1fffff);
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 < hubbub1->watermarks.c.urgent_latency_ns)
0291 wm_pending = true;
0292
0293
0294 if (safe_to_lower || watermarks->d.urgent_ns > hubbub1->watermarks.d.urgent_ns) {
0295 hubbub1->watermarks.d.urgent_ns = watermarks->d.urgent_ns;
0296 prog_wm_value = convert_and_clamp(watermarks->d.urgent_ns,
0297 refclk_mhz, 0x1fffff);
0298 REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0,
0299 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value,
0300 DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_D, prog_wm_value);
0301
0302 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n"
0303 "HW register value = 0x%x\n",
0304 watermarks->d.urgent_ns, prog_wm_value);
0305 } else if (watermarks->d.urgent_ns < hubbub1->watermarks.d.urgent_ns)
0306 wm_pending = true;
0307
0308
0309 if (safe_to_lower || watermarks->a.frac_urg_bw_flip
0310 > hubbub1->watermarks.a.frac_urg_bw_flip) {
0311 hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;
0312
0313 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, 0,
0314 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, watermarks->a.frac_urg_bw_flip);
0315 } else if (watermarks->a.frac_urg_bw_flip
0316 < hubbub1->watermarks.a.frac_urg_bw_flip)
0317 wm_pending = true;
0318
0319 if (safe_to_lower || watermarks->a.frac_urg_bw_nom
0320 > hubbub1->watermarks.a.frac_urg_bw_nom) {
0321 hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;
0322
0323 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 0,
0324 DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, watermarks->a.frac_urg_bw_nom);
0325 } else if (watermarks->a.frac_urg_bw_nom
0326 < hubbub1->watermarks.a.frac_urg_bw_nom)
0327 wm_pending = true;
0328
0329 if (safe_to_lower || watermarks->d.urgent_latency_ns > hubbub1->watermarks.d.urgent_latency_ns) {
0330 hubbub1->watermarks.d.urgent_latency_ns = watermarks->d.urgent_latency_ns;
0331 prog_wm_value = convert_and_clamp(watermarks->d.urgent_latency_ns,
0332 refclk_mhz, 0x1fffff);
0333 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0,
0334 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, prog_wm_value);
0335 } else if (watermarks->d.urgent_latency_ns < hubbub1->watermarks.d.urgent_latency_ns)
0336 wm_pending = true;
0337
0338 return wm_pending;
0339 }
0340
0341 bool hubbub21_program_stutter_watermarks(
0342 struct hubbub *hubbub,
0343 struct dcn_watermark_set *watermarks,
0344 unsigned int refclk_mhz,
0345 bool safe_to_lower)
0346 {
0347 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
0348 uint32_t prog_wm_value;
0349 bool wm_pending = false;
0350
0351
0352 if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
0353 > hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) {
0354 hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns =
0355 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns;
0356 prog_wm_value = convert_and_clamp(
0357 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns,
0358 refclk_mhz, 0x1fffff);
0359 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0,
0360 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value,
0361 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value);
0362 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"
0363 "HW register value = 0x%x\n",
0364 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
0365 } else if (watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
0366 < hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns)
0367 wm_pending = true;
0368
0369 if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns
0370 > hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns) {
0371 hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns =
0372 watermarks->a.cstate_pstate.cstate_exit_ns;
0373 prog_wm_value = convert_and_clamp(
0374 watermarks->a.cstate_pstate.cstate_exit_ns,
0375 refclk_mhz, 0x1fffff);
0376 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0,
0377 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value,
0378 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
0379 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"
0380 "HW register value = 0x%x\n",
0381 watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value);
0382 } else if (watermarks->a.cstate_pstate.cstate_exit_ns
0383 < hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns)
0384 wm_pending = true;
0385
0386
0387 if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
0388 > hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) {
0389 hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns =
0390 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns;
0391 prog_wm_value = convert_and_clamp(
0392 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns,
0393 refclk_mhz, 0x1fffff);
0394 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0,
0395 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value,
0396 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value);
0397 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n"
0398 "HW register value = 0x%x\n",
0399 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
0400 } else if (watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
0401 < hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns)
0402 wm_pending = true;
0403
0404 if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns
0405 > hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns) {
0406 hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns =
0407 watermarks->b.cstate_pstate.cstate_exit_ns;
0408 prog_wm_value = convert_and_clamp(
0409 watermarks->b.cstate_pstate.cstate_exit_ns,
0410 refclk_mhz, 0x1fffff);
0411 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0,
0412 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value,
0413 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
0414 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"
0415 "HW register value = 0x%x\n",
0416 watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value);
0417 } else if (watermarks->b.cstate_pstate.cstate_exit_ns
0418 < hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns)
0419 wm_pending = true;
0420
0421
0422 if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
0423 > hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) {
0424 hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns =
0425 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns;
0426 prog_wm_value = convert_and_clamp(
0427 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns,
0428 refclk_mhz, 0x1fffff);
0429 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0,
0430 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value,
0431 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value);
0432 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n"
0433 "HW register value = 0x%x\n",
0434 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
0435 } else if (watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
0436 < hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns)
0437 wm_pending = true;
0438
0439 if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns
0440 > hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns) {
0441 hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns =
0442 watermarks->c.cstate_pstate.cstate_exit_ns;
0443 prog_wm_value = convert_and_clamp(
0444 watermarks->c.cstate_pstate.cstate_exit_ns,
0445 refclk_mhz, 0x1fffff);
0446 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0,
0447 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value,
0448 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
0449 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"
0450 "HW register value = 0x%x\n",
0451 watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value);
0452 } else if (watermarks->c.cstate_pstate.cstate_exit_ns
0453 < hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns)
0454 wm_pending = true;
0455
0456
0457 if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
0458 > hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) {
0459 hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns =
0460 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns;
0461 prog_wm_value = convert_and_clamp(
0462 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns,
0463 refclk_mhz, 0x1fffff);
0464 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0,
0465 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value,
0466 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value);
0467 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n"
0468 "HW register value = 0x%x\n",
0469 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
0470 } else if (watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
0471 < hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns)
0472 wm_pending = true;
0473
0474 if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns
0475 > hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns) {
0476 hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns =
0477 watermarks->d.cstate_pstate.cstate_exit_ns;
0478 prog_wm_value = convert_and_clamp(
0479 watermarks->d.cstate_pstate.cstate_exit_ns,
0480 refclk_mhz, 0x1fffff);
0481 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0,
0482 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value,
0483 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
0484 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"
0485 "HW register value = 0x%x\n",
0486 watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value);
0487 } else if (watermarks->d.cstate_pstate.cstate_exit_ns
0488 < hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns)
0489 wm_pending = true;
0490
0491 return wm_pending;
0492 }
0493
0494 bool hubbub21_program_pstate_watermarks(
0495 struct hubbub *hubbub,
0496 struct dcn_watermark_set *watermarks,
0497 unsigned int refclk_mhz,
0498 bool safe_to_lower)
0499 {
0500 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
0501 uint32_t prog_wm_value;
0502
0503 bool wm_pending = false;
0504
0505
0506 if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns
0507 > hubbub1->watermarks.a.cstate_pstate.pstate_change_ns) {
0508 hubbub1->watermarks.a.cstate_pstate.pstate_change_ns =
0509 watermarks->a.cstate_pstate.pstate_change_ns;
0510 prog_wm_value = convert_and_clamp(
0511 watermarks->a.cstate_pstate.pstate_change_ns,
0512 refclk_mhz, 0x1fffff);
0513 REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, 0,
0514 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value,
0515 DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value);
0516 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"
0517 "HW register value = 0x%x\n\n",
0518 watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value);
0519 } else if (watermarks->a.cstate_pstate.pstate_change_ns
0520 < hubbub1->watermarks.a.cstate_pstate.pstate_change_ns)
0521 wm_pending = true;
0522
0523
0524 if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns
0525 > hubbub1->watermarks.b.cstate_pstate.pstate_change_ns) {
0526 hubbub1->watermarks.b.cstate_pstate.pstate_change_ns =
0527 watermarks->b.cstate_pstate.pstate_change_ns;
0528 prog_wm_value = convert_and_clamp(
0529 watermarks->b.cstate_pstate.pstate_change_ns,
0530 refclk_mhz, 0x1fffff);
0531 REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, 0,
0532 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value,
0533 DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value);
0534 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n"
0535 "HW register value = 0x%x\n\n",
0536 watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value);
0537 } else if (watermarks->b.cstate_pstate.pstate_change_ns
0538 < hubbub1->watermarks.b.cstate_pstate.pstate_change_ns)
0539 wm_pending = false;
0540
0541
0542 if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns
0543 > hubbub1->watermarks.c.cstate_pstate.pstate_change_ns) {
0544 hubbub1->watermarks.c.cstate_pstate.pstate_change_ns =
0545 watermarks->c.cstate_pstate.pstate_change_ns;
0546 prog_wm_value = convert_and_clamp(
0547 watermarks->c.cstate_pstate.pstate_change_ns,
0548 refclk_mhz, 0x1fffff);
0549 REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, 0,
0550 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value,
0551 DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value);
0552 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n"
0553 "HW register value = 0x%x\n\n",
0554 watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value);
0555 } else if (watermarks->c.cstate_pstate.pstate_change_ns
0556 < hubbub1->watermarks.c.cstate_pstate.pstate_change_ns)
0557 wm_pending = true;
0558
0559
0560 if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns
0561 > hubbub1->watermarks.d.cstate_pstate.pstate_change_ns) {
0562 hubbub1->watermarks.d.cstate_pstate.pstate_change_ns =
0563 watermarks->d.cstate_pstate.pstate_change_ns;
0564 prog_wm_value = convert_and_clamp(
0565 watermarks->d.cstate_pstate.pstate_change_ns,
0566 refclk_mhz, 0x1fffff);
0567 REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, 0,
0568 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value,
0569 DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value);
0570 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n"
0571 "HW register value = 0x%x\n\n",
0572 watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value);
0573 } else if (watermarks->d.cstate_pstate.pstate_change_ns
0574 < hubbub1->watermarks.d.cstate_pstate.pstate_change_ns)
0575 wm_pending = true;
0576
0577 return wm_pending;
0578 }
0579
0580 bool hubbub21_program_watermarks(
0581 struct hubbub *hubbub,
0582 struct dcn_watermark_set *watermarks,
0583 unsigned int refclk_mhz,
0584 bool safe_to_lower)
0585 {
0586 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
0587 bool wm_pending = false;
0588
0589 if (hubbub21_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
0590 wm_pending = true;
0591
0592 if (hubbub21_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
0593 wm_pending = true;
0594
0595 if (hubbub21_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
0596 wm_pending = true;
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611 REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0,
0612 DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
0613 REG_UPDATE_2(DCHUBBUB_ARB_DF_REQ_OUTSTAND,
0614 DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF,
0615 DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, 0xA);
0616 REG_UPDATE(DCHUBBUB_ARB_HOSTVM_CNTL,
0617 DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, 0xF);
0618
0619 hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
0620
0621 return wm_pending;
0622 }
0623
0624 void hubbub21_wm_read_state(struct hubbub *hubbub,
0625 struct dcn_hubbub_wm *wm)
0626 {
0627 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
0628 struct dcn_hubbub_wm_set *s;
0629
0630 memset(wm, 0, sizeof(struct dcn_hubbub_wm));
0631
0632 s = &wm->sets[0];
0633 s->wm_set = 0;
0634 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A,
0635 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, &s->data_urgent);
0636
0637 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A,
0638 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, &s->sr_enter);
0639
0640 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A,
0641 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, &s->sr_exit);
0642
0643 REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A,
0644 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, &s->dram_clk_chanage);
0645
0646 s = &wm->sets[1];
0647 s->wm_set = 1;
0648 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B,
0649 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, &s->data_urgent);
0650
0651 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B,
0652 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, &s->sr_enter);
0653
0654 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B,
0655 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, &s->sr_exit);
0656
0657 REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B,
0658 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, &s->dram_clk_chanage);
0659
0660 s = &wm->sets[2];
0661 s->wm_set = 2;
0662 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C,
0663 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, &s->data_urgent);
0664
0665 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C,
0666 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, &s->sr_enter);
0667
0668 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C,
0669 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, &s->sr_exit);
0670
0671 REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C,
0672 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, &s->dram_clk_chanage);
0673
0674 s = &wm->sets[3];
0675 s->wm_set = 3;
0676 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D,
0677 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, &s->data_urgent);
0678
0679 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D,
0680 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, &s->sr_enter);
0681
0682 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D,
0683 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, &s->sr_exit);
0684
0685 REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D,
0686 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, &s->dram_clk_chanage);
0687 }
0688
0689 static void hubbub21_apply_DEDCN21_147_wa(struct hubbub *hubbub)
0690 {
0691 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
0692 uint32_t prog_wm_value;
0693
0694 prog_wm_value = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A);
0695 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value);
0696 }
0697
0698 static const struct hubbub_funcs hubbub21_funcs = {
0699 .update_dchub = hubbub2_update_dchub,
0700 .init_dchub_sys_ctx = hubbub21_init_dchub,
0701 .init_vm_ctx = hubbub2_init_vm_ctx,
0702 .dcc_support_swizzle = hubbub2_dcc_support_swizzle,
0703 .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format,
0704 .get_dcc_compression_cap = hubbub2_get_dcc_compression_cap,
0705 .wm_read_state = hubbub21_wm_read_state,
0706 .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,
0707 .program_watermarks = hubbub21_program_watermarks,
0708 .allow_self_refresh_control = hubbub1_allow_self_refresh_control,
0709 .apply_DEDCN21_147_wa = hubbub21_apply_DEDCN21_147_wa,
0710 .hubbub_read_state = hubbub2_read_state,
0711 };
0712
0713 void hubbub21_construct(struct dcn20_hubbub *hubbub,
0714 struct dc_context *ctx,
0715 const struct dcn_hubbub_registers *hubbub_regs,
0716 const struct dcn_hubbub_shift *hubbub_shift,
0717 const struct dcn_hubbub_mask *hubbub_mask)
0718 {
0719 hubbub->base.ctx = ctx;
0720
0721 hubbub->base.funcs = &hubbub21_funcs;
0722
0723 hubbub->regs = hubbub_regs;
0724 hubbub->shifts = hubbub_shift;
0725 hubbub->masks = hubbub_mask;
0726
0727 hubbub->debug_test_index_pstate = 0xB;
0728 hubbub->detile_buf_size = 164 * 1024;
0729 }