mirror of
https://github.com/NVIDIA/open-gpu-kernel-modules.git
synced 2026-02-09 17:50:00 +00:00
580.95.05
This commit is contained in:
@@ -54,6 +54,7 @@ CFLAGS += -D__NO_CTYPE
|
||||
|
||||
CFLAGS += -DNV_CPU_INTRINSICS_KERNEL
|
||||
CFLAGS += -DNVHDMIPKT_RM_CALLS_INTERNAL=0
|
||||
CFLAGS += -DNVHDMIPKT_NVKMS
|
||||
|
||||
# XXX it would be nice to only define these for appropriate files...
|
||||
CFLAGS += -DSOFTFLOAT_ROUND_ODD
|
||||
|
||||
@@ -39,8 +39,6 @@ void nvDPNotifyShortPulse(NVDPLibConnectorPtr pNVDpLibConnector);
|
||||
|
||||
void nvDPDestroyConnector(NVDPLibConnectorPtr pNVDpLibConnector);
|
||||
|
||||
NvBool nvDPIsLinkAwaitingTransition(NVConnectorEvoPtr pConnectorEvo);
|
||||
|
||||
NVDPLibModesetStatePtr nvDPLibCreateModesetState(
|
||||
const NVDispEvoRec *pDispEvo,
|
||||
const NvU32 head,
|
||||
|
||||
@@ -28,5 +28,6 @@
|
||||
|
||||
void nvHandleHotplugEventDeferredWork(void *dataPtr, NvU32 dataU32);
|
||||
void nvHandleDPIRQEventDeferredWork(void *dataPtr, NvU32 dataU32);
|
||||
void nvHandleHDMIFRLRetrainEventDeferredWork(void *dataPtr, NvU32 dataU32);
|
||||
|
||||
#endif /* __NVKMS_EVENT_H__ */
|
||||
|
||||
@@ -61,14 +61,14 @@ void nvTeardownHdmiLibrary(NVDevEvoRec *pDevEvo);
|
||||
|
||||
NvBool nvHdmiFrlAssessLink(NVDpyEvoPtr pDpyEvo);
|
||||
NvBool nvHdmiDpySupportsFrl(const NVDpyEvoRec *pDpyEvo);
|
||||
NvBool nvHdmiFrlQueryConfig(const NVDpyEvoRec *pDpyEvo,
|
||||
const NvModeTimings *pModeTimings,
|
||||
const NVHwModeTimingsEvo *pHwTimings,
|
||||
NVDpyAttributeColor *pDpyColor,
|
||||
const NvBool b2Heads1Or,
|
||||
const struct NvKmsModeValidationParams *pValidationParams,
|
||||
HDMI_FRL_CONFIG *pConfig,
|
||||
NVDscInfoEvoRec *pDscInfo);
|
||||
NvBool nvHdmiFrlQueryConfigOneColorSpaceAndBpc(const NVDpyEvoRec *pDpyEvo,
|
||||
const NvModeTimings *pModeTimings,
|
||||
const NVHwModeTimingsEvo *pHwTimings,
|
||||
const NVDpyAttributeColor *pDpyColor,
|
||||
const NvBool b2Heads1Or,
|
||||
const struct NvKmsModeValidationParams *pValidationParams,
|
||||
HDMI_FRL_CONFIG *pConfig,
|
||||
NVDscInfoEvoRec *pDscInfo);
|
||||
void nvHdmiFrlClearConfig(NVDispEvoRec *pDispEvo, NvU32 activeRmId);
|
||||
void nvHdmiFrlSetConfig(NVDispEvoRec *pDispEvo, NvU32 head);
|
||||
|
||||
@@ -80,6 +80,12 @@ NvBool nvHdmiIsTmdsPossible(const NVDpyEvoRec *pDpyEvo,
|
||||
const NVHwModeTimingsEvo *pHwTimings,
|
||||
const NVDpyAttributeColor *pDpyColor);
|
||||
|
||||
static inline NvBool nvHdmiIsFrlPossible(const NVDpyEvoRec *pDpyEvo)
|
||||
{
|
||||
return nvHdmiDpySupportsFrl(pDpyEvo) &&
|
||||
(pDpyEvo->hdmi.sinkCaps.linkMaxFRLRate != HDMI_FRL_DATA_RATE_NONE);
|
||||
}
|
||||
|
||||
static inline NvBool nvHdmiDpySupportsDsc(const NVDpyEvoRec *pDpyEvo)
|
||||
{
|
||||
return nvDpyIsHdmiEvo(pDpyEvo) &&
|
||||
|
||||
@@ -277,7 +277,7 @@ typedef struct _NVHsChannelEvoRec {
|
||||
*/
|
||||
NVRgLine1CallbackPtr pRgIntrCallback;
|
||||
|
||||
#if NVKMS_PROCFS_ENABLE
|
||||
#if NVKMS_HEADSURFACE_STATS
|
||||
|
||||
/*
|
||||
* We track statistics differently for SwapGroup and non-SwapGroup
|
||||
@@ -342,7 +342,7 @@ typedef struct _NVHsChannelEvoRec {
|
||||
} statistics;
|
||||
#else
|
||||
#define NVKMS_HEADSURFACE_STATS_MAX_SEMAPHORES 0
|
||||
#endif /* NVKMS_PROCFS_ENABLE */
|
||||
#endif /* NVKMS_HEADSURFACE_STATS */
|
||||
|
||||
/*
|
||||
* We need one semaphore for the non-stall interrupt following rendering to
|
||||
|
||||
@@ -123,7 +123,7 @@ NVSurfaceEvoRec *nvHsGetNvKmsSurface(const NVDevEvoRec *pDevEvo,
|
||||
NvKmsSurfaceHandle surfaceHandle,
|
||||
const NvBool requireDisplayHardwareAccess);
|
||||
|
||||
#if NVKMS_PROCFS_ENABLE
|
||||
#if NVKMS_HEADSURFACE_STATS
|
||||
void nvHsProcFs(
|
||||
NVEvoInfoStringRec *pInfoString,
|
||||
NVDevEvoRec *pDevEvo,
|
||||
|
||||
@@ -66,9 +66,13 @@ extern "C" {
|
||||
#include "nv_smg.h"
|
||||
|
||||
#if defined(DEBUG) || defined(DEVELOP)
|
||||
#define NVKMS_PROCFS_ENABLE 1
|
||||
#define NVKMS_HEADSURFACE_STATS 1
|
||||
#define NVKMS_PROCFS_OBJECT_DUMP 1
|
||||
#define NVKMS_PROCFS_CRCS 1
|
||||
#else
|
||||
#define NVKMS_PROCFS_ENABLE 0
|
||||
#define NVKMS_HEADSURFACE_STATS 0
|
||||
#define NVKMS_PROCFS_OBJECT_DUMP 0
|
||||
#define NVKMS_PROCFS_CRCS 0
|
||||
#endif
|
||||
|
||||
#define NV_DMA_EVO_PUSH_BUFFER_SIZE (4 * 1024)
|
||||
@@ -2041,8 +2045,10 @@ typedef struct _NVDispEvoRec {
|
||||
NVDevEvoPtr pDevEvo;
|
||||
NvU32 hotplugEventHandle;
|
||||
NvU32 DPIRQEventHandle;
|
||||
NvU32 HDMIFRLRetrainEventHandle;
|
||||
NVOS10_EVENT_KERNEL_CALLBACK_EX rmHotplugCallback;
|
||||
NVOS10_EVENT_KERNEL_CALLBACK_EX rmDPIRQCallback;
|
||||
NVOS10_EVENT_KERNEL_CALLBACK_EX rmHDMIFRLRetrainCallback;
|
||||
|
||||
NVDispHeadStateEvoRec headState[NVKMS_MAX_HEADS_PER_DISP];
|
||||
NVDispApiHeadStateEvoRec apiHeadState[NVKMS_MAX_HEADS_PER_DISP];
|
||||
@@ -2296,6 +2302,8 @@ typedef struct _NVDpyEvoRec {
|
||||
struct {
|
||||
HDMI_SRC_CAPS srcCaps;
|
||||
HDMI_SINK_CAPS sinkCaps;
|
||||
|
||||
NvBool reassessFrlLinkCaps : 1;
|
||||
} hdmi;
|
||||
|
||||
struct {
|
||||
@@ -2831,7 +2839,7 @@ struct _NVSurfaceEvoRec {
|
||||
NvU64 rmRefCnt;
|
||||
NvU64 structRefCnt;
|
||||
|
||||
#if NVKMS_PROCFS_ENABLE
|
||||
#if NVKMS_PROCFS_OBJECT_DUMP
|
||||
NvBool procFsFlag;
|
||||
#endif
|
||||
|
||||
@@ -3288,6 +3296,7 @@ typedef const struct _nv_evo_hal {
|
||||
NvU32 supportsDPAudio192KHz :1;
|
||||
NvU32 supportsInputColorSpace :1;
|
||||
NvU32 supportsInputColorRange :1;
|
||||
NvU32 supportsYCbCr422OverHDMIFRL :1;
|
||||
|
||||
NvU32 supportedDitheringModes;
|
||||
size_t impStructSize;
|
||||
|
||||
@@ -279,7 +279,7 @@ void nvEvoDestroyApiHandles(NVEvoApiHandlesPtr pEvoApiHandles);
|
||||
(_pointer) = nvEvoGetPointerFromApiHandleNext(_pEvoApiHandles, \
|
||||
&(_handle)))
|
||||
|
||||
|
||||
NvBool nvDoDebugLogging(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
|
||||
@@ -667,7 +667,9 @@ enum NvKmsInputTf {
|
||||
enum NvKmsOutputColorimetry {
|
||||
NVKMS_OUTPUT_COLORIMETRY_DEFAULT = 0,
|
||||
|
||||
NVKMS_OUTPUT_COLORIMETRY_BT2100 = 1,
|
||||
NVKMS_OUTPUT_COLORIMETRY_BT601 = 1,
|
||||
NVKMS_OUTPUT_COLORIMETRY_BT709 = 2,
|
||||
NVKMS_OUTPUT_COLORIMETRY_BT2100 = 3,
|
||||
};
|
||||
|
||||
enum NvKmsOutputTf {
|
||||
|
||||
@@ -119,6 +119,7 @@ NvBool nvkms_vblank_sem_control(void);
|
||||
NvBool nvkms_opportunistic_display_sync(void);
|
||||
enum NvKmsDebugForceColorSpace nvkms_debug_force_color_space(void);
|
||||
NvBool nvkms_enable_overlay_layers(void);
|
||||
NvBool nvkms_debug_logging(void);
|
||||
|
||||
void nvkms_call_rm (void *ops);
|
||||
void* nvkms_alloc (size_t size,
|
||||
|
||||
@@ -151,16 +151,6 @@ void nvDPDestroyConnector(NVDPLibConnectorPtr pNVDpLibConnector)
|
||||
nvFree(pNVDpLibConnector);
|
||||
}
|
||||
|
||||
NvBool nvDPIsLinkAwaitingTransition(NVConnectorEvoPtr pConnectorEvo)
|
||||
{
|
||||
if (nvConnectorUsesDPLib(pConnectorEvo)) {
|
||||
DisplayPort::Connector *c = pConnectorEvo->pDpLibConnector->connector;
|
||||
return c->isLinkAwaitingTransition();
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Create a new DisplayPort group and populate it with the devices specified by
|
||||
* dpyIdList. For MST groups, this allocates a dynamic RM display ID.
|
||||
@@ -1128,10 +1118,11 @@ void nvDPSetAllowMultiStreamingOneConnector(
|
||||
pDpLibConnector->connector->setAllowMultiStreaming(allowMST);
|
||||
}
|
||||
|
||||
static NvBool IsDpSinkMstCapableForceSst(const NVDispEvoRec *pDispEvo,
|
||||
const NvU32 apiHead,
|
||||
void *pData)
|
||||
static NvBool IsDpSinkMstTransitionNeeded(const NVDispEvoRec *pDispEvo,
|
||||
const NvU32 apiHead,
|
||||
void *pData)
|
||||
{
|
||||
const NvBool *pAllowMST = reinterpret_cast<const NvBool*>(pData);
|
||||
const NVDispApiHeadStateEvoRec *pApiHeadState =
|
||||
&pDispEvo->apiHeadState[apiHead];
|
||||
const NVDpyEvoRec *pDpyEvo =
|
||||
@@ -1147,49 +1138,24 @@ static NvBool IsDpSinkMstCapableForceSst(const NVDispEvoRec *pDispEvo,
|
||||
DisplayPort::Connector *c =
|
||||
pConnectorEvo->pDpLibConnector->connector;
|
||||
|
||||
return (c->getSinkMultiStreamCap() && !c->getAllowMultiStreaming());
|
||||
}
|
||||
return c->isLinkAwaitingTransition() ||
|
||||
(c->getSinkMultiStreamCap() &&
|
||||
c->getAllowMultiStreaming() != *pAllowMST);
|
||||
|
||||
static NvBool IsDpLinkTransitionWaitingForHeadShutDown(
|
||||
const NVDispEvoRec *pDispEvo,
|
||||
const NvU32 apiHead,
|
||||
void *pData)
|
||||
{
|
||||
const NVDispApiHeadStateEvoRec *pApiHeadState =
|
||||
&pDispEvo->apiHeadState[apiHead];
|
||||
const NVDpyEvoRec *pDpyEvo =
|
||||
nvGetOneArbitraryDpyEvo(pApiHeadState->activeDpys, pDispEvo);
|
||||
|
||||
return (pDpyEvo != NULL) &&
|
||||
nvDPIsLinkAwaitingTransition(pDpyEvo->pConnectorEvo);
|
||||
}
|
||||
|
||||
void nvDPSetAllowMultiStreaming(NVDevEvoPtr pDevEvo, NvBool allowMST)
|
||||
{
|
||||
NvBool needUpdate = FALSE;
|
||||
NVDispEvoPtr pDispEvo;
|
||||
NvU32 dispIndex;
|
||||
|
||||
FOR_ALL_EVO_DISPLAYS(pDispEvo, dispIndex, pDevEvo) {
|
||||
NVConnectorEvoPtr pConnectorEvo;
|
||||
|
||||
FOR_ALL_EVO_CONNECTORS(pConnectorEvo, pDispEvo) {
|
||||
NVDPLibConnectorPtr pDpLibConnector =
|
||||
pConnectorEvo->pDpLibConnector;
|
||||
if (pDpLibConnector &&
|
||||
pDpLibConnector->connector->getAllowMultiStreaming()
|
||||
!= allowMST) {
|
||||
needUpdate = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!needUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Shut down any heads that are driving SST and need to transition to MST,
|
||||
* and any heads where we're toggling the value of allowMST.
|
||||
*/
|
||||
nvShutDownApiHeads(pDevEvo, pDevEvo->pNvKmsOpenDev,
|
||||
IsDpSinkMstCapableForceSst, NULL /* pData */,
|
||||
IsDpSinkMstTransitionNeeded,
|
||||
reinterpret_cast<void *>(&allowMST),
|
||||
TRUE /* doRasterLock */);
|
||||
|
||||
/*
|
||||
@@ -1214,15 +1180,10 @@ void nvDPSetAllowMultiStreaming(NVDevEvoPtr pDevEvo, NvBool allowMST)
|
||||
}
|
||||
}
|
||||
|
||||
/* Shut down all DisplayPort heads that need to transition to/from SST. */
|
||||
nvShutDownApiHeads(pDevEvo, pDevEvo->pNvKmsOpenDev,
|
||||
IsDpLinkTransitionWaitingForHeadShutDown,
|
||||
NULL /* pData */,
|
||||
TRUE /* doRasterLock */);
|
||||
|
||||
/*
|
||||
* Handle any pending timers the DP library scheduled to notify us
|
||||
* about changes in the connected device list.
|
||||
* about changes to MST devices on connectors that now allow or disallow
|
||||
* MST.
|
||||
*/
|
||||
nvDPFireExpiredTimers(pDevEvo);
|
||||
}
|
||||
|
||||
@@ -63,6 +63,8 @@ void dpPrintf(DP_LOG_LEVEL severity, const char *format, ...)
|
||||
{
|
||||
if (severity == DP_SILENT) return;
|
||||
|
||||
if (!nvDoDebugLogging()) return;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
nvVEvoLog(dpSeverityToNvkmsMap(severity), NV_INVALID_GPU_LOG_INDEX, format, ap);
|
||||
|
||||
@@ -644,22 +644,13 @@ static void DpyPostColorSpaceOrRangeSetEvo(NVDpyEvoPtr pDpyEvo)
|
||||
colorSpaceChanged = (pApiHeadState->attributes.color.format != colorSpace);
|
||||
colorBpcChanged = (pApiHeadState->attributes.color.bpc != colorBpc);
|
||||
|
||||
/* For DP, neither color space nor bpc can be changed without a modeset */
|
||||
if (nvConnectorUsesDPLib(pDpyEvo->pConnectorEvo) &&
|
||||
/* For DP and HDMI FRL, neither color space nor bpc can be changed without a modeset */
|
||||
if ((nvConnectorUsesDPLib(pDpyEvo->pConnectorEvo) ||
|
||||
(pApiHeadState->timings.protocol == NVKMS_PROTOCOL_SOR_HDMI_FRL)) &&
|
||||
(colorSpaceChanged || colorBpcChanged)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hardware does not support HDMI FRL with YUV422, and it is not possible
|
||||
* to downgrade current color bpc on HDMI FRL at this point.
|
||||
*/
|
||||
if ((pApiHeadState->timings.protocol == NVKMS_PROTOCOL_SOR_HDMI_FRL) &&
|
||||
((colorSpace == NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr422) ||
|
||||
(pApiHeadState->attributes.color.bpc > colorBpc))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nvDpyIsHdmiEvo(pDpyEvo) &&
|
||||
(colorBpc > pApiHeadState->attributes.color.bpc)) {
|
||||
NVDpyAttributeColor tmpDpyColor = pApiHeadState->attributes.color;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "dp/nvdp-device.h"
|
||||
#include "dp/nvdp-connector-event-sink.h"
|
||||
|
||||
#include "nvkms-api-types.h"
|
||||
#include "nvkms-evo.h"
|
||||
#include "nvkms-dpy.h"
|
||||
#include "nvkms-dpy-override.h"
|
||||
@@ -44,6 +45,7 @@
|
||||
#include "timing/dpsdp.h"
|
||||
|
||||
#include "displayport/displayport.h"
|
||||
#include "timing/nvtiming.h"
|
||||
|
||||
#include <ctrl/ctrl0073/ctrl0073dfp.h> // NV0073_CTRL_DFP_FLAGS_*
|
||||
#include <ctrl/ctrl0073/ctrl0073dp.h> // NV0073_CTRL_CMD_DP_GET_LINK_CONFIG_*
|
||||
@@ -100,23 +102,6 @@ static void DpyDisconnectEvo(NVDpyEvoPtr pDpyEvo, const NvBool bSendHdmiCapsToRm
|
||||
ClearEdid(pDpyEvo, bSendHdmiCapsToRm);
|
||||
}
|
||||
|
||||
static void HdmiFrlSetConfig(NVDpyEvoRec *pDpyEvo)
|
||||
{
|
||||
NVDispEvoRec *pDispEvo = pDpyEvo->pDispEvo;
|
||||
NvU32 head;
|
||||
|
||||
if ((pDpyEvo->apiHead == NV_INVALID_HEAD) || !nvDpyIsHdmiEvo(pDpyEvo) ||
|
||||
!nvHdmiDpySupportsFrl(pDpyEvo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
head = nvGetPrimaryHwHead(pDispEvo, pDpyEvo->apiHead);
|
||||
|
||||
nvAssert(head != NV_INVALID_HEAD);
|
||||
|
||||
nvHdmiFrlSetConfig(pDispEvo, head);
|
||||
}
|
||||
|
||||
static NvBool DpyConnectEvo(
|
||||
NVDpyEvoPtr pDpyEvo,
|
||||
struct NvKmsQueryDpyDynamicDataParams *pParams)
|
||||
@@ -140,8 +125,6 @@ static NvBool DpyConnectEvo(
|
||||
|
||||
nvUpdateInfoFrames(pDpyEvo);
|
||||
|
||||
HdmiFrlSetConfig(pDpyEvo);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -682,7 +665,20 @@ static void ReadAndApplyEdidEvo(
|
||||
&infoString);
|
||||
} else {
|
||||
nvFree(edid.buffer);
|
||||
|
||||
if (nvDpyIsHdmiEvo(pDpyEvo) &&
|
||||
nvHdmiDpySupportsFrl(pDpyEvo) &&
|
||||
pDpyEvo->hdmi.reassessFrlLinkCaps) {
|
||||
/*
|
||||
* Although there’s no change in EDID, if there was a HPD or
|
||||
* re-training request, reassess the FRL Link.
|
||||
*/
|
||||
nvHdmiFrlAssessLink(pDpyEvo);
|
||||
}
|
||||
}
|
||||
|
||||
pDpyEvo->hdmi.reassessFrlLinkCaps = FALSE;
|
||||
|
||||
nvFree(pParsedEdid);
|
||||
}
|
||||
|
||||
@@ -2593,6 +2589,8 @@ void nvConstructDpVscSdp(const NVDispHeadInfoFrameStateEvoRec *pInfoFrame,
|
||||
sdp->db.colorimetryFormat =
|
||||
SDP_VSC_COLOR_FMT_RGB_COLORIMETRY_ITU_R_BT2020_RGB;
|
||||
break;
|
||||
case NVKMS_OUTPUT_COLORIMETRY_BT601:
|
||||
case NVKMS_OUTPUT_COLORIMETRY_BT709:
|
||||
case NVKMS_OUTPUT_COLORIMETRY_DEFAULT:
|
||||
sdp->db.colorimetryFormat =
|
||||
SDP_VSC_COLOR_FMT_RGB_COLORIMETRY_SRGB;
|
||||
@@ -2622,6 +2620,14 @@ void nvConstructDpVscSdp(const NVDispHeadInfoFrameStateEvoRec *pInfoFrame,
|
||||
sdp->db.colorimetryFormat =
|
||||
SDP_VSC_COLOR_FMT_YCBCR_COLORIMETRY_ITU_R_BT2020_YCBCR;
|
||||
break;
|
||||
case NVKMS_OUTPUT_COLORIMETRY_BT601:
|
||||
sdp->db.colorimetryFormat =
|
||||
SDP_VSC_COLOR_FMT_YCBCR_COLORIMETRY_ITU_R_BT601;
|
||||
break;
|
||||
case NVKMS_OUTPUT_COLORIMETRY_BT709:
|
||||
sdp->db.colorimetryFormat =
|
||||
SDP_VSC_COLOR_FMT_YCBCR_COLORIMETRY_ITU_R_BT709;
|
||||
break;
|
||||
case NVKMS_OUTPUT_COLORIMETRY_DEFAULT:
|
||||
sdp->db.colorimetryFormat =
|
||||
(pInfoFrame->hdTimings ?
|
||||
@@ -2674,6 +2680,7 @@ static void UpdateDpVscSdpInfoFrame(
|
||||
&pDispEvo->headState[head];
|
||||
NV0073_CTRL_SPECIFIC_SET_OD_PACKET_PARAMS params = { 0 };
|
||||
NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
|
||||
DPSDP_DP_VSC_SDP_DESCRIPTOR *sdp;
|
||||
NvU32 ret;
|
||||
|
||||
/*
|
||||
@@ -2687,31 +2694,23 @@ static void UpdateDpVscSdpInfoFrame(
|
||||
params.subDeviceInstance = pDispEvo->displayOwner;
|
||||
params.displayId = pHeadState->activeRmId;
|
||||
|
||||
if ((pDpyColor->format == NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr420) ||
|
||||
(pDpyColor->colorimetry == NVKMS_OUTPUT_COLORIMETRY_BT2100)) {
|
||||
// DPSDP_DP_VSC_SDP_DESCRIPTOR has a (dataSize, hb, db) layout, while
|
||||
// NV0073_CTRL_SPECIFIC_SET_OD_PACKET_PARAMS.aPacket needs to contain
|
||||
// (hb, db) without dataSize, so this makes sdp->hb align with aPacket.
|
||||
sdp = (DPSDP_DP_VSC_SDP_DESCRIPTOR *)(params.aPacket -
|
||||
offsetof(DPSDP_DP_VSC_SDP_DESCRIPTOR, hb));
|
||||
|
||||
// DPSDP_DP_VSC_SDP_DESCRIPTOR has a (dataSize, hb, db) layout, while
|
||||
// NV0073_CTRL_SPECIFIC_SET_OD_PACKET_PARAMS.aPacket needs to contain
|
||||
// (hb, db) without dataSize, so this makes sdp->hb align with aPacket.
|
||||
DPSDP_DP_VSC_SDP_DESCRIPTOR *sdp =
|
||||
(DPSDP_DP_VSC_SDP_DESCRIPTOR *)(params.aPacket -
|
||||
offsetof(DPSDP_DP_VSC_SDP_DESCRIPTOR, hb));
|
||||
nvAssert((void *)&sdp->hb == (void *)params.aPacket);
|
||||
|
||||
nvAssert((void *)&sdp->hb == (void *)params.aPacket);
|
||||
nvConstructDpVscSdp(pInfoFrame, pDpyColor, sdp);
|
||||
|
||||
nvConstructDpVscSdp(pInfoFrame, pDpyColor, sdp);
|
||||
params.packetSize = sizeof(sdp->hb) + sdp->hb.numValidDataBytes;
|
||||
|
||||
params.packetSize = sizeof(sdp->hb) + sdp->hb.numValidDataBytes;
|
||||
|
||||
params.transmitControl =
|
||||
DRF_DEF(0073_CTRL_SPECIFIC, _SET_OD_PACKET_TRANSMIT_CONTROL, _ENABLE, _YES) |
|
||||
DRF_DEF(0073_CTRL_SPECIFIC, _SET_OD_PACKET_TRANSMIT_CONTROL, _OTHER_FRAME, _DISABLE) |
|
||||
DRF_DEF(0073_CTRL_SPECIFIC, _SET_OD_PACKET_TRANSMIT_CONTROL, _SINGLE_FRAME, _DISABLE) |
|
||||
DRF_DEF(0073_CTRL_SPECIFIC, _SET_OD_PACKET_TRANSMIT_CONTROL, _ON_HBLANK, _DISABLE);
|
||||
} else {
|
||||
params.transmitControl =
|
||||
DRF_DEF(0073_CTRL_SPECIFIC, _SET_OD_PACKET_TRANSMIT_CONTROL, _ENABLE, _NO);
|
||||
}
|
||||
params.transmitControl =
|
||||
DRF_DEF(0073_CTRL_SPECIFIC, _SET_OD_PACKET_TRANSMIT_CONTROL, _ENABLE, _YES) |
|
||||
DRF_DEF(0073_CTRL_SPECIFIC, _SET_OD_PACKET_TRANSMIT_CONTROL, _OTHER_FRAME, _DISABLE) |
|
||||
DRF_DEF(0073_CTRL_SPECIFIC, _SET_OD_PACKET_TRANSMIT_CONTROL, _SINGLE_FRAME, _DISABLE) |
|
||||
DRF_DEF(0073_CTRL_SPECIFIC, _SET_OD_PACKET_TRANSMIT_CONTROL, _ON_HBLANK, _DISABLE);
|
||||
|
||||
ret = nvRmApiControl(nvEvoGlobal.clientHandle,
|
||||
pDevEvo->displayCommonHandle,
|
||||
@@ -3360,10 +3359,10 @@ NvKmsDpyOutputColorFormatInfo nvDpyGetOutputColorFormatInfo(
|
||||
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
|
||||
}
|
||||
} else if (nvConnectorUsesDPLib(pDpyEvo->pConnectorEvo)) {
|
||||
const NVT_EDID_INFO *info = &pDpyEvo->parsedEdid.info;
|
||||
|
||||
if (pDpyEvo->parsedEdid.valid &&
|
||||
pDpyEvo->parsedEdid.info.input.isDigital &&
|
||||
pDpyEvo->parsedEdid.info.version >= NVT_EDID_VER_1_4) {
|
||||
info->input.isDigital && info->version >= NVT_EDID_VER_1_4) {
|
||||
if (pDpyEvo->parsedEdid.info.input.u.digital.bpc >= 10) {
|
||||
colorFormatsInfo.rgb444.maxBpc =
|
||||
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_10;
|
||||
@@ -3407,6 +3406,39 @@ NvKmsDpyOutputColorFormatInfo nvDpyGetOutputColorFormatInfo(
|
||||
colorFormatsInfo.rgb444.minBpc =
|
||||
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
|
||||
}
|
||||
|
||||
if (pDpyEvo->parsedEdid.valid && info->input.isDigital &&
|
||||
(info->input.u.digital.video_interface ==
|
||||
NVT_EDID_DIGITAL_VIDEO_INTERFACE_STANDARD_HDMI_A_SUPPORTED ||
|
||||
info->input.u.digital.video_interface ==
|
||||
NVT_EDID_DIGITAL_VIDEO_INTERFACE_STANDARD_HDMI_B_SUPPORTED)) {
|
||||
|
||||
/*
|
||||
* Prevent RGB 444 @ 6 BPC on active DP-to-HDMI adapters since
|
||||
* HDMI does not support RGB 444 @ 6 BPC.
|
||||
*/
|
||||
if (colorFormatsInfo.rgb444.minBpc ==
|
||||
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_6) {
|
||||
colorFormatsInfo.rgb444.minBpc =
|
||||
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
|
||||
}
|
||||
|
||||
// Prevent >=10 BPC on active DP-to-HDMI adapters, if the dc_30_bit is not set
|
||||
if ((info->version < NVT_EDID_VER_1_4 ||
|
||||
!info->hdmiLlcInfo.dc_30_bit) &&
|
||||
colorFormatsInfo.rgb444.maxBpc !=
|
||||
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_UNKNOWN) {
|
||||
colorFormatsInfo.rgb444.maxBpc =
|
||||
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
|
||||
}
|
||||
if ((info->version < NVT_EDID_VER_1_4 ||
|
||||
!info->hdmiLlcInfo.dc_30_bit) &&
|
||||
colorFormatsInfo.yuv444.maxBpc !=
|
||||
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_UNKNOWN) {
|
||||
colorFormatsInfo.yuv444.maxBpc =
|
||||
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
colorFormatsInfo.rgb444.maxBpc =
|
||||
nvDpyIsHdmiDepth30Evo(pDpyEvo) ?
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "nvkms-utils.h"
|
||||
#include "nvkms-private.h"
|
||||
#include "nvkms-evo.h"
|
||||
#include "nvkms-hdmi.h"
|
||||
|
||||
/*
|
||||
* Handle a display device hotplug event.
|
||||
@@ -180,6 +181,10 @@ nvHandleHotplugEventDeferredWork(void *dataPtr, NvU32 dataU32)
|
||||
} else {
|
||||
nvSendDpyEventEvo(pDpyEvo, NVKMS_EVENT_TYPE_DPY_CHANGED);
|
||||
}
|
||||
|
||||
if (nvDpyIsHdmiEvo(pDpyEvo)) {
|
||||
pDpyEvo->hdmi.reassessFrlLinkCaps = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,3 +210,14 @@ nvHandleDPIRQEventDeferredWork(void *dataPtr, NvU32 dataU32)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nvHandleHDMIFRLRetrainEventDeferredWork(void *dataPtr, NvU32 dataU32)
|
||||
{
|
||||
NVDispEvoPtr pDispEvo = dataPtr;
|
||||
NVDpyId id = nvNvU32ToDpyId(dataU32);
|
||||
NVDpyEvoRec *pDpyEvo = nvGetDpyEvoFromDispEvo(pDispEvo, id);
|
||||
|
||||
nvSendDpyEventEvo(pDpyEvo, NVKMS_EVENT_TYPE_DPY_CHANGED);
|
||||
pDpyEvo->hdmi.reassessFrlLinkCaps = TRUE;
|
||||
}
|
||||
|
||||
@@ -1025,10 +1025,8 @@ void nvEvoSetDpVscSdp(NVDispEvoPtr pDispEvo,
|
||||
|
||||
nvPushEvoSubDevMaskDisp(pDispEvo);
|
||||
|
||||
if (((pDpyColor->format == NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr420) ||
|
||||
(pDpyColor->colorimetry == NVKMS_OUTPUT_COLORIMETRY_BT2100)) &&
|
||||
((pTimings->protocol == NVKMS_PROTOCOL_SOR_DP_A) ||
|
||||
(pTimings->protocol == NVKMS_PROTOCOL_SOR_DP_B))) {
|
||||
if (pTimings->protocol == NVKMS_PROTOCOL_SOR_DP_A ||
|
||||
pTimings->protocol == NVKMS_PROTOCOL_SOR_DP_B) {
|
||||
DPSDP_DP_VSC_SDP_DESCRIPTOR sdp = { };
|
||||
nvConstructDpVscSdp(pInfoFrame, pDpyColor, &sdp);
|
||||
pDevEvo->hal->SetDpVscSdp(pDispEvo, head, &sdp, updateState);
|
||||
@@ -3048,12 +3046,23 @@ void nvUpdateCurrentHardwareColorSpaceAndRangeEvo(
|
||||
case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr444:
|
||||
case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr422:
|
||||
case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr420:
|
||||
if (pDpyColor->colorimetry == NVKMS_OUTPUT_COLORIMETRY_BT2100) {
|
||||
switch (pDpyColor->colorimetry) {
|
||||
case NVKMS_OUTPUT_COLORIMETRY_BT2100:
|
||||
pHeadState->procAmp.colorimetry = NVT_COLORIMETRY_BT2020YCC;
|
||||
} else if (nvEvoIsHDQualityVideoTimings(&pHeadState->timings)) {
|
||||
break;
|
||||
case NVKMS_OUTPUT_COLORIMETRY_BT709:
|
||||
pHeadState->procAmp.colorimetry = NVT_COLORIMETRY_YUV_709;
|
||||
} else {
|
||||
break;
|
||||
case NVKMS_OUTPUT_COLORIMETRY_BT601:
|
||||
pHeadState->procAmp.colorimetry = NVT_COLORIMETRY_YUV_601;
|
||||
break;
|
||||
case NVKMS_OUTPUT_COLORIMETRY_DEFAULT:
|
||||
if (nvEvoIsHDQualityVideoTimings(&pHeadState->timings)) {
|
||||
pHeadState->procAmp.colorimetry = NVT_COLORIMETRY_YUV_709;
|
||||
} else {
|
||||
pHeadState->procAmp.colorimetry = NVT_COLORIMETRY_YUV_601;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -6867,10 +6876,19 @@ ConstructHwModeTimingsViewPort(const NVDispEvoRec *pDispEvo,
|
||||
}
|
||||
|
||||
|
||||
static NvBool GetDefaultFrlDpyColor(
|
||||
static NvBool FrlOverrideForYCbCr422(
|
||||
const NVDevEvoRec *pDevEvo,
|
||||
const NvKmsDpyOutputColorFormatInfo *pColorFormatsInfo,
|
||||
NVDpyAttributeColor *pDpyColor)
|
||||
{
|
||||
/*
|
||||
* If the hardware natively supports YCbCr422 + FRL,
|
||||
* there is nothing to do.
|
||||
*/
|
||||
if (pDevEvo->hal->caps.supportsYCbCr422OverHDMIFRL) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
nvkms_memset(pDpyColor, 0, sizeof(*pDpyColor));
|
||||
pDpyColor->colorimetry = NVKMS_OUTPUT_COLORIMETRY_DEFAULT;
|
||||
|
||||
@@ -6916,14 +6934,18 @@ static NvBool GetDfpHdmiProtocol(
|
||||
NVKMS_MODE_VALIDATION_REQUIRE_BOOT_CLOCKS) == 0) &&
|
||||
(!nvHdmiIsTmdsPossible(pDpyEvo, pTimings, pDpyColor) ||
|
||||
nvGetPreferHdmiFrlMode(pDevEvo, pValidationParams)) &&
|
||||
/* If FRL is supported... */
|
||||
nvHdmiDpySupportsFrl(pDpyEvo)) {
|
||||
/* If FRL is possible... */
|
||||
nvHdmiIsFrlPossible(pDpyEvo)) {
|
||||
|
||||
/* Hardware does not support HDMI FRL with YUV422 */
|
||||
if ((pDpyColor->format ==
|
||||
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr422) &&
|
||||
!GetDefaultFrlDpyColor(&colorFormatsInfo, pDpyColor)) {
|
||||
return FALSE;
|
||||
/*
|
||||
* Not all hardware configurations support YCbCr422 with FRL;
|
||||
* override if necessary, or fail FRL.
|
||||
*/
|
||||
if (pDpyColor->format ==
|
||||
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr422) {
|
||||
if (!FrlOverrideForYCbCr422(pDevEvo, &colorFormatsInfo, pDpyColor)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
*pTimingsProtocol = NVKMS_PROTOCOL_SOR_HDMI_FRL;
|
||||
|
||||
@@ -4098,6 +4098,7 @@ NVEvoHAL nvEvo97 = {
|
||||
FALSE, /* supportsDPAudio192KHz */
|
||||
FALSE, /* supportsInputColorSpace */
|
||||
FALSE, /* supportsInputColorRange */
|
||||
FALSE, /* supportsYCbCr422OverHDMIFRL */
|
||||
NV_EVO2_SUPPORTED_DITHERING_MODES, /* supportedDitheringModes */
|
||||
sizeof(NV5070_CTRL_CMD_IS_MODE_POSSIBLE_PARAMS), /* impStructSize */
|
||||
NV_EVO_SCALER_1TAP, /* minScalerTaps */
|
||||
@@ -4196,6 +4197,7 @@ NVEvoHAL nvEvo94 = {
|
||||
FALSE, /* supportsDPAudio192KHz */
|
||||
FALSE, /* supportsInputColorSpace */
|
||||
FALSE, /* supportsInputColorRange */
|
||||
FALSE, /* supportsYCbCr422OverHDMIFRL */
|
||||
NV_EVO2_SUPPORTED_DITHERING_MODES, /* supportedDitheringModes */
|
||||
sizeof(NV5070_CTRL_CMD_IS_MODE_POSSIBLE_PARAMS), /* impStructSize */
|
||||
NV_EVO_SCALER_1TAP, /* minScalerTaps */
|
||||
|
||||
@@ -8146,6 +8146,7 @@ NVEvoHAL nvEvoC3 = {
|
||||
FALSE, /* supportsDPAudio192KHz */
|
||||
FALSE, /* supportsInputColorSpace */
|
||||
FALSE, /* supportsInputColorRange */
|
||||
FALSE, /* supportsYCbCr422OverHDMIFRL */
|
||||
NV_EVO3_SUPPORTED_DITHERING_MODES, /* supportedDitheringModes */
|
||||
sizeof(NVC372_CTRL_IS_MODE_POSSIBLE_PARAMS), /* impStructSize */
|
||||
NV_EVO_SCALER_2TAPS, /* minScalerTaps */
|
||||
@@ -8244,6 +8245,7 @@ NVEvoHAL nvEvoC5 = {
|
||||
FALSE, /* supportsDPAudio192KHz */
|
||||
TRUE, /* supportsInputColorSpace */
|
||||
TRUE, /* supportsInputColorRange */
|
||||
FALSE, /* supportsYCbCr422OverHDMIFRL */
|
||||
NV_EVO3_SUPPORTED_DITHERING_MODES, /* supportedDitheringModes */
|
||||
sizeof(NVC372_CTRL_IS_MODE_POSSIBLE_PARAMS), /* impStructSize */
|
||||
NV_EVO_SCALER_2TAPS, /* minScalerTaps */
|
||||
@@ -8342,6 +8344,7 @@ NVEvoHAL nvEvoC6 = {
|
||||
FALSE, /* supportsDPAudio192KHz */
|
||||
TRUE, /* supportsInputColorSpace */
|
||||
TRUE, /* supportsInputColorRange */
|
||||
FALSE, /* supportsYCbCr422OverHDMIFRL */
|
||||
NV_EVO3_SUPPORTED_DITHERING_MODES, /* supportedDitheringModes */
|
||||
sizeof(NVC372_CTRL_IS_MODE_POSSIBLE_PARAMS), /* impStructSize */
|
||||
NV_EVO_SCALER_2TAPS, /* minScalerTaps */
|
||||
|
||||
@@ -3140,6 +3140,7 @@ NVEvoHAL nvEvoC9 = {
|
||||
TRUE, /* supportsDPAudio192KHz */
|
||||
TRUE, /* supportsInputColorSpace */
|
||||
TRUE, /* supportsInputColorRange */
|
||||
TRUE, /* supportsYCbCr422OverHDMIFRL */
|
||||
NV_EVO3_SUPPORTED_DITHERING_MODES, /* supportedDitheringModes */
|
||||
sizeof(NVC372_CTRL_IS_MODE_POSSIBLE_PARAMS), /* impStructSize */
|
||||
NV_EVO_SCALER_2TAPS, /* minScalerTaps */
|
||||
@@ -3238,6 +3239,7 @@ NVEvoHAL nvEvoCA = {
|
||||
TRUE, /* supportsDPAudio192KHz */
|
||||
TRUE, /* supportsInputColorSpace */
|
||||
TRUE, /* supportsInputColorRange */
|
||||
TRUE, /* supportsYCbCr422OverHDMIFRL */
|
||||
NV_EVO3_SUPPORTED_DITHERING_MODES, /* supportedDitheringModes */
|
||||
sizeof(NVC372_CTRL_IS_MODE_POSSIBLE_PARAMS), /* impStructSize */
|
||||
NV_EVO_SCALER_2TAPS, /* minScalerTaps */
|
||||
|
||||
@@ -51,6 +51,19 @@
|
||||
#define CAP_HDMI_SUPPORT_MONITOR_36_BPP 0x00000008
|
||||
#define CAP_HDMI_SUPPORT_MONITOR_30_BPP 0x00000010
|
||||
|
||||
#define SRC_TEST_CONFIG_DSC_FRL_MAX_OFFSET 6
|
||||
#define SRC_TEST_CONFIG_FRL_MAX_OFFSET 7
|
||||
|
||||
typedef enum {
|
||||
FORCE_NONE,
|
||||
FORCE_MAX_FRL_RATE,
|
||||
FORCE_MAX_DSC_FRL_RATE,
|
||||
} NVForceMaxFrlRateType;
|
||||
|
||||
static NVForceMaxFrlRateType GetForceMaxFrlRateType(
|
||||
const NVDpyEvoRec *pDpyEvo,
|
||||
const NVDpyId displayId);
|
||||
|
||||
static inline const NVT_EDID_CEA861_INFO *GetExt861(const NVParsedEdidEvoRec *pParsedEdid,
|
||||
int extIndex)
|
||||
{
|
||||
@@ -102,6 +115,8 @@ static void CalculateVideoInfoFrameColorFormat(
|
||||
pCtrl->extended_colorimetry =
|
||||
NVT_VIDEO_INFOFRAME_BYTE3_EC_BT2020RGBYCC;
|
||||
break;
|
||||
case NVKMS_OUTPUT_COLORIMETRY_BT601:
|
||||
case NVKMS_OUTPUT_COLORIMETRY_BT709:
|
||||
case NVKMS_OUTPUT_COLORIMETRY_DEFAULT:
|
||||
pCtrl->colorimetry = NVT_VIDEO_INFOFRAME_BYTE2_C1C0_NO_DATA;
|
||||
break;
|
||||
@@ -115,6 +130,12 @@ static void CalculateVideoInfoFrameColorFormat(
|
||||
pCtrl->extended_colorimetry =
|
||||
NVT_VIDEO_INFOFRAME_BYTE3_EC_BT2020RGBYCC;
|
||||
break;
|
||||
case NVKMS_OUTPUT_COLORIMETRY_BT601:
|
||||
pCtrl->colorimetry = NVT_VIDEO_INFOFRAME_BYTE2_C1C0_SMPTE170M_ITU601;
|
||||
break;
|
||||
case NVKMS_OUTPUT_COLORIMETRY_BT709:
|
||||
pCtrl->colorimetry = NVT_VIDEO_INFOFRAME_BYTE2_C1C0_ITU709;
|
||||
break;
|
||||
case NVKMS_OUTPUT_COLORIMETRY_DEFAULT:
|
||||
pCtrl->colorimetry =
|
||||
(hdTimings ? NVT_VIDEO_INFOFRAME_BYTE2_C1C0_ITU709 :
|
||||
@@ -1869,11 +1890,13 @@ static void HdmiLibPrint(
|
||||
{
|
||||
NVDevEvoRec *pDevEvo = handle;
|
||||
|
||||
if (!nvDoDebugLogging()) return;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
/* The HDMI library doesn't have log levels, but currently only logs in
|
||||
* debug builds. It's pretty chatty (e.g., it prints "Initialize Success"
|
||||
* when it inits), so hardcode it to INFO level for now. */
|
||||
/* The HDMI library doesn't have log levels. It's pretty chatty (e.g., it
|
||||
* prints "Initialize Success" when it inits), so hardcode it to INFO level
|
||||
* for now. */
|
||||
nvVEvoLog(EVO_LOG_INFO, pDevEvo->gpuLogIndex, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
@@ -1962,19 +1985,40 @@ NvBool nvHdmiFrlAssessLink(NVDpyEvoPtr pDpyEvo)
|
||||
NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
|
||||
NVHDMIPKT_RESULT ret;
|
||||
const NvU32 displayId = nvDpyIdToNvU32(pDpyEvo->pConnectorEvo->displayId);
|
||||
NvBool bIsDisplayActive = NV_FALSE;
|
||||
NvBool bPerformLinkTrainingToAssess = NV_TRUE;
|
||||
HDMI_FRL_DATA_RATE currFRLRate = HDMI_FRL_DATA_RATE_NONE;
|
||||
|
||||
nvAssert(nvDpyIsHdmiEvo(pDpyEvo));
|
||||
nvAssert(nvDpyIsHdmiEvo(pDpyEvo) && nvHdmiDpySupportsFrl(pDpyEvo));
|
||||
|
||||
if (pDpyEvo->apiHead != NV_INVALID_HEAD) {
|
||||
const NvU32 head =
|
||||
nvGetPrimaryHwHead(pDispEvo, pDpyEvo->apiHead);
|
||||
const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
|
||||
const HDMI_FRL_CONFIG *pFrlConfig = &pHeadState->hdmiFrlConfig;
|
||||
|
||||
bIsDisplayActive = NV_TRUE;
|
||||
if (pFrlConfig->frlRate == HDMI_FRL_DATA_RATE_NONE) {
|
||||
bPerformLinkTrainingToAssess = NV_FALSE;
|
||||
} else {
|
||||
bPerformLinkTrainingToAssess = NV_TRUE;
|
||||
}
|
||||
currFRLRate = pFrlConfig->frlRate;
|
||||
}
|
||||
|
||||
/* HDMI dpys not dynamic dpy so its connector should have a dpyId. */
|
||||
nvAssert(displayId != 0);
|
||||
nvAssert(pDpyEvo->parsedEdid.valid);
|
||||
|
||||
ret = NvHdmi_AssessLinkCapabilities(pDevEvo->hdmiLib.handle,
|
||||
pDispEvo->displayOwner,
|
||||
displayId,
|
||||
&pDpyEvo->parsedEdid.info,
|
||||
&pDpyEvo->hdmi.srcCaps,
|
||||
&pDpyEvo->hdmi.sinkCaps);
|
||||
ret = NvHdmi_AssessLinkCapabilities2(pDevEvo->hdmiLib.handle,
|
||||
pDispEvo->displayOwner,
|
||||
displayId,
|
||||
&pDpyEvo->parsedEdid.info,
|
||||
bPerformLinkTrainingToAssess,
|
||||
bIsDisplayActive,
|
||||
currFRLRate,
|
||||
&pDpyEvo->hdmi.srcCaps,
|
||||
&pDpyEvo->hdmi.sinkCaps);
|
||||
if (ret != NVHDMIPKT_SUCCESS) {
|
||||
nvAssert(ret == NVHDMIPKT_SUCCESS);
|
||||
return FALSE;
|
||||
@@ -2120,7 +2164,7 @@ static NvU64 GetHdmiFrlLinkRate(HDMI_FRL_DATA_RATE frlRate)
|
||||
return hdmiLinkRate;
|
||||
}
|
||||
|
||||
static NvBool nvHdmiFrlQueryConfigOneBpc(
|
||||
NvBool nvHdmiFrlQueryConfigOneColorSpaceAndBpc(
|
||||
const NVDpyEvoRec *pDpyEvo,
|
||||
const NvModeTimings *pModeTimings,
|
||||
const NVHwModeTimingsEvo *pHwTimings,
|
||||
@@ -2130,8 +2174,11 @@ static NvBool nvHdmiFrlQueryConfigOneBpc(
|
||||
HDMI_FRL_CONFIG *pConfig,
|
||||
NVDscInfoEvoRec *pDscInfo)
|
||||
{
|
||||
const NVConnectorEvoRec *pConnectorEvo = pDpyEvo->pConnectorEvo;
|
||||
const NVDispEvoRec *pDispEvo = pDpyEvo->pDispEvo;
|
||||
const NVDevEvoRec *pDevEvo = pDispEvo->pDevEvo;
|
||||
const NVForceMaxFrlRateType forceMaxFrlType =
|
||||
GetForceMaxFrlRateType(pDpyEvo, pConnectorEvo->displayId);
|
||||
HDMI_VIDEO_TRANSPORT_INFO videoTransportInfo = { };
|
||||
HDMI_QUERY_FRL_CLIENT_CONTROL clientControl = { };
|
||||
const NVT_TIMING *pNvtTiming;
|
||||
@@ -2145,7 +2192,7 @@ static NvBool nvHdmiFrlQueryConfigOneBpc(
|
||||
}
|
||||
|
||||
nvAssert(nvDpyIsHdmiEvo(pDpyEvo));
|
||||
nvAssert(nvHdmiDpySupportsFrl(pDpyEvo));
|
||||
nvAssert(nvHdmiIsFrlPossible(pDpyEvo));
|
||||
|
||||
nvAssert(!nvHdmiIsTmdsPossible(pDpyEvo, pHwTimings, pDpyColor) ||
|
||||
nvGetPreferHdmiFrlMode(pDevEvo, pValidationParams));
|
||||
@@ -2202,21 +2249,32 @@ static NvBool nvHdmiFrlQueryConfigOneBpc(
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* TODO: support YUV/YCbCr 444 and 422 packing modes. */
|
||||
switch (pModeTimings->yuv420Mode) {
|
||||
case NV_YUV420_MODE_NONE:
|
||||
switch (pDpyColor->format) {
|
||||
case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_RGB:
|
||||
videoTransportInfo.packing = HDMI_PIXEL_PACKING_RGB;
|
||||
break;
|
||||
case NV_YUV420_MODE_SW:
|
||||
/*
|
||||
* Don't bother implementing this with FRL.
|
||||
* HDMI FRL and HW YUV420 support were both added in nvdisplay 4.0
|
||||
* hardware, so if the hardware supports FRL it should support
|
||||
* YUV420_MODE_HW.
|
||||
*/
|
||||
return FALSE;
|
||||
case NV_YUV420_MODE_HW:
|
||||
videoTransportInfo.packing = HDMI_PIXEL_PACKING_YCbCr420;
|
||||
case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr422:
|
||||
nvAssert(pDevEvo->hal->caps.supportsYCbCr422OverHDMIFRL);
|
||||
videoTransportInfo.packing = HDMI_PIXEL_PACKING_YCbCr422;
|
||||
break;
|
||||
case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr444:
|
||||
videoTransportInfo.packing = HDMI_PIXEL_PACKING_YCbCr444;
|
||||
break;
|
||||
case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr420:
|
||||
switch (pModeTimings->yuv420Mode) {
|
||||
case NV_YUV420_MODE_NONE:
|
||||
case NV_YUV420_MODE_SW:
|
||||
/*
|
||||
* Don't bother implementing this with FRL.
|
||||
* HDMI FRL and HW YUV420 support were both added in nvdisplay 4.0
|
||||
* hardware, so if the hardware supports FRL it should support
|
||||
* YUV420_MODE_HW.
|
||||
*/
|
||||
return FALSE;
|
||||
case NV_YUV420_MODE_HW:
|
||||
videoTransportInfo.packing = HDMI_PIXEL_PACKING_YCbCr420;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2224,8 +2282,32 @@ static NvBool nvHdmiFrlQueryConfigOneBpc(
|
||||
|
||||
clientControl.option = HDMI_QUERY_FRL_HIGHEST_PIXEL_QUALITY;
|
||||
|
||||
if (pValidationParams->dscMode == NVKMS_DSC_MODE_FORCE_ENABLE) {
|
||||
clientControl.enableDSC = TRUE;
|
||||
switch (pValidationParams->dscMode) {
|
||||
case NVKMS_DSC_MODE_FORCE_DISABLE:
|
||||
clientControl.forceDisableDSC = TRUE;
|
||||
break;
|
||||
case NVKMS_DSC_MODE_FORCE_ENABLE:
|
||||
clientControl.enableDSC = TRUE;
|
||||
break;
|
||||
case NVKMS_DSC_MODE_DEFAULT:
|
||||
clientControl.forceFRLRate = (forceMaxFrlType != FORCE_NONE);
|
||||
switch (forceMaxFrlType) {
|
||||
case FORCE_MAX_FRL_RATE:
|
||||
clientControl.forceDisableDSC = TRUE;
|
||||
clientControl.frlRate =
|
||||
NV_MIN(pDpyEvo->hdmi.srcCaps.linkMaxFRLRate,
|
||||
pDpyEvo->hdmi.sinkCaps.linkMaxFRLRate);
|
||||
break;
|
||||
case FORCE_MAX_DSC_FRL_RATE:
|
||||
clientControl.enableDSC = TRUE;
|
||||
clientControl.frlRate =
|
||||
NV_MIN(pDpyEvo->hdmi.srcCaps.linkMaxFRLRate,
|
||||
pDpyEvo->hdmi.sinkCaps.linkMaxFRLRateDSC);
|
||||
break;
|
||||
case FORCE_NONE:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2233,7 +2315,7 @@ static NvBool nvHdmiFrlQueryConfigOneBpc(
|
||||
* but YUV420 is not, force DSC.
|
||||
*/
|
||||
if (b2Heads1Or && (pHwTimings->yuv420Mode != NV_YUV420_MODE_HW)) {
|
||||
if (pValidationParams->dscMode == NVKMS_DSC_MODE_FORCE_DISABLE) {
|
||||
if (clientControl.forceDisableDSC) {
|
||||
return FALSE;
|
||||
}
|
||||
clientControl.enableDSC = TRUE;
|
||||
@@ -2334,34 +2416,48 @@ void nvHdmiFrlClearConfig(NVDispEvoRec *pDispEvo, NvU32 activeRmId)
|
||||
}
|
||||
}
|
||||
|
||||
NvBool nvHdmiFrlQueryConfig(
|
||||
static NVForceMaxFrlRateType GetForceMaxFrlRateType(
|
||||
const NVDpyEvoRec *pDpyEvo,
|
||||
const NvModeTimings *pModeTimings,
|
||||
const NVHwModeTimingsEvo *pHwTimings,
|
||||
NVDpyAttributeColor *pDpyColor,
|
||||
const NvBool b2Heads1Or,
|
||||
const struct NvKmsModeValidationParams *pValidationParams,
|
||||
HDMI_FRL_CONFIG *pConfig,
|
||||
NVDscInfoEvoRec *pDscInfo)
|
||||
const NVDpyId displayId)
|
||||
{
|
||||
const NvKmsDpyOutputColorFormatInfo supportedColorFormats =
|
||||
nvDpyGetOutputColorFormatInfo(pDpyEvo);
|
||||
NVDpyAttributeColor dpyColor = *pDpyColor;
|
||||
do {
|
||||
if (nvHdmiFrlQueryConfigOneBpc(pDpyEvo,
|
||||
pModeTimings,
|
||||
pHwTimings,
|
||||
&dpyColor,
|
||||
b2Heads1Or,
|
||||
pValidationParams,
|
||||
pConfig,
|
||||
pDscInfo)) {
|
||||
*pDpyColor = dpyColor;
|
||||
return TRUE;
|
||||
}
|
||||
} while(nvDowngradeColorBpc(&supportedColorFormats, &dpyColor) &&
|
||||
(dpyColor.bpc >= NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8));
|
||||
return FALSE;
|
||||
const NVDispEvoRec *pDispEvo = pDpyEvo->pDispEvo;
|
||||
const NVDevEvoRec *pDevEvo = pDispEvo->pDevEvo;
|
||||
const NVParsedEdidEvoRec *pParsedEdid = &pDpyEvo->parsedEdid;
|
||||
const NVT_HDMI_FORUM_INFO *pHdmiInfo = &pParsedEdid->info.hdmiForumInfo;
|
||||
|
||||
NvBool bTestMaxFrlRate;
|
||||
NvBool bTestMaxDscFrlRate;
|
||||
NvU32 ret;
|
||||
|
||||
if (!pHdmiInfo->scdc_present) {
|
||||
return FORCE_NONE;
|
||||
}
|
||||
|
||||
NV0073_CTRL_SPECIFIC_GET_HDMI_SCDC_DATA_PARAMS scdcParams;
|
||||
nvkms_memset(&scdcParams, 0, sizeof(scdcParams));
|
||||
|
||||
scdcParams.subDeviceInstance = 0;
|
||||
scdcParams.displayId = nvDpyIdToNvU32(displayId);
|
||||
scdcParams.offset = NV0073_CTRL_CMD_SPECIFIC_GET_HDMI_SCDC_DATA_OFFSET_SOURCE_TEST_CONFIGURATION;
|
||||
|
||||
ret = nvRmApiControl(nvEvoGlobal.clientHandle,
|
||||
pDevEvo->displayCommonHandle,
|
||||
NV0073_CTRL_CMD_SPECIFIC_GET_HDMI_SCDC_DATA,
|
||||
&scdcParams,
|
||||
sizeof(scdcParams));
|
||||
|
||||
if (ret != NVOS_STATUS_SUCCESS) {
|
||||
return FORCE_NONE;
|
||||
}
|
||||
|
||||
bTestMaxFrlRate = !!(scdcParams.data & NVBIT(SRC_TEST_CONFIG_FRL_MAX_OFFSET));
|
||||
bTestMaxDscFrlRate = !!(scdcParams.data & NVBIT(SRC_TEST_CONFIG_DSC_FRL_MAX_OFFSET));
|
||||
|
||||
if (bTestMaxFrlRate != bTestMaxDscFrlRate) {
|
||||
return bTestMaxFrlRate ? FORCE_MAX_FRL_RATE : FORCE_MAX_DSC_FRL_RATE;
|
||||
}
|
||||
|
||||
return FORCE_NONE;
|
||||
}
|
||||
|
||||
void nvHdmiFrlSetConfig(NVDispEvoRec *pDispEvo, NvU32 head)
|
||||
|
||||
@@ -1257,7 +1257,7 @@ static inline NvGpuSemaphore *Hs3dGetSemaphore(
|
||||
return (NvGpuSemaphore *) pNotifier;
|
||||
}
|
||||
|
||||
#if NVKMS_PROCFS_ENABLE
|
||||
#if NVKMS_HEADSURFACE_STATS
|
||||
/*!
|
||||
* Get the semaphore index (e.g., to be passed into
|
||||
* nvPushGetNotifierGpuAddress()) for an (eye, slot) pair.
|
||||
@@ -1358,7 +1358,7 @@ static void Hs3dStatisticsComputeFps(
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* NVKMS_PROCFS_ENABLE */
|
||||
#endif /* NVKMS_HEADSURFACE_STATS */
|
||||
|
||||
/*!
|
||||
* Collect statistics on headSurface rendering.
|
||||
@@ -1380,7 +1380,7 @@ static void Hs3dStatisticsBefore(
|
||||
const NvU8 eye,
|
||||
const NvU8 slot)
|
||||
{
|
||||
#if NVKMS_PROCFS_ENABLE
|
||||
#if NVKMS_HEADSURFACE_STATS
|
||||
NVHsChannelStatisticsOneEyeRec *pPerEye =
|
||||
&pHsChannel->statistics.perEye[eye][slot];
|
||||
|
||||
@@ -1438,7 +1438,7 @@ done:
|
||||
semIndex + NVKMS_HEADSURFACE_STATS_SEMAPHORE_BEFORE,
|
||||
pPerEye->nFrames);
|
||||
|
||||
#endif /* NVKMS_PROCFS_ENABLE */
|
||||
#endif /* NVKMS_HEADSURFACE_STATS */
|
||||
}
|
||||
|
||||
static void Hs3dStatisticsAfter(
|
||||
@@ -1446,7 +1446,7 @@ static void Hs3dStatisticsAfter(
|
||||
const NvU8 eye,
|
||||
const NvU8 slot)
|
||||
{
|
||||
#if NVKMS_PROCFS_ENABLE
|
||||
#if NVKMS_HEADSURFACE_STATS
|
||||
NVHsChannelStatisticsOneEyeRec *pPerEye =
|
||||
&pHsChannel->statistics.perEye[eye][slot];
|
||||
const NvU8 semIndex = Hs3dGetStatisticsSemaphoreIndex(eye, slot);
|
||||
@@ -1458,7 +1458,7 @@ static void Hs3dStatisticsAfter(
|
||||
|
||||
pPerEye->nFrames++;
|
||||
|
||||
#endif /* NVKMS_PROCFS_ENABLE */
|
||||
#endif /* NVKMS_HEADSURFACE_STATS */
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -1866,7 +1866,7 @@ static void HsProcFsRecordScanline(
|
||||
const NVDispEvoRec *pDispEvo,
|
||||
const NvU32 apiHead)
|
||||
{
|
||||
#if NVKMS_PROCFS_ENABLE
|
||||
#if NVKMS_HEADSURFACE_STATS
|
||||
NVHsChannelEvoRec *pHsChannel = pDispEvo->pHsChannel[apiHead];
|
||||
NvU16 scanLine = 0;
|
||||
NvBool inBlankingPeriod = FALSE;
|
||||
@@ -1890,13 +1890,13 @@ static void HsProcFsRecordScanline(
|
||||
scanLine, pHsChannel->statistics.scanLine.vVisible);
|
||||
}
|
||||
}
|
||||
#endif /* NVKMS_PROCFS_ENABLE */
|
||||
#endif /* NVKMS_HEADSURFACE_STATS */
|
||||
}
|
||||
|
||||
static void HsProcFsRecordPreviousFrameNotDone(
|
||||
NVHsChannelEvoPtr pHsChannel)
|
||||
{
|
||||
#if NVKMS_PROCFS_ENABLE
|
||||
#if NVKMS_HEADSURFACE_STATS
|
||||
pHsChannel->statistics.nPreviousFrameNotDone++;
|
||||
#endif
|
||||
}
|
||||
@@ -1905,19 +1905,19 @@ static void HsProcFsRecordFullscreenSgFrames(
|
||||
NVHsChannelEvoPtr pHsChannel,
|
||||
NvBool isFullscreen)
|
||||
{
|
||||
#if NVKMS_PROCFS_ENABLE
|
||||
#if NVKMS_HEADSURFACE_STATS
|
||||
if (isFullscreen) {
|
||||
pHsChannel->statistics.nFullscreenSgFrames++;
|
||||
} else {
|
||||
pHsChannel->statistics.nNonFullscreenSgFrames++;
|
||||
}
|
||||
#endif /* NVKMS_PROCFS_ENABLE */
|
||||
#endif /* NVKMS_HEADSURFACE_STATS */
|
||||
}
|
||||
|
||||
static void HsProcFsRecordOmittedNonSgHsUpdate(
|
||||
NVHsChannelEvoPtr pHsChannel)
|
||||
{
|
||||
#if NVKMS_PROCFS_ENABLE
|
||||
#if NVKMS_HEADSURFACE_STATS
|
||||
pHsChannel->statistics.nOmittedNonSgHsUpdates++;
|
||||
#endif
|
||||
}
|
||||
@@ -2416,7 +2416,7 @@ void nvHsRemoveVBlankCallback(NVHsChannelEvoPtr pHsChannel)
|
||||
void nvHsAllocStatistics(
|
||||
NVHsChannelEvoRec *pHsChannel)
|
||||
{
|
||||
#if NVKMS_PROCFS_ENABLE
|
||||
#if NVKMS_HEADSURFACE_STATS
|
||||
const NVDispEvoRec *pDispEvo = pHsChannel->pDispEvo;
|
||||
const NvU32 apiHead = pHsChannel->apiHead;
|
||||
const NVHwModeTimingsEvo *pTimings =
|
||||
@@ -2430,19 +2430,19 @@ void nvHsAllocStatistics(
|
||||
n = pHsChannel->statistics.scanLine.vVisible + 1;
|
||||
|
||||
pHsChannel->statistics.scanLine.pHistogram = nvCalloc(1, sizeof(NvU64) * n);
|
||||
#endif /* NVKMS_PROCFS_ENABLE */
|
||||
#endif /* NVKMS_HEADSURFACE_STATS */
|
||||
}
|
||||
|
||||
void nvHsFreeStatistics(
|
||||
NVHsChannelEvoRec *pHsChannel)
|
||||
{
|
||||
#if NVKMS_PROCFS_ENABLE
|
||||
#if NVKMS_HEADSURFACE_STATS
|
||||
nvFree(pHsChannel->statistics.scanLine.pHistogram);
|
||||
nvkms_memset(&pHsChannel->statistics, 0, sizeof(pHsChannel->statistics));
|
||||
#endif /* NVKMS_PROCFS_ENABLE */
|
||||
#endif /* NVKMS_HEADSURFACE_STATS */
|
||||
}
|
||||
|
||||
#if NVKMS_PROCFS_ENABLE
|
||||
#if NVKMS_HEADSURFACE_STATS
|
||||
|
||||
static const struct {
|
||||
const char *before;
|
||||
@@ -2972,4 +2972,4 @@ void nvHsProcFs(
|
||||
|
||||
HsProcFsScanLine(pInfoString, pHsChannel);
|
||||
}
|
||||
#endif /* NVKMS_PROCFS_ENABLE */
|
||||
#endif /* NVKMS_HEADSURFACE_STATS */
|
||||
|
||||
@@ -1714,18 +1714,27 @@ static NvBool ValidateMode(NVDpyEvoPtr pDpyEvo,
|
||||
b2Heads1Or = nvEvoUse2Heads1OR(pDpyEvo, pTimingsEvo, pParams);
|
||||
|
||||
if (nvDpyIsHdmiEvo(pDpyEvo)) {
|
||||
if (!nvHdmiFrlQueryConfig(pDpyEvo,
|
||||
&pKmsMode->timings,
|
||||
pTimingsEvo,
|
||||
&dpyColor,
|
||||
b2Heads1Or,
|
||||
pParams,
|
||||
pHdmiFrlConfig,
|
||||
pDscInfo)) {
|
||||
NvBool foundFrlConfig = FALSE;
|
||||
do {
|
||||
if (nvHdmiFrlQueryConfigOneColorSpaceAndBpc(pDpyEvo,
|
||||
&pKmsMode->timings,
|
||||
pTimingsEvo,
|
||||
&dpyColor,
|
||||
b2Heads1Or,
|
||||
pParams,
|
||||
pHdmiFrlConfig,
|
||||
pDscInfo)) {
|
||||
foundFrlConfig = TRUE;
|
||||
break;
|
||||
}
|
||||
} while (nvDowngradeColorSpaceAndBpc(pDpyEvo, &supportedColorFormats, &dpyColor));
|
||||
|
||||
if (!foundFrlConfig) {
|
||||
LogModeValidationEnd(pDispEvo, pInfoString,
|
||||
"Unable to determine HDMI 2.1 Fixed Rate Link configuration.");
|
||||
goto done;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!nvDPValidateModeEvo(pDpyEvo, pTimingsEvo, &dpyColor, b2Heads1Or,
|
||||
pDscInfo, pParams)) {
|
||||
|
||||
@@ -102,6 +102,14 @@
|
||||
#include "nvkms-attributes.h"
|
||||
#include "nvkms-headsurface-config.h"
|
||||
|
||||
static NvBool
|
||||
AssignProposedHdmiFrlConfig(
|
||||
NVProposedModeSetStateOneApiHead *pProposedApiHead,
|
||||
NVProposedModeSetHwStateOneHead *pProposedPrimaryHead,
|
||||
const struct NvKmsSetModeOneHeadRequest *pRequestHead,
|
||||
const NVDispEvoRec *pDispEvo,
|
||||
const NVDpyEvoRec *pDpyEvo);
|
||||
|
||||
static NvBool
|
||||
GetColorSpaceAndColorRange(
|
||||
const NVDispEvoRec *pDispEvo,
|
||||
@@ -1367,15 +1375,11 @@ AssignProposedModeSetHwState(NVDevEvoRec *pDevEvo,
|
||||
* proposed modeset state, to broadcast it onto all hardware heads
|
||||
* during modeset.
|
||||
*/
|
||||
if (!nvHdmiFrlQueryConfig(pDpyEvo,
|
||||
&pRequestHead->mode.timings,
|
||||
&pProposedApiHead->timings,
|
||||
&pProposedApiHead->attributes.color,
|
||||
(nvPopCount32(pProposedApiHead->hwHeadsMask) > 1)
|
||||
/* b2Heads1Or */,
|
||||
&pProposedApiHead->modeValidationParams,
|
||||
&pProposedPrimaryHead->hdmiFrlConfig,
|
||||
&pProposedApiHead->dscInfo)) {
|
||||
if (!AssignProposedHdmiFrlConfig(pProposedApiHead,
|
||||
pProposedPrimaryHead,
|
||||
pRequestHead,
|
||||
pDispEvo,
|
||||
pDpyEvo)) {
|
||||
pReply->disp[sd].head[apiHead].status =
|
||||
NVKMS_SET_MODE_ONE_HEAD_STATUS_INVALID_MODE;
|
||||
ret = FALSE;
|
||||
@@ -1763,6 +1767,31 @@ static NvBool DowngradeColorSpaceAndBpcOneConnectorEvo(
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static NvBool AssignProposedHdmiFrlConfig(
|
||||
NVProposedModeSetStateOneApiHead *pProposedApiHead,
|
||||
NVProposedModeSetHwStateOneHead *pProposedPrimaryHead,
|
||||
const struct NvKmsSetModeOneHeadRequest *pRequestHead,
|
||||
const NVDispEvoRec *pDispEvo,
|
||||
const NVDpyEvoRec *pDpyEvo)
|
||||
{
|
||||
do {
|
||||
if (nvHdmiFrlQueryConfigOneColorSpaceAndBpc(pDpyEvo,
|
||||
&pRequestHead->mode.timings,
|
||||
&pProposedApiHead->timings,
|
||||
&pProposedApiHead->attributes.color,
|
||||
(nvPopCount32(pProposedApiHead->hwHeadsMask) > 1)
|
||||
/* b2Heads1Or */,
|
||||
&pProposedApiHead->modeValidationParams,
|
||||
&pProposedPrimaryHead->hdmiFrlConfig,
|
||||
&pProposedApiHead->dscInfo)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} while (DowngradeColorSpaceAndBpcOneHead(pDispEvo, pProposedApiHead));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static NvBool ValidateProposedModeSetHwStateOneConnectorDPlib(
|
||||
const NVConnectorEvoRec *pConnectorEvo,
|
||||
NVProposedModeSetHwStateOneDisp *pProposedDisp,
|
||||
|
||||
@@ -1584,6 +1584,19 @@ static void ReceiveDPIRQEvent(void *arg, void *pEventDataVoid, NvU32 hEvent,
|
||||
0);
|
||||
}
|
||||
|
||||
static void ReceiveHDMIFRLRetrainEvent(void *arg, void *pEventDataVoid, NvU32 hEvent,
|
||||
NvU32 Data, NV_STATUS Status)
|
||||
{
|
||||
Nv2080HdmiFrlRequestNotification *pEventData =
|
||||
(Nv2080HdmiFrlRequestNotification *) pEventDataVoid;
|
||||
|
||||
(void) nvkms_alloc_timer_with_ref_ptr(
|
||||
nvHandleHDMIFRLRetrainEventDeferredWork, /* callback */
|
||||
arg, /* argument (this is a ref_ptr to a pDispEvo) */
|
||||
pEventData->displayId, /* dataU32 */
|
||||
0);
|
||||
}
|
||||
|
||||
NvBool nvRmRegisterCallback(const NVDevEvoRec *pDevEvo,
|
||||
NVOS10_EVENT_KERNEL_CALLBACK_EX *cb,
|
||||
struct nvkms_ref_ptr *ref_ptr,
|
||||
@@ -1820,6 +1833,35 @@ enum NvKmsAllocDeviceStatus nvRmAllocDisplays(NVDevEvoPtr pDevEvo)
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate a handler for the HDMI "FRL Retraining" event, which is signaled
|
||||
// when there's a FRL retraining request from the sink.
|
||||
FOR_ALL_EVO_DISPLAYS(pDispEvo, sd, pDevEvo) {
|
||||
NV2080_CTRL_EVENT_SET_NOTIFICATION_PARAMS setEventParams = { };
|
||||
NvU32 subDevice, ret;
|
||||
|
||||
subDevice = pDevEvo->pSubDevices[pDispEvo->displayOwner]->handle;
|
||||
pDispEvo->HDMIFRLRetrainEventHandle =
|
||||
nvGenerateUnixRmHandle(&pDevEvo->handleAllocator);
|
||||
if (!RegisterDispCallback(&pDispEvo->rmHDMIFRLRetrainCallback, pDispEvo,
|
||||
pDispEvo->HDMIFRLRetrainEventHandle, ReceiveHDMIFRLRetrainEvent,
|
||||
NV2080_NOTIFIERS_HDMI_FRL_RETRAINING_REQUEST)) {
|
||||
nvEvoLogDev(pDevEvo, EVO_LOG_WARN,
|
||||
"Failed to register HDMI FRL retrain event");
|
||||
}
|
||||
// Enable HDMI FRL retrain event notifications for this subdevice.
|
||||
setEventParams.event = NV2080_NOTIFIERS_HDMI_FRL_RETRAINING_REQUEST;
|
||||
setEventParams.action = NV2080_CTRL_EVENT_SET_NOTIFICATION_ACTION_REPEAT;
|
||||
if ((ret = nvRmApiControl(nvEvoGlobal.clientHandle,
|
||||
subDevice,
|
||||
NV2080_CTRL_CMD_EVENT_SET_NOTIFICATION,
|
||||
&setEventParams,
|
||||
sizeof(setEventParams)))
|
||||
!= NVOS_STATUS_SUCCESS) {
|
||||
nvEvoLogDev(pDevEvo, EVO_LOG_WARN,
|
||||
"Failed to enable HDMI FRL retrain notifications (subdevice: %d) (error: 0x%x)", sd, ret);
|
||||
}
|
||||
}
|
||||
|
||||
FOR_ALL_EVO_DISPLAYS(pDispEvo, sd, pDevEvo) {
|
||||
ProbeBootDisplays(pDispEvo);
|
||||
|
||||
@@ -1850,7 +1892,7 @@ void nvRmDestroyDisplays(NVDevEvoPtr pDevEvo)
|
||||
nvFreeVrrEvo(pDevEvo);
|
||||
|
||||
FOR_ALL_EVO_DISPLAYS(pDispEvo, dispIndex, pDevEvo) {
|
||||
|
||||
const NvU32 subDevice = pDevEvo->pSubDevices[pDispEvo->displayOwner]->handle;
|
||||
// Before freeing anything, dump anything left in the RM's DisplayPort
|
||||
// AUX channel log.
|
||||
if (pDispEvo->dpAuxLoggingEnabled) {
|
||||
@@ -1882,6 +1924,31 @@ void nvRmDestroyDisplays(NVDevEvoPtr pDevEvo)
|
||||
pDispEvo->hotplugEventHandle);
|
||||
pDispEvo->hotplugEventHandle = 0;
|
||||
}
|
||||
|
||||
// Free the HDMI FRL retrain event
|
||||
if (pDispEvo->HDMIFRLRetrainEventHandle != 0) {
|
||||
NV2080_CTRL_EVENT_SET_NOTIFICATION_PARAMS setEventParams = { };
|
||||
|
||||
// Disable HDMI FRL retrain notifications for this subdevice
|
||||
setEventParams.event = NV2080_NOTIFIERS_HDMI_FRL_RETRAINING_REQUEST;
|
||||
setEventParams.action = NV2080_CTRL_EVENT_SET_NOTIFICATION_ACTION_DISABLE;
|
||||
if ((ret = nvRmApiControl(nvEvoGlobal.clientHandle,
|
||||
subDevice,
|
||||
NV2080_CTRL_CMD_EVENT_SET_NOTIFICATION,
|
||||
&setEventParams,
|
||||
sizeof(setEventParams))
|
||||
!= NVOS_STATUS_SUCCESS)) {
|
||||
nvEvoLogDev(pDevEvo, EVO_LOG_WARN,
|
||||
"Failed to disable HDMI FRL retrain notifications (subdevice: %d) (error: 0x%x)", dispIndex, ret);
|
||||
}
|
||||
|
||||
nvRmApiFree(nvEvoGlobal.clientHandle,
|
||||
nvEvoGlobal.clientHandle,
|
||||
pDispEvo->HDMIFRLRetrainEventHandle);
|
||||
nvFreeUnixRmHandle(&pDevEvo->handleAllocator,
|
||||
pDispEvo->HDMIFRLRetrainEventHandle);
|
||||
pDispEvo->HDMIFRLRetrainEventHandle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
FOR_ALL_EVO_DISPLAYS(pDispEvo, dispIndex, pDevEvo) {
|
||||
|
||||
@@ -801,3 +801,14 @@ void nvDebugAssert(const char *expString, const char *filenameString,
|
||||
}
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
NvBool nvDoDebugLogging(void)
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
/* Always do debug logging in debug builds. */
|
||||
return TRUE;
|
||||
#endif
|
||||
|
||||
/* Otherwise, do debug logging if the kernel module is enabled. */
|
||||
return nvkms_debug_logging();
|
||||
}
|
||||
|
||||
@@ -5345,7 +5345,7 @@ fail:
|
||||
|
||||
extern const char *const pNV_KMS_ID;
|
||||
|
||||
#if NVKMS_PROCFS_ENABLE
|
||||
#if NVKMS_PROCFS_OBJECT_DUMP
|
||||
|
||||
static const char *ProcFsPerOpenTypeString(
|
||||
enum NvKmsPerOpenType type)
|
||||
@@ -5713,44 +5713,6 @@ ProcFsPrintSurfaces(
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ProcFsPrintHeadSurface(
|
||||
void *data,
|
||||
char *buffer,
|
||||
size_t size,
|
||||
nvkms_procfs_out_string_func_t *outString)
|
||||
{
|
||||
NVDevEvoPtr pDevEvo;
|
||||
NVDispEvoPtr pDispEvo;
|
||||
NvU32 dispIndex, apiHead;
|
||||
NVEvoInfoStringRec infoString;
|
||||
|
||||
FOR_ALL_EVO_DEVS(pDevEvo) {
|
||||
|
||||
nvInitInfoString(&infoString, buffer, size);
|
||||
nvEvoLogInfoString(&infoString,
|
||||
"pDevEvo (deviceId:%02d) : %p",
|
||||
pDevEvo->deviceId.rmDeviceId, pDevEvo);
|
||||
outString(data, buffer);
|
||||
|
||||
FOR_ALL_EVO_DISPLAYS(pDispEvo, dispIndex, pDevEvo) {
|
||||
|
||||
nvInitInfoString(&infoString, buffer, size);
|
||||
nvEvoLogInfoString(&infoString,
|
||||
" pDispEvo (dispIndex:%02d) : %p",
|
||||
dispIndex, pDispEvo);
|
||||
outString(data, buffer);
|
||||
|
||||
for (apiHead = 0; apiHead < pDevEvo->numApiHeads; apiHead++) {
|
||||
nvInitInfoString(&infoString, buffer, size);
|
||||
nvHsProcFs(&infoString, pDevEvo, dispIndex, apiHead);
|
||||
nvEvoLogInfoString(&infoString, "");
|
||||
outString(data, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char *SwapGroupPerEyeStereoString(const NvU32 request)
|
||||
{
|
||||
const NvU32 value =
|
||||
@@ -5942,6 +5904,50 @@ ProcFsPrintDeferredRequestFifos(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* NVKMS_PROCFS_OBJECT_DUMP */
|
||||
|
||||
#if NVKMS_HEADSURFACE_STATS
|
||||
static void
|
||||
ProcFsPrintHeadSurface(
|
||||
void *data,
|
||||
char *buffer,
|
||||
size_t size,
|
||||
nvkms_procfs_out_string_func_t *outString)
|
||||
{
|
||||
NVDevEvoPtr pDevEvo;
|
||||
NVDispEvoPtr pDispEvo;
|
||||
NvU32 dispIndex, apiHead;
|
||||
NVEvoInfoStringRec infoString;
|
||||
|
||||
FOR_ALL_EVO_DEVS(pDevEvo) {
|
||||
|
||||
nvInitInfoString(&infoString, buffer, size);
|
||||
nvEvoLogInfoString(&infoString,
|
||||
"pDevEvo (deviceId:%02d) : %p",
|
||||
pDevEvo->deviceId.rmDeviceId, pDevEvo);
|
||||
outString(data, buffer);
|
||||
|
||||
FOR_ALL_EVO_DISPLAYS(pDispEvo, dispIndex, pDevEvo) {
|
||||
|
||||
nvInitInfoString(&infoString, buffer, size);
|
||||
nvEvoLogInfoString(&infoString,
|
||||
" pDispEvo (dispIndex:%02d) : %p",
|
||||
dispIndex, pDispEvo);
|
||||
outString(data, buffer);
|
||||
|
||||
for (apiHead = 0; apiHead < pDevEvo->numApiHeads; apiHead++) {
|
||||
nvInitInfoString(&infoString, buffer, size);
|
||||
nvHsProcFs(&infoString, pDevEvo, dispIndex, apiHead);
|
||||
nvEvoLogInfoString(&infoString, "");
|
||||
outString(data, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* NVKMS_HEADSURFACE_STATS */
|
||||
|
||||
#if NVKMS_PROCFS_CRCS
|
||||
static void
|
||||
ProcFsPrintDpyCrcs(
|
||||
void *data,
|
||||
@@ -6024,17 +6030,37 @@ ProcFsPrintDpyCrcs(
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* NVKMS_PROCFS_CRCS */
|
||||
|
||||
static const char *
|
||||
SignalFormatString(NvKmsConnectorSignalFormat signalFormat)
|
||||
SignalFormatString(const enum nvKmsTimingsProtocol protocol)
|
||||
{
|
||||
switch (signalFormat) {
|
||||
case NVKMS_CONNECTOR_SIGNAL_FORMAT_VGA: return "VGA";
|
||||
case NVKMS_CONNECTOR_SIGNAL_FORMAT_LVDS: return "LVDS";
|
||||
case NVKMS_CONNECTOR_SIGNAL_FORMAT_TMDS: return "TMDS";
|
||||
case NVKMS_CONNECTOR_SIGNAL_FORMAT_DP: return "DP";
|
||||
case NVKMS_CONNECTOR_SIGNAL_FORMAT_DSI: return "DSI";
|
||||
case NVKMS_CONNECTOR_SIGNAL_FORMAT_UNKNOWN: break;
|
||||
switch (protocol) {
|
||||
case NVKMS_PROTOCOL_DAC_RGB:
|
||||
return "VGA";
|
||||
|
||||
case NVKMS_PROTOCOL_SOR_SINGLE_TMDS_A:
|
||||
case NVKMS_PROTOCOL_SOR_SINGLE_TMDS_B:
|
||||
return "TMDS";
|
||||
|
||||
case NVKMS_PROTOCOL_SOR_DUAL_TMDS:
|
||||
return "Dual TMDS";
|
||||
|
||||
case NVKMS_PROTOCOL_SOR_DP_A:
|
||||
case NVKMS_PROTOCOL_SOR_DP_B:
|
||||
return "DP";
|
||||
|
||||
case NVKMS_PROTOCOL_SOR_LVDS_CUSTOM:
|
||||
return "LVDS";
|
||||
|
||||
case NVKMS_PROTOCOL_SOR_HDMI_FRL:
|
||||
return "HDMI FRL";
|
||||
|
||||
case NVKMS_PROTOCOL_DSI:
|
||||
return "DSI";
|
||||
|
||||
case NVKMS_PROTOCOL_PIOR_EXT_TMDS_ENC:
|
||||
return "EXT TMDS";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
@@ -6070,27 +6096,24 @@ ProcFsPrintHeads(
|
||||
|
||||
nvInitInfoString(&infoString, buffer, size);
|
||||
nvEvoLogInfoString(&infoString,
|
||||
"pDevEvo (deviceId:%02d) : %p",
|
||||
pDevEvo->deviceId.rmDeviceId, pDevEvo);
|
||||
"deviceId : %02d",
|
||||
pDevEvo->deviceId.rmDeviceId);
|
||||
outString(data, buffer);
|
||||
|
||||
FOR_ALL_EVO_DISPLAYS(pDispEvo, dispIndex, pDevEvo) {
|
||||
const NVLockGroup *pLockGroup = pDispEvo->pLockGroup;
|
||||
|
||||
nvInitInfoString(&infoString, buffer, size);
|
||||
nvEvoLogInfoString(&infoString,
|
||||
" pDispEvo (dispIndex:%02d) : %p",
|
||||
dispIndex, pDispEvo);
|
||||
if (pLockGroup != NULL) {
|
||||
const NvBool flipLocked = nvIsLockGroupFlipLocked(pLockGroup);
|
||||
nvInitInfoString(&infoString, buffer, size);
|
||||
nvEvoLogInfoString(&infoString,
|
||||
" pLockGroup : %p",
|
||||
" pLockGroup : %p",
|
||||
pLockGroup);
|
||||
nvEvoLogInfoString(&infoString,
|
||||
" flipLock : %s",
|
||||
" flipLock : %s",
|
||||
flipLocked ? "yes" : "no");
|
||||
outString(data, buffer);
|
||||
}
|
||||
outString(data, buffer);
|
||||
|
||||
if (pDevEvo->coreInitMethodsPending) {
|
||||
/* If the core channel has been allocated but no mode has yet
|
||||
@@ -6098,7 +6121,7 @@ ProcFsPrintHeads(
|
||||
* driven by the console, but data like the mode timings will
|
||||
* be bogus. */
|
||||
nvInitInfoString(&infoString, buffer, size);
|
||||
nvEvoLogInfoString(&infoString, " (not yet initialized)");
|
||||
nvEvoLogInfoString(&infoString, " (not yet initialized)");
|
||||
outString(data, buffer);
|
||||
continue;
|
||||
}
|
||||
@@ -6114,29 +6137,43 @@ ProcFsPrintHeads(
|
||||
nvInitInfoString(&infoString, buffer, size);
|
||||
if (pConnectorEvo == NULL) {
|
||||
nvEvoLogInfoString(&infoString,
|
||||
" head %d : inactive",
|
||||
" head %d : inactive",
|
||||
head);
|
||||
} else {
|
||||
const NvU32 refreshRate10kHz =
|
||||
nvGetRefreshRate10kHz(pHwModeTimings);
|
||||
const NVDpyEvoRec *pDpyEvo;
|
||||
|
||||
/* Find the dpy driven by this head. Multiple heads may be
|
||||
* driving the same dpy with 2head1or, but a head should
|
||||
* only drive one dpy at a time. */
|
||||
FOR_ALL_EVO_DPYS(pDpyEvo, pDispEvo->validDisplays, pDispEvo) {
|
||||
const NvU32 apiHead = pDpyEvo->apiHead;
|
||||
if (apiHead == NV_INVALID_HEAD) {
|
||||
continue;
|
||||
}
|
||||
if (pDispEvo->apiHeadState[apiHead].hwHeadsMask &
|
||||
NVBIT(head)) {
|
||||
nvEvoLogInfoString(&infoString,
|
||||
" head %d : %s",
|
||||
head, pDpyEvo->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nvEvoLogInfoString(&infoString,
|
||||
" head %d : %s",
|
||||
head, pConnectorEvo->name);
|
||||
" protocol : %s",
|
||||
SignalFormatString(pHwModeTimings->protocol));
|
||||
|
||||
nvEvoLogInfoString(&infoString,
|
||||
" protocol : %s",
|
||||
SignalFormatString(pConnectorEvo->signalFormat));
|
||||
|
||||
nvEvoLogInfoString(&infoString,
|
||||
" mode : %u x %u @ %u.%04u Hz",
|
||||
" mode : %u x %u @ %u.%04u Hz",
|
||||
nvEvoVisibleWidth(pHwModeTimings),
|
||||
nvEvoVisibleHeight(pHwModeTimings),
|
||||
refreshRate10kHz / 10000,
|
||||
refreshRate10kHz % 10000);
|
||||
|
||||
nvEvoLogInfoString(&infoString,
|
||||
" depth : %s",
|
||||
" depth : %s",
|
||||
PixelDepthString(pHeadState->pixelDepth));
|
||||
}
|
||||
outString(data, buffer);
|
||||
@@ -6145,25 +6182,107 @@ ProcFsPrintHeads(
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* NVKMS_PROCFS_ENABLE */
|
||||
/*
|
||||
* Dump all dpys for all devices, grouped by connector.
|
||||
* With DP MST there may be multiple dpys on the same connector.
|
||||
*/
|
||||
static void
|
||||
ProcFsPrintDpys(
|
||||
void *data,
|
||||
char *buffer,
|
||||
size_t size,
|
||||
nvkms_procfs_out_string_func_t *outString)
|
||||
{
|
||||
const NVDevEvoRec *pDevEvo;
|
||||
const NVDispEvoRec *pDispEvo;
|
||||
NvU32 dispIndex;
|
||||
NVEvoInfoStringRec infoString;
|
||||
|
||||
FOR_ALL_EVO_DEVS(pDevEvo) {
|
||||
|
||||
nvInitInfoString(&infoString, buffer, size);
|
||||
nvEvoLogInfoString(&infoString,
|
||||
"deviceId : %02d",
|
||||
pDevEvo->deviceId.rmDeviceId);
|
||||
outString(data, buffer);
|
||||
|
||||
FOR_ALL_EVO_DISPLAYS(pDispEvo, dispIndex, pDevEvo) {
|
||||
|
||||
const NVConnectorEvoRec *pConnectorEvo;
|
||||
|
||||
FOR_ALL_EVO_CONNECTORS(pConnectorEvo, pDispEvo) {
|
||||
const NVDpyEvoRec *pDpyEvo;
|
||||
|
||||
nvInitInfoString(&infoString, buffer, size);
|
||||
nvEvoLogInfoString(&infoString,
|
||||
" connector : %s",
|
||||
pConnectorEvo->name);
|
||||
outString(data, buffer);
|
||||
|
||||
FOR_ALL_EVO_DPYS(pDpyEvo, pDispEvo->validDisplays, pDispEvo) {
|
||||
const char *name;
|
||||
|
||||
if (pDpyEvo->pConnectorEvo != pConnectorEvo) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nvInitInfoString(&infoString, buffer, size);
|
||||
if (nvDpyIdIsInDpyIdList(pDpyEvo->id,
|
||||
pDispEvo->connectedDisplays)) {
|
||||
|
||||
name = pDpyEvo->name;
|
||||
} else {
|
||||
name = "(not connected)";
|
||||
}
|
||||
|
||||
nvEvoLogInfoString(&infoString,
|
||||
" dpy : %s", name);
|
||||
|
||||
if (pDpyEvo->edid.length) {
|
||||
NvU32 i;
|
||||
const NvU8 *buf = pDpyEvo->edid.buffer;
|
||||
nvEvoLogInfoStringRaw(&infoString,
|
||||
" edid :");
|
||||
|
||||
for (i = 0; i < pDpyEvo->edid.length; i++) {
|
||||
if (i % 16 == 0) {
|
||||
nvEvoLogInfoStringRaw(&infoString, "\n ");
|
||||
}
|
||||
if (i % 8 == 0) {
|
||||
nvEvoLogInfoStringRaw(&infoString, " ");
|
||||
}
|
||||
nvEvoLogInfoStringRaw(&infoString, " %02x",
|
||||
buf[i]);
|
||||
}
|
||||
nvEvoLogInfoStringRaw(&infoString, "\n");
|
||||
}
|
||||
outString(data, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nvKmsGetProcFiles(const nvkms_procfs_file_t **ppProcFiles)
|
||||
{
|
||||
#if NVKMS_PROCFS_ENABLE
|
||||
static const nvkms_procfs_file_t procFiles[] = {
|
||||
#if NVKMS_PROCFS_OBJECT_DUMP
|
||||
{ "clients", ProcFsPrintClients },
|
||||
{ "surfaces", ProcFsPrintSurfaces },
|
||||
{ "headsurface", ProcFsPrintHeadSurface },
|
||||
{ "deferred-request-fifos", ProcFsPrintDeferredRequestFifos },
|
||||
#endif
|
||||
#if NVKMS_HEADSURFACE_STATS
|
||||
{ "headsurface", ProcFsPrintHeadSurface },
|
||||
#endif
|
||||
#if NVKMS_PROCFS_CRCS
|
||||
{ "crcs", ProcFsPrintDpyCrcs },
|
||||
#endif
|
||||
{ "heads", ProcFsPrintHeads },
|
||||
{ "dpys", ProcFsPrintDpys },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
*ppProcFiles = procFiles;
|
||||
#else
|
||||
*ppProcFiles = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void FreeGlobalState(void)
|
||||
|
||||
Reference in New Issue
Block a user