FILE
dcn35_hubbub.c
File preview with syntax highlighting.
linux-6.19.14/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c
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 49void 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 74void 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 95static 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 112static bool hubbub35_program_stutter_z8_watermarks( 113 struct hubbub *hubbub, 114 union 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 258void 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 298bool hubbub35_program_watermarks( 299 struct hubbub *hubbub, 300 union 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 if (safe_to_lower || hubbub->ctx->dc->debug.disable_stutter) 330 hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); 331 332 hubbub32_force_usr_retraining_allow(hubbub, hubbub->ctx->dc->debug.force_usr_allow); 333 334 return wm_pending; 335} 336 337/* Copy values from WM set A to all other sets */ 338void hubbub35_init_watermarks(struct hubbub *hubbub) 339{ 340 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 341 uint32_t reg; 342 343 reg = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A); 344 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, reg); 345 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, reg); 346 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, reg); 347 348 reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A); 349 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, reg); 350 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, reg); 351 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, reg); 352 353 reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A); 354 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, reg); 355 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, reg); 356 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, reg); 357 358 reg = REG_READ(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A); 359 REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, reg); 360 REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, reg); 361 REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, reg); 362 363 reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A); 364 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, reg); 365 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, reg); 366 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, reg); 367 368 reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A); 369 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, reg); 370 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, reg); 371 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, reg); 372 373 reg = REG_READ(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A); 374 REG_WRITE(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, reg); 375 REG_WRITE(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, reg); 376 REG_WRITE(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, reg); 377 378 reg = REG_READ(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A); 379 REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, reg); 380 REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, reg); 381 REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, reg); 382 383 reg = REG_READ(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A); 384 REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, reg); 385 REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, reg); 386 REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, reg); 387 388 reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A); 389 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, reg); 390 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, reg); 391 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, reg); 392 393 reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A); 394 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, reg); 395 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, reg); 396 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, reg); 397 398} 399 400void hubbub35_wm_read_state(struct hubbub *hubbub, 401 struct dcn_hubbub_wm *wm) 402{ 403 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 404 struct dcn_hubbub_wm_set *s; 405 406 memset(wm, 0, sizeof(struct dcn_hubbub_wm)); 407 408 s = &wm->sets[0]; 409 s->wm_set = 0; 410 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 411 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, &s->data_urgent); 412 413 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 414 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, &s->sr_enter); 415 416 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 417 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, &s->sr_exit); 418 419 REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, 420 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, &s->dram_clk_change); 421 422 REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, 423 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, &s->usr_retrain); 424 425 REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, 426 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, &s->fclk_pstate_change); 427 428 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, 429 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, &s->sr_enter_exit_Z8); 430 431 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, 432 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, &s->sr_enter_Z8); 433 s = &wm->sets[1]; 434 s->wm_set = 1; 435 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 436 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, &s->data_urgent); 437 438 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 439 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, &s->sr_enter); 440 441 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 442 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, &s->sr_exit); 443 444 REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, 445 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, &s->dram_clk_change); 446 447 REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, 448 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, &s->usr_retrain); 449 450 REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, 451 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, &s->fclk_pstate_change); 452 453 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, 454 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, &s->sr_enter_exit_Z8); 455 456 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, 457 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, &s->sr_enter_Z8); 458 459 s = &wm->sets[2]; 460 s->wm_set = 2; 461 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 462 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, &s->data_urgent); 463 464 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 465 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, &s->sr_enter); 466 467 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 468 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, &s->sr_exit); 469 470 REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, 471 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, &s->dram_clk_change); 472 473 REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, 474 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, &s->usr_retrain); 475 476 REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, 477 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, &s->fclk_pstate_change); 478 479 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, 480 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, &s->sr_enter_exit_Z8); 481 482 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, 483 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, &s->sr_enter_Z8); 484 485 s = &wm->sets[3]; 486 s->wm_set = 3; 487 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 488 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, &s->data_urgent); 489 490 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 491 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, &s->sr_enter); 492 493 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 494 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, &s->sr_exit); 495 496 REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, 497 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, &s->dram_clk_change); 498 499 REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, 500 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, &s->usr_retrain); 501 502 REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, 503 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, &s->fclk_pstate_change); 504 505 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, 506 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, &s->sr_enter_exit_Z8); 507 508 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, 509 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, &s->sr_enter_Z8); 510} 511 512static void hubbub35_set_fgcg(struct dcn20_hubbub *hubbub2, bool enable) 513{ 514 REG_UPDATE(DCHUBBUB_CLOCK_CNTL, DCHUBBUB_FGCG_REP_DIS, !enable); 515} 516 517void hubbub35_init(struct hubbub *hubbub) 518{ 519 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 520 /*Enable clock gaters*/ 521 if (hubbub->ctx->dc->debug.disable_clock_gate) { 522 /*done in hwseq*/ 523 /*REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);*/ 524 525 REG_UPDATE_2(DCHUBBUB_CLOCK_CNTL, 526 DISPCLK_R_DCHUBBUB_GATE_DIS, 1, 527 DCFCLK_R_DCHUBBUB_GATE_DIS, 1); 528 } 529 hubbub35_set_fgcg(hubbub2, 530 hubbub->ctx->dc->debug.enable_fine_grain_clock_gating 531 .bits.dchubbub); 532 /* 533 ignore the "df_pre_cstate_req" from the SDP port control. 534 only the DCN will determine when to connect the SDP port 535 */ 536 REG_UPDATE(DCHUBBUB_SDPIF_CFG0, 537 SDPIF_PORT_CONTROL, 1); 538 /*Set SDP's max outstanding request 539 When set to 1: Max outstanding is 512 540 When set to 0: Max outstanding is 256 541 must set the register back to 0 (max outstanding = 256) in zero frame buffer mode*/ 542 REG_UPDATE(DCHUBBUB_SDPIF_CFG1, 543 SDPIF_MAX_NUM_OUTSTANDING, 0); 544 545 REG_UPDATE_2(DCHUBBUB_ARB_DF_REQ_OUTSTAND, 546 DCHUBBUB_ARB_MAX_REQ_OUTSTAND, 256, 547 DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 256); 548 549 memset(&hubbub2->watermarks.a.cstate_pstate, 0, sizeof(hubbub2->watermarks.a.cstate_pstate)); 550} 551 552void dcn35_dchvm_init(struct hubbub *hubbub) 553{ 554 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 555 uint32_t riommu_active; 556 int i; 557 558 //Init DCHVM block 559 REG_UPDATE(DCHVM_CTRL0, HOSTVM_INIT_REQ, 1); 560 561 //Poll until RIOMMU_ACTIVE = 1 562 for (i = 0; i < 100; i++) { 563 REG_GET(DCHVM_RIOMMU_STAT0, RIOMMU_ACTIVE, &riommu_active); 564 565 if (riommu_active) 566 break; 567 else 568 udelay(5); 569 } 570 571 if (riommu_active) { 572 // Disable gating and memory power requests 573 REG_UPDATE(DCHVM_MEM_CTRL, HVM_GPUVMRET_PWR_REQ_DIS, 1); 574 REG_UPDATE_4(DCHVM_CLK_CTRL, 575 HVM_DISPCLK_R_GATE_DIS, 1, 576 HVM_DISPCLK_G_GATE_DIS, 1, 577 HVM_DCFCLK_R_GATE_DIS, 1, 578 HVM_DCFCLK_G_GATE_DIS, 1); 579 580 //Reflect the power status of DCHUBBUB 581 REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, 1); 582 583 //Start rIOMMU prefetching 584 REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, 1); 585 586 //Poll until HOSTVM_PREFETCH_DONE = 1 587 REG_WAIT(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, 1, 5, 100); 588 589 //Enable memory power requests 590 REG_UPDATE(DCHVM_MEM_CTRL, HVM_GPUVMRET_PWR_REQ_DIS, 0); 591 // Enable dynamic clock gating 592 REG_UPDATE_4(DCHVM_CLK_CTRL, 593 HVM_DISPCLK_R_GATE_DIS, 0, 594 HVM_DISPCLK_G_GATE_DIS, 0, 595 HVM_DCFCLK_R_GATE_DIS, 0, 596 HVM_DCFCLK_G_GATE_DIS, 0); 597 hubbub->riommu_active = true; 598 } 599} 600 601/*static void hubbub35_set_request_limit(struct hubbub *hubbub, 602 int memory_channel_count, 603 int words_per_channel) 604{ 605 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 606 607 uint32_t request_limit = 3 * memory_channel_count * words_per_channel / 4; 608 609 ASSERT((request_limit & (~0xFFF)) == 0); //field is only 24 bits long 610 ASSERT(request_limit > 0); //field is only 24 bits long 611 612 if (request_limit > 0xFFF) 613 request_limit = 0xFFF; 614 615 if (request_limit > 0) 616 REG_UPDATE(SDPIF_REQUEST_RATE_LIMIT, SDPIF_REQUEST_RATE_LIMIT, request_limit); 617}*/ 618 619static const struct hubbub_funcs hubbub35_funcs = { 620 .update_dchub = hubbub2_update_dchub, 621 .init_dchub_sys_ctx = hubbub31_init_dchub_sys_ctx, 622 .init_vm_ctx = hubbub2_init_vm_ctx, 623 .dcc_support_swizzle = hubbub3_dcc_support_swizzle, 624 .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format, 625 .get_dcc_compression_cap = hubbub3_get_dcc_compression_cap, 626 .wm_read_state = hubbub35_wm_read_state, 627 .get_dchub_ref_freq = hubbub35_get_dchub_ref_freq, 628 .program_watermarks = hubbub35_program_watermarks, 629 .allow_self_refresh_control = hubbub1_allow_self_refresh_control, 630 .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, 631 .verify_allow_pstate_change_high = hubbub1_verify_allow_pstate_change_high, 632 .force_wm_propagate_to_pipes = hubbub32_force_wm_propagate_to_pipes, 633 .force_pstate_change_control = hubbub3_force_pstate_change_control, 634 .init_watermarks = hubbub35_init_watermarks, 635 .program_det_size = dcn32_program_det_size, 636 .program_compbuf_size = dcn35_program_compbuf_size, 637 .init_crb = dcn35_init_crb, 638 .hubbub_read_state = hubbub2_read_state, 639 .force_usr_retraining_allow = hubbub32_force_usr_retraining_allow, 640 .dchubbub_init = hubbub35_init, 641 .hubbub_read_reg_state = hubbub3_read_reg_state, 642 .dchvm_init = dcn35_dchvm_init 643}; 644 645void hubbub35_construct(struct dcn20_hubbub *hubbub2, 646 struct dc_context *ctx, 647 const struct dcn_hubbub_registers *hubbub_regs, 648 const struct dcn_hubbub_shift *hubbub_shift, 649 const struct dcn_hubbub_mask *hubbub_mask, 650 int det_size_kb, 651 int pixel_chunk_size_kb, 652 int config_return_buffer_size_kb) 653{ 654 hubbub2->base.ctx = ctx; 655 hubbub2->base.funcs = &hubbub35_funcs; 656 hubbub2->regs = hubbub_regs; 657 hubbub2->shifts = hubbub_shift; 658 hubbub2->masks = hubbub_mask; 659 660 hubbub2->debug_test_index_pstate = 0xB; 661 hubbub2->detile_buf_size = det_size_kb * 1024; 662 hubbub2->pixel_chunk_size = pixel_chunk_size_kb * 1024; 663 hubbub2->crb_size_segs = config_return_buffer_size_kb / DCN35_CRB_SEGMENT_SIZE_KB; /*todo*/ 664}
~/
Read-only file preview.