1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright 2023 Advanced Micro Devices, Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 * OTHER DEALINGS IN THE SOFTWARE. 22 * 23 * Authors: AMD 24 * 25 */ 26 27 #include "dml_logger.h" 28 #include "dml1_frl_cap_chk.h" 29 #include "dml_inline_defs.h" 30 31 static const double __maybe_unused EPSILON = 0.01; 32 static const double __maybe_unused DBL_EPSILON = 2.2204460492503131e-16; 33 static const double __maybe_unused OVERHEAD_M = 0.003; /* % */ 34 static const double __maybe_unused TOLERANCE_PIXEL_CLOCK = 0.005; /* % */ 35 static const double __maybe_unused DML_TOLERANCE_AUDIO_CLOCK = 1000; /* ppm */ 36 37 #define frl_dump_var(fmt, var) {} 38 #define frl_print(fmt, ...) {} 39 40 const struct frl_primary_format prim_format_444[] = { 41 /* VIC/Rate/Lanes/HCactive/HCBlank */ 42 {64, 3, 3, 960, 360}, /* 1920x1080 @ 100 */ 43 {77, 3, 3, 960, 360}, /* 1920x1080 @ 100 */ 44 {63, 3, 3, 960, 140}, /* 1920x1080 @ 120 */ 45 {78, 3, 3, 960, 140}, /* 1920x1080 @ 120 */ 46 {93, 3, 3, 1920, 828}, /* 3840x2160 @ 24 */ 47 {103, 3, 3, 1920, 828}, /* 3840x2160 @ 24 */ 48 {94, 3, 3, 1920, 720}, /* 3840x2160 @ 25 */ 49 {104, 3, 3, 1920, 720}, /* 3840x2160 @ 25 */ 50 {95, 3, 3, 1920, 280}, /* 3840x2160 @ 30 */ 51 {105, 3, 3, 1920, 280}, /* 3840x2160 @ 30 */ 52 {114, 3, 3, 1920, 828}, /* 3840x2160 @ 48 */ 53 {116, 3, 3, 1920, 828}, /* 3840x2160 @ 48 */ 54 {96, 3, 3, 1920, 720}, /* 3840x2160 @ 50 */ 55 {106, 3, 3, 1920, 720}, /* 3840x2160 @ 50 */ 56 {97, 3, 3, 1920, 280}, /* 3840x2160 @ 60 */ 57 {107, 3, 3, 1920, 280}, /* 3840x2160 @ 60 */ 58 {117, 6, 3, 1920, 720}, /* 3840x2160 @ 100 */ 59 {119, 6, 3, 1920, 720}, /* 3840x2160 @ 100 */ 60 {118, 6, 3, 1920, 280}, /* 3840x2160 @ 120 */ 61 {120, 6, 3, 1920, 280}, /* 3840x2160 @ 120 */ 62 {98, 3, 3, 2048, 700}, /* 4096x2160 @ 24 */ 63 {99, 3, 3, 2048, 592}, /* 4096x2160 @ 25 */ 64 {100, 3, 3, 2048, 152}, /* 4096x2160 @ 30 */ 65 {115, 3, 3, 2048, 700}, /* 4096x2160 @ 48 */ 66 {101, 3, 3, 2048, 592}, /* 4096x2160 @ 50 */ 67 {102, 3, 3, 2048, 152}, /* 4096x2160 @ 60 */ 68 {218, 6, 3, 2048, 592}, /* 4096x2160 @ 100 */ 69 {219, 6, 3, 2048, 152}, /* 4096x2160 @ 120 */ 70 {121, 3, 3, 2560, 1188}, /* 5120x2160 @ 24 */ 71 {122, 3, 3, 2560, 1040}, /* 5120x2160 @ 25 */ 72 {123, 3, 3, 2560, 440}, /* 5120x2160 @ 30 */ 73 {124, 3, 3, 2560, 256}, /* 5120x2160 @ 48 */ 74 {125, 3, 3, 2560, 484}, /* 5120x2160 @ 50 */ 75 {126, 3, 3, 2307, 144}, /* 5120x2160 @ 60 */ 76 {127, 6, 3, 2560, 484}, /* 5120x2160 @ 100 */ 77 {193, 6, 3, 2334, 104}, /* 5120x2160 @ 120 */ 78 {194, 6, 3, 3840, 1660}, /* 7680x2160 @ 24 */ 79 {202, 6, 3, 3840, 1660}, /* 7680x2160 @ 24 */ 80 {195, 6, 3, 3840, 1560}, /* 7680x2160 @ 25 */ 81 {203, 6, 3, 3840, 1560}, /* 7680x2160 @ 25 */ 82 {196, 6, 3, 3840, 660}, /* 7680x2160 @ 30 */ 83 {204, 6, 3, 3840, 660}, /* 7680x2160 @ 30 */ 84 {197, 6, 4, 3142, 1292}, /* 7680x2160 @ 48 */ 85 {205, 6, 4, 3142, 1292}, /* 7680x2160 @ 48 */ 86 {198, 6, 4, 3142, 1180}, /* 7680x2160 @ 50 */ 87 {206, 6, 4, 3142, 1180}, /* 7680x2160 @ 50 */ 88 {199, 6, 4, 3182, 140}, /* 7680x2160 @ 60 */ 89 {207, 6, 4, 3182, 140}, /* 7680x2160 @ 60 */ 90 {200, 10, 4, 2680, 784}, /* 7680x2160 @ 100 */ 91 {208, 10, 4, 2680, 784}, /* 7680x2160 @ 100 */ 92 {201, 10, 4, 2600, 100}, /* 7680x2160 @ 120 */ 93 {209, 10, 4, 2600, 100}, /* 7680x2160 @ 120 */ 94 {210, 6, 3, 4854, 912}, /* 10240x4320 @ 24 */ 95 {211, 6, 3, 4827, 1536}, /* 10240x4320 @ 25 */ 96 {212, 6, 3, 4720, 128}, /* 10240x4320 @ 30 */ 97 {213, 8, 4, 4347, 756}, /* 10240x4320 @ 48 */ 98 {214, 8, 4, 4320, 1376}, /* 10240x4320 @ 50 */ 99 {215, 8, 4, 4187, 124}, /* 10240x4320 @ 60 */ 100 }; 101 102 const struct frl_primary_format prim_format_422[] = { 103 /* VIC/Rate/Lanes/HCactive/HCBlank */ 104 {64, 3, 3, 960, 360}, /* 1920x1080 @ 100 */ 105 {77, 3, 3, 960, 360}, /* 1920x1080 @ 100 */ 106 {63, 3, 3, 960, 140}, /* 1920x1080 @ 120 */ 107 {78, 3, 3, 960, 140}, /* 1920x1080 @ 120 */ 108 {93, 3, 3, 1920, 828}, /* 3840x2160 @ 24 */ 109 {103, 3, 3, 1920, 828}, /* 3840x2160 @ 24 */ 110 {94, 3, 3, 1920, 720}, /* 3840x2160 @ 25 */ 111 {104, 3, 3, 1920, 720}, /* 3840x2160 @ 25 */ 112 {95, 3, 3, 1920, 280}, /* 3840x2160 @ 30 */ 113 {105, 3, 3, 1920, 280}, /* 3840x2160 @ 30 */ 114 {114, 3, 3, 1920, 828}, /* 3840x2160 @ 48 */ 115 {116, 3, 3, 1920, 828}, /* 3840x2160 @ 48 */ 116 {96, 3, 3, 1920, 720}, /* 3840x2160 @ 50 */ 117 {106, 3, 3, 1920, 720}, /* 3840x2160 @ 50 */ 118 {97, 3, 3, 1920, 280}, /* 3840x2160 @ 60 */ 119 {107, 3, 3, 1920, 280}, /* 3840x2160 @ 60 */ 120 {117, 3, 3, 1370, 104}, /* 3840x2160 @ 100 */ 121 {119, 3, 3, 1370, 104}, /* 3840x2160 @ 100 */ 122 {118, 3, 3, 1130, 104}, /* 3840x2160 @ 120 */ 123 {120, 3, 3, 1130, 104}, /* 3840x2160 @ 120 */ 124 {98, 3, 3, 2048, 700}, /* 4096x2160 @ 24 */ 125 {99, 3, 3, 2048, 592}, /* 4096x2160 @ 25 */ 126 {100, 3, 3, 2048, 152}, /* 4096x2160 @ 30 */ 127 {115, 3, 3, 2048, 700}, /* 4096x2160 @ 48 */ 128 {101, 3, 3, 2048, 592}, /* 4096x2160 @ 50 */ 129 {102, 3, 3, 2048, 152}, /* 4096x2160 @ 60 */ 130 {218, 6, 3, 2048, 592}, /* 4096x2160 @ 100 */ 131 {219, 6, 3, 2048, 152}, /* 4096x2160 @ 120 */ 132 {121, 3, 3, 2560, 1188}, /* 5120x2160 @ 24 */ 133 {122, 3, 3, 2560, 1040}, /* 5120x2160 @ 25 */ 134 {123, 3, 3, 2560, 440}, /* 5120x2160 @ 30 */ 135 {124, 3, 3, 2560, 256}, /* 5120x2160 @ 48 */ 136 {125, 3, 3, 2560, 484}, /* 5120x2160 @ 50 */ 137 {126, 3, 3, 2307, 144}, /* 5120x2160 @ 60 */ 138 {127, 6, 3, 2560, 484}, /* 5120x2160 @ 100 */ 139 {193, 6, 3, 2334, 104}, /* 5120x2160 @ 120 */ 140 {194, 3, 3, 2460, 816}, /* 7680x2160 @ 24 */ 141 {202, 3, 3, 2460, 816}, /* 7680x2160 @ 24 */ 142 {195, 3, 3, 2460, 732}, /* 7680x2160 @ 25 */ 143 {203, 3, 3, 2460, 732}, /* 7680x2160 @ 25 */ 144 {196, 3, 3, 2360, 144}, /* 7680x2160 @ 30 */ 145 {204, 3, 3, 2360, 144}, /* 7680x2160 @ 30 */ 146 {197, 6, 3, 2460, 816}, /* 7680x2160 @ 48 */ 147 {205, 6, 3, 2460, 816}, /* 7680x2160 @ 48 */ 148 {198, 6, 3, 2460, 732}, /* 7680x2160 @ 50 */ 149 {206, 6, 3, 2460, 732}, /* 7680x2160 @ 50 */ 150 {199, 6, 3, 2380, 116}, /* 7680x2160 @ 60 */ 151 {207, 6, 3, 2380, 116}, /* 7680x2160 @ 60 */ 152 {200, 10, 4, 2680, 784}, /* 7680x2160 @ 100 */ 153 {208, 10, 4, 2680, 784}, /* 7680x2160 @ 100 */ 154 {201, 10, 4, 2600, 100}, /* 7680x2160 @ 120 */ 155 {209, 10, 4, 2600, 100}, /* 7680x2160 @ 120 */ 156 {210, 6, 3, 4854, 912}, /* 10240x4320 @ 24 */ 157 {211, 6, 3, 4827, 1536}, /* 10240x4320 @ 25 */ 158 {212, 6, 3, 4720, 128}, /* 10240x4320 @ 30 */ 159 {213, 6, 4, 3360, 420}, /* 10240x4320 @ 48 */ 160 {214, 6, 4, 3334, 892}, /* 10240x4320 @ 50 */ 161 {215, 6, 4, 3120, 124}, /* 10240x4320 @ 60 */ 162 {216, 12, 4, 3334, 764}, /* 10240x4320 @ 100 */ 163 {217, 12, 4, 3120, 124}, /* 10240x4320 @ 120 */ 164 }; 165 166 const struct frl_primary_format prim_format_420[] = { 167 /* VIC/Rate/Lanes/HCactive/HCBlank */ 168 {114, 3, 3, 1920, 828}, /* 3840x2160 @ 48 */ 169 {116, 3, 3, 1920, 828}, /* 3840x2160 @ 48 */ 170 {96, 3, 3, 1920, 720}, /* 3840x2160 @ 50 */ 171 {106, 3, 3, 1920, 720}, /* 3840x2160 @ 50 */ 172 {97, 3, 3, 1920, 280}, /* 3840x2160 @ 60 */ 173 {107, 3, 3, 1920, 280}, /* 3840x2160 @ 60 */ 174 {117, 3, 3, 1370, 104}, /* 3840x2160 @ 100 */ 175 {119, 3, 3, 1370, 104}, /* 3840x2160 @ 100 */ 176 {118, 3, 3, 1130, 104}, /* 3840x2160 @ 120 */ 177 {120, 3, 3, 1130, 104}, /* 3840x2160 @ 120 */ 178 {115, 3, 3, 2048, 700}, /* 4096x2160 @ 48 */ 179 {101, 3, 3, 2048, 592}, /* 4096x2160 @ 50 */ 180 {102, 3, 3, 2048, 152}, /* 4096x2160 @ 60 */ 181 {218, 3, 3, 1376, 96}, /* 4096x2160 @ 100 */ 182 {219, 3, 3, 1131, 84}, /* 4096x2160 @ 120 */ 183 {124, 3, 3, 2560, 256}, /* 5120x2160 @ 48 */ 184 {125, 3, 3, 2560, 484}, /* 5120x2160 @ 50 */ 185 {126, 3, 3, 2307, 144}, /* 5120x2160 @ 60 */ 186 {127, 6, 3, 2560, 484}, /* 5120x2160 @ 100 */ 187 {193, 6, 3, 2334, 104}, /* 5120x2160 @ 120 */ 188 {194, 3, 3, 2460, 816}, /* 7680x2160 @ 24 */ 189 {202, 3, 3, 2460, 816}, /* 7680x2160 @ 24 */ 190 {195, 3, 3, 2460, 732}, /* 7680x2160 @ 25 */ 191 {203, 3, 3, 2460, 732}, /* 7680x2160 @ 25 */ 192 {196, 3, 3, 2360, 144}, /* 7680x2160 @ 30 */ 193 {204, 3, 3, 2360, 144}, /* 7680x2160 @ 30 */ 194 {197, 6, 3, 2460, 816}, /* 7680x2160 @ 48 */ 195 {205, 6, 3, 2460, 816}, /* 7680x2160 @ 48 */ 196 {198, 6, 3, 2460, 732}, /* 7680x2160 @ 50 */ 197 {206, 6, 3, 2460, 732}, /* 7680x2160 @ 50 */ 198 {199, 6, 3, 2380, 116}, /* 7680x2160 @ 60 */ 199 {207, 6, 3, 2380, 116}, /* 7680x2160 @ 60 */ 200 {200, 8, 4, 2240, 480}, /* 7680x2160 @ 100 */ 201 {208, 8, 4, 2240, 480}, /* 7680x2160 @ 100 */ 202 {201, 8, 4, 2062, 108}, /* 7680x2160 @ 120 */ 203 {209, 8, 4, 2062, 108}, /* 7680x2160 @ 120 */ 204 {210, 3, 3, 2614, 172}, /* 10240x4320 @ 24 */ 205 {211, 3, 3, 2614, 500}, /* 10240x4320 @ 25 */ 206 {212, 6, 3, 4720, 128}, /* 10240x4320 @ 30 */ 207 {213, 6, 3, 2614, 172}, /* 10240x4320 @ 48 */ 208 {214, 6, 4, 3334, 892}, /* 10240x4320 @ 50 */ 209 {215, 6, 4, 3120, 124}, /* 10240x4320 @ 60 */ 210 {216, 10, 4, 2854, 520}, /* 10240x4320 @ 100 */ 211 {217, 10, 4, 2587, 120}, /* 10240x4320 @ 120 */ 212 }; 213 214 enum frl_cap_chk_result dml1_frl_cap_chk_common(struct frl_cap_chk_intermediates *inter, 215 struct frl_cap_chk_params *params) 216 { 217 double audio_bw_reserve = (params->compressed ? 192000.0 : 0.0); 218 219 dc_assert_fp_enabled(); 220 221 #ifdef DEBUG_FRL_CAP_CHK 222 { 223 printf("frl_cap_chk inputs:\n"); 224 printf("-------------------\n"); 225 frl_dump_var("%i", params->lanes); 226 frl_dump_var("%le", params->f_pixel_clock_nominal); 227 frl_dump_var("%le", params->r_bit_nominal); 228 frl_dump_var("%i", params->audio_packet_type); 229 frl_dump_var("%le", params->f_audio); 230 frl_dump_var("%i", params->h_active); 231 frl_dump_var("%i", params->h_blank); 232 frl_dump_var("%i", params->bpc); 233 frl_dump_var("%i", params->pixel_encoding); 234 frl_dump_var("%i", params->compressed); 235 frl_dump_var("%i", params->slices); 236 frl_dump_var("%i", params->slice_width); 237 frl_dump_var("%le", params->bpp_target); 238 frl_dump_var("%i", params->layout); 239 frl_dump_var("%i", params->acat); 240 printf("frl_cap_chk outputs:\n"); 241 printf("---------------------\n"); 242 } 243 #endif 244 245 inter->c_frl_sb = 4 * C_FRL_CB + params->lanes; 246 inter->overhead_sb = (double)params->lanes / inter->c_frl_sb; 247 inter->overhead_rs = 8.0 * 4.0 / inter->c_frl_sb; 248 inter->overhead_map = 2.5 / inter->c_frl_sb; 249 inter->overhead_min = inter->overhead_sb + inter->overhead_rs + inter->overhead_map; 250 inter->overhead_max = inter->overhead_min + OVERHEAD_M; 251 inter->f_pixel_clock_max = params->f_pixel_clock_nominal * (1.0 + TOLERANCE_PIXEL_CLOCK); 252 inter->t_line = (params->h_active + params->h_blank) / inter->f_pixel_clock_max; 253 inter->r_bit_min = params->r_bit_nominal * (1.0 - TOLERANCE_FRL_BIT / 1000000.0); 254 inter->r_frl_char_min = inter->r_bit_min / 18.0; 255 inter->c_frl_line = dml_floor(inter->t_line * inter->r_frl_char_min * params->lanes, 1); 256 257 #ifdef DEBUG_FRL_CAP_CHK 258 { 259 frl_dump_var("%i", inter->c_frl_sb); 260 frl_dump_var("%le", inter->overhead_sb); 261 frl_dump_var("%le", inter->overhead_rs); 262 frl_dump_var("%le", inter->overhead_map); 263 frl_dump_var("%le", inter->overhead_min); 264 frl_dump_var("%le", inter->overhead_max); 265 frl_dump_var("%le", inter->f_pixel_clock_max); 266 frl_dump_var("%le", inter->t_line); 267 frl_dump_var("%le", inter->r_bit_min); 268 frl_dump_var("%le", inter->r_frl_char_min); 269 frl_dump_var("%le", inter->c_frl_line); 270 } 271 #endif 272 273 switch (params->audio_packet_type) { 274 case 0x02: 275 if (params->layout == 0) 276 inter->ap = 0.25; 277 else if (params->layout == 1) 278 inter->ap = 1.0; 279 break; 280 case 0x08: 281 inter->ap = 0.25; 282 break; 283 case 0x09: 284 inter->ap = 1.0; 285 break; 286 case 0x07: 287 case 0x0e: 288 case 0x0f: 289 case 0x0b: 290 case 0x0c: 291 /* Unsupported audio format */ 292 return FRL_CAP_CHK_ERROR_UNSUPPORTED_AUDIO; 293 default: 294 inter->ap = 0.0; 295 } 296 297 inter->r_ap = (dml_max(audio_bw_reserve, params->f_audio * inter->ap) + 2 * ACR_RATE_MAX) * (1 + DML_TOLERANCE_AUDIO_CLOCK / 1000000.0); 298 inter->avg_audio_packets_line = inter->r_ap * inter->t_line; 299 inter->audio_packets_line = (int)dml_ceil(inter->avg_audio_packets_line, 1); 300 inter->blank_audio_min = 32 + 32 * inter->audio_packets_line; // h_blank_audio_min or hc_blank_audio_min 301 302 params->borrow_params.audio_packets_line = inter->audio_packets_line; 303 304 #ifdef DEBUG_FRL_CAP_CHK 305 { 306 frl_dump_var("%le", inter->ap); 307 frl_dump_var("%le", inter->r_ap); 308 frl_dump_var("%le", inter->avg_audio_packets_line); 309 frl_dump_var("%i", inter->audio_packets_line); 310 frl_dump_var("%i", inter->blank_audio_min); 311 } 312 #endif 313 314 return FRL_CAP_CHK_OK; 315 } 316 317 enum frl_cap_chk_result dml1_frl_cap_chk_uncompressed(struct frl_cap_chk_params *params, 318 struct frl_cap_chk_intermediates *inter) 319 { 320 enum frl_cap_chk_result res; 321 int k_420; 322 double k_cd; 323 int c_frl_free; 324 int c_frl_rc_margin; 325 int c_frl_rc_savings; 326 int bpp; 327 double bytes_line; 328 int tb_active; 329 int tb_blank; 330 double f_tb_average; 331 double t_active_ref; 332 double t_blank_ref; 333 double t_active_min; 334 double t_blank_min; 335 double t_borrowed; 336 double tb_borrowed; 337 int c_frl_actual_payload; 338 double utilization; 339 double margin; 340 341 dc_assert_fp_enabled(); 342 343 res = dml1_frl_cap_chk_common(inter, params); 344 if (res != FRL_CAP_CHK_OK) 345 return res; 346 347 k_420 = params->pixel_encoding == HDMI_FRL_PIXEL_ENCODING_420 ? 2 : 1; 348 k_cd = params->pixel_encoding == HDMI_FRL_PIXEL_ENCODING_422 ? 1.0 : params->bpc / 8.0; 349 c_frl_free = (int)dml_max(params->h_blank * k_cd / k_420 - 32 * (1 + inter->audio_packets_line) - 7, 0); 350 c_frl_rc_margin = 4; 351 c_frl_rc_savings = (int)dml_floor(dml_max(((7.0 / 8.0) * c_frl_free) - c_frl_rc_margin, 0.0), 1); 352 bpp = (int)(24 * k_cd / k_420); 353 bytes_line = bpp * params->h_active / 8.0; 354 tb_active = (int)dml_ceil(bytes_line / 3, 1); 355 tb_blank = (int)dml_ceil(params->h_blank * k_cd / k_420, 1); 356 357 #ifdef DEBUG_FRL_CAP_CHK 358 { 359 frl_dump_var("%i", k_420); 360 frl_dump_var("%le", k_cd); 361 frl_dump_var("%i", c_frl_free); 362 frl_dump_var("%i", c_frl_rc_margin); 363 frl_dump_var("%i", c_frl_rc_savings); 364 frl_dump_var("%i", bpp); 365 frl_dump_var("%le", bytes_line); 366 frl_dump_var("%i", tb_active); 367 frl_dump_var("%i", tb_blank); 368 } 369 #endif 370 371 if (!(inter->blank_audio_min <= tb_blank)) { 372 frl_dump_var("%i", inter->blank_audio_min); 373 frl_dump_var("%i", tb_blank); 374 return FRL_CAP_CHK_ERROR_AUDIO_BW; 375 } 376 377 f_tb_average = (inter->f_pixel_clock_max / (params->h_active + params->h_blank)) * (tb_active + tb_blank); 378 t_active_ref = inter->t_line * ((double)params->h_active / (params->h_active + params->h_blank)); 379 t_blank_ref = inter->t_line * ((double)params->h_blank / (params->h_active + params->h_blank)); 380 t_active_min = (3.0 / 2.0) * tb_active / (params->lanes * inter->r_frl_char_min * (1.0 - inter->overhead_max)); 381 t_blank_min = tb_blank / (params->lanes * inter->r_frl_char_min * (1.0 - inter->overhead_max)); 382 383 #ifdef DEBUG_FRL_CAP_CHK 384 { 385 frl_dump_var("%le", f_tb_average); 386 frl_dump_var("%le", t_active_ref); 387 frl_dump_var("%le", t_blank_ref); 388 frl_dump_var("%le", t_active_min); 389 frl_dump_var("%le", t_blank_min); 390 } 391 #endif 392 393 if (t_active_ref >= t_active_min && t_blank_ref >= t_blank_min) { 394 t_borrowed = 0; 395 params->borrow_params.borrow_mode = FRL_BORROW_MODE_NONE; 396 } else if ((t_active_ref < t_active_min) && (t_blank_ref >= t_blank_min)) { 397 t_borrowed = t_active_min - t_active_ref; 398 params->borrow_params.borrow_mode = FRL_BORROW_MODE_FROM_BLANK; 399 } else { 400 return FRL_CAP_CHK_ERROR_BORROW; 401 } 402 403 tb_borrowed = dml_ceil(t_borrowed * f_tb_average, 1); 404 405 #ifdef DEBUG_FRL_CAP_CHK 406 { 407 frl_dump_var("%le", tb_borrowed); 408 frl_dump_var("%i", params->borrow_params.borrow_mode); 409 } 410 #endif 411 412 if (!(tb_borrowed <= TB_BORROWED_MAX)) 413 return FRL_CAP_CHK_ERROR_MAX_BORROW; 414 415 c_frl_actual_payload = (int)(dml_ceil((3.0 / 2.0) * tb_active, 1) + tb_blank - c_frl_rc_savings); 416 utilization = c_frl_actual_payload / inter->c_frl_line; 417 margin = 1.0 - (utilization + inter->overhead_max); 418 419 #ifdef DEBUG_FRL_CAP_CHK 420 { 421 frl_dump_var("%i", c_frl_actual_payload); 422 frl_dump_var("%le", utilization); 423 frl_dump_var("%le", margin); 424 } 425 #endif 426 427 if (margin < 0 && dcn_bw_fabs(margin) > EPSILON) 428 return FRL_CAP_CHK_ERROR_MARGIN; 429 430 return FRL_CAP_CHK_OK; 431 } 432 433 #if defined (CONFIG_DRM_AMD_DC_FP) 434 enum frl_cap_chk_result dml1_frl_cap_chk_compressed(struct frl_cap_chk_params *params, 435 struct frl_cap_chk_intermediates *inter) 436 { 437 enum frl_cap_chk_result res; 438 int c_frl_available; 439 #if defined(DEBUG_FRL_CAP_CHK) 440 int c_frl_active_available; 441 int c_frl_blank_available; 442 #endif 443 int bytes_target = 0; 444 int hc_active_target; 445 int hc_blank_target_est1; 446 int hc_blank_target_est2; 447 int hc_blank_target = 0; 448 int c_frl_actual_target_payload; 449 double utilization_targeted; 450 double margin_target; 451 double f_tb_average; 452 double t_active_ref; 453 double t_blank_ref; 454 double t_active_target; 455 double t_blank_target; 456 double tb_borrowed; 457 #ifdef DEBUG_FRL_CAP_CHK 458 double tb_delta; 459 double tb_delta_limit; 460 int tb_worst; 461 #endif 462 int table_size_444 = ARRAY_SIZE(prim_format_444); 463 int table_size_422 = ARRAY_SIZE(prim_format_422); 464 int table_size_420 = ARRAY_SIZE(prim_format_420); 465 int i; 466 bool hc_active_blank_predefined = false; 467 468 dc_assert_fp_enabled(); 469 470 res = dml1_frl_cap_chk_common(inter, params); 471 472 if (res != FRL_CAP_CHK_OK) 473 return res; 474 475 c_frl_available = (int)dml_floor((1 - inter->overhead_max) * inter->c_frl_line, 1); 476 #if defined(DEBUG_FRL_CAP_CHK) 477 c_frl_active_available = dml_floor(c_frl_available * ((double)params->h_active / (params->h_active + params->h_blank)), 1); 478 c_frl_blank_available = dml_floor(c_frl_available * ((double)params->h_blank / (params->h_active + params->h_blank)), 1); 479 #endif 480 bytes_target = (int)(params->slices * dml_ceil(params->bpp_target * params->slice_width / 8.0, 1)); 481 482 if (!params->bypass_hc_target_calc) 483 hc_active_target = (int)dml_ceil(bytes_target / 3.0, 1); 484 else 485 hc_active_target = params->borrow_params.hc_active_target; 486 487 if (!params->allow_all_bpp && params->vic != 0) { 488 if (params->pixel_encoding == HDMI_FRL_PIXEL_ENCODING_444) { 489 for (i = 0; i < table_size_444 ; i++) { 490 if (prim_format_444[i].vic == params->vic) { 491 params->borrow_params.hc_active_target = prim_format_444[i].hc_active; 492 params->borrow_params.hc_blank_target = prim_format_444[i].hc_blank; 493 hc_active_blank_predefined = true; 494 break; 495 } 496 } 497 } else if (params->pixel_encoding == HDMI_FRL_PIXEL_ENCODING_422) { 498 for (i = 0; i < table_size_422 ; i++) { 499 if (prim_format_422[i].vic == params->vic) { 500 params->borrow_params.hc_active_target = prim_format_422[i].hc_active; 501 params->borrow_params.hc_blank_target = prim_format_422[i].hc_blank; 502 hc_active_blank_predefined = true; 503 break; 504 } 505 } 506 } else if (params->pixel_encoding == HDMI_FRL_PIXEL_ENCODING_420) { 507 for (i = 0; i < table_size_420 ; i++) { 508 if (prim_format_420[i].vic == params->vic) { 509 params->borrow_params.hc_active_target = prim_format_420[i].hc_active; 510 params->borrow_params.hc_blank_target = prim_format_420[i].hc_blank; 511 hc_active_blank_predefined = true; 512 break; 513 } 514 } 515 } 516 517 if (hc_active_blank_predefined) { 518 hc_active_target = params->borrow_params.hc_active_target; 519 hc_blank_target = params->borrow_params.hc_blank_target; 520 } 521 } 522 523 hc_blank_target_est1 = (int)dml_ceil(hc_active_target * ((double)params->h_blank / params->h_active), 1); 524 hc_blank_target_est2 = (int)dml_max(hc_blank_target_est1, inter->blank_audio_min); 525 526 if (!hc_active_blank_predefined) { 527 if (!params->bypass_hc_target_calc) { 528 hc_blank_target = (int)(4 * dml_floor(dml_min(hc_blank_target_est2, c_frl_available - 3.0 / 2.0 * hc_active_target) / 4.0, 1)); 529 530 params->borrow_params.hc_active_target = hc_active_target; 531 params->borrow_params.hc_blank_target = hc_blank_target; 532 } else { 533 hc_blank_target = params->borrow_params.hc_blank_target; 534 } 535 } 536 537 #ifdef DEBUG_FRL_CAP_CHK 538 { 539 frl_dump_var("%i", c_frl_available); 540 frl_dump_var("%i", c_frl_active_available); 541 frl_dump_var("%i", c_frl_blank_available); 542 frl_dump_var("%i", bytes_target); 543 frl_dump_var("%i", hc_active_target); 544 frl_dump_var("%i", hc_blank_target_est1); 545 frl_dump_var("%i", hc_blank_target_est2); 546 frl_dump_var("%i", hc_blank_target); 547 } 548 #endif 549 550 if (!(inter->blank_audio_min <= hc_blank_target)) { 551 frl_dump_var("%i", inter->blank_audio_min); 552 frl_dump_var("%i", hc_blank_target); 553 return FRL_CAP_CHK_ERROR_AUDIO_BW; 554 } 555 556 f_tb_average = inter->f_pixel_clock_max / (params->h_active + params->h_blank) * (hc_active_target + hc_blank_target); 557 t_active_ref = inter->t_line * ((double)params->h_active / (params->h_active + params->h_blank)); 558 t_blank_ref = inter->t_line - t_active_ref; // * ((double) params->h_blank / (params->h_active + params->h_blank)); 559 t_active_target = dml_max((hc_active_target / f_tb_average), 560 (3.0 / 2.0 * hc_active_target) / 561 (params->lanes * inter->r_frl_char_min * (1.0 - inter->overhead_max))); 562 t_blank_target = inter->t_line - t_active_target; 563 564 tb_borrowed = t_active_target * f_tb_average - hc_active_target; 565 #ifdef DEBUG_FRL_CAP_CHK 566 tb_delta = dcn_bw_fabs(t_active_target - t_active_ref) * (hc_active_target + hc_blank_target_est1) / inter->t_line; 567 568 { 569 frl_dump_var("%le", f_tb_average); 570 frl_dump_var("%le", t_active_ref); 571 frl_dump_var("%le", t_blank_ref); 572 frl_dump_var("%le", t_active_target); 573 frl_dump_var("%le", t_blank_target); 574 frl_dump_var("%le", tb_delta); 575 } 576 #endif 577 578 if (t_blank_target - t_blank_ref > DBL_EPSILON) { 579 #ifdef DEBUG_FRL_CAP_CHK 580 tb_delta_limit = (t_active_ref - hc_active_target / f_tb_average) * (hc_active_target + hc_blank_target_est1) / inter->t_line; 581 #endif 582 params->borrow_params.borrow_mode = FRL_BORROW_MODE_FROM_ACTIVE; 583 } else if (t_active_target - t_active_ref > DBL_EPSILON) { 584 #ifdef DEBUG_FRL_CAP_CHK 585 tb_delta_limit = tb_delta; 586 #endif 587 params->borrow_params.borrow_mode = FRL_BORROW_MODE_FROM_BLANK; 588 } else { 589 #ifdef DEBUG_FRL_CAP_CHK 590 tb_delta_limit = 0; 591 #endif 592 params->borrow_params.borrow_mode = FRL_BORROW_MODE_NONE; 593 } 594 595 #ifdef DEBUG_FRL_CAP_CHK 596 tb_worst = dml_ceil(dml_max(tb_borrowed, tb_delta_limit), 1); 597 598 { 599 frl_dump_var("%le", tb_delta_limit); 600 frl_dump_var("%le", tb_borrowed); 601 frl_dump_var("%i", params->borrow_params.borrow_mode); 602 frl_dump_var("%i", tb_worst); 603 } 604 #endif 605 606 if (!(tb_borrowed <= TB_BORROWED_MAX)) 607 return FRL_CAP_CHK_ERROR_MAX_BORROW; 608 609 c_frl_actual_target_payload = (int)(dml_ceil(3.0 / 2.0 * hc_active_target, 1) + hc_blank_target); 610 utilization_targeted = c_frl_actual_target_payload / inter->c_frl_line; 611 margin_target = 1.0 - (utilization_targeted + inter->overhead_max); 612 613 #ifdef DEBUG_FRL_CAP_CHK 614 { 615 frl_dump_var("%i", c_frl_actual_target_payload); 616 frl_dump_var("%le", utilization_targeted); 617 frl_dump_var("%le", margin_target); 618 } 619 #endif 620 621 // oversubscribed bandwidth relative to margin 622 if (margin_target < 0 && dcn_bw_fabs(margin_target) > EPSILON) 623 return FRL_CAP_CHK_ERROR_MARGIN; 624 625 return FRL_CAP_CHK_OK; 626 } 627 #endif 628 629 enum frl_cap_chk_result dml1_frl_cap_chk(struct frl_cap_chk_params *params) 630 { 631 struct frl_cap_chk_intermediates inter; 632 633 #if defined (CONFIG_DRM_AMD_DC_FP) 634 if (params->compressed) 635 return dml1_frl_cap_chk_compressed(params, &inter); 636 #endif 637 638 return dml1_frl_cap_chk_inter(params, &inter); 639 } 640 641 enum frl_cap_chk_result dml1_frl_cap_chk_inter(struct frl_cap_chk_params *params, 642 struct frl_cap_chk_intermediates *inter) 643 { 644 return dml1_frl_cap_chk_uncompressed(params, inter); 645 } 646 647 static double calculate_compressed_active_time(uint32_t h_active, 648 const uint32_t h_blank, 649 const int hc_active, 650 const int hc_blank, 651 const uint32_t frl_num_lanes, 652 const double pix_clk, 653 const int frl_link_rate) 654 { 655 double f_tb_average; 656 double r_bit_nominal; 657 double r_bit_min; 658 double r_frl_char_min; 659 double t_active_est_1; 660 double t_active_est_2; 661 double t_active_target; 662 int c_frl_sb = 510; 663 int frl_bit_tolerance = 300; 664 double overhead_m = 0.003; 665 double overhead_sb; 666 double overhead_rs; 667 double overhead_map; 668 double overhead_min; 669 double overhead_max; 670 671 switch (frl_link_rate) { 672 case FRL_LINK_RATE_3GBPS: 673 r_bit_nominal = 3.0e9; 674 break; 675 case FRL_LINK_RATE_6GBPS: 676 case FRL_LINK_RATE_6GBPS_4LANE: 677 r_bit_nominal = 6.0e9; 678 break; 679 case FRL_LINK_RATE_8GBPS: 680 r_bit_nominal = 8.0e9; 681 break; 682 case FRL_LINK_RATE_10GBPS: 683 default: 684 r_bit_nominal = 10.0e9; 685 break; 686 case FRL_LINK_RATE_12GBPS: 687 r_bit_nominal = 12.0e9; 688 break; 689 } 690 691 f_tb_average = pix_clk / (h_active + h_blank) 692 * (hc_active + hc_blank); 693 694 c_frl_sb = 4 * c_frl_sb + frl_num_lanes; 695 overhead_sb = (double)frl_num_lanes / c_frl_sb; 696 overhead_rs = 8.0 * 4.0 / c_frl_sb; 697 overhead_map = 2.5 / c_frl_sb; 698 overhead_min = overhead_sb + overhead_rs + overhead_map; 699 overhead_max = overhead_min + overhead_m; 700 701 r_bit_min = r_bit_nominal * (1.0 - frl_bit_tolerance / 1000000.0); 702 r_frl_char_min = r_bit_min / 18.0; 703 t_active_est_1 = hc_active / f_tb_average; 704 t_active_est_2 = (3.0 / 2.0 * hc_active) / 705 (frl_num_lanes * r_frl_char_min * (1.0 - overhead_max)); 706 707 if (t_active_est_1 > t_active_est_2) { 708 t_active_target = t_active_est_1; 709 } else { 710 t_active_target = t_active_est_2; 711 } 712 713 return t_active_target; 714 } 715 716 void frl_modified_pix_clock_for_dsc_padding(const int hc_active_target, 717 const int hc_blank_target, 718 const uint8_t frl_num_lanes, 719 const uint32_t pix_clk_100hz, 720 const int frl_link_rate, 721 const uint32_t h_addressable, 722 const uint32_t h_border_left, 723 const uint32_t h_border_right, 724 const uint32_t h_total, 725 const uint32_t h_addressable_otg, 726 uint32_t *pix_clk_100hz_otg, 727 uint32_t *h_total_otg) 728 { 729 double pix_clk; 730 int h_active; 731 int h_blank; 732 double t_active_target; 733 double hw_pix_clk; 734 double h_total_otg_temp; 735 736 pix_clk = (double)pix_clk_100hz * 100; 737 738 h_active = h_addressable + h_border_left + h_border_right; 739 h_blank = h_total - h_active; 740 741 t_active_target = calculate_compressed_active_time(h_active, h_blank, hc_active_target, hc_blank_target, frl_num_lanes, pix_clk, frl_link_rate); 742 743 h_total_otg_temp = ((double)h_addressable_otg * (double)h_total) / ((double)pix_clk_100hz * 100.0 * t_active_target); 744 /* Htotal must be a multiple of 4, also take the ceiling */ 745 *h_total_otg = (uint32_t)dml_ceil(h_total_otg_temp, 4.0); 746 747 hw_pix_clk = (double)(pix_clk_100hz * 100.0 * (double)*h_total_otg) / (double)h_total; 748 *pix_clk_100hz_otg = (uint32_t)(hw_pix_clk / 100.0); 749 } 750 751 int frl_modify_borrow_mode_for_dsc_padding(const uint32_t pix_clk_100hz, 752 const uint32_t h_active, 753 const uint32_t h_active_padded, 754 const uint32_t h_blank, 755 const uint32_t h_blank_padded, 756 const int hc_active, 757 const int hc_blank, 758 const uint8_t frl_num_lanes, 759 const int frl_link_rate) 760 { 761 double f_pixel_clock_max; 762 double t_line; 763 double t_active; 764 double t_blank; 765 double t_active_target; 766 double t_blank_target; 767 double pix_clk_tolerance = 0.005; 768 769 enum frl_borrow_mode borrow_mode; 770 771 f_pixel_clock_max = (double)pix_clk_100hz * (1.0 + pix_clk_tolerance); 772 t_line = (double)(h_active + h_blank) / f_pixel_clock_max; 773 774 t_active_target = calculate_compressed_active_time(h_active, h_blank, hc_active, hc_blank, frl_num_lanes, f_pixel_clock_max, frl_link_rate); 775 776 t_active = t_line * ((double)h_active_padded / (h_active_padded + h_blank_padded)); 777 t_blank = t_line - t_active; 778 779 t_blank_target = t_line - t_active_target; 780 781 if (t_blank_target - t_blank > DBL_EPSILON) { 782 borrow_mode = FRL_BORROW_MODE_FROM_ACTIVE; 783 } else if (t_active_target - t_active > DBL_EPSILON) { 784 borrow_mode = FRL_BORROW_MODE_FROM_BLANK; 785 } else { 786 borrow_mode = FRL_BORROW_MODE_NONE; 787 } 788 789 return borrow_mode; 790 } 791