1 /* SPDX-License-Identifier: MIT */ 2 /* 3 * Copyright 2023 Advanced Micro Devices, Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 * OTHER DEALINGS IN THE SOFTWARE. 22 * 23 * Authors: AMD 24 * 25 */ 26 27 28 #include "dcn30/dcn30_hubbub.h" 29 #include "dcn31/dcn31_hubbub.h" 30 #include "dcn32/dcn32_hubbub.h" 31 #include "dcn35_hubbub.h" 32 #include "dm_services.h" 33 #include "reg_helper.h" 34 35 36 #define CTX \ 37 hubbub2->base.ctx 38 #define DC_LOGGER \ 39 hubbub2->base.ctx->logger 40 #define REG(reg)\ 41 hubbub2->regs->reg 42 43 #undef FN 44 #define FN(reg_name, field_name) \ 45 hubbub2->shifts->field_name, hubbub2->masks->field_name 46 47 #define DCN35_CRB_SEGMENT_SIZE_KB 64 48 49 static void dcn35_init_crb(struct hubbub *hubbub) 50 { 51 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 52 53 REG_GET(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, 54 &hubbub2->det0_size); 55 56 REG_GET(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, 57 &hubbub2->det1_size); 58 59 REG_GET(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, 60 &hubbub2->det2_size); 61 62 REG_GET(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, 63 &hubbub2->det3_size); 64 65 REG_GET(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT, 66 &hubbub2->compbuf_size_segments); 67 68 REG_SET_2(COMPBUF_RESERVED_SPACE, 0, 69 COMPBUF_RESERVED_SPACE_64B, hubbub2->pixel_chunk_size / 32, 70 COMPBUF_RESERVED_SPACE_ZS, hubbub2->pixel_chunk_size / 128); 71 REG_UPDATE(DCHUBBUB_DEBUG_CTRL_0, DET_DEPTH, 0x5FF); 72 } 73 74 static void dcn35_program_compbuf_size(struct hubbub *hubbub, unsigned int compbuf_size_kb, bool safe_to_increase) 75 { 76 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 77 unsigned int compbuf_size_segments = (compbuf_size_kb + DCN35_CRB_SEGMENT_SIZE_KB - 1) / DCN35_CRB_SEGMENT_SIZE_KB; 78 79 if (safe_to_increase || compbuf_size_segments <= hubbub2->compbuf_size_segments) { 80 if (compbuf_size_segments > hubbub2->compbuf_size_segments) { 81 REG_WAIT(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, hubbub2->det0_size, 1, 100); 82 REG_WAIT(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, hubbub2->det1_size, 1, 100); 83 REG_WAIT(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, hubbub2->det2_size, 1, 100); 84 REG_WAIT(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, hubbub2->det3_size, 1, 100); 85 } 86 /* Should never be hit, if it is we have an erroneous hw config*/ 87 ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size 88 + hubbub2->det3_size + compbuf_size_segments <= hubbub2->crb_size_segs); 89 REG_UPDATE(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, compbuf_size_segments); 90 hubbub2->compbuf_size_segments = compbuf_size_segments; 91 ASSERT(REG_GET(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, &compbuf_size_segments) && !compbuf_size_segments); 92 } 93 } 94 95 static uint32_t convert_and_clamp( 96 uint32_t wm_ns, 97 uint32_t refclk_mhz, 98 uint32_t clamp_value) 99 { 100 uint32_t ret_val = 0; 101 102 ret_val = wm_ns * refclk_mhz; 103 104 ret_val /= 1000; 105 106 if (ret_val > clamp_value) 107 ret_val = clamp_value; 108 109 return ret_val; 110 } 111 112 static bool hubbub35_program_stutter_z8_watermarks( 113 struct hubbub *hubbub, 114 struct dcn_watermark_set *watermarks, 115 unsigned int refclk_mhz, 116 bool safe_to_lower) 117 { 118 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 119 uint32_t prog_wm_value; 120 bool wm_pending = false; 121 122 /* clock state A */ 123 if (watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns 124 > hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns) { 125 hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns = 126 watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns; 127 prog_wm_value = convert_and_clamp( 128 watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns, 129 refclk_mhz, 0xfffff); 130 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, 0, 131 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, prog_wm_value); 132 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_A calculated =%d\n" 133 "HW register value = 0x%x\n", 134 watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns, prog_wm_value); 135 } else if (watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns 136 < hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns) 137 wm_pending = true; 138 139 if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_z8_ns 140 > hubbub2->watermarks.a.cstate_pstate.cstate_exit_z8_ns) { 141 hubbub2->watermarks.a.cstate_pstate.cstate_exit_z8_ns = 142 watermarks->a.cstate_pstate.cstate_exit_z8_ns; 143 prog_wm_value = convert_and_clamp( 144 watermarks->a.cstate_pstate.cstate_exit_z8_ns, 145 refclk_mhz, 0xfffff); 146 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, 0, 147 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, prog_wm_value); 148 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_A calculated =%d\n" 149 "HW register value = 0x%x\n", 150 watermarks->a.cstate_pstate.cstate_exit_z8_ns, prog_wm_value); 151 } else if (watermarks->a.cstate_pstate.cstate_exit_z8_ns 152 < hubbub2->watermarks.a.cstate_pstate.cstate_exit_z8_ns) 153 wm_pending = true; 154 155 /* clock state B */ 156 157 if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns 158 > hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_z8_ns) { 159 hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_z8_ns = 160 watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns; 161 prog_wm_value = convert_and_clamp( 162 watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns, 163 refclk_mhz, 0xfffff); 164 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, 0, 165 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, prog_wm_value); 166 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_B calculated =%d\n" 167 "HW register value = 0x%x\n", 168 watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns, prog_wm_value); 169 } else if (watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns 170 < hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_z8_ns) 171 wm_pending = true; 172 173 if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_z8_ns 174 > hubbub2->watermarks.b.cstate_pstate.cstate_exit_z8_ns) { 175 hubbub2->watermarks.b.cstate_pstate.cstate_exit_z8_ns = 176 watermarks->b.cstate_pstate.cstate_exit_z8_ns; 177 prog_wm_value = convert_and_clamp( 178 watermarks->b.cstate_pstate.cstate_exit_z8_ns, 179 refclk_mhz, 0xfffff); 180 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, 0, 181 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, prog_wm_value); 182 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_B calculated =%d\n" 183 "HW register value = 0x%x\n", 184 watermarks->b.cstate_pstate.cstate_exit_z8_ns, prog_wm_value); 185 } else if (watermarks->b.cstate_pstate.cstate_exit_z8_ns 186 < hubbub2->watermarks.b.cstate_pstate.cstate_exit_z8_ns) 187 wm_pending = true; 188 189 /* clock state C */ 190 if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns 191 > hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_z8_ns) { 192 hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_z8_ns = 193 watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns; 194 prog_wm_value = convert_and_clamp( 195 watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns, 196 refclk_mhz, 0xfffff); 197 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, 0, 198 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, prog_wm_value); 199 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_C calculated =%d\n" 200 "HW register value = 0x%x\n", 201 watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns, prog_wm_value); 202 } else if (watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns 203 < hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_z8_ns) 204 wm_pending = true; 205 206 if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_z8_ns 207 > hubbub2->watermarks.c.cstate_pstate.cstate_exit_z8_ns) { 208 hubbub2->watermarks.c.cstate_pstate.cstate_exit_z8_ns = 209 watermarks->c.cstate_pstate.cstate_exit_z8_ns; 210 prog_wm_value = convert_and_clamp( 211 watermarks->c.cstate_pstate.cstate_exit_z8_ns, 212 refclk_mhz, 0xfffff); 213 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, 0, 214 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, prog_wm_value); 215 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_C calculated =%d\n" 216 "HW register value = 0x%x\n", 217 watermarks->c.cstate_pstate.cstate_exit_z8_ns, prog_wm_value); 218 } else if (watermarks->c.cstate_pstate.cstate_exit_z8_ns 219 < hubbub2->watermarks.c.cstate_pstate.cstate_exit_z8_ns) 220 wm_pending = true; 221 222 /* clock state D */ 223 if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns 224 > hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_z8_ns) { 225 hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_z8_ns = 226 watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns; 227 prog_wm_value = convert_and_clamp( 228 watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns, 229 refclk_mhz, 0xfffff); 230 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, 0, 231 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, prog_wm_value); 232 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_D calculated =%d\n" 233 "HW register value = 0x%x\n", 234 watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns, prog_wm_value); 235 } else if (watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns 236 < hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_z8_ns) 237 wm_pending = true; 238 239 if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_z8_ns 240 > hubbub2->watermarks.d.cstate_pstate.cstate_exit_z8_ns) { 241 hubbub2->watermarks.d.cstate_pstate.cstate_exit_z8_ns = 242 watermarks->d.cstate_pstate.cstate_exit_z8_ns; 243 prog_wm_value = convert_and_clamp( 244 watermarks->d.cstate_pstate.cstate_exit_z8_ns, 245 refclk_mhz, 0xfffff); 246 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, 0, 247 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, prog_wm_value); 248 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_D calculated =%d\n" 249 "HW register value = 0x%x\n", 250 watermarks->d.cstate_pstate.cstate_exit_z8_ns, prog_wm_value); 251 } else if (watermarks->d.cstate_pstate.cstate_exit_z8_ns 252 < hubbub2->watermarks.d.cstate_pstate.cstate_exit_z8_ns) 253 wm_pending = true; 254 255 return wm_pending; 256 } 257 258 static void hubbub35_get_dchub_ref_freq(struct hubbub *hubbub, 259 unsigned int dccg_ref_freq_inKhz, 260 unsigned int *dchub_ref_freq_inKhz) 261 { 262 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 263 uint32_t ref_div = 0; 264 uint32_t ref_en = 0; 265 unsigned int dc_refclk_khz = 24000; 266 267 REG_GET_2(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, &ref_div, 268 DCHUBBUB_GLOBAL_TIMER_ENABLE, &ref_en); 269 270 if (ref_en) { 271 if (ref_div == 2) 272 *dchub_ref_freq_inKhz = dc_refclk_khz / 2; 273 else 274 *dchub_ref_freq_inKhz = dc_refclk_khz; 275 276 /* 277 * The external Reference Clock may change based on the board or 278 * platform requirements and the programmable integer divide must 279 * be programmed to provide a suitable DLG RefClk frequency between 280 * a minimum of 20MHz and maximum of 50MHz 281 */ 282 if (*dchub_ref_freq_inKhz < 20000 || *dchub_ref_freq_inKhz > 50000) 283 ASSERT_CRITICAL(false); 284 285 return; 286 } else { 287 *dchub_ref_freq_inKhz = dc_refclk_khz; 288 /*init sequence issue on bringup patch*/ 289 REG_UPDATE_2(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 1, 290 DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); 291 // HUBBUB global timer must be enabled. 292 ASSERT_CRITICAL(false); 293 return; 294 } 295 } 296 297 298 static bool hubbub35_program_watermarks( 299 struct hubbub *hubbub, 300 struct dcn_watermark_set *watermarks, 301 unsigned int refclk_mhz, 302 bool safe_to_lower) 303 { 304 bool wm_pending = false; 305 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 306 307 if (hubbub32_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) 308 wm_pending = true; 309 310 if (hubbub32_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) 311 wm_pending = true; 312 313 if (hubbub32_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) 314 wm_pending = true; 315 316 if (hubbub32_program_usr_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) 317 wm_pending = true; 318 319 if (hubbub35_program_stutter_z8_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) 320 wm_pending = true; 321 322 REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0, 323 DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); 324 REG_UPDATE_2(DCHUBBUB_ARB_DF_REQ_OUTSTAND, 325 DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0xFF, 326 DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, 0xA);/*hw delta*/ 327 REG_UPDATE(DCHUBBUB_ARB_HOSTVM_CNTL, DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, 0xF); 328 329 hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); 330 331 hubbub32_force_usr_retraining_allow(hubbub, hubbub->ctx->dc->debug.force_usr_allow); 332 333 return wm_pending; 334 } 335 336 /* Copy values from WM set A to all other sets */ 337 static void hubbub35_init_watermarks(struct hubbub *hubbub) 338 { 339 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 340 uint32_t reg; 341 342 reg = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A); 343 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, reg); 344 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, reg); 345 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, reg); 346 347 reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A); 348 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, reg); 349 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, reg); 350 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, reg); 351 352 reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A); 353 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, reg); 354 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, reg); 355 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, reg); 356 357 reg = REG_READ(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A); 358 REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, reg); 359 REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, reg); 360 REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, reg); 361 362 reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A); 363 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, reg); 364 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, reg); 365 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, reg); 366 367 reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A); 368 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, reg); 369 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, reg); 370 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, reg); 371 372 reg = REG_READ(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A); 373 REG_WRITE(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, reg); 374 REG_WRITE(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, reg); 375 REG_WRITE(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, reg); 376 377 reg = REG_READ(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A); 378 REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, reg); 379 REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, reg); 380 REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, reg); 381 382 reg = REG_READ(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A); 383 REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, reg); 384 REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, reg); 385 REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, reg); 386 387 reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A); 388 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, reg); 389 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, reg); 390 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, reg); 391 392 reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A); 393 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, reg); 394 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, reg); 395 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, reg); 396 397 } 398 399 static void hubbub35_wm_read_state(struct hubbub *hubbub, 400 struct dcn_hubbub_wm *wm) 401 { 402 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 403 struct dcn_hubbub_wm_set *s; 404 405 memset(wm, 0, sizeof(struct dcn_hubbub_wm)); 406 407 s = &wm->sets[0]; 408 s->wm_set = 0; 409 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 410 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, &s->data_urgent); 411 412 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 413 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, &s->sr_enter); 414 415 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 416 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, &s->sr_exit); 417 418 REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, 419 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, &s->dram_clk_change); 420 421 REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, 422 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, &s->usr_retrain); 423 424 REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, 425 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, &s->fclk_pstate_change); 426 427 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, 428 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, &s->sr_enter_exit_Z8); 429 430 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, 431 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, &s->sr_enter_Z8); 432 s = &wm->sets[1]; 433 s->wm_set = 1; 434 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 435 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, &s->data_urgent); 436 437 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 438 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, &s->sr_enter); 439 440 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 441 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, &s->sr_exit); 442 443 REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, 444 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, &s->dram_clk_change); 445 446 REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, 447 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, &s->usr_retrain); 448 449 REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, 450 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, &s->fclk_pstate_change); 451 452 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, 453 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, &s->sr_enter_exit_Z8); 454 455 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, 456 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, &s->sr_enter_Z8); 457 458 s = &wm->sets[2]; 459 s->wm_set = 2; 460 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 461 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, &s->data_urgent); 462 463 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 464 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, &s->sr_enter); 465 466 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 467 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, &s->sr_exit); 468 469 REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, 470 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, &s->dram_clk_change); 471 472 REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, 473 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, &s->usr_retrain); 474 475 REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, 476 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, &s->fclk_pstate_change); 477 478 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, 479 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, &s->sr_enter_exit_Z8); 480 481 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, 482 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, &s->sr_enter_Z8); 483 484 s = &wm->sets[3]; 485 s->wm_set = 3; 486 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 487 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, &s->data_urgent); 488 489 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 490 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, &s->sr_enter); 491 492 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 493 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, &s->sr_exit); 494 495 REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, 496 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, &s->dram_clk_change); 497 498 REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, 499 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, &s->usr_retrain); 500 501 REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, 502 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, &s->fclk_pstate_change); 503 504 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, 505 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, &s->sr_enter_exit_Z8); 506 507 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, 508 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, &s->sr_enter_Z8); 509 } 510 511 static void hubbub35_set_fgcg(struct dcn20_hubbub *hubbub2, bool enable) 512 { 513 REG_UPDATE(DCHUBBUB_CLOCK_CNTL, DCHUBBUB_FGCG_REP_DIS, !enable); 514 } 515 516 static void hubbub35_init(struct hubbub *hubbub) 517 { 518 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 519 /*Enable clock gaters*/ 520 if (hubbub->ctx->dc->debug.disable_clock_gate) { 521 /*done in hwseq*/ 522 /*REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);*/ 523 524 REG_UPDATE_2(DCHUBBUB_CLOCK_CNTL, 525 DISPCLK_R_DCHUBBUB_GATE_DIS, 1, 526 DCFCLK_R_DCHUBBUB_GATE_DIS, 1); 527 } 528 hubbub35_set_fgcg(hubbub2, 529 hubbub->ctx->dc->debug.enable_fine_grain_clock_gating 530 .bits.dchubbub); 531 /* 532 ignore the "df_pre_cstate_req" from the SDP port control. 533 only the DCN will determine when to connect the SDP port 534 */ 535 REG_UPDATE(DCHUBBUB_SDPIF_CFG0, 536 SDPIF_PORT_CONTROL, 1); 537 /*Set SDP's max outstanding request 538 When set to 1: Max outstanding is 512 539 When set to 0: Max outstanding is 256 540 must set the register back to 0 (max outstanding = 256) in zero frame buffer mode*/ 541 REG_UPDATE(DCHUBBUB_SDPIF_CFG1, 542 SDPIF_MAX_NUM_OUTSTANDING, 0); 543 544 REG_UPDATE_2(DCHUBBUB_ARB_DF_REQ_OUTSTAND, 545 DCHUBBUB_ARB_MAX_REQ_OUTSTAND, 256, 546 DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 256); 547 548 } 549 550 /*static void hubbub35_set_request_limit(struct hubbub *hubbub, 551 int memory_channel_count, 552 int words_per_channel) 553 { 554 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 555 556 uint32_t request_limit = 3 * memory_channel_count * words_per_channel / 4; 557 558 ASSERT((request_limit & (~0xFFF)) == 0); //field is only 24 bits long 559 ASSERT(request_limit > 0); //field is only 24 bits long 560 561 if (request_limit > 0xFFF) 562 request_limit = 0xFFF; 563 564 if (request_limit > 0) 565 REG_UPDATE(SDPIF_REQUEST_RATE_LIMIT, SDPIF_REQUEST_RATE_LIMIT, request_limit); 566 }*/ 567 568 static const struct hubbub_funcs hubbub35_funcs = { 569 .update_dchub = hubbub2_update_dchub, 570 .init_dchub_sys_ctx = hubbub31_init_dchub_sys_ctx, 571 .init_vm_ctx = hubbub2_init_vm_ctx, 572 .dcc_support_swizzle = hubbub3_dcc_support_swizzle, 573 .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format, 574 .get_dcc_compression_cap = hubbub3_get_dcc_compression_cap, 575 .wm_read_state = hubbub35_wm_read_state, 576 .get_dchub_ref_freq = hubbub35_get_dchub_ref_freq, 577 .program_watermarks = hubbub35_program_watermarks, 578 .allow_self_refresh_control = hubbub1_allow_self_refresh_control, 579 .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, 580 .verify_allow_pstate_change_high = hubbub1_verify_allow_pstate_change_high, 581 .force_wm_propagate_to_pipes = hubbub32_force_wm_propagate_to_pipes, 582 .force_pstate_change_control = hubbub3_force_pstate_change_control, 583 .init_watermarks = hubbub35_init_watermarks, 584 .program_det_size = dcn32_program_det_size, 585 .program_compbuf_size = dcn35_program_compbuf_size, 586 .init_crb = dcn35_init_crb, 587 .hubbub_read_state = hubbub2_read_state, 588 .force_usr_retraining_allow = hubbub32_force_usr_retraining_allow, 589 .dchubbub_init = hubbub35_init, 590 }; 591 592 void hubbub35_construct(struct dcn20_hubbub *hubbub2, 593 struct dc_context *ctx, 594 const struct dcn_hubbub_registers *hubbub_regs, 595 const struct dcn_hubbub_shift *hubbub_shift, 596 const struct dcn_hubbub_mask *hubbub_mask, 597 int det_size_kb, 598 int pixel_chunk_size_kb, 599 int config_return_buffer_size_kb) 600 { 601 hubbub2->base.ctx = ctx; 602 hubbub2->base.funcs = &hubbub35_funcs; 603 hubbub2->regs = hubbub_regs; 604 hubbub2->shifts = hubbub_shift; 605 hubbub2->masks = hubbub_mask; 606 607 hubbub2->debug_test_index_pstate = 0xB; 608 hubbub2->detile_buf_size = det_size_kb * 1024; 609 hubbub2->pixel_chunk_size = pixel_chunk_size_kb * 1024; 610 hubbub2->crb_size_segs = config_return_buffer_size_kb / DCN35_CRB_SEGMENT_SIZE_KB; /*todo*/ 611 } 612