1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2010-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 * SPDX-License-Identifier: MIT 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 /******************************* List **************************************\ 25 * * 26 * Module: dp_linkconfig.h * 27 * Link Configuration object implementation * 28 * * 29 \***************************************************************************/ 30 #ifndef INCLUDED_DP_LINKCONFIG_H 31 #define INCLUDED_DP_LINKCONFIG_H 32 33 #include "dp_auxdefs.h" 34 #include "dp_internal.h" 35 #include "dp_watermark.h" 36 #include "ctrl/ctrl0073/ctrl0073specific.h" // NV0073_CTRL_HDCP_VPRIME_SIZE 37 #include "displayport.h" 38 39 namespace DisplayPort 40 { 41 typedef NvU64 LinkRate; 42 43 class LinkRates : virtual public Object 44 { 45 public: 46 NvU8 entries; 47 48 virtual void clear() = 0; import(NvU8 linkBw)49 virtual bool import(NvU8 linkBw) 50 { 51 DP_ASSERT(0); 52 return false; 53 } 54 55 virtual LinkRate getLowerRate(LinkRate rate) = 0; 56 virtual LinkRate getMaxRate() = 0; 57 virtual NvU8 getNumElements() = 0; 58 getNumLinkRates()59 NvU8 getNumLinkRates() 60 { 61 return entries; 62 } 63 64 }; 65 66 class LinkRates1x : virtual public LinkRates 67 { 68 public: 69 // Store link rate in multipler of 270MBPS to save space 70 NvU8 element[NV_SUPPORTED_DP1X_LINK_RATES__SIZE]; 71 LinkRates1x()72 LinkRates1x() 73 { 74 entries = 0; 75 for (int i = 0; i < NV_SUPPORTED_DP1X_LINK_RATES__SIZE; i++) 76 { 77 element[i] = 0; 78 } 79 } 80 clear()81 virtual void clear() 82 { 83 entries = 0; 84 for (int i = 0; i < NV_SUPPORTED_DP1X_LINK_RATES__SIZE; i++) 85 { 86 element[i] = 0; 87 } 88 } 89 import(NvU8 linkBw)90 virtual bool import(NvU8 linkBw) 91 { 92 if (!IS_VALID_LINKBW(linkBw)) 93 { 94 DP_ASSERT(0 && "Unsupported Link Bandwidth"); 95 return false; 96 } 97 98 if (entries < NV_SUPPORTED_DP1X_LINK_RATES__SIZE) 99 { 100 element[entries] = linkBw; 101 entries++; 102 return true; 103 } 104 else 105 return false; 106 } 107 getLowerRate(LinkRate rate)108 virtual LinkRate getLowerRate(LinkRate rate) 109 { 110 int i; 111 NvU8 linkBw = (NvU8)(rate / DP_LINK_BW_FREQ_MULTI_MBPS); 112 113 if ((entries == 0) || (linkBw <= element[0])) 114 return 0; 115 116 for (i = entries - 1; i > 0; i--) 117 { 118 if (linkBw > element[i]) 119 break; 120 } 121 122 rate = (LinkRate)element[i] * DP_LINK_BW_FREQ_MULTI_MBPS; 123 return rate; 124 } 125 getMaxRate()126 virtual LinkRate getMaxRate() 127 { 128 LinkRate rate = 0; 129 if ((entries > 0) && 130 (entries <= NV_SUPPORTED_DP1X_LINK_RATES__SIZE)) 131 { 132 rate = (LinkRate)element[entries - 1] * DP_LINK_BW_FREQ_MULTI_MBPS; 133 } 134 135 return rate; 136 } getNumElements()137 virtual NvU8 getNumElements() 138 { 139 return NV_SUPPORTED_DP1X_LINK_RATES__SIZE; 140 } 141 142 }; 143 144 class LinkPolicy : virtual public Object 145 { 146 protected: 147 bool bNoFallback; // No fallback when LT fails 148 LinkRates1x linkRates; 149 public: LinkPolicy()150 LinkPolicy() : bNoFallback(false) 151 { 152 } skipFallback()153 bool skipFallback() 154 { 155 return bNoFallback; 156 } setSkipFallBack(bool bSkipFallback)157 void setSkipFallBack(bool bSkipFallback) 158 { 159 bNoFallback = bSkipFallback; 160 } 161 getLinkRates()162 LinkRates *getLinkRates() 163 { 164 return &linkRates; 165 } 166 }; 167 168 enum 169 { 170 totalTimeslots = 64, 171 totalUsableTimeslots = totalTimeslots - 1 172 }; 173 174 // 175 // Link Data Rate per DP Lane, in MBPS, 176 // For 8b/10b channel coding: 177 // Link Data Rate = link rate * (8 / 10) / 8 178 // = link rate * 0.1 179 // For 128b/132b channel coding: 180 // Link Data Rate = link rate * (128 / 132) / 8 181 // = link rate * 4 / 33 182 // ~= link rate * 0.12 183 // 184 // Link Bandwidth = Lane Count * Link Data Rate 185 // 186 enum 187 { 188 RBR = 162000000, 189 EDP_2_16GHZ = 216000000, 190 EDP_2_43GHZ = 243000000, 191 HBR = 270000000, 192 EDP_3_24GHZ = 324000000, 193 EDP_4_32GHZ = 432000000, 194 HBR2 = 540000000, 195 HBR3 = 810000000 196 }; 197 198 struct HDCPState 199 { 200 bool HDCP_State_Encryption; 201 bool HDCP_State_1X_Capable; 202 bool HDCP_State_22_Capable; 203 bool HDCP_State_Authenticated; 204 bool HDCP_State_Repeater_Capable; 205 }; 206 207 struct HDCPValidateData 208 { 209 }; 210 211 typedef enum 212 { 213 DP_SINGLE_HEAD_MULTI_STREAM_MODE_NONE, 214 DP_SINGLE_HEAD_MULTI_STREAM_MODE_SST, 215 DP_SINGLE_HEAD_MULTI_STREAM_MODE_MST, 216 }DP_SINGLE_HEAD_MULTI_STREAM_MODE; 217 218 #define HEAD_INVALID_STREAMS 0 219 #define HEAD_DEFAULT_STREAMS 1 220 221 typedef enum 222 { 223 DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY = 0, 224 DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_SECONDARY = 1, 225 DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_MAX = DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_SECONDARY, 226 } DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID; 227 228 #define DP_INVALID_SOR_INDEX 0xFFFFFFFF 229 #define DSC_DEPTH_FACTOR 16 230 231 232 class LinkConfiguration : virtual public Object 233 { 234 public: 235 LinkPolicy policy; 236 unsigned lanes; 237 LinkRate peakRatePossible; 238 LinkRate peakRate; 239 LinkRate minRate; 240 bool enhancedFraming; 241 bool multistream; 242 bool disablePostLTRequest; 243 bool bEnableFEC; 244 bool bDisableLTTPR; 245 // 246 // The counter to record how many times link training happens. 247 // Client can reset the counter by calling setLTCounter(0) 248 // 249 unsigned linkTrainCounter; 250 LinkConfiguration()251 LinkConfiguration() : 252 lanes(0), peakRatePossible(0), peakRate(0), minRate(0), 253 enhancedFraming(false), multistream(false), disablePostLTRequest(false), 254 bEnableFEC(false), bDisableLTTPR(false), 255 linkTrainCounter(0) {}; 256 257 LinkConfiguration(LinkPolicy * p, unsigned lanes, LinkRate peakRate, 258 bool enhancedFraming, bool MST, bool disablePostLTRequest = false, 259 bool bEnableFEC = false, bool bDisableLTTPR = false) : lanes(lanes)260 lanes(lanes), peakRatePossible(peakRate), peakRate(peakRate), 261 enhancedFraming(enhancedFraming), multistream(MST), 262 disablePostLTRequest(disablePostLTRequest), 263 bEnableFEC(bEnableFEC), bDisableLTTPR(bDisableLTTPR), 264 linkTrainCounter(0) 265 { 266 // downrate for spread and FEC 267 minRate = linkOverhead(peakRate); 268 if (p) 269 { 270 policy = *p; 271 } 272 } 273 setLTCounter(unsigned counter)274 void setLTCounter(unsigned counter) 275 { 276 linkTrainCounter = counter; 277 } 278 getLTCounter()279 unsigned getLTCounter() 280 { 281 return linkTrainCounter; 282 } 283 linkOverhead(NvU64 rate)284 NvU64 linkOverhead(NvU64 rate) 285 { 286 if(bEnableFEC) 287 { 288 289 // if FEC is enabled, we have to account for 3% overhead 290 // for FEC+downspread according to DP 1.4 spec 291 292 return rate - 3 * rate/ 100; 293 } 294 else 295 { 296 // if FEC is not enabled, link overhead comprises only of 297 // 0.6% downspread. 298 return rate - 6 * rate/ 1000; 299 300 } 301 } 302 enableFEC(bool setFEC)303 void enableFEC(bool setFEC) 304 { 305 bEnableFEC = setFEC; 306 307 // If FEC is enabled, update minRate with FEC+downspread overhead. 308 minRate = linkOverhead(peakRate); 309 } 310 LinkConfiguration(unsigned long TotalLinkPBN)311 LinkConfiguration(unsigned long TotalLinkPBN) 312 : enhancedFraming(true), 313 multistream(true), 314 disablePostLTRequest(false), 315 bEnableFEC(false), 316 bDisableLTTPR(false), 317 linkTrainCounter(0) 318 { 319 // 320 // Reverse engineer a link configuration from Total TotalLinkPBN 321 // Note that HBR2 twice HBR. The table below treats HBR2x1 and HBRx2, etc. 322 // 323 // PBN Calculation 324 // Definition of PBN is "54/64 MBps". 325 // Note this is the "data" actually transmitted in the main link. 326 // So we need to take channel coding into consideration. 327 // Formula: PBN = Lane Count * Link Rate (Gbps) * 1000 * (1/8) * ChannelCoding Efficiency * (64 / 54) 328 // Example: 329 // 1. 4 * HBR2: 4 * 5.4 * 1000 * (1/8) * (8/10) * (64/54) = 2560 330 // 2. 2 * UHBR10: 2 * 10 * 1000 * (1/8) * (128/132) * (64/54) = 2873 331 // 332 // Full list: 333 // 334 // BW (Gbps) Lanes TotalLinkPBN 335 // 1.62 1 192 336 // 1.62 2 384 337 // 1.62 4 768 338 // 2.70 1 320 339 // 2.70 2 640 340 // 2.70 4 1280 341 // 5.40 1 640 342 // 5.40 2 1280 343 // 5.40 4 2560 344 // 8.10 1 960 345 // 8.10 2 1920 346 // 8.10 4 3840 347 // 10.00 1 1436 348 // 10.00 2 2873 349 // 10.00 4 5746 350 // 13.50 1 1939 351 // 13.50 2 3878 352 // 13.50 4 7757 353 // 20.00 1 2873 354 // 20.00 2 5746 355 // 20.00 4 11492 356 // 357 358 if (TotalLinkPBN <= 90) 359 { 360 peakRatePossible = peakRate = RBR; 361 minRate = linkOverhead(RBR); 362 lanes = 0; // FAIL 363 } 364 if (TotalLinkPBN <= 192) 365 { 366 peakRatePossible = peakRate = RBR; 367 minRate = linkOverhead(RBR); 368 lanes = 1; 369 } 370 else if (TotalLinkPBN <= 320) 371 { 372 peakRatePossible = peakRate = HBR; 373 minRate = linkOverhead(HBR); 374 lanes = 1; 375 } 376 else if (TotalLinkPBN <= 384) 377 { 378 peakRatePossible = peakRate = RBR; 379 minRate = linkOverhead(RBR); 380 lanes = 2; 381 } 382 else if (TotalLinkPBN <= 640) 383 { 384 // could be HBR2 x 1, but TotalLinkPBN works out same 385 peakRatePossible = peakRate = HBR; 386 minRate = linkOverhead(HBR); 387 lanes = 2; 388 } 389 else if (TotalLinkPBN <= 768) 390 { 391 peakRatePossible = peakRate = RBR; 392 minRate = linkOverhead(RBR); 393 lanes = 4; 394 } 395 else if (TotalLinkPBN <= 960) 396 { 397 peakRatePossible = peakRate = HBR3; 398 minRate = linkOverhead(HBR3); 399 lanes = 1; 400 } 401 else if (TotalLinkPBN <= 1280) 402 { 403 // could be HBR2 x 2 404 peakRatePossible = peakRate = HBR; 405 minRate = linkOverhead(HBR); 406 lanes = 4; 407 } 408 else if (TotalLinkPBN <= 1920) 409 { 410 peakRatePossible = peakRate = HBR3; 411 minRate = linkOverhead(HBR3); 412 lanes = 2; 413 } 414 else if (TotalLinkPBN <= 2560) 415 { 416 peakRatePossible = peakRate = HBR2; 417 minRate = linkOverhead(HBR2); 418 lanes = 4; 419 } 420 else if (TotalLinkPBN <= 3840) 421 { 422 peakRatePossible = peakRate = HBR3; 423 minRate = linkOverhead(HBR3); 424 lanes = 4; 425 } 426 else { 427 peakRatePossible = peakRate = RBR, minRate = linkOverhead(RBR), lanes = 0; // FAIL 428 DP_ASSERT(0 && "Unknown configuration"); 429 } 430 } 431 setEnhancedFraming(bool newEnhancedFraming)432 void setEnhancedFraming(bool newEnhancedFraming) 433 { 434 enhancedFraming = newEnhancedFraming; 435 } 436 isValid()437 bool isValid() 438 { 439 return lanes != laneCount_0; 440 } 441 442 bool lowerConfig(bool bReduceLaneCnt = false) 443 { 444 // 445 // TODO: bReduceLaneCnt is set to fallback to 4 lanes with lower 446 // valid link rate. But we should reset to max lane count 447 // sink supports instead. 448 // 449 450 LinkRate lowerRate = policy.getLinkRates()->getLowerRate(peakRate); 451 452 if(bReduceLaneCnt) 453 { 454 // Reduce laneCount before reducing linkRate 455 if(lanes == laneCount_1) 456 { 457 if (lowerRate) 458 { 459 lanes = laneCount_4; 460 peakRate = lowerRate; 461 } 462 else 463 { 464 lanes = laneCount_0; 465 } 466 } 467 else 468 { 469 lanes /= 2; 470 } 471 } 472 else 473 { 474 // Reduce the link rate instead of lane count 475 if (lowerRate) 476 { 477 peakRate = lowerRate; 478 } 479 else 480 { 481 lanes /= 2; 482 } 483 } 484 485 minRate = linkOverhead(peakRate); 486 return lanes != laneCount_0; 487 } 488 setLaneRate(LinkRate newRate,unsigned newLanes)489 void setLaneRate(LinkRate newRate, unsigned newLanes) 490 { 491 peakRate = newRate; 492 lanes = newLanes; 493 minRate = linkOverhead(peakRate); 494 } 495 pbnTotal()496 unsigned pbnTotal() 497 { 498 return PBNForSlots(totalUsableTimeslots); 499 } 500 pbnRequired(const ModesetInfo & modesetInfo,unsigned & base_pbn,unsigned & slots,unsigned & slots_pbn)501 void pbnRequired(const ModesetInfo & modesetInfo, unsigned & base_pbn, unsigned & slots, unsigned & slots_pbn) 502 { 503 base_pbn = pbnForMode(modesetInfo); 504 if (bEnableFEC) 505 { 506 // IF FEC is enabled, we need to consider 3% overhead as per DP1.4 spec. 507 base_pbn = (NvU32)(divide_ceil(base_pbn * 100, 97)); 508 } 509 slots = slotsForPBN(base_pbn); 510 slots_pbn = PBNForSlots(slots); 511 } 512 513 NvU32 slotsForPBN(NvU32 allocatedPBN, bool usable = false) 514 { 515 NvU64 bytes_per_pbn = 54 * 1000000 / 64; // this comes out exact 516 NvU64 bytes_per_timeslot = peakRate * lanes / 64; 517 518 if (bytes_per_timeslot == 0) 519 return (NvU32)-1; 520 521 if (usable) 522 { 523 // round down to find the usable integral slots for a given value of PBN. 524 NvU32 slots = (NvU32)divide_floor(allocatedPBN * bytes_per_pbn, bytes_per_timeslot); 525 DP_ASSERT(slots <= 64); 526 527 return slots; 528 } 529 else 530 return (NvU32)divide_ceil(allocatedPBN * bytes_per_pbn, bytes_per_timeslot); 531 } 532 PBNForSlots(NvU32 slots)533 NvU32 PBNForSlots(NvU32 slots) // Rounded down 534 { 535 NvU64 bytes_per_pbn = 54 * 1000000 / 64; // this comes out exact 536 NvU64 bytes_per_timeslot = peakRate * lanes / 64; 537 538 return (NvU32)(bytes_per_timeslot * slots/ bytes_per_pbn); 539 } 540 541 bool operator!= (const LinkConfiguration & right) const 542 { 543 return !(*this == right); 544 } 545 546 bool operator== (const LinkConfiguration & right) const 547 { 548 return (this->lanes == right.lanes && 549 this->peakRate == right.peakRate && 550 this->enhancedFraming == right.enhancedFraming && 551 this->multistream == right.multistream && 552 this->bEnableFEC == right.bEnableFEC); 553 } 554 555 bool operator< (const LinkConfiguration & right) const 556 { 557 NvU64 leftMKBps = peakRate * lanes; 558 NvU64 rightMKBps = right.peakRate * right.lanes; 559 560 if (leftMKBps == rightMKBps) 561 { 562 return (lanes < right.lanes); 563 } 564 else 565 { 566 return (leftMKBps < rightMKBps); 567 } 568 } 569 }; 570 } 571 #endif //INCLUDED_DP_LINKCONFIG_H 572