1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 1993-2024 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 /******************************* DisplayPort*********************************\ 25 * * 26 * Module: dp_connector.cpp * 27 * * 28 \***************************************************************************/ 29 #ifndef INCLUDED_DP_DEVICEIMPL_H 30 #define INCLUDED_DP_DEVICEIMPL_H 31 32 #include "dp_connector.h" 33 #include "dp_internal.h" 34 #include "dp_edid.h" 35 #include "dp_list.h" 36 #include "dp_auxdefs.h" 37 #include "dp_vrr.h" 38 39 namespace DisplayPort 40 { 41 #define PREDEFINED_DSC_MST_BPPX16 160; 42 #define MAX_DSC_COMPRESSION_BPPX16 128; 43 #define HDCP_BCAPS_DDC_OFFSET 0x40 44 #define HDCP_BCAPS_DDC_EN_BIT 0x80 45 #define HDCP_BCAPS_DP_EN_BIT 0x01 46 #define HDCP_I2C_CLIENT_ADDR 0x74 47 48 struct GroupImpl; 49 struct ConnectorImpl; 50 class DeviceHDCPDetection; 51 class VrrEnablement; 52 53 struct DeviceImpl : public Device, 54 public AuxBus, 55 public ListElement 56 { 57 // 58 // Shadow state: This is the last state delivered to DD. 59 // see the ConnectorImpl::fireEvents() function for handling. 60 // 61 // State is double buffered to allow for allow announces 62 // to happen at the end of the state updates. We assume 63 // the DD can call any Connector API in response to the 64 // event. 65 // 66 struct Shadow 67 { 68 bool plugged; 69 bool zombie; 70 bool cableOk; 71 bool mustDisconnect; 72 bool hdcpCapDone; 73 LinkConfiguration highestAssessedLC; 74 } shadow; 75 76 struct BandWidth 77 { 78 struct _Enum_Path 79 { 80 unsigned availableStreams, total, free; 81 bool bPathFECCapable; 82 bool dataValid; // Is the cache valid? 83 } enum_path; 84 85 struct Compound_Query_State 86 { 87 unsigned totalTimeSlots; // Total timeslots available for allocation across this node 88 89 unsigned timeslots_used_by_query; // Timeslots accounted for. 90 91 unsigned bandwidthAllocatedForIndex; // Compound query is compromised of several 92 // qeuery attaches. These query attaches 93 // may have more than one device associated. 94 // this mask keeps track of which queryAttach's 95 // have already had the stream "rounted" past 96 // this node. 97 } compound_query_state; 98 99 LinkConfiguration lastHopLinkConfig; // inferred from enum_path.total 100 101 } bandwidth; 102 103 enum rawEprState 104 { 105 software, 106 hardware 107 }; 108 109 void resetCacheInferredLink(); 110 LinkConfiguration * inferLeafLink(unsigned * totalLinkSlots); 111 112 113 DeviceImpl * parent; // Upstream parent device 114 DeviceImpl * children[16]; 115 PortMap portMap; 116 117 Edid rawEDID; 118 Edid processedEdid; 119 Edid ddcEdid; 120 DPCDHAL * hal; 121 GroupImpl * activeGroup; 122 ConnectorImpl * connector; 123 ConnectorType connectorType; 124 Address address; 125 GUID guid; 126 GUID guid2; 127 bool bVirtualPeerDevice; 128 NvU8 peerDevice; 129 NvU8 dpcdRevisionMajor; 130 NvU8 dpcdRevisionMinor; 131 bool multistream; 132 bool videoSink, audioSink; 133 bool plugged; 134 135 136 AuxRetry friendlyAux; 137 bool payloadAllocated; // did the allocate payload go through? 138 139 unsigned char BCAPS[HDCP_BCAPS_SIZE]; // Hdcp1.x bCaps raw data 140 unsigned char BKSV[HDCP_KSV_SIZE]; // Hdcp1.x bKsv raw data 141 unsigned char nvBCaps[HDCP_BCAPS_SIZE]; // NV generic HDCP BCAPS including 1.x, 2.2, ... 142 NvU64 maxTmdsClkRate; 143 144 145 bool isPendingNewDevice(); 146 bool isPendingLostDevice(); 147 bool isPendingZombie(); 148 bool isPendingCableOk(); 149 bool isPendingBandwidthChange(); 150 bool isPendingHDCPCapDone(); 151 152 TriState isHDCPCap; 153 bool isDeviceHDCPDetectionAlive; 154 DeviceHDCPDetection * deviceHDCPDetection; 155 156 PCONCaps pconCaps; 157 158 // this flag signifies that the compliance device has requested EDID read test and may follow 159 // hidden and lazy zombie policy. 160 bool complianceDeviceEdidReadTest; 161 162 bool lazyExitNow; 163 164 // VRR Enablement structure 165 VrrEnablement *vrrEnablement; 166 167 // DSC fields 168 NvU8 rawDscCaps[16]; 169 DscCaps dscCaps; 170 171 // Panel replay Caps 172 PanelReplayCaps prCaps; 173 174 bool bIsFakedMuxDevice; 175 bool bIsPreviouslyFakedMuxDevice; 176 bool bisMarkedForDeletion; 177 bool bIgnoreMsaCap; 178 bool bIgnoreMsaCapCached; 179 180 // 181 // Device doing the DSC decompression for this device. This could be device itself 182 // or its parent 183 // 184 DeviceImpl* devDoingDscDecompression; 185 // 186 // If DSC stream can be sent to this device or not. Either device itself or it's 187 // parent can do DSC decompression 188 // 189 bool bDSCPossible; 190 191 bool bFECSupported; 192 bool bFECUncorrectedSupported; 193 bool bFECCorrectedSupported; 194 bool bFECBitSupported; 195 bool bFECParityBlockSupported; 196 bool bFECParitySupported; 197 198 TriState bSdpExtCapable; 199 TriState bAsyncSDPCapable; 200 bool bMSAOverMSTCapable; 201 bool bDscPassThroughColorFormatWar; 202 bool bSkipFakeDeviceDpcdAccess; 203 204 DeviceImpl(DPCDHAL * hal, ConnectorImpl * connector, DeviceImpl * parent, bool bSkipFakeDeviceDpcdAccess); 205 ~DeviceImpl(); 206 207 virtual bool isCableOk(); 208 virtual bool isLogical(); 209 virtual bool isZombie(); 210 211 virtual unsigned getEDIDSize() const; 212 virtual bool getEDID(char * buffer, unsigned size) const; 213 virtual unsigned getRawEDIDSize() const; 214 virtual bool getRawEDID(char * buffer, unsigned size) const; 215 216 virtual bool getPCONCaps(PCONCaps *pPCONCaps); 217 getOwningGroupDeviceImpl218 virtual Group * getOwningGroup() 219 { 220 return (Group *)activeGroup; 221 } 222 223 bool isActive(); 224 225 void applyOUIOverrides(); 226 getParentDeviceImpl227 virtual Device * getParent() 228 { 229 return parent; 230 } 231 getChildDeviceImpl232 virtual Device * getChild(unsigned portNumber) 233 { 234 return children[portNumber]; 235 } 236 isMultistreamDeviceImpl237 virtual bool isMultistream() // Sink supports multistream, remember we can have 1.1 targets 238 { 239 return address.size() != 0; 240 } 241 isNativeDPCDDeviceImpl242 virtual bool isNativeDPCD() 243 { 244 return (address.size() < 2); 245 } 246 isVideoSinkDeviceImpl247 virtual bool isVideoSink() 248 { 249 return videoSink; 250 } 251 isAudioSinkDeviceImpl252 virtual bool isAudioSink() 253 { 254 return audioSink; 255 } 256 isLoopDeviceImpl257 virtual bool isLoop() 258 { 259 // implementation is pending (bug 791059) 260 return false; 261 } 262 isRedundantDeviceImpl263 virtual bool isRedundant() 264 { 265 // implementation is pending (bug 791059) 266 return false; 267 } 268 269 virtual bool isMustDisconnect(); 270 isPluggedDeviceImpl271 virtual bool isPlugged() 272 { 273 return plugged; 274 } 275 getTopologyAddressDeviceImpl276 virtual Address getTopologyAddress() const 277 { 278 return address; 279 } 280 getConnectorTypeDeviceImpl281 virtual ConnectorType getConnectorType() 282 { 283 return connectorType; 284 } 285 isFallbackEdidDeviceImpl286 virtual bool isFallbackEdid() 287 { 288 return this->processedEdid.isFallbackEdid(); 289 } 290 getGUIDDeviceImpl291 virtual GUID getGUID() const 292 { 293 return guid; 294 } 295 getPortMapDeviceImpl296 virtual PortMap getPortMap() const 297 { 298 return portMap; 299 } 300 301 virtual TriState hdcpAvailableHop(); 302 virtual TriState hdcpAvailable(); 303 isMSAOverMSTCapableDeviceImpl304 virtual bool isMSAOverMSTCapable() 305 { 306 return bMSAOverMSTCapable; 307 } 308 309 virtual bool isFakedMuxDevice(); 310 virtual bool isPreviouslyFakedMuxDevice(); 311 bypassDpcdPowerOffDeviceImpl312 bool bypassDpcdPowerOff() 313 { 314 return processedEdid.WARFlags.disableDpcdPowerOff; 315 } 316 powerOnMonitorBeforeLtDeviceImpl317 bool powerOnMonitorBeforeLt() 318 { 319 return processedEdid.WARFlags.powerOnBeforeLt; 320 } 321 forceMaxLinkConfigDeviceImpl322 bool forceMaxLinkConfig() 323 { 324 return processedEdid.WARFlags.forceMaxLinkConfig; 325 } 326 skipRedundantLtDeviceImpl327 bool skipRedundantLt() 328 { 329 return processedEdid.WARFlags.skipRedundantLt; 330 } 331 ignoreRedundantHotplugDeviceImpl332 bool ignoreRedundantHotplug() 333 { 334 return processedEdid.WARFlags.ignoreRedundantHotplug; 335 } 336 isOptimalLinkConfigOverriddenDeviceImpl337 bool isOptimalLinkConfigOverridden() 338 { 339 return processedEdid.WARFlags.overrideOptimalLinkCfg; 340 } 341 342 // Apply DPCD overrides if required 343 void dpcdOverrides(); 344 getDpcdRevisionDeviceImpl345 bool getDpcdRevision(unsigned * major, unsigned * minor) 346 { 347 if (!major || !minor) 348 { 349 DP_ASSERT(0 && "Null pointers passed in."); 350 return false; 351 } 352 353 *major = this->dpcdRevisionMajor; 354 *minor = this->dpcdRevisionMinor; 355 return true; 356 } 357 358 bool getIgnoreMSACap(); 359 360 AuxRetry::status setIgnoreMSAEnable(bool msaTimingParamIgnoreEn); 361 isVirtualPeerDeviceDeviceImpl362 bool isVirtualPeerDevice() 363 { 364 return bVirtualPeerDevice; 365 } 366 isBranchDeviceDeviceImpl367 bool isBranchDevice() 368 { 369 return !isVideoSink() && !isAudioSink(); 370 } 371 isAtLeastVersionDeviceImpl372 bool isAtLeastVersion(unsigned major, unsigned minor) 373 { 374 if (dpcdRevisionMajor > major) 375 return true; 376 377 if (dpcdRevisionMajor < major) 378 return false; 379 380 return dpcdRevisionMinor >= minor; 381 } 382 383 virtual void queryGUID2(); 384 385 virtual bool getSDPExtnForColorimetrySupported(); 386 virtual bool getAsyncSDPSupported(); 387 388 virtual bool getPanelFwRevision(NvU16 *revision); 389 390 virtual bool isPowerSuspended(); 391 392 virtual void setPanelPowerParams(bool bSinkPowerStateD0, bool bPanelPowerStateOn); 393 394 virtual status transaction(Action action, Type type, int address, 395 NvU8 * buffer, unsigned sizeRequested, 396 unsigned * sizeCompleted, 397 unsigned *pNakReason= NULL, 398 NvU8 offset= 0, NvU8 nWriteTransactions= 0); 399 virtual unsigned transactionSize(); 400 // default behaviour is querying first three registers for every lane --> flags = 0x7 401 virtual status fecTransaction(NvU8 *fecStatus, NvU16 **fecErrorCount, NvU32 flags = NV_DP_FEC_FLAGS_SELECT_ALL); getRawAuxChannelDeviceImpl402 virtual AuxBus * getRawAuxChannel() { return this; } getAuxChannelDeviceImpl403 virtual AuxRetry * getAuxChannel() { return &friendlyAux; } 404 virtual AuxBus::status getDpcdData(unsigned offset, NvU8 * buffer, 405 unsigned sizeRequested, 406 unsigned * sizeCompleted, 407 unsigned * pNakReason=NULL); 408 virtual AuxBus::status setDpcdData(unsigned offset, NvU8 * buffer, 409 unsigned sizeRequested, 410 unsigned * sizeCompleted, 411 unsigned * pNakReason=NULL); 412 virtual AuxBus::status queryFecData(NvU8 *fecStatus, NvU16 **fecErrorCount, NvU32 flags); 413 414 virtual DscCaps getDscCaps(); 415 416 // 417 // This function returns the device itself or its parent device that is doing 418 // DSC decompression for it. 419 // 420 virtual Device* getDevDoingDscDecompression(); markDeviceForDeletionDeviceImpl421 virtual void markDeviceForDeletion() {bisMarkedForDeletion = true;}; isMarkedForDeletionDeviceImpl422 virtual bool isMarkedForDeletion() {return bisMarkedForDeletion;}; 423 virtual bool getRawDscCaps(NvU8 *buffer, NvU32 bufferSize); 424 425 virtual AuxBus::status dscCrcControl(NvBool bEnable, gpuDscCrc *dataGpu, sinkDscCrc *dataSink); 426 427 // 428 // Parameter bForceMot in both getI2cData and setI2cData is used to forfully set 429 // the MOT bit. It is needed for some special cases where the MOT bit shouldn't 430 // be set but some customers need it to please their monitors. 431 // 432 virtual bool getI2cData(unsigned offset, NvU8 * buffer, unsigned sizeRequested, unsigned * sizeCompleted, bool bForceMot = false); 433 virtual bool setI2cData(unsigned offset, NvU8 * buffer, unsigned sizeRequested, unsigned * sizeCompleted, bool bForceMot = false); 434 virtual bool getRawEpr(unsigned * totalEpr, unsigned * freeEpr, rawEprState eprState); 435 436 void switchToComplianceFallback(); 437 438 // VRR Display Enablement Functions 439 bool startVrrEnablement(void); 440 void resetVrrEnablement(void); 441 bool isVrrMonitorEnabled(void); 442 bool isVrrDriverEnabled(void); 443 444 // Panel replay related functions 445 bool isPanelReplaySupported(void); 446 void getPanelReplayCaps(void); 447 bool setPanelReplayConfig(panelReplayConfig prcfg); 448 bool getPanelReplayStatus(PanelReplayStatus *pPrStatus); 449 450 NvBool getDSCSupport(); 451 bool getFECSupport(); 452 NvBool isDSCPassThroughSupported(); 453 NvBool isDynamicPPSSupported(); 454 NvBool isDynamicDscToggleSupported(); 455 NvBool isDSCSupported(); 456 NvBool isDSCDecompressionSupported(); 457 NvBool isDSCPossible(); 458 bool isFECSupported(); 459 bool readAndParseDSCCaps(); 460 bool readAndParseBranchSpecificDSCCaps(); 461 bool parseDscCaps(const NvU8 *buffer, NvU32 bufferSize); 462 bool parseBranchSpecificDscCaps(const NvU8 *buffer, NvU32 bufferSize); 463 bool setDscEnable(bool enable); 464 bool setDscEnableDPToHDMIPCON(bool bDscEnable, bool bEnablePassThroughForPCON); 465 bool getDscEnable(bool *pEnable); 466 unsigned getDscVersionMajor(); 467 unsigned getDscVersionMinor(); 468 unsigned getDscRcBufferSize(); 469 unsigned getDscRcBufferBlockSize(); 470 unsigned getDscMaxSlicesPerSink(); 471 unsigned getDscLineBufferBitDepth(); 472 NvBool isDscBlockPredictionSupported(); 473 unsigned getDscMaxBitsPerPixel(); 474 NvBool isDscRgbSupported(); 475 NvBool isDscYCbCr444Supported(); 476 NvBool isDscYCbCrSimple422Supported(); 477 NvBool isDscYCbCr422NativeSupported(); 478 NvBool isDscYCbCr420NativeSupported(); 479 unsigned getDscPeakThroughputMode0(); 480 unsigned getDscPeakThroughputModel(); 481 unsigned getDscMaxSliceWidth(); 482 unsigned getDscDecoderColorDepthSupportMask(); 483 void setDscDecompressionDevice(bool bDscCapBasedOnParent); 484 }; 485 class DeviceHDCPDetection : public Object, MessageManager::Message::MessageEventSink, Timer::TimerCallback 486 { 487 DeviceImpl* parent; 488 RemoteDpcdReadMessage remoteBKSVReadMessage; 489 RemoteDpcdReadMessage remoteBCapsReadMessage; 490 RemoteDpcdReadMessage remote22BCapsReadMessage; 491 MessageManager * messageManager; // For transmit and receive 492 Timer * timer; 493 bool bksvReadCompleted; 494 bool bCapsReadCompleted; 495 bool isValidBKSV; 496 bool isBCapsHDCP; 497 unsigned retriesRemoteBKSVReadMessage; 498 unsigned retriesRemoteBCapsReadMessage; 499 unsigned retriesRemote22BCapsReadMessage; 500 bool retryRemoteBKSVReadMessage; 501 bool retryRemoteBCapsReadMessage; 502 bool retryRemote22BCapsReadMessage; 503 bool bBKSVReadMessagePending; 504 bool bBCapsReadMessagePending; 505 506 public: 507 DeviceHDCPDetection(DeviceImpl * parent,MessageManager * messageManager,Timer * timer)508 DeviceHDCPDetection(DeviceImpl * parent, MessageManager * messageManager, Timer * timer) 509 : bksvReadCompleted(false),bCapsReadCompleted(false),isValidBKSV(false), 510 isBCapsHDCP(false), retriesRemoteBKSVReadMessage(0), retriesRemoteBCapsReadMessage(0), 511 retriesRemote22BCapsReadMessage(0), retryRemoteBKSVReadMessage(false), 512 retryRemoteBCapsReadMessage(false), retryRemote22BCapsReadMessage(false), 513 bBKSVReadMessagePending(false), bBCapsReadMessagePending(false) 514 515 { 516 this->parent = parent; 517 this->messageManager = messageManager; 518 this->timer = timer; 519 } 520 521 ~DeviceHDCPDetection(); 522 void expired(const void * tag); 523 void start(); 524 void waivePendingHDCPCapDoneNotification(); 525 526 bool hdcpValidateKsv(const NvU8 *ksv, NvU32 Size); 527 void handleRemoteDpcdReadDownReply(MessageManager::Message * from); 528 void messageFailed(MessageManager::Message * from, NakData * nakData); 529 void messageCompleted(MessageManager::Message * from); 530 }; 531 } 532 533 #endif //INCLUDED_DP_DEVICEIMPL_H 534 535