/* * SPDX-FileCopyrightText: Copyright (c) 1993-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: MIT * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /******************************* List **************************************\ * * * Module: dp_evoadapter.h * * Interface for low level access to the aux bus. * * This is the synchronous version of the interface. * * * \***************************************************************************/ #ifndef INCLUDED_DP_EVOADAPTER_H #define INCLUDED_DP_EVOADAPTER_H #include "dp_timer.h" #include "dp_auxbus.h" #include "dp_mainlink.h" #include "dp_wardatabase.h" #include "dp_auxdefs.h" #include "dp_regkeydatabase.h" #include #define HDCP_DUMMY_CN (0x1) #define HDCP_DUMMY_CKSV (0xFFFFF) namespace DisplayPort { class EvoInterface { public: // // IOCTL access to RM class DISPLAY_COMMON and NV50_DISPLAY // virtual NvU32 rmControl0073(NvU32 command, void * params, NvU32 paramSize) = 0; virtual NvU32 rmControl5070(NvU32 command, void * params, NvU32 paramSize) = 0; virtual bool getMaxLinkConfigFromUefi(NvU8 &linkRate, NvU8 &laneCount) { linkRate = 0; laneCount = 0; return true; } // // Call to tell DD that linkTraining will be performed. // Required when head is attached & we enter in flush mode GPUs. // Required to enable/disable Audio. // // Derived classes that override these functions must call down to // DisplayPort::EvoInterface::pre/postLinkTraining() to inherit this // implementation. // virtual void preLinkTraining(NvU32 head) { } virtual void postLinkTraining(NvU32 head) { } virtual NvU32 getSubdeviceIndex() = 0; virtual NvU32 getDisplayId() = 0; virtual NvU32 getSorIndex() = 0; virtual NvU32 getLinkIndex() = 0; // Link A = 0, Link B = 1 // // Query the value of a registry key. Implementations should return 0 // if the regkey is not set. // virtual NvU32 getRegkeyValue(const char *key) { return 0; } virtual NvU32 monitorDenylistInfo(NvU32 manufId, NvU32 productId, DpMonitorDenylistData *pDenylistData) { return 0; } virtual bool isInbandStereoSignalingSupported() { return false; } }; MainLink * MakeEvoMainLink(EvoInterface * provider, Timer * timer); AuxBus * MakeEvoAuxBus(EvoInterface * provider, Timer * timer); class EvoAuxBus : public AuxBus { public: EvoAuxBus(EvoInterface * provider, Timer * timer) : provider(provider), timer(timer), displayId(provider->getDisplayId()), subdeviceIndex(provider->getSubdeviceIndex()), devicePlugged(false) { } virtual status transaction(Action action, Type type, int address, NvU8 * buffer, unsigned sizeRequested, unsigned * sizeCompleted, unsigned * pNakReason = NULL, NvU8 offset = 0, NvU8 nWriteTransactions = 0); virtual unsigned transactionSize(); virtual void setDevicePlugged(bool); private: EvoInterface * provider; Timer * timer; NvU32 displayId; NvU32 subdeviceIndex; bool devicePlugged; }; class EvoMainLink : public MainLink { EvoInterface * provider; Timer * timer; NvU32 displayId; NvU32 subdeviceIndex; NvU32 _maxLinkRateSupportedGpu; NvU32 _maxLinkRateSupportedDfp; unsigned allHeadMask; bool _hasIncreasedWatermarkLimits; bool _hasMultistream; bool _isPC2Disabled; bool _isEDP; // // Bit mask for GPU supported DP versions. // Defines the same as NV0073_CTRL_CMD_DP_GET_CAPS_PARAMS.dpVersionsSupported // NvU32 _gpuSupportedDpVersions; bool _isStreamCloningEnabled; bool _needForceRmEdid; bool _skipPowerdownEDPPanelWhenHeadDetach; bool _isDscDisabledByRegkey; bool _isMstDisabledByRegkey; bool _isFECSupported; bool _useDfpMaxLinkRateCaps; bool _applyLinkBwOverrideWarRegVal; bool _isDynamicMuxCapable; bool _enableMSAOverrideOverMST; bool _enableFecCheckForDDS; bool _isLTPhyRepeaterSupported; // // LTTPR count reported by RM, it might not be the same with DPLib probe // For example, some Intel LTTPR might not be ready to response 0xF0000 probe // done by RM, but when DPLib checks the same DPCD offsets it responses // properly. This will cause serious LT problem. // unsigned _rmPhyRepeaterCount; struct DSC { bool isDscSupported; unsigned encoderColorFormatMask; unsigned lineBufferSizeKB; unsigned rateBufferSizeKB; unsigned bitsPerPixelPrecision; unsigned maxNumHztSlices; unsigned lineBufferBitDepth; }_DSC; private: void initializeRegkeyDatabase(); void applyRegkeyOverrides(); public: EvoMainLink(EvoInterface * provider, Timer * timer); virtual bool hasIncreasedWatermarkLimits() { return _hasIncreasedWatermarkLimits; } virtual bool hasMultistream() { return _hasMultistream; } virtual bool isPC2Disabled() { return _isPC2Disabled; } virtual NvU32 getGpuDpSupportedVersions() { return _gpuSupportedDpVersions; } virtual bool isFECSupported() { return _isFECSupported; } virtual bool isStreamCloningEnabled() { return _isStreamCloningEnabled; } virtual NvU32 maxLinkRateSupported() { // // For cases where RM asks dplib to honor the maxLinkRate limit defined in DCB, always use // this as the limit. Regkey has no meaning in this case. // In other cases, based on regkey either honor the dcb limit or the max link rate for the // specific GPU architecture. This is needed to avoid regressions on existing chips. // if ((_applyLinkBwOverrideWarRegVal || _useDfpMaxLinkRateCaps) && (_maxLinkRateSupportedDfp < _maxLinkRateSupportedGpu)) { return _maxLinkRateSupportedDfp; } return _maxLinkRateSupportedGpu; } virtual bool isForceRmEdidRequired() { return _needForceRmEdid; } virtual bool fetchEdidByRmCtrl(NvU8* edidBuffer, NvU32 bufferSize); virtual bool applyEdidOverrideByRmCtrl(NvU8* edidBuffer, NvU32 bufferSize); virtual bool isDynamicMuxCapable() { return _isDynamicMuxCapable; } virtual bool isInternalPanelDynamicMuxCapable() { return (_isDynamicMuxCapable && _isEDP); } // Get GPU DSC capabilities virtual void getDscCaps(bool *pbDscSupported, unsigned *pEncoderColorFormatMask, unsigned *pLineBufferSizeKB, unsigned *pRateBufferSizeKB, unsigned *pBitsPerPixelPrecision, unsigned *pMaxNumHztSlices, unsigned *pLineBufferBitDepth) { if (pbDscSupported) { *pbDscSupported = _DSC.isDscSupported; } if (pEncoderColorFormatMask) { *pEncoderColorFormatMask = _DSC.encoderColorFormatMask; } if (pLineBufferSizeKB) { *pLineBufferSizeKB = _DSC.lineBufferSizeKB; } if (pRateBufferSizeKB) { *pRateBufferSizeKB = _DSC.rateBufferSizeKB; } if (pBitsPerPixelPrecision) { *pBitsPerPixelPrecision = _DSC.bitsPerPixelPrecision; } if (pMaxNumHztSlices) { *pMaxNumHztSlices = _DSC.maxNumHztSlices; } if (pLineBufferBitDepth) { *pLineBufferBitDepth = _DSC.lineBufferBitDepth; } } virtual NvU32 getRootDisplayId() { return this->displayId; } virtual bool isLttprSupported() { return this->_isLTPhyRepeaterSupported; } // Return the current mux state. Returns false if device is not mux capable bool getDynamicMuxState(NvU32 *muxState); virtual bool aquireSema(); virtual void releaseSema(); virtual bool physicalLayerSetTestPattern(PatternInfo * patternInfo); virtual void preLinkTraining(NvU32 head); virtual void postLinkTraining(NvU32 head); virtual NvU32 getRegkeyValue(const char *key); virtual const DP_REGKEY_DATABASE& getRegkeyDatabase(); virtual NvU32 getSorIndex(); virtual bool isInbandStereoSignalingSupported(); virtual bool train(const LinkConfiguration & link, bool force, LinkTrainingType linkTrainingType, LinkConfiguration *retLink, bool bSkipLt = false, bool isPostLtAdjRequestGranted = false, unsigned phyRepeaterCount = 0); virtual bool retrieveRingBuffer(NvU8 dpRingBuffertype, NvU32 numRecords); virtual void getLinkConfig(unsigned & laneCount, NvU64 & linkRate); virtual bool getMaxLinkConfigFromUefi(NvU8 &linkRate, NvU8 &laneCount); virtual bool setDpMSAParameters(bool bStereoEnable, const NV0073_CTRL_CMD_DP_SET_MSA_PROPERTIES_PARAMS &msaparams); virtual bool setDpStereoMSAParameters(bool bStereoEnable, const NV0073_CTRL_CMD_DP_SET_MSA_PROPERTIES_PARAMS &msaparams); virtual bool setFlushMode(); virtual void clearFlushMode(unsigned headMask, bool testMode=false); virtual bool dscCrcTransaction(NvBool bEnable, gpuDscCrc *data, NvU16 *headIndex); void triggerACT(); void configureHDCPRenegotiate(NvU64 cN = HDCP_DUMMY_CN, NvU64 cKsv = HDCP_DUMMY_CKSV, bool bForceReAuth = false, bool bRxIDMsgPending = false); void configureHDCPGetHDCPState(HDCPState &hdcpState); bool rmUpdateDynamicDfpCache(NvU32 headIndex, RmDfpCache * dfpCache, NvBool bResetDfp); virtual NvU32 streamToHead(NvU32 streamId, DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID streamIdentifier = DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY); virtual NvU32 headToStream(NvU32 head, DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID streamIdentifier = DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY); void configureSingleStream(NvU32 head, NvU32 hBlankSym, NvU32 vBlankSym, bool bEnhancedFraming, NvU32 tuSize, NvU32 waterMark, DP_COLORFORMAT colorFormat, DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID streamId = DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY, DP_SINGLE_HEAD_MULTI_STREAM_MODE singleHeadMultistreamMode = DP_SINGLE_HEAD_MULTI_STREAM_MODE_NONE, bool bEnableAudioOverRightPanel = false, bool bEnable2Head1Or = false); void configureMultiStream(NvU32 head, NvU32 hBlankSym, NvU32 vBlankSym, NvU32 slotStart, NvU32 slotEnd, NvU32 PBN, NvU32 Timeslice, DP_COLORFORMAT colorFormat, DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID streamIdentifier = DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY, DP_SINGLE_HEAD_MULTI_STREAM_MODE singleHeadMultistreamMode = DP_SINGLE_HEAD_MULTI_STREAM_MODE_NONE, bool bEnableAudioOverRightPanel = false, bool bEnable2Head1Or = false); void configureSingleHeadMultiStreamMode(NvU32 displayIDs[], NvU32 numStreams, NvU32 mode, bool bSetConfig, NvU8 vbiosPrimaryDispIdIndex = DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY); void configureMsScratchRegisters(NvU32 address, NvU32 hopCount, NvU32 driverState); bool isActive(); bool isEDP(); bool skipPowerdownEdpPanelWhenHeadDetach(); bool supportMSAOverMST(); bool queryAndUpdateDfpParams(); bool controlRateGoverning(NvU32 head, bool enable, bool updateNow); bool getDpTestPattern(NV0073_CTRL_DP_TESTPATTERN *testPattern); bool setDpTestPattern(NV0073_CTRL_DP_TESTPATTERN testPattern, NvU8 laneMask, NV0073_CTRL_DP_CSTM cstm, NvBool bIsHBR2, NvBool bSkipLaneDataOverride); bool getDpLaneData(NvU32 *numLanes, NvU32 *data); bool setDpLaneData(NvU32 numLanes, NvU32 *data); void configurePowerState(bool bPowerUp); NvU32 monitorDenylistInfo(NvU32 ManufacturerID, NvU32 ProductID, DpMonitorDenylistData *pDenylistData); NvU32 allocDisplayId(); bool freeDisplayId(NvU32 displayId); void queryGPUCapability(); bool getEdpPowerData(bool *panelPowerOn, bool *dpcdPowerStateD0); virtual bool vrrRunEnablementStage(unsigned stage, NvU32 *status); void configureTriggerSelect(NvU32 head, DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID streamIdentifier = DP_SINGLE_HEAD_MULTI_STREAM_PIPELINE_ID_PRIMARY); void configureTriggerAll(NvU32 head, bool enable); bool configureLinkRateTable(const NvU16 *pLinkRateTable, LinkRates *pLinkRates); bool configureFec(const bool bEnableFec); }; } #endif //INCLUDED_DP_EVOADAPTER_H