1 // SPDX-License-Identifier: MIT 2 // 3 // Copyright 2026 Advanced Micro Devices, Inc. 4 5 #include "dcn30/dcn30_hubbub.h" 6 #include "dcn31/dcn31_hubbub.h" 7 #include "dcn32/dcn32_hubbub.h" 8 #include "dcn35/dcn35_hubbub.h" 9 #include "dcn401/dcn401_hubbub.h" 10 #include "dcn42/dcn42_hubbub.h" 11 #include "dm_services.h" 12 #include "reg_helper.h" 13 14 #define DCN42_CRB_SEGMENT_SIZE_KB 64 15 16 #define CTX \ 17 hubbub2->base.ctx 18 #define DC_LOGGER \ 19 hubbub2->base.ctx->logger 20 #define REG(reg)\ 21 hubbub2->regs->reg 22 23 #undef FN 24 #define FN(reg_name, field_name) \ 25 hubbub2->shifts->field_name, hubbub2->masks->field_name 26 27 static bool hubbub42_program_urgent_watermarks( 28 struct hubbub *hubbub, 29 union dcn_watermark_set *watermarks, 30 bool safe_to_lower) 31 { 32 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 33 bool wm_pending = false; 34 35 /* Repeat for water mark set A, B, C and D. */ 36 /* clock state A */ 37 if (safe_to_lower || watermarks->dcn4x.a.urgent > hubbub2->watermarks.dcn4x.a.urgent) { 38 hubbub2->watermarks.dcn4x.a.urgent = watermarks->dcn4x.a.urgent; 39 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0, 40 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, watermarks->dcn4x.a.urgent); 41 } else if (watermarks->dcn4x.a.urgent < hubbub2->watermarks.dcn4x.a.urgent) 42 wm_pending = true; 43 44 /* determine the transfer time for a quantity of data for a particular requestor.*/ 45 if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip) { 46 hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip = watermarks->dcn4x.a.frac_urg_bw_flip; 47 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0, 48 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, watermarks->dcn4x.a.frac_urg_bw_flip); 49 } else if (watermarks->dcn4x.a.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip) 50 wm_pending = true; 51 52 if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom) { 53 hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom = watermarks->dcn4x.a.frac_urg_bw_nom; 54 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0, 55 DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->dcn4x.a.frac_urg_bw_nom); 56 } else if (watermarks->dcn4x.a.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom) 57 wm_pending = true; 58 59 if (safe_to_lower || watermarks->dcn4x.a.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem) { 60 hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem = watermarks->dcn4x.a.refcyc_per_trip_to_mem; 61 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0, 62 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, watermarks->dcn4x.a.refcyc_per_trip_to_mem); 63 } else if (watermarks->dcn4x.a.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem) 64 wm_pending = true; 65 66 /* clock state B */ 67 if (safe_to_lower || watermarks->dcn4x.b.urgent > hubbub2->watermarks.dcn4x.b.urgent) { 68 hubbub2->watermarks.dcn4x.b.urgent = watermarks->dcn4x.b.urgent; 69 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0, 70 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, watermarks->dcn4x.b.urgent); 71 } else if (watermarks->dcn4x.b.urgent < hubbub2->watermarks.dcn4x.b.urgent) 72 wm_pending = true; 73 74 /* determine the transfer time for a quantity of data for a particular requestor.*/ 75 if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip) { 76 hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip = watermarks->dcn4x.b.frac_urg_bw_flip; 77 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0, 78 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, watermarks->dcn4x.b.frac_urg_bw_flip); 79 } else if (watermarks->dcn4x.b.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip) 80 wm_pending = true; 81 82 if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom) { 83 hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom = watermarks->dcn4x.b.frac_urg_bw_nom; 84 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0, 85 DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->dcn4x.b.frac_urg_bw_nom); 86 } else if (watermarks->dcn4x.b.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom) 87 wm_pending = true; 88 89 if (safe_to_lower || watermarks->dcn4x.b.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem) { 90 hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem = watermarks->dcn4x.b.refcyc_per_trip_to_mem; 91 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0, 92 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, watermarks->dcn4x.b.refcyc_per_trip_to_mem); 93 } else if (watermarks->dcn4x.b.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem) 94 wm_pending = true; 95 96 /* clock state C */ 97 if (safe_to_lower || watermarks->dcn4x.c.urgent > hubbub2->watermarks.dcn4x.c.urgent) { 98 hubbub2->watermarks.dcn4x.c.urgent = watermarks->dcn4x.c.urgent; 99 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0, 100 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, watermarks->dcn4x.c.urgent); 101 } else if (watermarks->dcn4x.c.urgent < hubbub2->watermarks.dcn4x.c.urgent) 102 wm_pending = true; 103 104 /* determine the transfer time for a quantity of data for a particular requestor.*/ 105 if (safe_to_lower || watermarks->dcn4x.c.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.c.frac_urg_bw_flip) { 106 hubbub2->watermarks.dcn4x.c.frac_urg_bw_flip = watermarks->dcn4x.c.frac_urg_bw_flip; 107 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, 0, 108 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, watermarks->dcn4x.c.frac_urg_bw_flip); 109 } else if (watermarks->dcn4x.c.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.c.frac_urg_bw_flip) 110 wm_pending = true; 111 112 if (safe_to_lower || watermarks->dcn4x.c.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.c.frac_urg_bw_nom) { 113 hubbub2->watermarks.dcn4x.c.frac_urg_bw_nom = watermarks->dcn4x.c.frac_urg_bw_nom; 114 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, 0, 115 DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, watermarks->dcn4x.c.frac_urg_bw_nom); 116 } else if (watermarks->dcn4x.c.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.c.frac_urg_bw_nom) 117 wm_pending = true; 118 119 if (safe_to_lower || watermarks->dcn4x.c.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.c.refcyc_per_trip_to_mem) { 120 hubbub2->watermarks.dcn4x.c.refcyc_per_trip_to_mem = watermarks->dcn4x.c.refcyc_per_trip_to_mem; 121 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 0, 122 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, watermarks->dcn4x.c.refcyc_per_trip_to_mem); 123 } else if (watermarks->dcn4x.c.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.c.refcyc_per_trip_to_mem) 124 wm_pending = true; 125 126 /* clock state D */ 127 if (safe_to_lower || watermarks->dcn4x.d.urgent > hubbub2->watermarks.dcn4x.d.urgent) { 128 hubbub2->watermarks.dcn4x.d.urgent = watermarks->dcn4x.d.urgent; 129 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0, 130 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, watermarks->dcn4x.d.urgent); 131 } else if (watermarks->dcn4x.d.urgent < hubbub2->watermarks.dcn4x.d.urgent) 132 wm_pending = true; 133 134 /* determine the transfer time for a quantity of data for a particular requestor.*/ 135 if (safe_to_lower || watermarks->dcn4x.d.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.d.frac_urg_bw_flip) { 136 hubbub2->watermarks.dcn4x.d.frac_urg_bw_flip = watermarks->dcn4x.d.frac_urg_bw_flip; 137 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, 0, 138 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, watermarks->dcn4x.d.frac_urg_bw_flip); 139 } else if (watermarks->dcn4x.d.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.d.frac_urg_bw_flip) 140 wm_pending = true; 141 142 if (safe_to_lower || watermarks->dcn4x.d.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.d.frac_urg_bw_nom) { 143 hubbub2->watermarks.dcn4x.d.frac_urg_bw_nom = watermarks->dcn4x.d.frac_urg_bw_nom; 144 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 0, 145 DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, watermarks->dcn4x.d.frac_urg_bw_nom); 146 } else if (watermarks->dcn4x.d.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.d.frac_urg_bw_nom) 147 wm_pending = true; 148 149 if (safe_to_lower || watermarks->dcn4x.d.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.d.refcyc_per_trip_to_mem) { 150 hubbub2->watermarks.dcn4x.d.refcyc_per_trip_to_mem = watermarks->dcn4x.d.refcyc_per_trip_to_mem; 151 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0, 152 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, watermarks->dcn4x.d.refcyc_per_trip_to_mem); 153 } else if (watermarks->dcn4x.d.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.d.refcyc_per_trip_to_mem) 154 wm_pending = true; 155 156 return wm_pending; 157 } 158 159 static bool hubbub42_program_stutter_watermarks( 160 struct hubbub *hubbub, 161 union dcn_watermark_set *watermarks, 162 bool safe_to_lower) 163 { 164 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 165 bool wm_pending = false; 166 167 /* clock state A */ 168 if (safe_to_lower || watermarks->dcn4x.a.sr_enter > hubbub2->watermarks.dcn4x.a.sr_enter) { 169 hubbub2->watermarks.dcn4x.a.sr_enter = watermarks->dcn4x.a.sr_enter; 170 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0, 171 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, watermarks->dcn4x.a.sr_enter); 172 } else if (watermarks->dcn4x.a.sr_enter < hubbub2->watermarks.dcn4x.a.sr_enter) 173 wm_pending = true; 174 175 if (safe_to_lower || watermarks->dcn4x.a.sr_exit > hubbub2->watermarks.dcn4x.a.sr_exit) { 176 hubbub2->watermarks.dcn4x.a.sr_exit = watermarks->dcn4x.a.sr_exit; 177 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0, 178 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, watermarks->dcn4x.a.sr_exit); 179 } else if (watermarks->dcn4x.a.sr_exit < hubbub2->watermarks.dcn4x.a.sr_exit) 180 wm_pending = true; 181 182 /* clock state B */ 183 if (safe_to_lower || watermarks->dcn4x.b.sr_enter > hubbub2->watermarks.dcn4x.b.sr_enter) { 184 hubbub2->watermarks.dcn4x.b.sr_enter = watermarks->dcn4x.b.sr_enter; 185 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0, 186 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, watermarks->dcn4x.b.sr_enter); 187 } else if (watermarks->dcn4x.b.sr_enter < hubbub2->watermarks.dcn4x.b.sr_enter) 188 wm_pending = true; 189 190 if (safe_to_lower || watermarks->dcn4x.b.sr_exit > hubbub2->watermarks.dcn4x.b.sr_exit) { 191 hubbub2->watermarks.dcn4x.b.sr_exit = watermarks->dcn4x.b.sr_exit; 192 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0, 193 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, watermarks->dcn4x.b.sr_exit); 194 } else if (watermarks->dcn4x.b.sr_exit < hubbub2->watermarks.dcn4x.b.sr_exit) 195 wm_pending = true; 196 197 /* clock state C */ 198 if (safe_to_lower || watermarks->dcn4x.c.sr_enter > hubbub2->watermarks.dcn4x.c.sr_enter) { 199 hubbub2->watermarks.dcn4x.c.sr_enter = watermarks->dcn4x.c.sr_enter; 200 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0, 201 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, watermarks->dcn4x.c.sr_enter); 202 } else if (watermarks->dcn4x.c.sr_enter < hubbub2->watermarks.dcn4x.c.sr_enter) 203 wm_pending = true; 204 205 if (safe_to_lower || watermarks->dcn4x.c.sr_exit > hubbub2->watermarks.dcn4x.c.sr_exit) { 206 hubbub2->watermarks.dcn4x.c.sr_exit = watermarks->dcn4x.c.sr_exit; 207 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0, 208 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, watermarks->dcn4x.c.sr_exit); 209 } else if (watermarks->dcn4x.c.sr_exit < hubbub2->watermarks.dcn4x.c.sr_exit) 210 wm_pending = true; 211 212 /* clock state D */ 213 if (safe_to_lower || watermarks->dcn4x.d.sr_enter > hubbub2->watermarks.dcn4x.d.sr_enter) { 214 hubbub2->watermarks.dcn4x.d.sr_enter = watermarks->dcn4x.d.sr_enter; 215 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0, 216 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, watermarks->dcn4x.d.sr_enter); 217 } else if (watermarks->dcn4x.d.sr_enter < hubbub2->watermarks.dcn4x.d.sr_enter) 218 wm_pending = true; 219 220 if (safe_to_lower || watermarks->dcn4x.d.sr_exit > hubbub2->watermarks.dcn4x.d.sr_exit) { 221 hubbub2->watermarks.dcn4x.d.sr_exit = watermarks->dcn4x.d.sr_exit; 222 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0, 223 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, watermarks->dcn4x.d.sr_exit); 224 } else if (watermarks->dcn4x.d.sr_exit < hubbub2->watermarks.dcn4x.d.sr_exit) 225 wm_pending = true; 226 227 return wm_pending; 228 } 229 230 static bool hubbub42_program_pstate_watermarks( 231 struct hubbub *hubbub, 232 union dcn_watermark_set *watermarks, 233 bool safe_to_lower) 234 { 235 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 236 bool wm_pending = false; 237 238 /* Section for UCLK_PSTATE_CHANGE_WATERMARKS */ 239 /* UCLK state A */ 240 if (safe_to_lower || watermarks->dcn4x.a.uclk_pstate > hubbub2->watermarks.dcn4x.a.uclk_pstate) { 241 hubbub2->watermarks.dcn4x.a.uclk_pstate = watermarks->dcn4x.a.uclk_pstate; 242 REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, 0, 243 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, watermarks->dcn4x.a.uclk_pstate); 244 } else if (watermarks->dcn4x.a.uclk_pstate < hubbub2->watermarks.dcn4x.a.uclk_pstate) 245 wm_pending = true; 246 247 /* UCLK state B */ 248 if (safe_to_lower || watermarks->dcn4x.b.uclk_pstate > hubbub2->watermarks.dcn4x.b.uclk_pstate) { 249 hubbub2->watermarks.dcn4x.b.uclk_pstate = watermarks->dcn4x.b.uclk_pstate; 250 REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, 0, 251 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, watermarks->dcn4x.b.uclk_pstate); 252 } else if (watermarks->dcn4x.b.uclk_pstate < hubbub2->watermarks.dcn4x.b.uclk_pstate) 253 wm_pending = true; 254 255 /* UCLK state C */ 256 if (safe_to_lower || watermarks->dcn4x.c.uclk_pstate > hubbub2->watermarks.dcn4x.c.uclk_pstate) { 257 hubbub2->watermarks.dcn4x.c.uclk_pstate = watermarks->dcn4x.c.uclk_pstate; 258 REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, 0, 259 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, watermarks->dcn4x.c.uclk_pstate); 260 } else if (watermarks->dcn4x.c.uclk_pstate < hubbub2->watermarks.dcn4x.c.uclk_pstate) 261 wm_pending = true; 262 263 /* UCLK state D */ 264 if (safe_to_lower || watermarks->dcn4x.d.uclk_pstate > hubbub2->watermarks.dcn4x.d.uclk_pstate) { 265 hubbub2->watermarks.dcn4x.d.uclk_pstate = watermarks->dcn4x.d.uclk_pstate; 266 REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, 0, 267 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, watermarks->dcn4x.d.uclk_pstate); 268 } else if (watermarks->dcn4x.d.uclk_pstate < hubbub2->watermarks.dcn4x.d.uclk_pstate) 269 wm_pending = true; 270 271 /* Section for FCLK_PSTATE_CHANGE_WATERMARKS */ 272 /* FCLK state A */ 273 if (safe_to_lower || watermarks->dcn4x.a.fclk_pstate > hubbub2->watermarks.dcn4x.a.fclk_pstate) { 274 hubbub2->watermarks.dcn4x.a.fclk_pstate = watermarks->dcn4x.a.fclk_pstate; 275 REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, 0, 276 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, watermarks->dcn4x.a.fclk_pstate); 277 } else if (watermarks->dcn4x.a.fclk_pstate < hubbub2->watermarks.dcn4x.a.fclk_pstate) 278 wm_pending = true; 279 280 /* FCLK state B */ 281 if (safe_to_lower || watermarks->dcn4x.b.fclk_pstate > hubbub2->watermarks.dcn4x.b.fclk_pstate) { 282 hubbub2->watermarks.dcn4x.b.fclk_pstate = watermarks->dcn4x.b.fclk_pstate; 283 REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, 0, 284 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, watermarks->dcn4x.b.fclk_pstate); 285 } else if (watermarks->dcn4x.b.fclk_pstate < hubbub2->watermarks.dcn4x.b.fclk_pstate) 286 wm_pending = true; 287 288 /* FCLK state C */ 289 if (safe_to_lower || watermarks->dcn4x.c.fclk_pstate > hubbub2->watermarks.dcn4x.c.fclk_pstate) { 290 hubbub2->watermarks.dcn4x.c.fclk_pstate = watermarks->dcn4x.c.fclk_pstate; 291 REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, 0, 292 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, watermarks->dcn4x.c.fclk_pstate); 293 } else if (watermarks->dcn4x.c.fclk_pstate < hubbub2->watermarks.dcn4x.c.fclk_pstate) 294 wm_pending = true; 295 296 /* FCLK state D */ 297 if (safe_to_lower || watermarks->dcn4x.d.fclk_pstate > hubbub2->watermarks.dcn4x.d.fclk_pstate) { 298 hubbub2->watermarks.dcn4x.d.fclk_pstate = watermarks->dcn4x.d.fclk_pstate; 299 REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, 0, 300 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, watermarks->dcn4x.d.fclk_pstate); 301 } else if (watermarks->dcn4x.d.fclk_pstate < hubbub2->watermarks.dcn4x.d.fclk_pstate) 302 wm_pending = true; 303 304 return wm_pending; 305 } 306 307 static bool hubbub42_program_usr_watermarks( 308 struct hubbub *hubbub, 309 union dcn_watermark_set *watermarks, 310 bool safe_to_lower) 311 { 312 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 313 bool wm_pending = false; 314 315 /* clock state A */ 316 if (safe_to_lower || watermarks->dcn4x.a.usr > hubbub2->watermarks.dcn4x.a.usr) { 317 hubbub2->watermarks.dcn4x.a.usr = watermarks->dcn4x.a.usr; 318 REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, 0, 319 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, watermarks->dcn4x.a.usr); 320 } else if (watermarks->dcn4x.a.usr < hubbub2->watermarks.dcn4x.a.usr) 321 wm_pending = true; 322 323 /* clock state B */ 324 if (safe_to_lower || watermarks->dcn4x.b.usr > hubbub2->watermarks.dcn4x.b.usr) { 325 hubbub2->watermarks.dcn4x.b.usr = watermarks->dcn4x.b.usr; 326 REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, 0, 327 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, watermarks->dcn4x.b.usr); 328 } else if (watermarks->dcn4x.b.usr < hubbub2->watermarks.dcn4x.b.usr) 329 wm_pending = true; 330 331 /* clock state C */ 332 if (safe_to_lower || watermarks->dcn4x.c.usr > hubbub2->watermarks.dcn4x.c.usr) { 333 hubbub2->watermarks.dcn4x.c.usr = watermarks->dcn4x.c.usr; 334 REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, 0, 335 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, watermarks->dcn4x.c.usr); 336 } else if (watermarks->dcn4x.c.usr < hubbub2->watermarks.dcn4x.c.usr) 337 wm_pending = true; 338 339 /* clock state D */ 340 if (safe_to_lower || watermarks->dcn4x.d.usr > hubbub2->watermarks.dcn4x.d.usr) { 341 hubbub2->watermarks.dcn4x.d.usr = watermarks->dcn4x.d.usr; 342 REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, 0, 343 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, watermarks->dcn4x.d.usr); 344 } else if (watermarks->dcn4x.d.usr < hubbub2->watermarks.dcn4x.d.usr) 345 wm_pending = true; 346 347 return wm_pending; 348 } 349 350 static bool hubbub42_program_stutter_z8_watermarks( 351 struct hubbub *hubbub, 352 union dcn_watermark_set *watermarks, 353 bool safe_to_lower) 354 { 355 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 356 bool wm_pending = false; 357 358 /* clock state A */ 359 if (safe_to_lower || watermarks->dcn4x.a.sr_enter_z8 > hubbub2->watermarks.dcn4x.a.sr_enter_z8) { 360 hubbub2->watermarks.dcn4x.a.sr_enter_z8 = watermarks->dcn4x.a.sr_enter_z8; 361 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, 0, 362 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, watermarks->dcn4x.a.sr_enter_z8); 363 } else if (watermarks->dcn4x.a.sr_enter_z8 < hubbub2->watermarks.dcn4x.a.sr_enter_z8) 364 wm_pending = true; 365 366 if (safe_to_lower || watermarks->dcn4x.a.sr_exit_z8 > hubbub2->watermarks.dcn4x.a.sr_exit_z8) { 367 hubbub2->watermarks.dcn4x.a.sr_exit_z8 = watermarks->dcn4x.a.sr_exit_z8; 368 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, 0, 369 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, watermarks->dcn4x.a.sr_exit_z8); 370 } else if (watermarks->dcn4x.a.sr_exit_z8 < hubbub2->watermarks.dcn4x.a.sr_exit_z8) 371 wm_pending = true; 372 373 /* clock state B */ 374 if (safe_to_lower || watermarks->dcn4x.b.sr_enter_z8 > hubbub2->watermarks.dcn4x.b.sr_enter_z8) { 375 hubbub2->watermarks.dcn4x.b.sr_enter_z8 = watermarks->dcn4x.b.sr_enter_z8; 376 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, 0, 377 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, watermarks->dcn4x.b.sr_enter_z8); 378 } else if (watermarks->dcn4x.b.sr_enter_z8 < hubbub2->watermarks.dcn4x.b.sr_enter_z8) 379 wm_pending = true; 380 381 if (safe_to_lower || watermarks->dcn4x.b.sr_exit_z8 > hubbub2->watermarks.dcn4x.b.sr_exit_z8) { 382 hubbub2->watermarks.dcn4x.b.sr_exit_z8 = watermarks->dcn4x.b.sr_exit_z8; 383 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, 0, 384 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, watermarks->dcn4x.b.sr_exit_z8); 385 } else if (watermarks->dcn4x.b.sr_exit_z8 < hubbub2->watermarks.dcn4x.b.sr_exit_z8) 386 wm_pending = true; 387 388 /* clock state C */ 389 if (safe_to_lower || watermarks->dcn4x.c.sr_enter_z8 > hubbub2->watermarks.dcn4x.c.sr_enter_z8) { 390 hubbub2->watermarks.dcn4x.c.sr_enter_z8 = watermarks->dcn4x.c.sr_enter_z8; 391 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, 0, 392 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, watermarks->dcn4x.c.sr_enter_z8); 393 } else if (watermarks->dcn4x.c.sr_enter_z8 < hubbub2->watermarks.dcn4x.c.sr_enter_z8) 394 wm_pending = true; 395 396 if (safe_to_lower || watermarks->dcn4x.c.sr_exit_z8 > hubbub2->watermarks.dcn4x.c.sr_exit_z8) { 397 hubbub2->watermarks.dcn4x.c.sr_exit_z8 = watermarks->dcn4x.c.sr_exit_z8; 398 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, 0, 399 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, watermarks->dcn4x.c.sr_exit_z8); 400 } else if (watermarks->dcn4x.c.sr_exit_z8 < hubbub2->watermarks.dcn4x.c.sr_exit_z8) 401 wm_pending = true; 402 403 /* clock state D */ 404 if (safe_to_lower || watermarks->dcn4x.d.sr_enter_z8 > hubbub2->watermarks.dcn4x.d.sr_enter_z8) { 405 hubbub2->watermarks.dcn4x.d.sr_enter_z8 = watermarks->dcn4x.d.sr_enter_z8; 406 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, 0, 407 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, watermarks->dcn4x.d.sr_enter_z8); 408 } else if (watermarks->dcn4x.d.sr_enter_z8 < hubbub2->watermarks.dcn4x.d.sr_enter_z8) 409 wm_pending = true; 410 411 if (safe_to_lower || watermarks->dcn4x.d.sr_exit_z8 > hubbub2->watermarks.dcn4x.d.sr_exit_z8) { 412 hubbub2->watermarks.dcn4x.d.sr_exit_z8 = watermarks->dcn4x.d.sr_exit_z8; 413 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, 0, 414 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, watermarks->dcn4x.d.sr_exit_z8); 415 } else if (watermarks->dcn4x.d.sr_exit_z8 < hubbub2->watermarks.dcn4x.d.sr_exit_z8) 416 wm_pending = true; 417 418 return wm_pending; 419 } 420 421 static void hubbub42_allow_self_refresh_control(struct hubbub *hubbub, bool allow) 422 { 423 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 424 425 /* 426 * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 1 means do not allow stutter 427 * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0 means allow stutter 428 */ 429 430 REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, 431 DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0, 432 DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, !allow); 433 } 434 static void hubbub42_set_sdp_control(struct hubbub *hubbub, bool dc_control) 435 { 436 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 437 438 REG_UPDATE(DCHUBBUB_SDPIF_CFG0, 439 SDPIF_PORT_CONTROL, dc_control); 440 } 441 442 static bool hubbub42_program_watermarks( 443 struct hubbub *hubbub, 444 union dcn_watermark_set *watermarks, 445 unsigned int refclk_mhz, 446 bool safe_to_lower) 447 { 448 bool wm_pending = false; 449 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 450 451 if (!safe_to_lower && hubbub->ctx->dc->debug.disable_stutter_for_wm_program) { 452 /* before raising watermarks, SDP control give to DF, stutter must be disabled */ 453 wm_pending = true; 454 hubbub42_set_sdp_control(hubbub, false); 455 hubbub42_allow_self_refresh_control(hubbub, false); 456 } 457 if (hubbub42_program_urgent_watermarks(hubbub, watermarks, safe_to_lower)) 458 wm_pending = true; 459 460 if (hubbub42_program_stutter_watermarks(hubbub, watermarks, safe_to_lower)) 461 wm_pending = true; 462 463 if (hubbub42_program_pstate_watermarks(hubbub, watermarks, safe_to_lower)) 464 wm_pending = true; 465 466 if (hubbub42_program_usr_watermarks(hubbub, watermarks, safe_to_lower)) 467 wm_pending = true; 468 469 if (hubbub42_program_stutter_z8_watermarks(hubbub, watermarks, safe_to_lower)) 470 wm_pending = true; 471 472 REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0, 473 DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); 474 REG_UPDATE_2(DCHUBBUB_ARB_DF_REQ_OUTSTAND, 475 DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0xFF, 476 DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, 0xA);/*hw delta*/ 477 REG_UPDATE(DCHUBBUB_ARB_HOSTVM_CNTL, DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, 0xF); 478 479 if (safe_to_lower || hubbub->ctx->dc->debug.disable_stutter) 480 hubbub42_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); 481 if (safe_to_lower && hubbub->ctx->dc->debug.disable_stutter_for_wm_program) { 482 hubbub42_set_sdp_control(hubbub, true); 483 } 484 hubbub32_force_usr_retraining_allow(hubbub, hubbub->ctx->dc->debug.force_usr_allow); 485 486 return wm_pending; 487 } 488 489 static void hubbub42_set_request_limit(struct hubbub *hubbub, int memory_channel_count, int words_per_channel) 490 { 491 (void)memory_channel_count; 492 (void)words_per_channel; 493 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 494 uint32_t request_limit = 96; //MAX(12 * memory_channel_count, 96); 495 496 REG_UPDATE(SDPIF_REQUEST_RATE_LIMIT, SDPIF_REQUEST_RATE_LIMIT, request_limit); 497 } 498 499 static bool dcn42_program_arbiter(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs, 500 bool safe_to_lower) 501 { 502 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 503 504 bool wm_pending = false; 505 uint32_t temp; 506 507 /* request backpressure and outstanding return threshold (unused)*/ 508 //REG_UPDATE(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_REQ_STALL_THRESHOLD, arb_regs->req_stall_threshold); 509 510 /* 401 delta: do not update P-State stall threshold (handled by fw) */ 511 // REG_UPDATE(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_PSTATE_STALL_THRESHOLD, arb_regs->pstate_stall_threshold); 512 513 if (safe_to_lower || arb_regs->allow_sdpif_rate_limit_when_cstate_req > hubbub2->allow_sdpif_rate_limit_when_cstate_req) { 514 hubbub2->allow_sdpif_rate_limit_when_cstate_req = arb_regs->allow_sdpif_rate_limit_when_cstate_req; 515 516 /* only update the required bits */ 517 REG_GET(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, &temp); 518 if (hubbub2->allow_sdpif_rate_limit_when_cstate_req) { 519 temp |= (1 << 5); 520 } else { 521 temp &= ~(1 << 5); 522 } 523 REG_UPDATE(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, temp); 524 } else { 525 wm_pending = true; 526 } 527 528 return wm_pending; 529 } 530 531 static const struct hubbub_funcs hubbub42_funcs = { 532 .update_dchub = hubbub2_update_dchub, 533 .init_dchub_sys_ctx = hubbub31_init_dchub_sys_ctx, 534 .init_vm_ctx = hubbub2_init_vm_ctx, 535 .dcc_support_swizzle = hubbub3_dcc_support_swizzle, 536 .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format, 537 .get_dcc_compression_cap = hubbub3_get_dcc_compression_cap, 538 .wm_read_state = hubbub35_wm_read_state, 539 .get_dchub_ref_freq = hubbub35_get_dchub_ref_freq, 540 .program_watermarks = hubbub42_program_watermarks, 541 .allow_self_refresh_control = hubbub42_allow_self_refresh_control, 542 .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, 543 .force_wm_propagate_to_pipes = hubbub32_force_wm_propagate_to_pipes, 544 .force_pstate_change_control = hubbub3_force_pstate_change_control, 545 .init_watermarks = hubbub35_init_watermarks, 546 .init_crb = dcn401_init_crb, 547 .dchvm_init = dcn35_dchvm_init, 548 .hubbub_read_state = hubbub2_read_state, 549 .force_usr_retraining_allow = hubbub32_force_usr_retraining_allow, 550 .set_request_limit = hubbub42_set_request_limit, 551 .program_det_segments = dcn401_program_det_segments, 552 .program_compbuf_segments = dcn401_program_compbuf_segments, 553 .wait_for_det_update = dcn401_wait_for_det_update, 554 .program_arbiter = dcn42_program_arbiter, 555 .hubbub_read_reg_state = hubbub3_read_reg_state 556 }; 557 558 void hubbub42_construct(struct dcn20_hubbub *hubbub2, 559 struct dc_context *ctx, 560 const struct dcn_hubbub_registers *hubbub_regs, 561 const struct dcn_hubbub_shift *hubbub_shift, 562 const struct dcn_hubbub_mask *hubbub_mask, 563 int det_size_kb, 564 int pixel_chunk_size_kb, 565 int config_return_buffer_size_kb) 566 { 567 hubbub2->base.ctx = ctx; 568 hubbub2->base.funcs = &hubbub42_funcs; 569 hubbub2->regs = hubbub_regs; 570 hubbub2->shifts = hubbub_shift; 571 hubbub2->masks = hubbub_mask; 572 573 hubbub2->detile_buf_size = det_size_kb * 1024; 574 hubbub2->pixel_chunk_size = pixel_chunk_size_kb * 1024; 575 hubbub2->crb_size_segs = config_return_buffer_size_kb / DCN42_CRB_SEGMENT_SIZE_KB; 576 } 577