1239 lines · c
1/*2 * Copyright 2023 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *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.ctx35#define DC_LOGGER \36 hubbub2->base.ctx->logger37#define REG(reg)\38 hubbub2->regs->reg39 40#undef FN41#define FN(reg_name, field_name) \42 hubbub2->shifts->field_name, hubbub2->masks->field_name43 44static 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 64Bytes65}66 67bool 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_flip90 > 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_flip95 < hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip)96 wm_pending = true;97 98 if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_nom99 > 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_nom104 < hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom)105 wm_pending = true;106 107 if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_mall108 > 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_flip143 > 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_flip148 < hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip)149 wm_pending = true;150 151 if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_nom152 > 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_nom157 < hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom)158 wm_pending = true;159 160 if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_mall161 > 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 185bool 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_enter196 > 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 value205 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_enter213 < hubbub2->watermarks.dcn4x.a.sr_enter)214 wm_pending = true;215 216 if (safe_to_lower || watermarks->dcn4x.a.sr_exit217 > 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 value226 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_exit234 < hubbub2->watermarks.dcn4x.a.sr_exit)235 wm_pending = true;236 237 /* clock state B */238 if (safe_to_lower || watermarks->dcn4x.b.sr_enter239 > 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 value248 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_enter256 < hubbub2->watermarks.dcn4x.b.sr_enter)257 wm_pending = true;258 259 if (safe_to_lower || watermarks->dcn4x.b.sr_exit260 > 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 value269 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_exit277 < hubbub2->watermarks.dcn4x.b.sr_exit)278 wm_pending = true;279 280 return wm_pending;281}282 283 284bool 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_pstate296 > 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_pstate305 < hubbub2->watermarks.dcn4x.a.uclk_pstate)306 wm_pending = true;307 308 /* clock state B */309 if (safe_to_lower || watermarks->dcn4x.b.uclk_pstate310 > 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_pstate319 < 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_ppt324 > 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_ppt333 < 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_ppt338 > 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_ppt347 < 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_pstate353 > 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_pstate362 < hubbub2->watermarks.dcn4x.a.fclk_pstate)363 wm_pending = true;364 365 /* clock state B */366 if (safe_to_lower || watermarks->dcn4x.b.fclk_pstate367 > 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_pstate376 < 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_ppt381 > 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_ppt390 < 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_ppt395 > 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_ppt404 < hubbub2->watermarks.dcn4x.b.temp_read_or_ppt)405 wm_pending = true;406 407 return wm_pending;408}409 410 411bool 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.usr422 > 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.usr430 < hubbub2->watermarks.dcn4x.a.usr)431 wm_pending = true;432 433 /* clock state B */434 if (safe_to_lower || watermarks->dcn4x.b.usr435 > 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.usr443 < hubbub2->watermarks.dcn4x.b.usr)444 wm_pending = true;445 446 return wm_pending;447}448 449 450static 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 are473 * well ahead of their amortized schedule, then it is safe to prevent the next winner474 * from being committed and sent to the fabric.475 * The utilization of the memory controller is approximated by ensuring that476 * the number of outstanding requests is greater than a threshold specified477 * by the ARB_MIN_REQ_OUTSTANDING. To determine that the DCHub requestors are well ahead of the amortized478 * 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 */497static 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 552static 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 601bool 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 650bool 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 706void 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 724void 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 plane0744 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 buffer771 * 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 fit791 * in de-tile buffer, check if one plane can use 256B request while792 * the other plane is using 128B requests793 */794 if (*p0_req128_horz_wc) {795 // If ratio around 1:1 between p0 and p1 try to recalulate if p0 can use 256B796 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 256B812 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}827bool 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 else862 plane0_width = input->surface_size.width;863 864 if (input->surface_size.height > 6144 + 16)865 plane0_height = 6160;866 else867 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 else879 plane0_width = input->surface_size.width;880 881 if (input->surface_size.height > 4320 + 16)882 plane0_height = 4336;883 else884 plane0_height = input->surface_size.height;885 886 if (input->plane1_size.width > 7680 + 16)887 plane1_width = 7696 / 2;888 else889 plane1_width = input->plane1_size.width;890 891 if (input->plane1_size.height > 4320 + 16)892 plane1_height = 4336 / 2;893 else894 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 else904 plane0_width = input->surface_size.width;905 906 if (input->surface_size.height > 5120 + 16)907 plane0_height = 5136;908 else909 plane0_height = input->surface_size.height;910 911 if (input->plane1_size.width > 5120 + 16)912 plane1_width = 5136;913 else914 plane1_width = input->plane1_size.width;915 916 if (input->plane1_size.height > 5120 + 16)917 plane1_height = 5136;918 else919 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 else949 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 else956 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 else965 /* req128 is true for either horz and vert966 * but segment_order is contiguous967 */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 else1019 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 else1026 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 else1035 /* req128 is true for either horz and vert1036 * but segment_order is contiguous1037 */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 else1068 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 else1075 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 else1084 /* req128 is true for either horz and vert1085 * but segment_order is contiguous1086 */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 1113static 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_size1142 + 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 1150static 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_size1165 + 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 1173static 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 1195static 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 1220void 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