1 /* 2 * Copyright 2023 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: AMD 23 * 24 */ 25 26 27 #include "dcn30/dcn30_hubbub.h" 28 #include "dcn401_hubbub.h" 29 #include "dm_services.h" 30 #include "reg_helper.h" 31 32 33 #define CTX \ 34 hubbub2->base.ctx 35 #define DC_LOGGER \ 36 hubbub2->base.ctx->logger 37 #define REG(reg)\ 38 hubbub2->regs->reg 39 40 #undef FN 41 #define FN(reg_name, field_name) \ 42 hubbub2->shifts->field_name, hubbub2->masks->field_name 43 44 static void dcn401_init_crb(struct hubbub *hubbub) 45 { 46 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 47 48 REG_GET(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, 49 &hubbub2->det0_size); 50 51 REG_GET(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, 52 &hubbub2->det1_size); 53 54 REG_GET(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, 55 &hubbub2->det2_size); 56 57 REG_GET(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, 58 &hubbub2->det3_size); 59 60 REG_GET(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT, 61 &hubbub2->compbuf_size_segments); 62 63 REG_SET(COMPBUF_RESERVED_SPACE, 0, 64 COMPBUF_RESERVED_SPACE_64B, hubbub2->pixel_chunk_size / 32); // 256 64Bytes 65 } 66 67 bool hubbub401_program_urgent_watermarks( 68 struct hubbub *hubbub, 69 union dcn_watermark_set *watermarks, 70 unsigned int refclk_mhz, 71 bool safe_to_lower) 72 { 73 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 74 bool wm_pending = false; 75 76 /* Repeat for water mark set A and B */ 77 /* clock state A */ 78 if (safe_to_lower || watermarks->dcn4x.a.urgent > hubbub2->watermarks.dcn4x.a.urgent) { 79 hubbub2->watermarks.dcn4x.a.urgent = watermarks->dcn4x.a.urgent; 80 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0, 81 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, watermarks->dcn4x.a.urgent); 82 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n" 83 "HW register value = 0x%x\n", 84 watermarks->dcn4x.a.urgent, watermarks->dcn4x.a.urgent); 85 } else if (watermarks->dcn4x.a.urgent < hubbub2->watermarks.dcn4x.a.urgent) 86 wm_pending = true; 87 88 /* determine the transfer time for a quantity of data for a particular requestor.*/ 89 if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_flip 90 > hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip) { 91 hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip = watermarks->dcn4x.a.frac_urg_bw_flip; 92 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0, 93 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, watermarks->dcn4x.a.frac_urg_bw_flip); 94 } else if (watermarks->dcn4x.a.frac_urg_bw_flip 95 < hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip) 96 wm_pending = true; 97 98 if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_nom 99 > hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom) { 100 hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom = watermarks->dcn4x.a.frac_urg_bw_nom; 101 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0, 102 DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->dcn4x.a.frac_urg_bw_nom); 103 } else if (watermarks->dcn4x.a.frac_urg_bw_nom 104 < hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom) 105 wm_pending = true; 106 107 if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_mall 108 > hubbub2->watermarks.dcn4x.a.frac_urg_bw_mall) { 109 hubbub2->watermarks.dcn4x.a.frac_urg_bw_mall = watermarks->dcn4x.a.frac_urg_bw_mall; 110 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_MALL_A, 0, 111 DCHUBBUB_ARB_FRAC_URG_BW_MALL_A, watermarks->dcn4x.a.frac_urg_bw_mall); 112 } else if (watermarks->dcn4x.a.frac_urg_bw_mall < hubbub2->watermarks.dcn4x.a.frac_urg_bw_mall) 113 wm_pending = true; 114 115 if (safe_to_lower || watermarks->dcn4x.a.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem) { 116 hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem = watermarks->dcn4x.a.refcyc_per_trip_to_mem; 117 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0, 118 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, watermarks->dcn4x.a.refcyc_per_trip_to_mem); 119 } else if (watermarks->dcn4x.a.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem) 120 wm_pending = true; 121 122 if (safe_to_lower || watermarks->dcn4x.a.refcyc_per_meta_trip_to_mem > hubbub2->watermarks.dcn4x.a.refcyc_per_meta_trip_to_mem) { 123 hubbub2->watermarks.dcn4x.a.refcyc_per_meta_trip_to_mem = watermarks->dcn4x.a.refcyc_per_meta_trip_to_mem; 124 REG_SET(DCHUBBUB_ARB_REFCYC_PER_META_TRIP_A, 0, 125 DCHUBBUB_ARB_REFCYC_PER_META_TRIP_A, watermarks->dcn4x.a.refcyc_per_meta_trip_to_mem); 126 } else if (watermarks->dcn4x.a.refcyc_per_meta_trip_to_mem < hubbub2->watermarks.dcn4x.a.refcyc_per_meta_trip_to_mem) 127 wm_pending = true; 128 129 130 /* clock state B */ 131 if (safe_to_lower || watermarks->dcn4x.b.urgent > hubbub2->watermarks.dcn4x.b.urgent) { 132 hubbub2->watermarks.dcn4x.b.urgent = watermarks->dcn4x.b.urgent; 133 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0, 134 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, watermarks->dcn4x.b.urgent); 135 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n" 136 "HW register value = 0x%x\n", 137 watermarks->dcn4x.b.urgent, watermarks->dcn4x.b.urgent); 138 } else if (watermarks->dcn4x.b.urgent < hubbub2->watermarks.dcn4x.b.urgent) 139 wm_pending = true; 140 141 /* determine the transfer time for a quantity of data for a particular requestor.*/ 142 if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_flip 143 > hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip) { 144 hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip = watermarks->dcn4x.b.frac_urg_bw_flip; 145 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0, 146 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, watermarks->dcn4x.b.frac_urg_bw_flip); 147 } else if (watermarks->dcn4x.b.frac_urg_bw_flip 148 < hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip) 149 wm_pending = true; 150 151 if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_nom 152 > hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom) { 153 hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom = watermarks->dcn4x.b.frac_urg_bw_nom; 154 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0, 155 DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->dcn4x.b.frac_urg_bw_nom); 156 } else if (watermarks->dcn4x.b.frac_urg_bw_nom 157 < hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom) 158 wm_pending = true; 159 160 if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_mall 161 > hubbub2->watermarks.dcn4x.b.frac_urg_bw_mall) { 162 hubbub2->watermarks.dcn4x.b.frac_urg_bw_mall = watermarks->dcn4x.b.frac_urg_bw_mall; 163 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_MALL_B, 0, 164 DCHUBBUB_ARB_FRAC_URG_BW_MALL_B, watermarks->dcn4x.b.frac_urg_bw_mall); 165 } else if (watermarks->dcn4x.b.frac_urg_bw_mall < hubbub2->watermarks.dcn4x.b.frac_urg_bw_mall) 166 wm_pending = true; 167 168 if (safe_to_lower || watermarks->dcn4x.b.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem) { 169 hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem = watermarks->dcn4x.b.refcyc_per_trip_to_mem; 170 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0, 171 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, watermarks->dcn4x.b.refcyc_per_trip_to_mem); 172 } else if (watermarks->dcn4x.b.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem) 173 wm_pending = true; 174 175 if (safe_to_lower || watermarks->dcn4x.b.refcyc_per_meta_trip_to_mem > hubbub2->watermarks.dcn4x.b.refcyc_per_meta_trip_to_mem) { 176 hubbub2->watermarks.dcn4x.b.refcyc_per_meta_trip_to_mem = watermarks->dcn4x.b.refcyc_per_meta_trip_to_mem; 177 REG_SET(DCHUBBUB_ARB_REFCYC_PER_META_TRIP_B, 0, 178 DCHUBBUB_ARB_REFCYC_PER_META_TRIP_B, watermarks->dcn4x.b.refcyc_per_meta_trip_to_mem); 179 } else if (watermarks->dcn4x.b.refcyc_per_meta_trip_to_mem < hubbub2->watermarks.dcn4x.b.refcyc_per_meta_trip_to_mem) 180 wm_pending = true; 181 182 return wm_pending; 183 } 184 185 bool hubbub401_program_stutter_watermarks( 186 struct hubbub *hubbub, 187 union dcn_watermark_set *watermarks, 188 unsigned int refclk_mhz, 189 bool safe_to_lower) 190 { 191 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 192 bool wm_pending = false; 193 194 /* clock state A */ 195 if (safe_to_lower || watermarks->dcn4x.a.sr_enter 196 > hubbub2->watermarks.dcn4x.a.sr_enter) { 197 hubbub2->watermarks.dcn4x.a.sr_enter = 198 watermarks->dcn4x.a.sr_enter; 199 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0, 200 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, watermarks->dcn4x.a.sr_enter); 201 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" 202 "HW register value = 0x%x\n", 203 watermarks->dcn4x.a.sr_enter, watermarks->dcn4x.a.sr_enter); 204 // On dGPU Z states are N/A, so program all other 3 Stutter Enter wm A with the same value 205 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK1_A, 0, 206 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK1_A, watermarks->dcn4x.a.sr_enter); 207 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK2_A, 0, 208 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK2_A, watermarks->dcn4x.a.sr_enter); 209 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK3_A, 0, 210 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK3_A, watermarks->dcn4x.a.sr_enter); 211 212 } else if (watermarks->dcn4x.a.sr_enter 213 < hubbub2->watermarks.dcn4x.a.sr_enter) 214 wm_pending = true; 215 216 if (safe_to_lower || watermarks->dcn4x.a.sr_exit 217 > hubbub2->watermarks.dcn4x.a.sr_exit) { 218 hubbub2->watermarks.dcn4x.a.sr_exit = 219 watermarks->dcn4x.a.sr_exit; 220 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0, 221 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, watermarks->dcn4x.a.sr_exit); 222 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n" 223 "HW register value = 0x%x\n", 224 watermarks->dcn4x.a.sr_exit, watermarks->dcn4x.a.sr_exit); 225 // On dGPU Z states are N/A, so program all other 3 Stutter Exit wm A with the same value 226 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK1_A, 0, 227 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK1_A, watermarks->dcn4x.a.sr_exit); 228 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK2_A, 0, 229 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK2_A, watermarks->dcn4x.a.sr_exit); 230 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK3_A, 0, 231 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK3_A, watermarks->dcn4x.a.sr_exit); 232 233 } else if (watermarks->dcn4x.a.sr_exit 234 < hubbub2->watermarks.dcn4x.a.sr_exit) 235 wm_pending = true; 236 237 /* clock state B */ 238 if (safe_to_lower || watermarks->dcn4x.b.sr_enter 239 > hubbub2->watermarks.dcn4x.b.sr_enter) { 240 hubbub2->watermarks.dcn4x.b.sr_enter = 241 watermarks->dcn4x.b.sr_enter; 242 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0, 243 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, watermarks->dcn4x.b.sr_enter); 244 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n" 245 "HW register value = 0x%x\n", 246 watermarks->dcn4x.b.sr_enter, watermarks->dcn4x.b.sr_enter); 247 // On dGPU Z states are N/A, so program all other 3 Stutter Enter wm A with the same value 248 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK1_B, 0, 249 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK1_B, watermarks->dcn4x.b.sr_enter); 250 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK2_B, 0, 251 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK2_B, watermarks->dcn4x.b.sr_enter); 252 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK3_B, 0, 253 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK3_B, watermarks->dcn4x.b.sr_enter); 254 255 } else if (watermarks->dcn4x.b.sr_enter 256 < hubbub2->watermarks.dcn4x.b.sr_enter) 257 wm_pending = true; 258 259 if (safe_to_lower || watermarks->dcn4x.b.sr_exit 260 > hubbub2->watermarks.dcn4x.b.sr_exit) { 261 hubbub2->watermarks.dcn4x.b.sr_exit = 262 watermarks->dcn4x.b.sr_exit; 263 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0, 264 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, watermarks->dcn4x.b.sr_exit); 265 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n" 266 "HW register value = 0x%x\n", 267 watermarks->dcn4x.b.sr_exit, watermarks->dcn4x.b.sr_exit); 268 // On dGPU Z states are N/A, so program all other 3 Stutter Exit wm A with the same value 269 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK1_B, 0, 270 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK1_B, watermarks->dcn4x.b.sr_exit); 271 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK2_B, 0, 272 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK2_B, watermarks->dcn4x.b.sr_exit); 273 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK3_B, 0, 274 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK3_B, watermarks->dcn4x.b.sr_exit); 275 276 } else if (watermarks->dcn4x.b.sr_exit 277 < hubbub2->watermarks.dcn4x.b.sr_exit) 278 wm_pending = true; 279 280 return wm_pending; 281 } 282 283 284 bool hubbub401_program_pstate_watermarks( 285 struct hubbub *hubbub, 286 union dcn_watermark_set *watermarks, 287 unsigned int refclk_mhz, 288 bool safe_to_lower) 289 { 290 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 291 bool wm_pending = false; 292 293 /* Section for UCLK_PSTATE_CHANGE_WATERMARKS */ 294 /* clock state A */ 295 if (safe_to_lower || watermarks->dcn4x.a.uclk_pstate 296 > hubbub2->watermarks.dcn4x.a.uclk_pstate) { 297 hubbub2->watermarks.dcn4x.a.uclk_pstate = 298 watermarks->dcn4x.a.uclk_pstate; 299 REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, 0, 300 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, watermarks->dcn4x.a.uclk_pstate); 301 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n" 302 "HW register value = 0x%x\n\n", 303 watermarks->dcn4x.a.uclk_pstate, watermarks->dcn4x.a.uclk_pstate); 304 } else if (watermarks->dcn4x.a.uclk_pstate 305 < hubbub2->watermarks.dcn4x.a.uclk_pstate) 306 wm_pending = true; 307 308 /* clock state B */ 309 if (safe_to_lower || watermarks->dcn4x.b.uclk_pstate 310 > hubbub2->watermarks.dcn4x.b.uclk_pstate) { 311 hubbub2->watermarks.dcn4x.b.uclk_pstate = 312 watermarks->dcn4x.b.uclk_pstate; 313 REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, 0, 314 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, watermarks->dcn4x.b.uclk_pstate); 315 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n" 316 "HW register value = 0x%x\n\n", 317 watermarks->dcn4x.b.uclk_pstate, watermarks->dcn4x.b.uclk_pstate); 318 } else if (watermarks->dcn4x.b.uclk_pstate 319 < hubbub2->watermarks.dcn4x.b.uclk_pstate) 320 wm_pending = true; 321 322 /* Section for UCLK_PSTATE_CHANGE_WATERMARKS1 (DUMMY_PSTATE/TEMP_READ/PPT) */ 323 if (safe_to_lower || watermarks->dcn4x.a.temp_read_or_ppt 324 > hubbub2->watermarks.dcn4x.a.temp_read_or_ppt) { 325 hubbub2->watermarks.dcn4x.a.temp_read_or_ppt = 326 watermarks->dcn4x.a.temp_read_or_ppt; 327 REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK1_A, 0, 328 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK1_A, watermarks->dcn4x.a.temp_read_or_ppt); 329 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK1_A calculated =%d\n" 330 "HW register value = 0x%x\n\n", 331 watermarks->dcn4x.a.temp_read_or_ppt, watermarks->dcn4x.a.temp_read_or_ppt); 332 } else if (watermarks->dcn4x.a.temp_read_or_ppt 333 < hubbub2->watermarks.dcn4x.a.temp_read_or_ppt) 334 wm_pending = true; 335 336 /* clock state B */ 337 if (safe_to_lower || watermarks->dcn4x.b.temp_read_or_ppt 338 > hubbub2->watermarks.dcn4x.b.temp_read_or_ppt) { 339 hubbub2->watermarks.dcn4x.b.temp_read_or_ppt = 340 watermarks->dcn4x.b.temp_read_or_ppt; 341 REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK1_B, 0, 342 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK1_B, watermarks->dcn4x.b.temp_read_or_ppt); 343 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK1_B calculated =%d\n" 344 "HW register value = 0x%x\n\n", 345 watermarks->dcn4x.b.temp_read_or_ppt, watermarks->dcn4x.b.temp_read_or_ppt); 346 } else if (watermarks->dcn4x.b.temp_read_or_ppt 347 < hubbub2->watermarks.dcn4x.b.temp_read_or_ppt) 348 wm_pending = true; 349 350 /* Section for FCLK_PSTATE_CHANGE_WATERMARKS */ 351 /* clock state A */ 352 if (safe_to_lower || watermarks->dcn4x.a.fclk_pstate 353 > hubbub2->watermarks.dcn4x.a.fclk_pstate) { 354 hubbub2->watermarks.dcn4x.a.fclk_pstate = 355 watermarks->dcn4x.a.fclk_pstate; 356 REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, 0, 357 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, watermarks->dcn4x.a.fclk_pstate); 358 DC_LOG_BANDWIDTH_CALCS("FCLK_CHANGE_WATERMARK_A calculated =%d\n" 359 "HW register value = 0x%x\n\n", 360 watermarks->dcn4x.a.fclk_pstate, watermarks->dcn4x.a.fclk_pstate); 361 } else if (watermarks->dcn4x.a.fclk_pstate 362 < hubbub2->watermarks.dcn4x.a.fclk_pstate) 363 wm_pending = true; 364 365 /* clock state B */ 366 if (safe_to_lower || watermarks->dcn4x.b.fclk_pstate 367 > hubbub2->watermarks.dcn4x.b.fclk_pstate) { 368 hubbub2->watermarks.dcn4x.b.fclk_pstate = 369 watermarks->dcn4x.b.fclk_pstate; 370 REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, 0, 371 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, watermarks->dcn4x.b.fclk_pstate); 372 DC_LOG_BANDWIDTH_CALCS("FCLK_CHANGE_WATERMARK_B calculated =%d\n" 373 "HW register value = 0x%x\n\n", 374 watermarks->dcn4x.b.fclk_pstate, watermarks->dcn4x.b.fclk_pstate); 375 } else if (watermarks->dcn4x.b.fclk_pstate 376 < hubbub2->watermarks.dcn4x.b.fclk_pstate) 377 wm_pending = true; 378 379 /* Section for FCLK_CHANGE_WATERMARKS1 (DUMMY_PSTATE/TEMP_READ/PPT) */ 380 if (safe_to_lower || watermarks->dcn4x.a.temp_read_or_ppt 381 > hubbub2->watermarks.dcn4x.a.temp_read_or_ppt) { 382 hubbub2->watermarks.dcn4x.a.temp_read_or_ppt = 383 watermarks->dcn4x.a.temp_read_or_ppt; 384 REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK1_A, 0, 385 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK1_A, watermarks->dcn4x.a.temp_read_or_ppt); 386 DC_LOG_BANDWIDTH_CALCS("FCLK_CHANGE_WATERMARK1_A calculated =%d\n" 387 "HW register value = 0x%x\n\n", 388 watermarks->dcn4x.a.temp_read_or_ppt, watermarks->dcn4x.a.temp_read_or_ppt); 389 } else if (watermarks->dcn4x.a.temp_read_or_ppt 390 < hubbub2->watermarks.dcn4x.a.temp_read_or_ppt) 391 wm_pending = true; 392 393 /* clock state B */ 394 if (safe_to_lower || watermarks->dcn4x.b.temp_read_or_ppt 395 > hubbub2->watermarks.dcn4x.b.temp_read_or_ppt) { 396 hubbub2->watermarks.dcn4x.b.temp_read_or_ppt = 397 watermarks->dcn4x.b.temp_read_or_ppt; 398 REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK1_B, 0, 399 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK1_B, watermarks->dcn4x.b.temp_read_or_ppt); 400 DC_LOG_BANDWIDTH_CALCS("FCLK_CHANGE_WATERMARK1_B calculated =%d\n" 401 "HW register value = 0x%x\n\n", 402 watermarks->dcn4x.b.temp_read_or_ppt, watermarks->dcn4x.b.temp_read_or_ppt); 403 } else if (watermarks->dcn4x.b.temp_read_or_ppt 404 < hubbub2->watermarks.dcn4x.b.temp_read_or_ppt) 405 wm_pending = true; 406 407 return wm_pending; 408 } 409 410 411 bool hubbub401_program_usr_watermarks( 412 struct hubbub *hubbub, 413 union dcn_watermark_set *watermarks, 414 unsigned int refclk_mhz, 415 bool safe_to_lower) 416 { 417 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 418 bool wm_pending = false; 419 420 /* clock state A */ 421 if (safe_to_lower || watermarks->dcn4x.a.usr 422 > hubbub2->watermarks.dcn4x.a.usr) { 423 hubbub2->watermarks.dcn4x.a.usr = watermarks->dcn4x.a.usr; 424 REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, 0, 425 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, watermarks->dcn4x.a.usr); 426 DC_LOG_BANDWIDTH_CALCS("USR_RETRAINING_WATERMARK_A calculated =%d\n" 427 "HW register value = 0x%x\n\n", 428 watermarks->dcn4x.a.usr, watermarks->dcn4x.a.usr); 429 } else if (watermarks->dcn4x.a.usr 430 < hubbub2->watermarks.dcn4x.a.usr) 431 wm_pending = true; 432 433 /* clock state B */ 434 if (safe_to_lower || watermarks->dcn4x.b.usr 435 > hubbub2->watermarks.dcn4x.b.usr) { 436 hubbub2->watermarks.dcn4x.b.usr = watermarks->dcn4x.b.usr; 437 REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, 0, 438 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, watermarks->dcn4x.b.usr); 439 DC_LOG_BANDWIDTH_CALCS("USR_RETRAINING_WATERMARK_B calculated =%d\n" 440 "HW register value = 0x%x\n\n", 441 watermarks->dcn4x.b.usr, watermarks->dcn4x.b.usr); 442 } else if (watermarks->dcn4x.b.usr 443 < hubbub2->watermarks.dcn4x.b.usr) 444 wm_pending = true; 445 446 return wm_pending; 447 } 448 449 450 static bool hubbub401_program_watermarks( 451 struct hubbub *hubbub, 452 union dcn_watermark_set *watermarks, 453 unsigned int refclk_mhz, 454 bool safe_to_lower) 455 { 456 bool wm_pending = false; 457 458 if (hubbub401_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) 459 wm_pending = true; 460 461 if (hubbub401_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) 462 wm_pending = true; 463 464 if (hubbub401_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) 465 wm_pending = true; 466 467 if (hubbub401_program_usr_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) 468 wm_pending = true; 469 470 /* 471 * The DCHub arbiter has a mechanism to dynamically rate limit the DCHub request stream to the fabric. 472 * If the memory controller is fully utilized and the DCHub requestors are 473 * well ahead of their amortized schedule, then it is safe to prevent the next winner 474 * from being committed and sent to the fabric. 475 * The utilization of the memory controller is approximated by ensuring that 476 * the number of outstanding requests is greater than a threshold specified 477 * by the ARB_MIN_REQ_OUTSTANDING. To determine that the DCHub requestors are well ahead of the amortized 478 * schedule, the slack of the next winner is compared with the ARB_SAT_LEVEL in DLG RefClk cycles. 479 * 480 * TODO: Revisit request limit after figure out right number. request limit for RM isn't decided yet, 481 * set maximum value (0x1FF) to turn off it for now. 482 */ 483 /*REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0, 484 DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); 485 REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, 486 DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF); 487 */ 488 489 hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); 490 491 hubbub32_force_usr_retraining_allow(hubbub, hubbub->ctx->dc->debug.force_usr_allow); 492 493 return wm_pending; 494 } 495 496 /* Copy values from WM set A to all other sets */ 497 static void hubbub401_init_watermarks(struct hubbub *hubbub) 498 { 499 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 500 uint32_t reg; 501 502 reg = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A); 503 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, reg); 504 505 reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A); 506 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, reg); 507 508 reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A); 509 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, reg); 510 511 reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_MALL_A); 512 REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_MALL_B, reg); 513 514 reg = REG_READ(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A); 515 REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, reg); 516 517 reg = REG_READ(DCHUBBUB_ARB_REFCYC_PER_META_TRIP_A); 518 REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_META_TRIP_B, reg); 519 520 reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A); 521 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, reg); 522 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK1_A, reg); 523 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK1_B, reg); 524 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK2_A, reg); 525 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK2_B, reg); 526 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK3_A, reg); 527 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK3_B, reg); 528 529 reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A); 530 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, reg); 531 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK1_A, reg); 532 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK1_B, reg); 533 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK2_A, reg); 534 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK2_B, reg); 535 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK3_A, reg); 536 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK3_B, reg); 537 538 reg = REG_READ(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A); 539 REG_WRITE(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, reg); 540 541 reg = REG_READ(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A); 542 REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, reg); 543 reg = REG_READ(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK1_A); 544 REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK1_B, reg); 545 546 reg = REG_READ(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A); 547 REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, reg); 548 reg = REG_READ(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK1_A); 549 REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK1_B, reg); 550 } 551 552 static void hubbub401_wm_read_state(struct hubbub *hubbub, 553 struct dcn_hubbub_wm *wm) 554 { 555 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 556 struct dcn_hubbub_wm_set *s; 557 558 memset(wm, 0, sizeof(struct dcn_hubbub_wm)); 559 560 s = &wm->sets[0]; 561 s->wm_set = 0; 562 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 563 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, &s->data_urgent); 564 565 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 566 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, &s->sr_enter); 567 568 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 569 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, &s->sr_exit); 570 571 REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, 572 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, &s->dram_clk_change); 573 574 REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, 575 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, &s->usr_retrain); 576 577 REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, 578 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, &s->fclk_pstate_change); 579 580 s = &wm->sets[1]; 581 s->wm_set = 1; 582 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 583 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, &s->data_urgent); 584 585 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 586 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, &s->sr_enter); 587 588 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 589 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, &s->sr_exit); 590 591 REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, 592 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, &s->dram_clk_change); 593 594 REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, 595 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, &s->usr_retrain); 596 597 REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, 598 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, &s->fclk_pstate_change); 599 } 600 601 bool hubbub401_dcc_support_swizzle( 602 enum swizzle_mode_addr3_values swizzle, 603 unsigned int plane_pitch, 604 unsigned int bytes_per_element, 605 enum segment_order *segment_order_horz, 606 enum segment_order *segment_order_vert) 607 { 608 bool swizzle_supported = false; 609 610 switch (swizzle) { 611 case DC_ADDR3_SW_LINEAR: 612 if ((plane_pitch * bytes_per_element) % 256 == 0) 613 swizzle_supported = true; 614 break; 615 case DC_ADDR3_SW_64KB_2D: 616 case DC_ADDR3_SW_256KB_2D: 617 swizzle_supported = true; 618 break; 619 default: 620 swizzle_supported = false; 621 break; 622 } 623 624 if (swizzle_supported) { 625 if (bytes_per_element == 1) { 626 *segment_order_horz = segment_order__contiguous; 627 *segment_order_vert = segment_order__non_contiguous; 628 return true; 629 } 630 if (bytes_per_element == 2) { 631 *segment_order_horz = segment_order__non_contiguous; 632 *segment_order_vert = segment_order__contiguous; 633 return true; 634 } 635 if (bytes_per_element == 4) { 636 *segment_order_horz = segment_order__contiguous; 637 *segment_order_vert = segment_order__non_contiguous; 638 return true; 639 } 640 if (bytes_per_element == 8) { 641 *segment_order_horz = segment_order__contiguous; 642 *segment_order_vert = segment_order__non_contiguous; 643 return true; 644 } 645 } 646 647 return false; 648 } 649 650 bool hubbub401_dcc_support_pixel_format( 651 enum surface_pixel_format format, 652 unsigned int *plane0_bpe, 653 unsigned int *plane1_bpe) 654 { 655 switch (format) { 656 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 657 case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 658 *plane0_bpe = 2; 659 *plane1_bpe = 0; 660 return true; 661 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 662 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 663 *plane0_bpe = 1; 664 *plane1_bpe = 2; 665 return true; 666 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 667 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 668 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 669 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 670 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 671 case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX: 672 case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX: 673 case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT: 674 case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT: 675 case SURFACE_PIXEL_FORMAT_GRPH_RGBE: 676 *plane0_bpe = 4; 677 *plane1_bpe = 0; 678 return true; 679 case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: 680 *plane0_bpe = 4; 681 *plane1_bpe = 1; 682 return true; 683 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 684 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 685 *plane0_bpe = 2; 686 *plane1_bpe = 4; 687 return true; 688 case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010: 689 case SURFACE_PIXEL_FORMAT_VIDEO_CrYCbA1010102: 690 case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888: 691 *plane0_bpe = 4; 692 *plane1_bpe = 0; 693 return true; 694 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 695 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: 696 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 697 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 698 *plane0_bpe = 8; 699 *plane1_bpe = 0; 700 return true; 701 default: 702 return false; 703 } 704 } 705 706 void hubbub401_get_blk256_size(unsigned int *blk256_width, unsigned int *blk256_height, 707 unsigned int bytes_per_element) 708 { 709 if (bytes_per_element == 1) { 710 *blk256_width = 16; 711 *blk256_height = 16; 712 } else if (bytes_per_element == 2) { 713 *blk256_width = 16; 714 *blk256_height = 8; 715 } else if (bytes_per_element == 4) { 716 *blk256_width = 8; 717 *blk256_height = 8; 718 } else if (bytes_per_element == 8) { 719 *blk256_width = 8; 720 *blk256_height = 4; 721 } 722 } 723 724 void hubbub401_det_request_size( 725 unsigned int detile_buf_size, 726 enum surface_pixel_format format, 727 unsigned int p0_height, 728 unsigned int p0_width, 729 unsigned int p0_bpe, 730 unsigned int p1_height, 731 unsigned int p1_width, 732 unsigned int p1_bpe, 733 bool *p0_req128_horz_wc, 734 bool *p0_req128_vert_wc, 735 bool *p1_req128_horz_wc, 736 bool *p1_req128_vert_wc) 737 { 738 unsigned int blk256_height = 0; 739 unsigned int blk256_width = 0; 740 unsigned int p0_swath_bytes_horz_wc, p0_swath_bytes_vert_wc; 741 unsigned int p1_swath_bytes_horz_wc, p1_swath_bytes_vert_wc; 742 743 //For plane0 744 hubbub401_get_blk256_size(&blk256_width, &blk256_height, p0_bpe); 745 746 p0_swath_bytes_horz_wc = p0_width * blk256_height * p0_bpe; 747 p0_swath_bytes_vert_wc = p0_height * blk256_width * p0_bpe; 748 749 *p0_req128_horz_wc = (2 * p0_swath_bytes_horz_wc <= detile_buf_size) ? 750 false : /* full 256B request */ 751 true; /* half 128b request */ 752 753 *p0_req128_vert_wc = (2 * p0_swath_bytes_vert_wc <= detile_buf_size) ? 754 false : /* full 256B request */ 755 true; /* half 128b request */ 756 757 /*For dual planes needs to be considered together */ 758 if (p1_bpe) { 759 hubbub401_get_blk256_size(&blk256_width, &blk256_height, p1_bpe); 760 761 p1_swath_bytes_horz_wc = p1_width * blk256_height * p1_bpe; 762 p1_swath_bytes_vert_wc = p1_height * blk256_width * p1_bpe; 763 764 switch (format) { 765 default: 766 /* No any adjustment needed*/ 767 break; 768 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 769 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 770 /* Packing at the ratio of 3:2 is supported before the detile buffer 771 * for YUV420 video with 10bpc (P010). Need to adjust for that. 772 */ 773 p0_swath_bytes_horz_wc = (((p0_swath_bytes_horz_wc * 2) / 3 + 255) / 256) * 256; 774 p0_swath_bytes_vert_wc = (((p0_swath_bytes_vert_wc * 2) / 3 + 255) / 256) * 256; 775 p1_swath_bytes_horz_wc = (((p1_swath_bytes_horz_wc * 2) / 3 + 255) / 256) * 256; 776 p1_swath_bytes_vert_wc = (((p1_swath_bytes_vert_wc * 2) / 3 + 255) / 256) * 256; 777 break; 778 } 779 780 *p0_req128_horz_wc = *p1_req128_horz_wc = (2 * p0_swath_bytes_horz_wc + 781 2 * p1_swath_bytes_horz_wc <= detile_buf_size) ? 782 false : /* full 256B request */ 783 true; /* half 128B request */ 784 785 *p0_req128_vert_wc = *p1_req128_vert_wc = (2 * p0_swath_bytes_vert_wc + 786 2 * p1_swath_bytes_vert_wc <= detile_buf_size) ? 787 false : /* full 256B request */ 788 true; /* half 128B request */ 789 790 /* If 128B requests are true, meaning 2 full swaths of data cannot fit 791 * in de-tile buffer, check if one plane can use 256B request while 792 * the other plane is using 128B requests 793 */ 794 if (*p0_req128_horz_wc) { 795 // If ratio around 1:1 between p0 and p1 try to recalulate if p0 can use 256B 796 if (p0_swath_bytes_horz_wc <= p1_swath_bytes_horz_wc + p1_swath_bytes_horz_wc / 2) { 797 798 *p0_req128_horz_wc = (2 * p0_swath_bytes_horz_wc + p1_swath_bytes_horz_wc <= detile_buf_size) ? 799 false : /* full 256B request */ 800 true; /* half 128b request */ 801 802 } else { 803 /* ratio about 2:1 between p0 and p1, try to recalulate if p1 can use 256B */ 804 *p1_req128_horz_wc = (p0_swath_bytes_horz_wc + 2 * p1_swath_bytes_horz_wc <= detile_buf_size) ? 805 false : /* full 256B request */ 806 true; /* half 128b request */ 807 } 808 } 809 810 if (*p0_req128_vert_wc) { 811 // If ratio around 1:1 between p0 and p1 try to recalulate if p0 can use 256B 812 if (p0_swath_bytes_vert_wc <= p1_swath_bytes_vert_wc + p1_swath_bytes_vert_wc / 2) { 813 814 *p0_req128_vert_wc = (2 * p0_swath_bytes_vert_wc + p1_swath_bytes_vert_wc <= detile_buf_size) ? 815 false : /* full 256B request */ 816 true; /* half 128b request */ 817 818 } else { 819 /* ratio about 2:1 between p0 and p1, try to recalulate if p1 can use 256B */ 820 *p1_req128_vert_wc = (p0_swath_bytes_vert_wc + 2 * p1_swath_bytes_vert_wc <= detile_buf_size) ? 821 false : /* full 256B request */ 822 true; /* half 128b request */ 823 } 824 } 825 } 826 } 827 bool hubbub401_get_dcc_compression_cap(struct hubbub *hubbub, 828 const struct dc_dcc_surface_param *input, 829 struct dc_surface_dcc_cap *output) 830 { 831 struct dc *dc = hubbub->ctx->dc; 832 const unsigned int max_dcc_plane_width = dc->caps.dcc_plane_width_limit; 833 /* DCN4_Programming_Guide_DCHUB.docx, Section 5.11.2.2 */ 834 enum dcc_control dcc_control; 835 unsigned int plane0_bpe, plane1_bpe; 836 enum segment_order segment_order_horz, segment_order_vert; 837 enum segment_order p1_segment_order_horz, p1_segment_order_vert; 838 bool req128_horz_wc, req128_vert_wc; 839 unsigned int plane0_width = 0, plane0_height = 0, plane1_width = 0, plane1_height = 0; 840 bool p1_req128_horz_wc, p1_req128_vert_wc, is_dual_plane; 841 842 memset(output, 0, sizeof(*output)); 843 844 if (dc->debug.disable_dcc == DCC_DISABLE) 845 return false; 846 847 /* Conservatively disable DCC for cases where ODM4:1 may be required. */ 848 if (max_dcc_plane_width != 0 && 849 (input->surface_size.width > max_dcc_plane_width || input->plane1_size.width > max_dcc_plane_width)) 850 return false; 851 852 switch (input->format) { 853 default: 854 is_dual_plane = false; 855 856 plane1_width = 0; 857 plane1_height = 0; 858 859 if (input->surface_size.width > 6144 + 16) 860 plane0_width = 6160; 861 else 862 plane0_width = input->surface_size.width; 863 864 if (input->surface_size.height > 6144 + 16) 865 plane0_height = 6160; 866 else 867 plane0_height = input->surface_size.height; 868 869 break; 870 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 871 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 872 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 873 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 874 is_dual_plane = true; 875 876 if (input->surface_size.width > 7680 + 16) 877 plane0_width = 7696; 878 else 879 plane0_width = input->surface_size.width; 880 881 if (input->surface_size.height > 4320 + 16) 882 plane0_height = 4336; 883 else 884 plane0_height = input->surface_size.height; 885 886 if (input->plane1_size.width > 7680 + 16) 887 plane1_width = 7696 / 2; 888 else 889 plane1_width = input->plane1_size.width; 890 891 if (input->plane1_size.height > 4320 + 16) 892 plane1_height = 4336 / 2; 893 else 894 plane1_height = input->plane1_size.height; 895 896 break; 897 898 case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: 899 is_dual_plane = true; 900 901 if (input->surface_size.width > 5120 + 16) 902 plane0_width = 5136; 903 else 904 plane0_width = input->surface_size.width; 905 906 if (input->surface_size.height > 5120 + 16) 907 plane0_height = 5136; 908 else 909 plane0_height = input->surface_size.height; 910 911 if (input->plane1_size.width > 5120 + 16) 912 plane1_width = 5136; 913 else 914 plane1_width = input->plane1_size.width; 915 916 if (input->plane1_size.height > 5120 + 16) 917 plane1_height = 5136; 918 else 919 plane1_height = input->plane1_size.height; 920 921 break; 922 } 923 924 if (!hubbub->funcs->dcc_support_pixel_format_plane0_plane1(input->format, 925 &plane0_bpe, &plane1_bpe)) 926 return false; 927 928 /* Find plane0 DCC Controls */ 929 if (!is_dual_plane) { 930 931 if (!hubbub->funcs->dcc_support_swizzle_addr3(input->swizzle_mode_addr3, 932 input->plane0_pitch, plane0_bpe, 933 &segment_order_horz, &segment_order_vert)) 934 return false; 935 936 hubbub401_det_request_size(TO_DCN20_HUBBUB(hubbub)->detile_buf_size, input->format, 937 plane0_height, plane0_width, plane0_bpe, 938 plane1_height, plane1_width, plane1_bpe, 939 &req128_horz_wc, &req128_vert_wc, &p1_req128_horz_wc, &p1_req128_vert_wc); 940 941 if (!req128_horz_wc && !req128_vert_wc) { 942 dcc_control = dcc_control__256_256; 943 } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) { 944 if (!req128_horz_wc) 945 dcc_control = dcc_control__256_256; 946 else if (segment_order_horz == segment_order__contiguous) 947 dcc_control = dcc_control__256_128; 948 else 949 dcc_control = dcc_control__256_64; 950 } else if (input->scan == SCAN_DIRECTION_VERTICAL) { 951 if (!req128_vert_wc) 952 dcc_control = dcc_control__256_256; 953 else if (segment_order_vert == segment_order__contiguous) 954 dcc_control = dcc_control__256_128; 955 else 956 dcc_control = dcc_control__256_64; 957 } else { 958 if ((req128_horz_wc && 959 segment_order_horz == segment_order__non_contiguous) || 960 (req128_vert_wc && 961 segment_order_vert == segment_order__non_contiguous)) 962 /* access_dir not known, must use most constraining */ 963 dcc_control = dcc_control__256_64; 964 else 965 /* req128 is true for either horz and vert 966 * but segment_order is contiguous 967 */ 968 dcc_control = dcc_control__256_128; 969 } 970 971 if (dc->debug.disable_dcc == DCC_HALF_REQ_DISALBE && 972 dcc_control != dcc_control__256_256) 973 return false; 974 975 switch (dcc_control) { 976 case dcc_control__256_256: 977 output->grph.rgb.dcc_controls.dcc_256_256 = 1; 978 output->grph.rgb.dcc_controls.dcc_256_128 = 1; 979 output->grph.rgb.dcc_controls.dcc_256_64 = 1; 980 break; 981 case dcc_control__256_128: 982 output->grph.rgb.dcc_controls.dcc_256_128 = 1; 983 output->grph.rgb.dcc_controls.dcc_256_64 = 1; 984 break; 985 case dcc_control__256_64: 986 output->grph.rgb.dcc_controls.dcc_256_64 = 1; 987 break; 988 default: 989 /* Shouldn't get here */ 990 ASSERT(0); 991 break; 992 } 993 } else { 994 /* For dual plane cases, need to examine both planes together */ 995 if (!hubbub->funcs->dcc_support_swizzle_addr3(input->swizzle_mode_addr3, 996 input->plane0_pitch, plane0_bpe, 997 &segment_order_horz, &segment_order_vert)) 998 return false; 999 1000 if (!hubbub->funcs->dcc_support_swizzle_addr3(input->swizzle_mode_addr3, 1001 input->plane1_pitch, plane1_bpe, 1002 &p1_segment_order_horz, &p1_segment_order_vert)) 1003 return false; 1004 1005 hubbub401_det_request_size(TO_DCN20_HUBBUB(hubbub)->detile_buf_size, input->format, 1006 plane0_height, plane0_width, plane0_bpe, 1007 plane1_height, plane1_width, plane1_bpe, 1008 &req128_horz_wc, &req128_vert_wc, &p1_req128_horz_wc, &p1_req128_vert_wc); 1009 1010 /* Determine Plane 0 DCC Controls */ 1011 if (!req128_horz_wc && !req128_vert_wc) { 1012 dcc_control = dcc_control__256_256; 1013 } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) { 1014 if (!req128_horz_wc) 1015 dcc_control = dcc_control__256_256; 1016 else if (segment_order_horz == segment_order__contiguous) 1017 dcc_control = dcc_control__256_128; 1018 else 1019 dcc_control = dcc_control__256_64; 1020 } else if (input->scan == SCAN_DIRECTION_VERTICAL) { 1021 if (!req128_vert_wc) 1022 dcc_control = dcc_control__256_256; 1023 else if (segment_order_vert == segment_order__contiguous) 1024 dcc_control = dcc_control__256_128; 1025 else 1026 dcc_control = dcc_control__256_64; 1027 } else { 1028 if ((req128_horz_wc && 1029 segment_order_horz == segment_order__non_contiguous) || 1030 (req128_vert_wc && 1031 segment_order_vert == segment_order__non_contiguous)) 1032 /* access_dir not known, must use most constraining */ 1033 dcc_control = dcc_control__256_64; 1034 else 1035 /* req128 is true for either horz and vert 1036 * but segment_order is contiguous 1037 */ 1038 dcc_control = dcc_control__256_128; 1039 } 1040 1041 switch (dcc_control) { 1042 case dcc_control__256_256: 1043 output->video.luma.dcc_controls.dcc_256_256 = 1; 1044 output->video.luma.dcc_controls.dcc_256_128 = 1; 1045 output->video.luma.dcc_controls.dcc_256_64 = 1; 1046 break; 1047 case dcc_control__256_128: 1048 output->video.luma.dcc_controls.dcc_256_128 = 1; 1049 output->video.luma.dcc_controls.dcc_256_64 = 1; 1050 break; 1051 case dcc_control__256_64: 1052 output->video.luma.dcc_controls.dcc_256_64 = 1; 1053 break; 1054 default: 1055 ASSERT(0); 1056 break; 1057 } 1058 1059 /* Determine Plane 1 DCC Controls */ 1060 if (!p1_req128_horz_wc && !p1_req128_vert_wc) { 1061 dcc_control = dcc_control__256_256; 1062 } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) { 1063 if (!p1_req128_horz_wc) 1064 dcc_control = dcc_control__256_256; 1065 else if (p1_segment_order_horz == segment_order__contiguous) 1066 dcc_control = dcc_control__256_128; 1067 else 1068 dcc_control = dcc_control__256_64; 1069 } else if (input->scan == SCAN_DIRECTION_VERTICAL) { 1070 if (!p1_req128_vert_wc) 1071 dcc_control = dcc_control__256_256; 1072 else if (p1_segment_order_vert == segment_order__contiguous) 1073 dcc_control = dcc_control__256_128; 1074 else 1075 dcc_control = dcc_control__256_64; 1076 } else { 1077 if ((p1_req128_horz_wc && 1078 p1_segment_order_horz == segment_order__non_contiguous) || 1079 (p1_req128_vert_wc && 1080 p1_segment_order_vert == segment_order__non_contiguous)) 1081 /* access_dir not known, must use most constraining */ 1082 dcc_control = dcc_control__256_64; 1083 else 1084 /* req128 is true for either horz and vert 1085 * but segment_order is contiguous 1086 */ 1087 dcc_control = dcc_control__256_128; 1088 } 1089 1090 switch (dcc_control) { 1091 case dcc_control__256_256: 1092 output->video.chroma.dcc_controls.dcc_256_256 = 1; 1093 output->video.chroma.dcc_controls.dcc_256_128 = 1; 1094 output->video.chroma.dcc_controls.dcc_256_64 = 1; 1095 break; 1096 case dcc_control__256_128: 1097 output->video.chroma.dcc_controls.dcc_256_128 = 1; 1098 output->video.chroma.dcc_controls.dcc_256_64 = 1; 1099 break; 1100 case dcc_control__256_64: 1101 output->video.chroma.dcc_controls.dcc_256_64 = 1; 1102 break; 1103 default: 1104 ASSERT(0); 1105 break; 1106 } 1107 } 1108 1109 output->capable = true; 1110 return true; 1111 } 1112 1113 static void dcn401_program_det_segments(struct hubbub *hubbub, int hubp_inst, unsigned det_buffer_size_seg) 1114 { 1115 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 1116 1117 switch (hubp_inst) { 1118 case 0: 1119 REG_UPDATE(DCHUBBUB_DET0_CTRL, 1120 DET0_SIZE, det_buffer_size_seg); 1121 hubbub2->det0_size = det_buffer_size_seg; 1122 break; 1123 case 1: 1124 REG_UPDATE(DCHUBBUB_DET1_CTRL, 1125 DET1_SIZE, det_buffer_size_seg); 1126 hubbub2->det1_size = det_buffer_size_seg; 1127 break; 1128 case 2: 1129 REG_UPDATE(DCHUBBUB_DET2_CTRL, 1130 DET2_SIZE, det_buffer_size_seg); 1131 hubbub2->det2_size = det_buffer_size_seg; 1132 break; 1133 case 3: 1134 REG_UPDATE(DCHUBBUB_DET3_CTRL, 1135 DET3_SIZE, det_buffer_size_seg); 1136 hubbub2->det3_size = det_buffer_size_seg; 1137 break; 1138 default: 1139 break; 1140 } 1141 if (hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size 1142 + hubbub2->det3_size + hubbub2->compbuf_size_segments > hubbub2->crb_size_segs) { 1143 /* This may happen during seamless transition from ODM 2:1 to ODM4:1 */ 1144 DC_LOG_WARNING("CRB Config Warning: DET size (%d,%d,%d,%d) + Compbuf size (%d) > CRB segments (%d)\n", 1145 hubbub2->det0_size, hubbub2->det1_size, hubbub2->det2_size, hubbub2->det3_size, 1146 hubbub2->compbuf_size_segments, hubbub2->crb_size_segs); 1147 } 1148 } 1149 1150 static void dcn401_program_compbuf_segments(struct hubbub *hubbub, unsigned compbuf_size_seg, bool safe_to_increase) 1151 { 1152 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 1153 1154 unsigned int cur_compbuf_size_seg = 0; 1155 1156 if (safe_to_increase || compbuf_size_seg <= hubbub2->compbuf_size_segments) { 1157 if (compbuf_size_seg > hubbub2->compbuf_size_segments) { 1158 REG_WAIT(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, hubbub2->det0_size, 1, 100); 1159 REG_WAIT(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, hubbub2->det1_size, 1, 100); 1160 REG_WAIT(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, hubbub2->det2_size, 1, 100); 1161 REG_WAIT(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, hubbub2->det3_size, 1, 100); 1162 } 1163 /* Should never be hit, if it is we have an erroneous hw config*/ 1164 ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size 1165 + hubbub2->det3_size + compbuf_size_seg <= hubbub2->crb_size_segs); 1166 REG_UPDATE(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, compbuf_size_seg); 1167 hubbub2->compbuf_size_segments = compbuf_size_seg; 1168 1169 ASSERT(REG_GET(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, &cur_compbuf_size_seg) && !cur_compbuf_size_seg); 1170 } 1171 } 1172 1173 static void dcn401_wait_for_det_update(struct hubbub *hubbub, int hubp_inst) 1174 { 1175 struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); 1176 1177 switch (hubp_inst) { 1178 case 0: 1179 REG_WAIT(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, hubbub2->det0_size, 1, 100000); /* 1 vupdate at 10hz */ 1180 break; 1181 case 1: 1182 REG_WAIT(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, hubbub2->det1_size, 1, 100000); 1183 break; 1184 case 2: 1185 REG_WAIT(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, hubbub2->det2_size, 1, 100000); 1186 break; 1187 case 3: 1188 REG_WAIT(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, hubbub2->det3_size, 1, 100000); 1189 break; 1190 default: 1191 break; 1192 } 1193 } 1194 1195 static const struct hubbub_funcs hubbub4_01_funcs = { 1196 .update_dchub = hubbub2_update_dchub, 1197 .init_dchub_sys_ctx = hubbub3_init_dchub_sys_ctx, 1198 .init_vm_ctx = hubbub2_init_vm_ctx, 1199 .dcc_support_swizzle_addr3 = hubbub401_dcc_support_swizzle, 1200 .dcc_support_pixel_format_plane0_plane1 = hubbub401_dcc_support_pixel_format, 1201 .get_dcc_compression_cap = hubbub401_get_dcc_compression_cap, 1202 .wm_read_state = hubbub401_wm_read_state, 1203 .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq, 1204 .program_watermarks = hubbub401_program_watermarks, 1205 .allow_self_refresh_control = hubbub1_allow_self_refresh_control, 1206 .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, 1207 .verify_allow_pstate_change_high = NULL, 1208 .force_wm_propagate_to_pipes = hubbub32_force_wm_propagate_to_pipes, 1209 .force_pstate_change_control = hubbub3_force_pstate_change_control, 1210 .init_watermarks = hubbub401_init_watermarks, 1211 .init_crb = dcn401_init_crb, 1212 .hubbub_read_state = hubbub2_read_state, 1213 .force_usr_retraining_allow = hubbub32_force_usr_retraining_allow, 1214 .set_request_limit = hubbub32_set_request_limit, 1215 .program_det_segments = dcn401_program_det_segments, 1216 .program_compbuf_segments = dcn401_program_compbuf_segments, 1217 .wait_for_det_update = dcn401_wait_for_det_update, 1218 }; 1219 1220 void hubbub401_construct(struct dcn20_hubbub *hubbub2, 1221 struct dc_context *ctx, 1222 const struct dcn_hubbub_registers *hubbub_regs, 1223 const struct dcn_hubbub_shift *hubbub_shift, 1224 const struct dcn_hubbub_mask *hubbub_mask, 1225 int det_size_kb, 1226 int pixel_chunk_size_kb, 1227 int config_return_buffer_size_kb) 1228 { 1229 hubbub2->base.ctx = ctx; 1230 hubbub2->base.funcs = &hubbub4_01_funcs; 1231 hubbub2->regs = hubbub_regs; 1232 hubbub2->shifts = hubbub_shift; 1233 hubbub2->masks = hubbub_mask; 1234 1235 hubbub2->detile_buf_size = det_size_kb * 1024; 1236 hubbub2->pixel_chunk_size = pixel_chunk_size_kb * 1024; 1237 hubbub2->crb_size_segs = config_return_buffer_size_kb / DCN4_01_CRB_SEGMENT_SIZE_KB; 1238 } 1239