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