560.28.03

This commit is contained in:
Gaurav Juvekar
2024-07-19 15:45:15 -07:00
parent 5fdf5032fb
commit 448d5cc656
859 changed files with 165424 additions and 91129 deletions

View File

@@ -200,6 +200,7 @@ SHADER_OBJS =
$(eval $(call COMPRESS_SHADERS,turing))
$(eval $(call COMPRESS_SHADERS,ampere))
$(eval $(call COMPRESS_SHADERS,hopper))
$(eval $(call COMPRESS_SHADERS,blackwell))
OBJS = $(call BUILD_OBJECT_LIST,$(ALL_SRCS))
OBJS += $(SHADER_OBJS)

View File

@@ -83,7 +83,8 @@ NvBool nvDpyIsAdaptiveSyncDefaultlisted(const NVDpyEvoRec *pDpyEvo);
enum NvKmsDpyAttributeDigitalSignalValue
nvGetDefaultDpyAttributeDigitalSignalValue(const NVConnectorEvoRec *pConnectorEvo);
NVColorFormatInfoRec nvGetColorFormatInfo(const NVDpyEvoRec *pDpyEvo);
NvKmsDpyOutputColorFormatInfo nvDpyGetOutputColorFormatInfo(
const NVDpyEvoRec *pDpyEvo);
NvU32 nvDpyGetPossibleApiHeadsMask(const NVDpyEvoRec *pDpyEvo);

View File

@@ -180,10 +180,12 @@ NvBool nvConstructHwModeTimingsImpCheckEvo(
NvU32 *pNumHeads,
NVEvoInfoStringPtr pInfoString);
NvBool nvDowngradeColorBpc(NVDpyAttributeColor *pDpyColor);
NvBool nvDowngradeColorBpc(
const NvKmsDpyOutputColorFormatInfo *pSupportedColorFormats,
NVDpyAttributeColor *pDpyColor);
NvBool nvDowngradeColorSpaceAndBpc(
const NVColorFormatInfoRec *pSupportedColorFormats,
const NvKmsDpyOutputColorFormatInfo *pSupportedColorFormats,
NVDpyAttributeColor *pDpyColor);
NvBool nvDPValidateModeEvo(NVDpyEvoPtr pDpyEvo,
@@ -259,6 +261,7 @@ NvBool nvChooseCurrentColorSpaceAndRangeEvo(
const enum NvYuv420Mode yuv420Mode,
enum NvKmsOutputColorimetry colorimetry,
const enum NvKmsDpyAttributeRequestedColorSpaceValue requestedColorSpace,
const enum NvKmsDpyAttributeColorBpcValue requestedColorBpc,
const enum NvKmsDpyAttributeColorRangeValue requestedColorRange,
enum NvKmsDpyAttributeCurrentColorSpaceValue *pCurrentColorSpace,
enum NvKmsDpyAttributeColorBpcValue *pCurrentColorBpc,
@@ -347,8 +350,9 @@ enum nvKmsPixelDepth nvEvoDpyColorToPixelDepth(
void nvSuspendDevEvo(NVDevEvoRec *pDevEvo);
NvBool nvResumeDevEvo(NVDevEvoRec *pDevEvo);
NvBool nvGetDefaultDpyColor(const NVColorFormatInfoRec *pColorFormatsInfo,
NVDpyAttributeColor *pDpyColor);
NvBool nvGetDefaultDpyColor(
const NvKmsDpyOutputColorFormatInfo *pColorFormatsInfo,
NVDpyAttributeColor *pDpyColor);
static inline void nvEvoSetFlipOccurredEvent(const NVDispEvoRec *pDispEvo,
const NvU32 head,

View File

@@ -44,6 +44,7 @@ typedef struct {
NvBool hdrInfoFrameOverride;
NvU32 hdrStaticMetadataLayerMask;
NvBool colorSpaceSpecified : 1;
NvBool colorBpcSpecified : 1;
NvBool colorRangeSpecified : 1;
NvBool hs10bpcHint : 1;
NvBool changed : 1;

View File

@@ -680,19 +680,6 @@ typedef struct {
} maxDownscaleFactors;
} NVFlipChannelEvoHwState;
enum NvKmsDpyAttributeColorBpcValue {
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_UNKNOWN = 0,
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_10 = 10,
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8 = 8,
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_6 = 6,
};
typedef struct _NVColorFormatInfoRec {
struct {
enum NvKmsDpyAttributeColorBpcValue maxBpc;
} rgb444, yuv444, yuv422;
} NVColorFormatInfoRec;
typedef struct {
struct NvKmsPoint viewPortPointIn;
NVFlipCursorEvoHwState cursor;
@@ -1961,6 +1948,9 @@ typedef struct _NVDispEvoRec {
NVDpyIdList muxDisplays;
struct {
// Indicates whether a VRR cookie was detected
NvBool hasPlatformCookie;
nvkms_timer_handle_t *unstallTimer;
} vrr;
@@ -2151,6 +2141,7 @@ typedef struct _NVDpyEvoRec {
NvU8 laneCount; // NV0073_CTRL_DP_DATA_SET_LANE_COUNT
NvU8 linkRate; // NV0073_CTRL_DP_DATA_SET_LINK_BW
NvU32 linkRate10MHz;
enum NvKmsDpyAttributeDisplayportConnectorTypeValue connectorType;
NvBool sinkIsAudioCapable;
@@ -2192,7 +2183,6 @@ typedef struct _NVDpyEvoRec {
struct {
enum NvKmsDpyVRRType type;
NvU32 edidTimeoutMicroseconds;
NvBool needsSwFramePacing;
} vrr;
} NVDpyEvoRec;
@@ -2433,6 +2423,12 @@ static inline NvBool nvIsEmulationEvo(const NVDevEvoRec *pDevEvo)
NV2080_CTRL_GPU_GET_SIMULATION_INFO_TYPE_NONE;
}
static inline NvBool nvIsDfpgaEvo(const NVDevEvoRec *pDevEvo)
{
return pDevEvo->simulationType ==
NV2080_CTRL_GPU_GET_SIMULATION_INFO_TYPE_DFPGA;
}
static inline NvBool nvIs3DVisionStereoEvo(const enum NvKmsStereoMode stereo)
{
return (stereo == NVKMS_STEREO_NVIDIA_3D_VISION ||

View File

@@ -118,8 +118,8 @@ static inline NvBool nvExceedsTimeoutUSec(
{
const NvU64 currentTime = nvkms_get_usec();
if (nvIsEmulationEvo(pDevEvo)) {
return FALSE;
if (nvIsEmulationEvo(pDevEvo) && !nvIsDfpgaEvo(pDevEvo)) {
timeoutPeriod *= 100;
}
if (*pStartTime == 0) {

View File

@@ -36,11 +36,12 @@ nvGetAllowedDpyVrrType(const NVDpyEvoRec *pDpyEvo,
enum NvKmsStereoMode stereoMode,
const NvBool allowGsync,
const enum NvKmsAllowAdaptiveSync allowAdaptiveSync);
void nvAdjustHwModeTimingsForVrrEvo(NVHwModeTimingsEvoPtr pTimings,
const enum NvKmsDpyVRRType vrrType,
const NvU32 edidTimeoutMicroseconds,
const NvU32 vrrOverrideMinRefreshRate,
const NvBool needsSwFramePacing);
void nvAdjustHwModeTimingsForVrrEvo(
const NVDpyEvoRec *pDpyEvo,
const enum NvKmsDpyVRRType vrrType,
const NvU32 vrrOverrideMinRefreshRate,
const NvBool needsSwFramePacing,
NVHwModeTimingsEvoPtr pTimings);
NvU16 nvPrepareNextVrrNotifier(NVEvoChannelPtr pChannel, NvU32 sd, NvU32 head);
void nvTrackAndDelayFlipForVrrSwFramePacing(NVDispEvoPtr pDispEvo,
const struct NvKmsVrrFramePacingInfo *pVrrFramePacingInfo,
@@ -71,6 +72,8 @@ NvBool nvDispSupportsVrr(const NVDispEvoRec *pDispEvo);
NvBool nvExportVrrSemaphoreSurface(const NVDevEvoRec *pDevEvo, int fd);
void nvVrrSignalSemaphore(NVDevEvoPtr pDevEvo, NvS32 vrrSemaphoreIndex);
#ifdef __cplusplus
};
#endif

View File

@@ -440,9 +440,9 @@ struct NvKmsLayerCapabilities {
NvBool supportsWindowMode :1;
/*!
* Whether layer supports HDR pipe.
* Whether layer supports ICtCp pipe.
*/
NvBool supportsHDR :1;
NvBool supportsICtCp :1;
/*!

View File

@@ -271,6 +271,7 @@ enum NvKmsIoctlCommand {
NVKMS_IOCTL_ENABLE_VBLANK_SEM_CONTROL,
NVKMS_IOCTL_DISABLE_VBLANK_SEM_CONTROL,
NVKMS_IOCTL_ACCEL_VBLANK_SEM_CONTROLS,
NVKMS_IOCTL_VRR_SIGNAL_SEMAPHORE,
};
@@ -295,7 +296,8 @@ enum NvKmsIoctlCommand {
#define NVKMS_3DVISION_DONGLE_PARAM_BYTES 20
#define NVKMS_GPU_STRING_SIZE 80
#define NVKMS_VRR_SEMAPHORE_SURFACE_SIZE 1024
#define NVKMS_VRR_SEMAPHORE_SURFACE_COUNT 256
#define NVKMS_VRR_SEMAPHORE_SURFACE_SIZE (sizeof(NvU32) * NVKMS_VRR_SEMAPHORE_SURFACE_COUNT)
/*
* The GUID string has the form:
@@ -416,6 +418,12 @@ enum NvKmsStereoMode {
NVKMS_STEREO_OTHER,
};
enum NvKmsDscMode {
NVKMS_DSC_MODE_DEFAULT = 0,
NVKMS_DSC_MODE_FORCE_ENABLE,
NVKMS_DSC_MODE_FORCE_DISABLE,
};
struct NvKmsModeValidationParams {
NvBool verboseModeValidation;
NvBool moreVerboseModeValidation;
@@ -433,11 +441,11 @@ struct NvKmsModeValidationParams {
struct NvKmsModeValidationValidSyncs validSyncs;
/*!
* Normally, NVKMS will determine on its own whether to use Display
* Stream Compression (DSC). Use forceDsc to force NVKMS to use DSC,
* when the GPU supports it.
* Normally, NVKMS will determine on its own whether to enable/disable
* Display Stream Compression (DSC). Use dscMode to force NVKMS to
* enable/disable DSC, when both the GPU and display supports it.
*/
NvBool forceDsc;
enum NvKmsDscMode dscMode;
/*!
* When enabled, Display Stream Compression (DSC) has an
@@ -908,7 +916,7 @@ struct NvKmsFlipCommonParams {
/*
* This field can be used when
* NvKmsAllocDeviceReply::layerCaps[layer].supportsHDR = TRUE.
* NvKmsAllocDeviceReply::layerCaps[layer].supportsICtCp = TRUE.
*
* If staticMetadata is enabled for multiple layers, flip request
* will be rejected.
@@ -1413,6 +1421,23 @@ struct NvKmsQueryDpyDynamicDataRequest {
} edid;
};
/*! Values for the NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC attributes. */
enum NvKmsDpyAttributeColorBpcValue {
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_UNKNOWN = 0,
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_6 = 6,
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8 = 8,
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_10 = 10,
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_MAX =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_10,
};
typedef struct _NvKmsDpyOutputColorFormatInfo {
struct {
enum NvKmsDpyAttributeColorBpcValue maxBpc;
enum NvKmsDpyAttributeColorBpcValue minBpc;
} rgb444, yuv444, yuv422;
} NvKmsDpyOutputColorFormatInfo;
enum NvKmsDpyVRRType {
NVKMS_DPY_VRR_TYPE_NONE,
NVKMS_DPY_VRR_TYPE_GSYNC,
@@ -1480,6 +1505,8 @@ struct NvKmsQueryDpyDynamicDataReply {
char infoString[NVKMS_EDID_INFO_STRING_LENGTH];
} edid;
NvKmsDpyOutputColorFormatInfo supportedOutputColorFormats;
struct NvKmsSuperframeInfo superframeInfo;
};
@@ -1874,6 +1901,12 @@ struct NvKmsSetModeOneHeadRequest {
enum NvKmsDpyAttributeRequestedColorSpaceValue colorSpace;
NvBool colorSpaceSpecified;
/*!
* Output color bpc. Valid only when colorBpcSpecified is true.
*/
enum NvKmsDpyAttributeColorBpcValue colorBpc;
NvBool colorBpcSpecified;
/*!
* Output color range. Valid only when colorRangeSpecified is true.
*/
@@ -2558,9 +2591,11 @@ enum NvKmsDpyAttribute {
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE,
NV_KMS_DPY_ATTRIBUTE_REQUESTED_COLOR_RANGE,
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_RANGE,
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC,
NV_KMS_DPY_ATTRIBUTE_DIGITAL_SIGNAL,
NV_KMS_DPY_ATTRIBUTE_DIGITAL_LINK_TYPE,
NV_KMS_DPY_ATTRIBUTE_DISPLAYPORT_LINK_RATE,
NV_KMS_DPY_ATTRIBUTE_DISPLAYPORT_LINK_RATE_10MHZ,
NV_KMS_DPY_ATTRIBUTE_FRAMELOCK_DISPLAY_CONFIG,
/*
* XXX NVKMS TODO: Delete UPDATE_GLS_FRAMELOCK; this event-only
@@ -4168,4 +4203,25 @@ struct NvKmsAccelVblankSemControlsParams {
struct NvKmsAccelVblankSemControlsReply reply;
};
/*!
* NVKMS_IOCTL_VRR_SIGNAL_SEMAPHORE
*
* This IOCTL is used to signal a semaphore from VRR semaphore surface.
* It should be invoked after flip if needed. If device does not supports
* VRR semaphores, then this is a no-op action for compatibility.
*/
struct NvKmsVrrSignalSemaphoreRequest {
NvKmsDeviceHandle deviceHandle;
NvS32 vrrSemaphoreIndex;
};
struct NvKmsVrrSignalSemaphoreReply {
NvU32 padding;
};
struct NvKmsVrrSignalSemaphoreParams {
struct NvKmsVrrSignalSemaphoreRequest request; /*! in */
struct NvKmsVrrSignalSemaphoreReply reply; /*! out */
};
#endif /* NVKMS_API_H */

View File

@@ -41,6 +41,41 @@
nvEvoLogDebug(EVO_LOG_INFO, "[kapi][GPU Id 0x%08x] "__format, \
device->gpuId, ##__VA_ARGS__)
/*
* Semaphore values used when using semaphore-based synchronization between
* userspace rendering and flips.
*/
enum NvKmsKapiSemaphoreValues {
/*
* Initial state on driver init, and the value written by the hardware when
* it has completed processing of a frame using this semaphore.
*/
NVKMS_KAPI_SEMAPHORE_VALUE_DONE = 0xd00dd00d,
/*
* Value of the semaphore when a flip is pending in the display pushbuffer,
* but userspace rendering is not yet complete.
*/
NVKMS_KAPI_SEMAPHORE_VALUE_NOT_READY = 0x13371337,
/*
* Value of the semaphore when userspace rendering is complete and the
* pending flip may proceed.
*/
NVKMS_KAPI_SEMAPHORE_VALUE_READY = 0xf473f473,
};
struct NvKmsKapiNisoSurface {
NvU32 hRmHandle;
NvKmsSurfaceHandle hKmsHandle;
NvBool mapped;
void *pLinearAddress;
enum NvKmsNIsoFormat format;
};
struct NvKmsKapiDevice {
NvU32 gpuId;
@@ -87,20 +122,15 @@ struct NvKmsKapiDevice {
} caps;
NvU64 supportedSurfaceMemoryFormats[NVKMS_KAPI_LAYER_MAX];
NvBool supportsHDR[NVKMS_KAPI_LAYER_MAX];
NvBool supportsICtCp[NVKMS_KAPI_LAYER_MAX];
NvU32 numHeads;
NvU32 numLayers[NVKMS_KAPI_MAX_HEADS];
struct {
NvU32 hRmHandle;
NvKmsSurfaceHandle hKmsHandle;
struct NvKmsKapiNisoSurface notifier;
struct NvKmsKapiNisoSurface semaphore;
NvBool mapped;
void *pLinearAddress;
enum NvKmsNIsoFormat format;
} notifier;
NvU32 numDisplaySemaphores;
struct {
NvU32 currFlipNotifierIndex;

View File

@@ -72,8 +72,10 @@ static inline NvU32 NVKMS_KAPI_NOTIFIER_OFFSET(NvU32 head,
}
NvBool nvKmsKapiAllocateNotifiers(struct NvKmsKapiDevice *device, NvBool inVideoMemory);
NvBool nvKmsKapiAllocateSemaphores(struct NvKmsKapiDevice *device, NvBool inVideoMemory);
void nvKmsKapiFreeNotifiers(struct NvKmsKapiDevice *device);
void nvKmsKapiFreeNisoSurface(struct NvKmsKapiDevice *device,
struct NvKmsKapiNisoSurface *surf);
NvBool nvKmsKapiIsNotifierFinish(const struct NvKmsKapiDevice *device,
const NvU32 head, const NvU32 layer,
@@ -82,4 +84,16 @@ NvBool nvKmsKapiIsNotifierFinish(const struct NvKmsKapiDevice *device,
void nvKmsKapiNotifierSetNotBegun(struct NvKmsKapiDevice *device,
NvU32 head, NvU32 layer, NvU32 index);
NvBool nvKmsKapiResetDisplaySemaphore(struct NvKmsKapiDevice *device,
NvU32 index);
void nvKmsKapiSignalDisplaySemaphore(struct NvKmsKapiDevice *device,
NvU32 index);
void nvKmsKapiCancelDisplaySemaphore(struct NvKmsKapiDevice *device,
NvU32 index);
NvU32 nvKmsKapiGetDisplaySemaphoreOffset(struct NvKmsKapiDevice *device,
NvU32 index);
#endif /* __NVKMS_KAPI_NOTIFIERS_H__ */

View File

@@ -158,13 +158,17 @@ struct NvKmsKapiDeviceResourcesInfo {
NvU32 hasVideoMemory;
NvU32 numDisplaySemaphores;
NvU8 genericPageKind;
NvBool supportsSyncpts;
NvBool requiresVrrSemaphores;
} caps;
NvU64 supportedSurfaceMemoryFormats[NVKMS_KAPI_LAYER_MAX];
NvBool supportsHDR[NVKMS_KAPI_LAYER_MAX];
NvBool supportsICtCp[NVKMS_KAPI_LAYER_MAX];
};
#define NVKMS_KAPI_LAYER_MASK(layerType) (1 << (layerType))
@@ -210,18 +214,26 @@ struct NvKmsKapiStaticDisplayInfo {
NvU32 headMask;
};
struct NvKmsKapiSyncpt {
struct NvKmsKapiSyncParams {
union {
struct {
/*!
* Possible syncpt use case in kapi.
* For pre-syncpt, use only id and value
* and for post-syncpt, use only fd.
*/
NvU32 preSyncptId;
NvU32 preSyncptValue;
} syncpt;
/*!
* Possible syncpt use case in kapi.
* For pre-syncpt, use only id and value
* and for post-syncpt, use only fd.
*/
NvBool preSyncptSpecified;
NvU32 preSyncptId;
NvU32 preSyncptValue;
struct {
NvU32 index;
} semaphore;
} u;
NvBool postSyncptRequested;
NvBool preSyncptSpecified;
NvBool postSyncptRequested;
NvBool semaphoreSpecified;
};
struct NvKmsKapiLayerConfig {
@@ -231,7 +243,7 @@ struct NvKmsKapiLayerConfig {
NvU8 surfaceAlpha;
} compParams;
struct NvKmsRRParams rrParams;
struct NvKmsKapiSyncpt syncptParams;
struct NvKmsKapiSyncParams syncParams;
struct {
struct NvKmsHDRStaticMetadata val;
@@ -319,7 +331,6 @@ struct NvKmsKapiHeadModeSetConfig {
struct {
struct {
NvBool specified;
NvU32 depth;
NvU32 start;
NvU32 end;
@@ -327,7 +338,6 @@ struct NvKmsKapiHeadModeSetConfig {
} input;
struct {
NvBool specified;
NvBool enabled;
struct NvKmsLutRamps *pRamps;
} output;
@@ -342,7 +352,8 @@ struct NvKmsKapiHeadRequestedConfig {
NvBool modeChanged : 1;
NvBool hdrInfoFrameChanged : 1;
NvBool colorimetryChanged : 1;
NvBool lutChanged : 1;
NvBool ilutChanged : 1;
NvBool olutChanged : 1;
} flags;
struct NvKmsKapiCursorRequestedConfig cursorRequestedConfig;
@@ -368,6 +379,8 @@ struct NvKmsKapiHeadReplyConfig {
struct NvKmsKapiModeSetReplyConfig {
enum NvKmsFlipResult flipResult;
NvBool vrrFlip;
NvS32 vrrSemaphoreIndex;
struct NvKmsKapiHeadReplyConfig
headReplyConfig[NVKMS_KAPI_MAX_HEADS];
};
@@ -1410,6 +1423,87 @@ struct NvKmsKapiFunctionsTable {
(
NvKmsKapiSuspendResumeCallbackFunc *function
);
/*!
* Immediately reset the specified display semaphore to the pending state.
*
* Must be called prior to applying a mode set that utilizes the specified
* display semaphore for synchronization.
*
* \param [in] device The device which will utilize the semaphore.
*
* \param [in] semaphoreIndex Index of the desired semaphore within the
* NVKMS semaphore pool. Must be less than
* NvKmsKapiDeviceResourcesInfo::caps::numDisplaySemaphores
* for the specified device.
*/
NvBool
(*resetDisplaySemaphore)
(
struct NvKmsKapiDevice *device,
NvU32 semaphoreIndex
);
/*!
* Immediately set the specified display semaphore to the displayable state.
*
* Must be called after \ref resetDisplaySemaphore to indicate a mode
* configuration change that utilizes the specified display semaphore for
* synchronization may proceed.
*
* \param [in] device The device which will utilize the semaphore.
*
* \param [in] semaphoreIndex Index of the desired semaphore within the
* NVKMS semaphore pool. Must be less than
* NvKmsKapiDeviceResourcesInfo::caps::numDisplaySemaphores
* for the specified device.
*/
void
(*signalDisplaySemaphore)
(
struct NvKmsKapiDevice *device,
NvU32 semaphoreIndex
);
/*!
* Immediately cancel use of a display semaphore by resetting its value to
* its initial state.
*
* This can be used by clients to restore a semaphore to a consistent state
* when they have prepared it for use by previously calling
* \ref resetDisplaySemaphore() on it, but are then prevented from
* submitting the associated hardware operations to consume it due to the
* subsequent failure of some software or hardware operation.
*
* \param [in] device The device which will utilize the semaphore.
*
* \param [in] semaphoreIndex Index of the desired semaphore within the
* NVKMS semaphore pool. Must be less than
* NvKmsKapiDeviceResourcesInfo::caps::numDisplaySemaphores
* for the specified device.
*/
void
(*cancelDisplaySemaphore)
(
struct NvKmsKapiDevice *device,
NvU32 semaphoreIndex
);
/*!
* Signal the VRR semaphore at the specified index from the CPU.
* If device does not support VRR semaphores, this is a no-op.
* Returns true if signal is success or no-op, otherwise returns false.
*
* \param [in] device A device allocated using allocateDevice().
*
* \param [in] index The VRR semaphore index to be signalled.
*/
NvBool
(*signalVrrSemaphore)
(
struct NvKmsKapiDevice *device,
NvS32 index
);
};
/** @} */

View File

@@ -33,14 +33,15 @@
NVKMS_MAX_LAYERS_PER_HEAD * \
NVKMS_KAPI_MAX_NOTIFERS_PER_LAYER)
void nvKmsKapiFreeNotifiers(struct NvKmsKapiDevice *device)
void nvKmsKapiFreeNisoSurface(struct NvKmsKapiDevice *device,
struct NvKmsKapiNisoSurface *surface)
{
if (device->notifier.hKmsHandle != 0) {
if (surface->hKmsHandle != 0) {
struct NvKmsUnregisterSurfaceParams paramsUnreg = { };
NvBool status;
paramsUnreg.request.deviceHandle = device->hKmsDevice;
paramsUnreg.request.surfaceHandle = device->notifier.hKmsHandle;
paramsUnreg.request.surfaceHandle = surface->hKmsHandle;
status = nvkms_ioctl_from_kapi(device->pKmsOpen,
NVKMS_IOCTL_UNREGISTER_SURFACE,
@@ -55,13 +56,13 @@ void nvKmsKapiFreeNotifiers(struct NvKmsKapiDevice *device)
device->notifier.hKmsHandle = 0;
}
if (device->notifier.mapped) {
if (surface->mapped) {
NV_STATUS status;
status = nvRmApiUnmapMemory(device->hRmClient,
device->hRmSubDevice,
device->notifier.hRmHandle,
device->notifier.pLinearAddress,
surface->hRmHandle,
surface->pLinearAddress,
0);
if (status != NV_OK) {
@@ -74,12 +75,12 @@ void nvKmsKapiFreeNotifiers(struct NvKmsKapiDevice *device)
device->notifier.mapped = NV_FALSE;
}
if (device->notifier.hRmHandle != 0) {
if (surface->hRmHandle != 0) {
NvU32 status;
status = nvRmApiFree(device->hRmClient,
device->hRmDevice,
device->notifier.hRmHandle);
surface->hRmHandle);
if (status != NVOS_STATUS_SUCCESS) {
nvKmsKapiLogDeviceDebug(
@@ -88,8 +89,8 @@ void nvKmsKapiFreeNotifiers(struct NvKmsKapiDevice *device)
status);
}
nvFreeUnixRmHandle(&device->handleAllocator, device->notifier.hRmHandle);
device->notifier.hRmHandle = 0;
nvFreeUnixRmHandle(&device->handleAllocator, surface->hRmHandle);
surface->hRmHandle = 0;
}
}
@@ -102,9 +103,9 @@ static void InitNotifier(struct NvKmsKapiDevice *device,
device->notifier.pLinearAddress);
}
#define NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE 0x1000
NvBool nvKmsKapiAllocateNotifiers(struct NvKmsKapiDevice *device,
static NvBool AllocateNisoSurface(struct NvKmsKapiDevice *device,
struct NvKmsKapiNisoSurface *surface,
NvU64 size,
NvBool inVideoMemory)
{
struct NvKmsRegisterSurfaceParams surfParams = {};
@@ -112,19 +113,10 @@ NvBool nvKmsKapiAllocateNotifiers(struct NvKmsKapiDevice *device,
NvU8 compressible = 0;
NvBool ret;
ct_assert((NVKMS_KAPI_MAX_NOTIFIERS * NVKMS_KAPI_NOTIFIER_SIZE) <=
(NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE));
ct_assert(NVKMS_KAPI_NOTIFIER_SIZE >= sizeof(NvNotification));
nvAssert(NVKMS_KAPI_NOTIFIER_SIZE >=
nvKmsSizeOfNotifier(device->notifier.format, TRUE /* overlay */));
nvAssert(NVKMS_KAPI_NOTIFIER_SIZE >=
nvKmsSizeOfNotifier(device->notifier.format, FALSE /* overlay */));
device->notifier.hRmHandle =
surface->hRmHandle =
nvGenerateUnixRmHandle(&device->handleAllocator);
if (device->notifier.hRmHandle == 0x0) {
if (surface->hRmHandle == 0x0) {
nvKmsKapiLogDeviceDebug(
device,
"nvGenerateUnixRmHandle() failed");
@@ -133,32 +125,32 @@ NvBool nvKmsKapiAllocateNotifiers(struct NvKmsKapiDevice *device,
if (inVideoMemory) {
ret = nvKmsKapiAllocateVideoMemory(device,
device->notifier.hRmHandle,
surface->hRmHandle,
NvKmsSurfaceMemoryLayoutPitch,
NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE,
size,
NVKMS_KAPI_ALLOCATION_TYPE_NOTIFIER,
&compressible);
} else {
ret = nvKmsKapiAllocateSystemMemory(device,
device->notifier.hRmHandle,
NvKmsSurfaceMemoryLayoutPitch,
NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE,
surface->hRmHandle,
NvKmsSurfaceMemoryLayoutPitch,
size,
NVKMS_KAPI_ALLOCATION_TYPE_NOTIFIER,
&compressible);
}
if (!ret) {
nvFreeUnixRmHandle(&device->handleAllocator, device->notifier.hRmHandle);
device->notifier.hRmHandle = 0x0;
nvFreeUnixRmHandle(&device->handleAllocator, surface->hRmHandle);
surface->hRmHandle = 0x0;
goto failed;
}
status = nvRmApiMapMemory(device->hRmClient,
device->hRmSubDevice,
device->notifier.hRmHandle,
surface->hRmHandle,
0,
NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE,
&device->notifier.pLinearAddress,
size,
&surface->pLinearAddress,
0);
if (status != NV_OK) {
@@ -169,23 +161,22 @@ NvBool nvKmsKapiAllocateNotifiers(struct NvKmsKapiDevice *device,
goto failed;
}
device->notifier.mapped = NV_TRUE;
surface->mapped = NV_TRUE;
surfParams.request.deviceHandle = device->hKmsDevice;
surfParams.request.useFd = FALSE;
surfParams.request.rmClient = device->hRmClient;
surfParams.request.widthInPixels = NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE;
surfParams.request.widthInPixels = size;
surfParams.request.heightInPixels = 1;
surfParams.request.layout = NvKmsSurfaceMemoryLayoutPitch;
surfParams.request.format = NvKmsSurfaceMemoryFormatI8;
surfParams.request.log2GobsPerBlockY = 0;
surfParams.request.isoType = NVKMS_MEMORY_NISO;
surfParams.request.planes[0].u.rmObject = device->notifier.hRmHandle;
surfParams.request.planes[0].pitch = NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE;
surfParams.request.planes[0].rmObjectSizeInBytes =
NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE;
surfParams.request.planes[0].u.rmObject = surface->hRmHandle;
surfParams.request.planes[0].pitch = size;
surfParams.request.planes[0].rmObjectSizeInBytes = size;
if (!nvkms_ioctl_from_kapi(device->pKmsOpen,
NVKMS_IOCTL_REGISTER_SURFACE,
@@ -196,7 +187,37 @@ NvBool nvKmsKapiAllocateNotifiers(struct NvKmsKapiDevice *device,
goto failed;
}
device->notifier.hKmsHandle = surfParams.reply.surfaceHandle;
surface->hKmsHandle = surfParams.reply.surfaceHandle;
return NV_TRUE;
failed:
nvKmsKapiFreeNisoSurface(device, surface);
return NV_FALSE;
}
#define NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE 0x1000
NvBool nvKmsKapiAllocateNotifiers(struct NvKmsKapiDevice *device,
NvBool inVideoMemory)
{
ct_assert((NVKMS_KAPI_MAX_NOTIFIERS * NVKMS_KAPI_NOTIFIER_SIZE) <=
NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE);
ct_assert(NVKMS_KAPI_NOTIFIER_SIZE >= sizeof(NvNotification));
nvAssert(NVKMS_KAPI_NOTIFIER_SIZE >=
nvKmsSizeOfNotifier(device->notifier.format, TRUE /* overlay */));
nvAssert(NVKMS_KAPI_NOTIFIER_SIZE >=
nvKmsSizeOfNotifier(device->notifier.format, FALSE /* overlay */));
if (!AllocateNisoSurface(device,
&device->notifier,
NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE,
inVideoMemory)) {
return NV_FALSE;
}
/* Init Notifiers */
@@ -218,10 +239,117 @@ NvBool nvKmsKapiAllocateNotifiers(struct NvKmsKapiDevice *device,
}
return NV_TRUE;
failed:
nvKmsKapiFreeNotifiers(device);
return NV_FALSE;
}
static void ResetSemaphore(struct NvKmsKapiDevice *device,
NvU32 index,
NvU32 payload)
{
nvKmsResetSemaphore(device->semaphore.format,
index,
device->semaphore.pLinearAddress,
payload);
}
#define NVKMS_KAPI_SEMAPHORE_SURFACE_SIZE 0x1000
NvBool nvKmsKapiAllocateSemaphores(struct NvKmsKapiDevice *device,
NvBool inVideoMemory)
{
NvU32 index;
if (!AllocateNisoSurface(device,
&device->semaphore,
NVKMS_KAPI_SEMAPHORE_SURFACE_SIZE,
inVideoMemory)) {
return NV_FALSE;
}
/* Init Semaphores */
device->numDisplaySemaphores = NVKMS_KAPI_SEMAPHORE_SURFACE_SIZE /
nvKmsSizeOfSemaphore(device->semaphore.format);
/*
* See the comment in nvKmsKapiSignalDisplaySemaphore() for the full
* justification of this requirement. The current implementation requires
* only 16 semaphores (2 per window) given a maximum of one outstanding
* flip, but this value allows up to 32 outstanding flips, as recommended
* by the architecture team in an old hardware bug.
*/
nvAssert(device->numDisplaySemaphores >= 256);
for (index = 0; index < device->numDisplaySemaphores; index++) {
ResetSemaphore(device, index, NVKMS_KAPI_SEMAPHORE_VALUE_DONE);
}
return NV_TRUE;
}
NvBool nvKmsKapiResetDisplaySemaphore(struct NvKmsKapiDevice *device,
NvU32 index)
{
struct nvKmsParsedSemaphore semParsed;
nvKmsParseSemaphore(device->semaphore.format,
index,
device->semaphore.pLinearAddress,
&semParsed);
if (semParsed.payload != NVKMS_KAPI_SEMAPHORE_VALUE_DONE) {
nvKmsKapiLogDeviceDebug(
device,
"Attempt to reuse semaphore at index %u with pending status 0x%08x",
index,
semParsed.payload);
return NV_FALSE;
}
ResetSemaphore(device, index, NVKMS_KAPI_SEMAPHORE_VALUE_NOT_READY);
return NV_TRUE;
}
void nvKmsKapiSignalDisplaySemaphore(struct NvKmsKapiDevice *device,
NvU32 index)
{
/*
* Note most users of semaphores use a "ready" value that varies from
* frame to frame, citing bug 194936. However, this "bug" simply
* notes that the hardware may read ahead and grab semaphore values for
* pending semaphore acquires such that two pending frames using the
* same semaphore might be signaled "ready" by the same semaphore write.
* Given this implementation cycles through at least 256 semaphores,
* meaning if all 8 hardware windows were programmed in every flip, there
* could be at least 32 frames in-flight without re-using a semaphore
* slot, and the code above that initializes a semaphore for each frame
* first ensures the prior frame using that semaphore has completed,
* this approach is not necessary here. There should be no opportunity
* for the hardware to "pre-fetch" a prior frame's semaphore acquire
* value from the semaphore here, and hence a constant value is sufficient.
*/
ResetSemaphore(device, index, NVKMS_KAPI_SEMAPHORE_VALUE_READY);
}
void nvKmsKapiCancelDisplaySemaphore(struct NvKmsKapiDevice *device,
NvU32 index)
{
struct nvKmsParsedSemaphore semParsed;
nvKmsParseSemaphore(device->semaphore.format,
index,
device->semaphore.pLinearAddress,
&semParsed);
if (semParsed.payload != NVKMS_KAPI_SEMAPHORE_VALUE_DONE) {
nvAssert(semParsed.payload == NVKMS_KAPI_SEMAPHORE_VALUE_NOT_READY);
ResetSemaphore(device, index, NVKMS_KAPI_SEMAPHORE_VALUE_DONE);
}
}
NvU32 nvKmsKapiGetDisplaySemaphoreOffset(struct NvKmsKapiDevice *device,
NvU32 index)
{
return nvKmsSizeOfSemaphore(device->semaphore.format) * index;
}

View File

@@ -26,6 +26,7 @@
#include "nvidia-modeset-os-interface.h"
#include "nvkms-api.h"
#include "nvkms-sync.h"
#include "nvkms-rmapi.h"
#include "nvkms-vrr.h"
@@ -272,9 +273,10 @@ failed:
*/
static void KmsFreeDevice(struct NvKmsKapiDevice *device)
{
/* Free notifier memory */
/* Free notifier and semaphore memory */
nvKmsKapiFreeNotifiers(device);
nvKmsKapiFreeNisoSurface(device, &device->semaphore);
nvKmsKapiFreeNisoSurface(device, &device->notifier);
/* Free NVKMS device */
@@ -398,7 +400,7 @@ static NvBool KmsAllocateDevice(struct NvKmsKapiDevice *device)
for (layer = 0; layer < NVKMS_KAPI_LAYER_MAX; layer++) {
device->supportedSurfaceMemoryFormats[layer] =
paramsAlloc->reply.layerCaps[layer].supportedSurfaceMemoryFormats;
device->supportsHDR[layer] = paramsAlloc->reply.layerCaps[layer].supportsHDR;
device->supportsICtCp[layer] = paramsAlloc->reply.layerCaps[layer].supportsICtCp;
}
if (paramsAlloc->reply.validNIsoFormatMask &
@@ -413,6 +415,15 @@ static NvBool KmsAllocateDevice(struct NvKmsKapiDevice *device)
device->notifier.format = NVKMS_NISO_FORMAT_LEGACY;
}
if (paramsAlloc->reply.validNIsoFormatMask &
(1 << NVKMS_NISO_FORMAT_FOUR_WORD_NVDISPLAY)) {
device->semaphore.format = NVKMS_NISO_FORMAT_FOUR_WORD_NVDISPLAY;
} else {
nvAssert(paramsAlloc->reply.validNIsoFormatMask &
(1 << NVKMS_NISO_FORMAT_LEGACY));
device->semaphore.format = NVKMS_NISO_FORMAT_LEGACY;
}
/* XXX Add support for SLI/multiple display engines per device */
if (paramsAlloc->reply.numDisps != 1)
{
@@ -442,6 +453,14 @@ static NvBool KmsAllocateDevice(struct NvKmsKapiDevice *device)
goto done;
}
/* Allocate semaphore memory in video memory whenever available */
if (!nvKmsKapiAllocateSemaphores(device, !device->isSOC)) {
nvKmsKapiLogDebug(
"Failed to allocate Semaphore objects for GPU ID 0x%08x",
device->gpuId);
goto done;
}
ret = NV_TRUE;
done:
@@ -1010,6 +1029,7 @@ static NvBool GetDeviceResourcesInfo
info->caps.hasVideoMemory = !device->isSOC;
info->caps.genericPageKind = device->caps.genericPageKind;
info->caps.requiresVrrSemaphores = device->caps.requiresVrrSemaphores;
if (device->hKmsDevice == 0x0) {
info->caps.pitchAlignment = 0x1;
@@ -1085,6 +1105,8 @@ static NvBool GetDeviceResourcesInfo
info->caps.supportedCursorSurfaceMemoryFormats =
NVBIT(NvKmsSurfaceMemoryFormatA8R8G8B8);
info->caps.numDisplaySemaphores = device->numDisplaySemaphores;
ct_assert(sizeof(info->supportedSurfaceMemoryFormats) ==
sizeof(device->supportedSurfaceMemoryFormats));
@@ -1092,12 +1114,12 @@ static NvBool GetDeviceResourcesInfo
device->supportedSurfaceMemoryFormats,
sizeof(device->supportedSurfaceMemoryFormats));
ct_assert(sizeof(info->supportsHDR) ==
sizeof(device->supportsHDR));
ct_assert(sizeof(info->supportsICtCp) ==
sizeof(device->supportsICtCp));
nvkms_memcpy(info->supportsHDR,
device->supportsHDR,
sizeof(device->supportsHDR));
nvkms_memcpy(info->supportsICtCp,
device->supportsICtCp,
sizeof(device->supportsICtCp));
done:
return status;
@@ -1319,7 +1341,7 @@ static NvBool GetDynamicDisplayInfo(
sizeof(params->edid.buffer));
params->edid.bufferSize = pParamsDpyDynamic->reply.edid.bufferSize;
params->vrrSupported = (vrrSupported && !device->caps.requiresVrrSemaphores) ? NV_TRUE : NV_FALSE;
params->vrrSupported = vrrSupported;
}
done:
@@ -2471,25 +2493,48 @@ static NvBool AssignSyncObjectConfig(
struct NvKmsChannelSyncObjects *pSyncObject)
{
if (!device->supportsSyncpts) {
if (pLayerConfig->syncptParams.preSyncptSpecified ||
pLayerConfig->syncptParams.postSyncptRequested) {
if (pLayerConfig->syncParams.preSyncptSpecified ||
pLayerConfig->syncParams.postSyncptRequested) {
return NV_FALSE;
}
}
/* Syncpt and Semaphore usage are mutually exclusive. */
if (pLayerConfig->syncParams.semaphoreSpecified &&
(pLayerConfig->syncParams.preSyncptSpecified ||
pLayerConfig->syncParams.postSyncptRequested)) {
return NV_FALSE;
}
pSyncObject->useSyncpt = FALSE;
if (pLayerConfig->syncptParams.preSyncptSpecified) {
if (pLayerConfig->syncParams.preSyncptSpecified) {
pSyncObject->useSyncpt = TRUE;
pSyncObject->u.syncpts.pre.type = NVKMS_SYNCPT_TYPE_RAW;
pSyncObject->u.syncpts.pre.u.raw.id = pLayerConfig->syncptParams.preSyncptId;
pSyncObject->u.syncpts.pre.u.raw.value = pLayerConfig->syncptParams.preSyncptValue;
pSyncObject->u.syncpts.pre.u.raw.id = pLayerConfig->syncParams.u.syncpt.preSyncptId;
pSyncObject->u.syncpts.pre.u.raw.value = pLayerConfig->syncParams.u.syncpt.preSyncptValue;
} else if (pLayerConfig->syncParams.semaphoreSpecified) {
pSyncObject->u.semaphores.release.surface.surfaceHandle =
pSyncObject->u.semaphores.acquire.surface.surfaceHandle =
device->semaphore.hKmsHandle;
pSyncObject->u.semaphores.release.surface.format =
pSyncObject->u.semaphores.acquire.surface.format =
device->semaphore.format;
pSyncObject->u.semaphores.release.surface.offsetInWords =
pSyncObject->u.semaphores.acquire.surface.offsetInWords =
nvKmsKapiGetDisplaySemaphoreOffset(
device,
pLayerConfig->syncParams.u.semaphore.index) >> 2;
pSyncObject->u.semaphores.acquire.value =
NVKMS_KAPI_SEMAPHORE_VALUE_READY;
pSyncObject->u.semaphores.release.value =
NVKMS_KAPI_SEMAPHORE_VALUE_DONE;
}
if (pLayerConfig->syncptParams.postSyncptRequested) {
if (pLayerConfig->syncParams.postSyncptRequested) {
pSyncObject->useSyncpt = TRUE;
pSyncObject->u.syncpts.requestedPostType = NVKMS_SYNCPT_TYPE_FD;
}
return NV_TRUE;
@@ -2581,7 +2626,7 @@ static NvBool NvKmsKapiOverlayLayerConfigToKms(
params->layer[layer].colorSpace.specified = TRUE;
}
if (layerRequestedConfig->flags.cscChanged) {
if (layerRequestedConfig->flags.cscChanged || bFromKmsSetMode) {
params->layer[layer].csc.specified = NV_TRUE;
params->layer[layer].csc.useMain = layerConfig->cscUseMain;
if (!layerConfig->cscUseMain) {
@@ -2709,7 +2754,7 @@ static NvBool NvKmsKapiPrimaryLayerConfigToKms(
changed = TRUE;
}
if (layerRequestedConfig->flags.cscChanged) {
if (layerRequestedConfig->flags.cscChanged || bFromKmsSetMode) {
nvAssert(!layerConfig->cscUseMain);
params->layer[NVKMS_MAIN_LAYER].csc.specified = NV_TRUE;
@@ -2795,25 +2840,32 @@ static NvBool NvKmsKapiLayerConfigToKms(
}
static void NvKmsKapiHeadLutConfigToKms(
const struct NvKmsKapiHeadModeSetConfig *modeSetConfig,
struct NvKmsSetLutCommonParams *lutParams)
const struct NvKmsKapiHeadRequestedConfig *headRequestedConfig,
struct NvKmsSetLutCommonParams *lutParams,
NvBool bFromKmsSetMode)
{
const struct NvKmsKapiHeadModeSetConfig *modeSetConfig =
&headRequestedConfig->modeSetConfig;
struct NvKmsSetInputLutParams *input = &lutParams->input;
struct NvKmsSetOutputLutParams *output = &lutParams->output;
/* input LUT */
input->specified = modeSetConfig->lut.input.specified;
input->depth = modeSetConfig->lut.input.depth;
input->start = modeSetConfig->lut.input.start;
input->end = modeSetConfig->lut.input.end;
if (headRequestedConfig->flags.ilutChanged || bFromKmsSetMode) {
input->specified = NV_TRUE;
input->depth = modeSetConfig->lut.input.depth;
input->start = modeSetConfig->lut.input.start;
input->end = modeSetConfig->lut.input.end;
input->pRamps = nvKmsPointerToNvU64(modeSetConfig->lut.input.pRamps);
input->pRamps = nvKmsPointerToNvU64(modeSetConfig->lut.input.pRamps);
}
/* output LUT */
output->specified = modeSetConfig->lut.output.specified;
output->enabled = modeSetConfig->lut.output.enabled;
if (headRequestedConfig->flags.olutChanged || bFromKmsSetMode) {
output->specified = NV_TRUE;
output->enabled = modeSetConfig->lut.output.enabled;
output->pRamps = nvKmsPointerToNvU64(modeSetConfig->lut.output.pRamps);
output->pRamps = nvKmsPointerToNvU64(modeSetConfig->lut.output.pRamps);
}
}
static NvBool AnyLayerTransferFunctionChanged(
@@ -2925,9 +2977,9 @@ static NvBool NvKmsKapiRequestedModeSetConfigToKms(
NvKmsKapiDisplayModeToKapi(&headModeSetConfig->mode, &paramsHead->mode);
if (headRequestedConfig->flags.lutChanged) {
NvKmsKapiHeadLutConfigToKms(headModeSetConfig, &paramsHead->flip.lut);
}
NvKmsKapiHeadLutConfigToKms(headRequestedConfig,
&paramsHead->flip.lut,
NV_TRUE /* bFromKmsSetMode */);
NvKmsKapiCursorConfigToKms(&headRequestedConfig->cursorRequestedConfig,
&paramsHead->flip,
@@ -2975,13 +3027,8 @@ static NvBool NvKmsKapiRequestedModeSetConfigToKms(
paramsHead->viewPortSizeIn.height =
headModeSetConfig->mode.timings.vVisible;
if (device->caps.requiresVrrSemaphores) {
paramsHead->allowGsync = NV_FALSE;
paramsHead->allowAdaptiveSync = NVKMS_ALLOW_ADAPTIVE_SYNC_DISABLED;
} else {
paramsHead->allowGsync = NV_TRUE;
paramsHead->allowAdaptiveSync = NVKMS_ALLOW_ADAPTIVE_SYNC_ALL;
}
paramsHead->allowGsync = NV_TRUE;
paramsHead->allowAdaptiveSync = NVKMS_ALLOW_ADAPTIVE_SYNC_ALL;
}
return NV_TRUE;
@@ -3189,9 +3236,10 @@ static NvBool KmsFlip(
if (headModeSetConfig->vrrEnabled) {
params->request.allowVrr = NV_TRUE;
}
if (headRequestedConfig->flags.lutChanged) {
NvKmsKapiHeadLutConfigToKms(headModeSetConfig, &flipParams->lut);
}
NvKmsKapiHeadLutConfigToKms(headRequestedConfig,
&flipParams->lut,
NV_FALSE /* bFromKmsSetMode */);
}
if (params->request.numFlipHeads == 0) {
@@ -3216,6 +3264,9 @@ static NvBool KmsFlip(
}
/*! fill back flip reply */
replyConfig->vrrFlip = params->reply.vrrFlipType;
replyConfig->vrrSemaphoreIndex = params->reply.vrrSemaphoreIndex;
for (i = 0; i < params->request.numFlipHeads; i++) {
const struct NvKmsKapiHeadRequestedConfig *headRequestedConfig =
&requestedConfig->headRequestedConfig[pFlipHead[i].head];
@@ -3246,7 +3297,7 @@ static NvBool KmsFlip(
/*! initialize explicitly to -1 as 0 is valid file descriptor */
layerReplyConfig->postSyncptFd = -1;
if (layerRequestedConfig->syncptParams.postSyncptRequested) {
if (layerRequestedConfig->syncParams.postSyncptRequested) {
layerReplyConfig->postSyncptFd =
flipParams->layer[layer].postSyncpt.u.fd;
}
@@ -3457,6 +3508,25 @@ static void nvKmsKapiSetSuspendResumeCallback
pSuspendResumeFunc = function;
}
static NvBool SignalVrrSemaphore
(
struct NvKmsKapiDevice *device,
NvS32 index
)
{
NvBool status = NV_TRUE;
struct NvKmsVrrSignalSemaphoreParams params = { };
params.request.deviceHandle = device->hKmsDevice;
params.request.vrrSemaphoreIndex = index;
status = nvkms_ioctl_from_kapi(device->pKmsOpen,
NVKMS_IOCTL_VRR_SIGNAL_SEMAPHORE,
&params, sizeof(params));
if (!status) {
nvKmsKapiLogDeviceDebug(device, "NVKMS VrrSignalSemaphore failed");
}
return status;
}
NvBool nvKmsKapiGetFunctionsTableInternal
(
struct NvKmsKapiFunctionsTable *funcsTable
@@ -3537,5 +3607,10 @@ NvBool nvKmsKapiGetFunctionsTableInternal
nvKmsKapiSetSemaphoreSurfaceValue;
funcsTable->setSuspendResumeCallback = nvKmsKapiSetSuspendResumeCallback;
funcsTable->resetDisplaySemaphore = nvKmsKapiResetDisplaySemaphore;
funcsTable->signalDisplaySemaphore = nvKmsKapiSignalDisplaySemaphore;
funcsTable->cancelDisplaySemaphore = nvKmsKapiCancelDisplaySemaphore;
funcsTable->signalVrrSemaphore = SignalVrrSemaphore;
return NV_TRUE;
}

View File

@@ -238,9 +238,17 @@ static void EnableVRR(NVDpyEvoPtr pDpyEvo)
DisplayPort::Device *device = pDpyEvo->dp.pDpLibDevice->device;
const NvBool dispSupportsVrr = nvDispSupportsVrr(pDispEvo);
if (pDpyEvo->internal) {
// VRR + notebooks not supported, yet
pDpyEvo->vrr.type = NVKMS_DPY_VRR_TYPE_NONE;
// If the dpy is a laptop internal panel and an SBIOS cookie indicates that
// it supports VRR, override its enable flag and timeout. Note that in the
// internal panel scenario, the EDID may not claim VRR support, so honor
// hasPlatformCookie even if DpyHasVRREDID() reports FALSE.
if (pDpyEvo->internal && pDispEvo->vrr.hasPlatformCookie) {
if (pDispEvo->pDevEvo->hal->caps.supportsDisplayRate) {
pDpyEvo->vrr.needsSwFramePacing = TRUE;
}
pDpyEvo->vrr.type = NVKMS_DPY_VRR_TYPE_GSYNC;
return;
}
@@ -299,53 +307,6 @@ static void EnableVRR(NVDpyEvoPtr pDpyEvo)
pDpyEvo->vrr.type = NVKMS_DPY_VRR_TYPE_NONE;
}
}
if (pDpyEvo->parsedEdid.valid && nvDpyIsAdaptiveSync(pDpyEvo)) {
// Adaptive-Sync minimum refresh rate is either in DisplayID (Display
// ID spec 1.3 section 4.6 Video Timing Range Limits) or EDID (EDID
// spec 1.4 section 3.10.3.3 Display Range Limits & Additional Timing
// Descriptor Definition)
int minRR = 0;
if (pDpyEvo->parsedEdid.info.ext_displayid.version) {
minRR = pDpyEvo->parsedEdid.info.ext_displayid.range_limits[0].vfreq_min;
}
if (minRR == 0) {
NvU32 i;
for (i = 0; i < NVT_EDID_MAX_LONG_DISPLAY_DESCRIPTOR; i++) {
if (pDpyEvo->parsedEdid.info.ldd[i].tag ==
NVT_EDID_DISPLAY_DESCRIPTOR_DRL) {
minRR = pDpyEvo->parsedEdid.info.ldd[i].u.range_limit.min_v_rate;
}
}
}
if (minRR == 0) {
// Adaptive sync does not support self refresh (zero timeout)
nvEvoLogDisp(pDispEvo, EVO_LOG_WARN,
"%s: G-SYNC Compatible: EDID min refresh rate "
"invalid, disabling G-SYNC Compatible.",
pDpyEvo->name);
pDpyEvo->vrr.type = NVKMS_DPY_VRR_TYPE_NONE;
pDpyEvo->vrr.needsSwFramePacing = FALSE;
} else {
pDpyEvo->vrr.edidTimeoutMicroseconds = 1000000 / minRR;
}
} else if (DpyHasVRREDID(pDpyEvo)) {
// Update the minimum refresh rate if a VRR EDID block is present.
const int minRR =
pDpyEvo->parsedEdid.info.nvdaVsdbInfo.vrrData.v1.minRefreshRate;
if (minRR == 0) {
// Zero indicates that no refreshes are required (i.e. the panel is
// self-refreshing).
pDpyEvo->vrr.edidTimeoutMicroseconds = 0;
} else {
// Round the timeout down. It's better to refresh the panel too soon
// than too late.
pDpyEvo->vrr.edidTimeoutMicroseconds = 1000000 / minRR;
}
}
}
// when we get this event, the DP lib has done link training and the
@@ -604,11 +565,13 @@ void nvDPLibUpdateDpyLinkConfiguration(NVDpyEvoPtr pDpyEvo)
pDpyEvo->pConnectorEvo->pDpLibConnector->connector;
unsigned laneCount;
NvU64 linkRate;
NvU64 linkRate10MHz;
enum NvKmsDpyAttributeDisplayportConnectorTypeValue connectorType;
NvBool sinkIsAudioCapable;
if (!dev || !pDpLibDevice->isPlugged) {
linkRate = 0;
linkRate10MHz = 0;
laneCount = NV0073_CTRL_CMD_DP_GET_LINK_CONFIG_LANE_COUNT_1;
connectorType = NV_KMS_DPY_ATTRIBUTE_DISPLAYPORT_CONNECTOR_TYPE_UNKNOWN;
sinkIsAudioCapable = FALSE;
@@ -620,6 +583,7 @@ void nvDPLibUpdateDpyLinkConfiguration(NVDpyEvoPtr pDpyEvo)
// The DisplayPort library multiplies the link rate enum value by
// 27000000. Convert back to NV-CONTROL's defines.
linkRate /= 27000000;
linkRate10MHz = linkRate * 27;
nvkmsDisplayPort::EnableVRR(pDpyEvo);
@@ -667,6 +631,13 @@ void nvDPLibUpdateDpyLinkConfiguration(NVDpyEvoPtr pDpyEvo)
linkRate);
}
if (linkRate10MHz != pDpyEvo->dp.linkRate10MHz) {
pDpyEvo->dp.linkRate10MHz = linkRate10MHz;
nvSendDpyAttributeChangedEventEvo(pDpyEvo,
NV_KMS_DPY_ATTRIBUTE_DISPLAYPORT_LINK_RATE_10MHZ,
linkRate10MHz);
}
if (connectorType != pDpyEvo->dp.connectorType) {
pDpyEvo->dp.connectorType = connectorType;
nvSendDpyAttributeChangedEventEvo(pDpyEvo,

View File

@@ -468,14 +468,30 @@ static NvBool ConstructDpLibIsModesetPossibleParamsOneHead(
}
pParams->head[head].pDscParams->bCheckWithDsc = true;
pParams->head[head].pDscParams->forceDsc = pModeValidationParams->forceDsc ?
DisplayPort::DSC_FORCE_ENABLE :
DisplayPort::DSC_DEFAULT;
pParams->head[head].pDscParams->forceDsc = DisplayPort::DSC_DEFAULT;
switch (pModeValidationParams->dscMode) {
case NVKMS_DSC_MODE_FORCE_ENABLE:
pParams->head[head].pDscParams->forceDsc =
DisplayPort::DSC_FORCE_ENABLE;
break;
case NVKMS_DSC_MODE_FORCE_DISABLE:
pParams->head[head].pDscParams->forceDsc =
DisplayPort::DSC_FORCE_DISABLE;
break;
default:
pParams->head[head].pDscParams->forceDsc =
DisplayPort::DSC_DEFAULT;
break;
}
/*
* 2Heads1Or requires either YUV420 or DSC; if b2Heads1Or is enabled
* but YUV420 is not, force DSC.
*/
if (b2Heads1Or && (pTimings->yuv420Mode != NV_YUV420_MODE_HW)) {
if (pModeValidationParams->dscMode == NVKMS_DSC_MODE_FORCE_DISABLE) {
goto failed;
}
pParams->head[head].pDscParams->forceDsc = DisplayPort::DSC_FORCE_ENABLE;
}

View File

@@ -46,14 +46,6 @@ static NVEvoLogType dpSeverityToNvkmsMap(DP_LOG_LEVEL severity)
return level;
}
void dpPrint(const char *format, ...)
{
va_list ap;
va_start(ap, format);
nvVEvoLog(EVO_LOG_INFO, NV_INVALID_GPU_LOG_INDEX, format, ap);
va_end(ap);
}
void dpPrintf(DP_LOG_LEVEL severity, const char *format, ...)
{
if (severity == DP_SILENT) return;

View File

@@ -628,6 +628,7 @@ static void DpyPostColorSpaceOrRangeSetEvo(NVDpyEvoPtr pDpyEvo)
pApiHeadState->timings.yuv420Mode,
pApiHeadState->attributes.color.colorimetry,
pDpyEvo->requestedColorSpace,
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_UNKNOWN,
pDpyEvo->requestedColorRange,
&colorSpace,
&colorBpc,
@@ -668,8 +669,8 @@ static void DpyPostColorSpaceOrRangeSetEvo(NVDpyEvoPtr pDpyEvo)
if (pApiHeadState->timings.protocol == NVKMS_PROTOCOL_SOR_HDMI_FRL) {
tmpDpyColor.bpc = pApiHeadState->attributes.color.bpc;
} else {
const NVColorFormatInfoRec colorFormatsInfo =
nvGetColorFormatInfo(pDpyEvo);
const NvKmsDpyOutputColorFormatInfo colorFormatsInfo =
nvDpyGetOutputColorFormatInfo(pDpyEvo);
while (nvHdmiGetEffectivePixelClockKHz(pDpyEvo,
&pApiHeadState->timings,
@@ -878,6 +879,30 @@ static NvBool GetColorRangeValidValues(
return TRUE;
}
static NvBool GetCurrentColorBpc(const NVDpyEvoRec *pDpyEvo, NvS64 *pValue)
{
*pValue = pDpyEvo->currentAttributes.color.bpc;
return TRUE;
}
static NvBool GetColorBpcValidValues(
const NVDpyEvoRec *pDpyEvo,
struct NvKmsAttributeValidValuesCommonReply *pValidValues)
{
nvAssert(pValidValues->type == NV_KMS_ATTRIBUTE_TYPE_INTBITS);
/* If new enum values are added, update the u.bits.ints assignment. */
ct_assert(NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_MAX ==
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_10);
pValidValues->u.bits.ints =
NVBIT(NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_6) |
NVBIT(NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8) |
NVBIT(NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_10);
return TRUE;
}
static NvBool DigitalSignalAvailable(const NVDpyEvoRec *pDpyEvo)
{
return pDpyEvo->pConnectorEvo->legacyType ==
@@ -991,6 +1016,30 @@ static NvBool GetDisplayportLinkRateValidValues(
return TRUE;
}
static NvBool GetDisplayportLinkRate10MHz(const NVDpyEvoRec *pDpyEvo, NvS64 *pValue)
{
if (!DisplayportLinkRateAvailable(pDpyEvo)) {
return FALSE;
}
*pValue = pDpyEvo->dp.linkRate10MHz;
return TRUE;
}
static NvBool GetDisplayportLinkRate10MHzValidValues(
const NVDpyEvoRec *pDpyEvo,
struct NvKmsAttributeValidValuesCommonReply *pValidValues)
{
if (!DisplayportLinkRateAvailable(pDpyEvo)) {
return FALSE;
}
nvAssert(pValidValues->type == NV_KMS_ATTRIBUTE_TYPE_INTEGER);
return TRUE;
}
static NvBool GetDisplayportConnectorType(const NVDpyEvoRec *pDpyEvo,
NvS64 *pValue)
{
@@ -1139,6 +1188,7 @@ static NvBool GetVrrMinRefreshRateValidValues(
struct NvKmsAttributeValidValuesCommonReply *pValidValues)
{
NvU32 minMinRefreshRate, maxMinRefreshRate;
const NVHwModeTimingsEvo *pTimings;
const NVDispEvoRec *pDispEvo = pDpyEvo->pDispEvo;
NvU32 head;
@@ -1148,9 +1198,12 @@ static NvBool GetVrrMinRefreshRateValidValues(
head = nvGetPrimaryHwHead(pDispEvo, pDpyEvo->apiHead);
nvAssert(head != NV_INVALID_HEAD);
nvGetDpyMinRefreshRateValidValues(&pDispEvo->headState[head].timings,
pTimings = &pDispEvo->headState[head].timings;
nvGetDpyMinRefreshRateValidValues(pTimings,
pDpyEvo->vrr.type,
pDpyEvo->vrr.edidTimeoutMicroseconds,
pTimings->vrr.timeoutMicroseconds,
&minMinRefreshRate,
&maxMinRefreshRate);
#if defined(DEBUG)
@@ -1159,9 +1212,11 @@ static NvBool GetVrrMinRefreshRateValidValues(
FOR_EACH_EVO_HW_HEAD(pDispEvo, pDpyEvo->apiHead, h) {
NvU32 tmpMinMinRefreshRate, tmpMaxMinRefreshRate;
nvGetDpyMinRefreshRateValidValues(&pDispEvo->headState[h].timings,
pTimings = &pDispEvo->headState[h].timings;
nvGetDpyMinRefreshRateValidValues(pTimings,
pDpyEvo->vrr.type,
pDpyEvo->vrr.edidTimeoutMicroseconds,
pTimings->vrr.timeoutMicroseconds,
&tmpMinMinRefreshRate,
&tmpMaxMinRefreshRate);
@@ -1302,6 +1357,12 @@ static const struct {
.getValidValues = GetColorRangeValidValues,
.type = NV_KMS_ATTRIBUTE_TYPE_INTBITS,
},
[NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC] = {
.set = NULL,
.get = GetCurrentColorBpc,
.getValidValues = GetColorBpcValidValues,
.type = NV_KMS_ATTRIBUTE_TYPE_INTBITS,
},
[NV_KMS_DPY_ATTRIBUTE_DIGITAL_SIGNAL] = {
.set = NULL,
.get = GetDigitalSignal,
@@ -1320,6 +1381,12 @@ static const struct {
.getValidValues = GetDisplayportLinkRateValidValues,
.type = NV_KMS_ATTRIBUTE_TYPE_INTEGER,
},
[NV_KMS_DPY_ATTRIBUTE_DISPLAYPORT_LINK_RATE_10MHZ] = {
.set = NULL,
.get = GetDisplayportLinkRate10MHz,
.getValidValues = GetDisplayportLinkRate10MHzValidValues,
.type = NV_KMS_ATTRIBUTE_TYPE_INTEGER,
},
[NV_KMS_DPY_ATTRIBUTE_DISPLAYPORT_CONNECTOR_TYPE] = {
.set = NULL,
.get = GetDisplayportConnectorType,

View File

@@ -1660,6 +1660,46 @@ static void LogEdid(NVDpyEvoPtr pDpyEvo, NVEvoInfoStringPtr pInfoString)
pParsedEdid->info.nvdaVsdbInfo.vrrData.v1.minRefreshRate);
}
if (pParsedEdid->info.ext_displayid.version) {
nvEvoLogInfoString(pInfoString,
"DisplayID vfreq_min : %d Hz",
pParsedEdid->info.ext_displayid.range_limits[0].vfreq_min);
}
if (pParsedEdid->info.ext_displayid20.version &&
pParsedEdid->info.ext_displayid20.range_limits.seamless_dynamic_video_timing_change) {
nvEvoLogInfoString(pInfoString,
"DisplayID 2.0 vfreq_min : %d Hz",
pParsedEdid->info.ext_displayid20.range_limits.vfreq_min);
}
if (pParsedEdid->info.ext_displayid20.version &&
pParsedEdid->info.ext_displayid20.total_adaptive_sync_descriptor != 0) {
for (k = 0;
k < pParsedEdid->info.ext_displayid20.total_adaptive_sync_descriptor &&
k < ARRAY_LEN(pParsedEdid->info.ext_displayid20.adaptive_sync_descriptor);
k++) {
nvEvoLogInfoString(pInfoString,
"DisplayID 2.0 adaptive sync : %d Hz (max), %d Hz (min)",
pParsedEdid->info.ext_displayid20.adaptive_sync_descriptor[k].max_rr,
pParsedEdid->info.ext_displayid20.adaptive_sync_descriptor[k].min_rr);
}
}
for (k = 0; k < ARRAY_LEN(pParsedEdid->info.ldd); k++) {
if (pParsedEdid->info.ldd[k].tag == NVT_EDID_DISPLAY_DESCRIPTOR_DRL) {
nvEvoLogInfoString(pInfoString,
"min_v_rate : %d Hz",
pParsedEdid->info.ldd[k].u.range_limit.min_v_rate);
}
}
if (pParsedEdid->info.hdmiForumInfo.vrr_min != 0) {
nvEvoLogInfoString(pInfoString,
"HDMI Forum vrr_min : %d Hz",
pParsedEdid->info.hdmiForumInfo.vrr_min);
}
nvLogEdidCea861InfoEvo(pDpyEvo, pInfoString);
if (pParsedEdid->info.input.isDigital &&
@@ -3014,6 +3054,9 @@ NvBool nvDpyGetDynamicData(
nvkms_memcpy(pReply->edid.buffer, pDpyEvo->edid.buffer, pDpyEvo->edid.length);
}
pReply->supportedOutputColorFormats =
nvDpyGetOutputColorFormatInfo(pDpyEvo);
return TRUE;
}
@@ -3172,17 +3215,21 @@ static enum NvKmsDpyAttributeColorBpcValue GetYuv422MaxBpc(
return NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_UNKNOWN;
}
NVColorFormatInfoRec nvGetColorFormatInfo(const NVDpyEvoRec *pDpyEvo)
NvKmsDpyOutputColorFormatInfo nvDpyGetOutputColorFormatInfo(
const NVDpyEvoRec *pDpyEvo)
{
const NVConnectorEvoRec *pConnectorEvo =
pDpyEvo->pConnectorEvo;
NVColorFormatInfoRec colorFormatsInfo = { };
NvKmsDpyOutputColorFormatInfo colorFormatsInfo = { };
if (pConnectorEvo->legacyType ==
NV0073_CTRL_SPECIFIC_DISPLAY_TYPE_CRT) {
colorFormatsInfo.rgb444.maxBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_10;
colorFormatsInfo.rgb444.minBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_10;
} else if (pConnectorEvo->legacyType ==
NV0073_CTRL_SPECIFIC_DISPLAY_TYPE_DFP) {
@@ -3207,9 +3254,14 @@ NVColorFormatInfoRec nvGetColorFormatInfo(const NVDpyEvoRec *pDpyEvo)
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
break;
}
colorFormatsInfo.rgb444.minBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_6;
} else {
colorFormatsInfo.rgb444.maxBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
colorFormatsInfo.rgb444.minBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
}
} else if (nvConnectorUsesDPLib(pDpyEvo->pConnectorEvo)) {
@@ -3219,9 +3271,13 @@ NVColorFormatInfoRec nvGetColorFormatInfo(const NVDpyEvoRec *pDpyEvo)
if (pDpyEvo->parsedEdid.info.input.u.digital.bpc >= 10) {
colorFormatsInfo.rgb444.maxBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_10;
colorFormatsInfo.yuv444.maxBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_10;
} else if (pDpyEvo->parsedEdid.info.input.u.digital.bpc < 8) {
colorFormatsInfo.rgb444.maxBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_6;
colorFormatsInfo.yuv444.maxBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_UNKNOWN;
} else {
colorFormatsInfo.rgb444.maxBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
@@ -3229,23 +3285,56 @@ NVColorFormatInfoRec nvGetColorFormatInfo(const NVDpyEvoRec *pDpyEvo)
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
}
colorFormatsInfo.rgb444.minBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_6;
if (colorFormatsInfo.yuv444.maxBpc !=
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_UNKNOWN) {
colorFormatsInfo.yuv444.minBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
} else {
colorFormatsInfo.yuv444.minBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_UNKNOWN;
}
colorFormatsInfo.yuv422.maxBpc = GetYuv422MaxBpc(pDpyEvo);
if (colorFormatsInfo.yuv422.maxBpc !=
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_UNKNOWN) {
colorFormatsInfo.yuv422.minBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
} else {
colorFormatsInfo.yuv422.minBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_UNKNOWN;
}
} else {
colorFormatsInfo.rgb444.maxBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
colorFormatsInfo.rgb444.minBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
}
} else {
colorFormatsInfo.rgb444.maxBpc =
nvDpyIsHdmiDepth30Evo(pDpyEvo) ?
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_10 :
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
colorFormatsInfo.rgb444.minBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
if (nvDpyIsHdmiEvo(pDpyEvo)) {
// TODO: Handle depth 30 YUV
colorFormatsInfo.yuv444.maxBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
colorFormatsInfo.yuv422.maxBpc =
GetYuv422MaxBpc(pDpyEvo);
colorFormatsInfo.yuv444.minBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
colorFormatsInfo.yuv422.maxBpc = GetYuv422MaxBpc(pDpyEvo);
if (colorFormatsInfo.yuv422.maxBpc !=
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_UNKNOWN) {
colorFormatsInfo.yuv422.minBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
} else {
colorFormatsInfo.yuv422.minBpc =
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_UNKNOWN;
}
}
}
}

View File

@@ -2725,7 +2725,7 @@ void nvEnableMidFrameAndDWCFWatermark(NVDevEvoPtr pDevEvo,
}
static NvBool GetDefaultColorSpace(
const NVColorFormatInfoRec *pColorFormatsInfo,
const NvKmsDpyOutputColorFormatInfo *pColorFormatsInfo,
enum NvKmsDpyAttributeCurrentColorSpaceValue *pColorSpace,
enum NvKmsDpyAttributeColorBpcValue *pColorBpc)
{
@@ -2753,8 +2753,9 @@ static NvBool GetDefaultColorSpace(
return FALSE;
}
NvBool nvGetDefaultDpyColor(const NVColorFormatInfoRec *pColorFormatsInfo,
NVDpyAttributeColor *pDpyColor)
NvBool nvGetDefaultDpyColor(
const NvKmsDpyOutputColorFormatInfo *pColorFormatsInfo,
NVDpyAttributeColor *pDpyColor)
{
nvkms_memset(pDpyColor, 0, sizeof(*pDpyColor));
@@ -2806,6 +2807,23 @@ NvBool nvChooseColorRangeEvo(
return TRUE;
}
static enum NvKmsDpyAttributeColorBpcValue ChooseColorBpc(
const enum NvKmsDpyAttributeColorBpcValue requested,
const enum NvKmsDpyAttributeColorBpcValue max,
const enum NvKmsDpyAttributeColorBpcValue min)
{
if ((requested == NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_UNKNOWN) ||
(requested > max)) {
return max;
}
if (requested < min) {
return min;
}
return requested;
}
/*!
* Choose current colorSpace and colorRange for the given dpy based on
* the dpy's color format capailities, the given modeset parameters (YUV420
@@ -2823,6 +2841,7 @@ NvBool nvChooseCurrentColorSpaceAndRangeEvo(
const enum NvYuv420Mode yuv420Mode,
enum NvKmsOutputColorimetry colorimetry,
const enum NvKmsDpyAttributeRequestedColorSpaceValue requestedColorSpace,
const enum NvKmsDpyAttributeColorBpcValue requestedColorBpc,
const enum NvKmsDpyAttributeColorRangeValue requestedColorRange,
enum NvKmsDpyAttributeCurrentColorSpaceValue *pCurrentColorSpace,
enum NvKmsDpyAttributeColorBpcValue *pCurrentColorBpc,
@@ -2834,8 +2853,8 @@ NvBool nvChooseCurrentColorSpaceAndRangeEvo(
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_10;
enum NvKmsDpyAttributeColorRangeValue newColorRange =
NV_KMS_DPY_ATTRIBUTE_COLOR_RANGE_FULL;
const NVColorFormatInfoRec colorFormatsInfo =
nvGetColorFormatInfo(pDpyEvo);
const NvKmsDpyOutputColorFormatInfo colorFormatsInfo =
nvDpyGetOutputColorFormatInfo(pDpyEvo);
// XXX HDR TODO: Handle other colorimetries
// XXX HDR TODO: Handle YUV
@@ -2870,15 +2889,21 @@ NvBool nvChooseCurrentColorSpaceAndRangeEvo(
switch (requestedColorSpace) {
case NV_KMS_DPY_ATTRIBUTE_REQUESTED_COLOR_SPACE_RGB:
newColorSpace = NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_RGB;
newColorBpc = colorFormatsInfo.rgb444.maxBpc;
newColorBpc = ChooseColorBpc(requestedColorBpc,
colorFormatsInfo.rgb444.maxBpc,
colorFormatsInfo.rgb444.minBpc);
break;
case NV_KMS_DPY_ATTRIBUTE_REQUESTED_COLOR_SPACE_YCbCr422:
newColorSpace = NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr422;
newColorBpc = colorFormatsInfo.yuv422.maxBpc;
newColorBpc = ChooseColorBpc(requestedColorBpc,
colorFormatsInfo.yuv422.maxBpc,
colorFormatsInfo.yuv422.minBpc);
break;
case NV_KMS_DPY_ATTRIBUTE_REQUESTED_COLOR_SPACE_YCbCr444:
newColorSpace = NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr444;
newColorBpc = colorFormatsInfo.yuv444.maxBpc;
newColorBpc = ChooseColorBpc(requestedColorBpc,
colorFormatsInfo.yuv444.maxBpc,
colorFormatsInfo.yuv444.minBpc);
break;
default:
nvAssert(!"Invalid Requested ColorSpace");
@@ -6653,8 +6678,9 @@ ConstructHwModeTimingsViewPort(const NVDispEvoRec *pDispEvo,
}
static NvBool GetDefaultFrlDpyColor(const NVColorFormatInfoRec *pColorFormatsInfo,
NVDpyAttributeColor *pDpyColor)
static NvBool GetDefaultFrlDpyColor(
const NvKmsDpyOutputColorFormatInfo *pColorFormatsInfo,
NVDpyAttributeColor *pDpyColor)
{
nvkms_memset(pDpyColor, 0, sizeof(*pDpyColor));
pDpyColor->colorimetry = NVKMS_OUTPUT_COLORIMETRY_DEFAULT;
@@ -6686,8 +6712,8 @@ static NvBool GetDfpHdmiProtocol(const NVDpyEvoRec *pDpyEvo,
{
NVConnectorEvoPtr pConnectorEvo = pDpyEvo->pConnectorEvo;
const NvU32 rmProtocol = pConnectorEvo->or.protocol;
const NVColorFormatInfoRec colorFormatsInfo =
nvGetColorFormatInfo(pDpyEvo);
const NvKmsDpyOutputColorFormatInfo colorFormatsInfo =
nvDpyGetOutputColorFormatInfo(pDpyEvo);
const NvBool forceHdmiFrlIsSupported = FALSE;
nvAssert(rmProtocol == NV0073_CTRL_SPECIFIC_OR_PROTOCOL_SOR_SINGLE_TMDS_A ||
@@ -6888,18 +6914,55 @@ static NvBool ConstructHwModeTimingsEvoDfp(const NVDpyEvoRec *pDpyEvo,
pViewPortOut);
}
NvBool nvDowngradeColorBpc(NVDpyAttributeColor *pDpyColor)
static NvBool IsColorBpcSupported(
const NvKmsDpyOutputColorFormatInfo *pSupportedColorFormats,
const enum NvKmsDpyAttributeCurrentColorSpaceValue format,
const enum NvKmsDpyAttributeColorBpcValue bpc)
{
switch (format) {
case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_RGB:
return (bpc <= pSupportedColorFormats->rgb444.maxBpc) &&
(bpc >= pSupportedColorFormats->rgb444.minBpc);
case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr422:
return (bpc <= pSupportedColorFormats->yuv422.maxBpc) &&
(bpc >= pSupportedColorFormats->yuv422.minBpc);
case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr444:
return (bpc <= pSupportedColorFormats->yuv444.maxBpc) &&
(bpc >= pSupportedColorFormats->yuv444.minBpc);
case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr420:
return (bpc == NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8);
}
return FALSE;
}
NvBool nvDowngradeColorBpc(
const NvKmsDpyOutputColorFormatInfo *pSupportedColorFormats,
NVDpyAttributeColor *pDpyColor)
{
switch (pDpyColor->bpc) {
case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_10:
if (pDpyColor->colorimetry == NVKMS_OUTPUT_COLORIMETRY_BT2100) {
return FALSE;
}
if (!IsColorBpcSupported(pSupportedColorFormats,
pDpyColor->format,
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8)) {
return FALSE;
}
pDpyColor->bpc = NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
break;
case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8:
/* At depth 18 only RGB and full range are allowed */
if (pDpyColor->format == NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_RGB) {
if (!IsColorBpcSupported(pSupportedColorFormats,
pDpyColor->format,
NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_6)) {
return FALSE;
}
pDpyColor->bpc = NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_6;
pDpyColor->range = NV_KMS_DPY_ATTRIBUTE_COLOR_RANGE_FULL;
} else {
@@ -6915,10 +6978,10 @@ NvBool nvDowngradeColorBpc(NVDpyAttributeColor *pDpyColor)
}
NvBool nvDowngradeColorSpaceAndBpc(
const NVColorFormatInfoRec *pSupportedColorFormats,
const NvKmsDpyOutputColorFormatInfo *pSupportedColorFormats,
NVDpyAttributeColor *pDpyColor)
{
if (nvDowngradeColorBpc(pDpyColor)) {
if (nvDowngradeColorBpc(pSupportedColorFormats, pDpyColor)) {
return TRUE;
}
@@ -6961,8 +7024,8 @@ NvBool nvDPValidateModeEvo(NVDpyEvoPtr pDpyEvo,
{
NVConnectorEvoPtr pConnectorEvo = pDpyEvo->pConnectorEvo;
NVDpyAttributeColor dpyColor = *pDpyColor;
const NVColorFormatInfoRec supportedColorFormats =
nvGetColorFormatInfo(pDpyEvo);
const NvKmsDpyOutputColorFormatInfo supportedColorFormats =
nvDpyGetOutputColorFormatInfo(pDpyEvo);
/* Only do this for DP devices. */
if (!nvConnectorUsesDPLib(pConnectorEvo)) {

View File

@@ -5946,10 +5946,10 @@ static void SetHDRLayerCaps(NVDevEvoPtr pDevEvo)
* TODO: Rework API for per-head layerCaps if this assert trips.
*/
nvAssert(!hdrLayerCapSet[numLayers[head]] ||
(pDevEvo->caps.layerCaps[numLayers[head]].supportsHDR ==
(pDevEvo->caps.layerCaps[numLayers[head]].supportsICtCp ==
pWinCaps->tmoPresent));
pDevEvo->caps.layerCaps[numLayers[head]].supportsHDR = pWinCaps->tmoPresent;
pDevEvo->caps.layerCaps[numLayers[head]].supportsICtCp = pWinCaps->tmoPresent;
#if defined(DEBUG)
hdrLayerCapSet[numLayers[head]] = TRUE;
@@ -7042,14 +7042,14 @@ static void ForceFlipToNull(
NVDevEvoPtr pDevEvo,
NVEvoChannelPtr pChannel,
NvU32 sd,
NVEvoUpdateState *updateState)
NVEvoUpdateState *updateState,
const NVFlipChannelEvoHwState *pNullHwState)
{
NVFlipChannelEvoHwState hwState = { };
const NvU32 subDeviceMask = (1 << sd);
nvPushEvoSubDevMask(pDevEvo, subDeviceMask);
pDevEvo->hal->Flip(pDevEvo, pChannel, &hwState, updateState,
pDevEvo->hal->Flip(pDevEvo, pChannel, pNullHwState, updateState,
FALSE /* bypassComposition */);
nvPopEvoSubDevMask(pDevEvo);
@@ -7108,6 +7108,7 @@ typedef struct {
NvU32 accelerators;
NvBool overridden;
} window[NVKMS_MAX_WINDOWS_PER_DISP];
NVFlipChannelEvoHwState nullEvoHwState;
} EvoIdleChannelAcceleratorState;
static NvBool EvoForceIdleSatelliteChannelsWithAccel(
@@ -7162,8 +7163,16 @@ static NvBool EvoForceIdleSatelliteChannelsWithAccel(
}
pAcceleratorState[sd].window[window].overridden = TRUE;
/* Push a flip to null in this channel. */
ForceFlipToNull(pDevEvo, pChannel, sd, &updateState);
/*
* Push a flip to null in this channel.
*
* XXX nullEvoHwState isn't a valid state for NULL flip, for
* example 'csc' will be all 0s instead of the identity. This
* will also lead to the HW state being out of sync with the SW
* state.
*/
ForceFlipToNull(pDevEvo, pChannel, sd, &updateState,
&pAcceleratorState->nullEvoHwState);
}
}
}

View File

@@ -1415,8 +1415,6 @@ void nvDpyUpdateHdmiVRRCaps(NVDpyEvoPtr pDpyEvo)
}
pDpyEvo->vrr.needsSwFramePacing = TRUE;
pDpyEvo->vrr.edidTimeoutMicroseconds = 1000000 / edidVrrMin;
}
}
@@ -2311,7 +2309,7 @@ static NvBool nvHdmiFrlQueryConfigOneBpc(
clientControl.option = HDMI_QUERY_FRL_HIGHEST_PIXEL_QUALITY;
if (pValidationParams->forceDsc) {
if (pValidationParams->dscMode == NVKMS_DSC_MODE_FORCE_ENABLE) {
clientControl.enableDSC = TRUE;
}
@@ -2320,6 +2318,9 @@ 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) {
return FALSE;
}
clientControl.enableDSC = TRUE;
}
@@ -2357,6 +2358,13 @@ static NvBool nvHdmiFrlQueryConfigOneBpc(
if ((pConfig->frlRate != HDMI_FRL_DATA_RATE_NONE) &&
pConfig->dscInfo.bEnableDSC &&
(hdmiLinkRate != 0)) {
if (pValidationParams->dscMode ==
NVKMS_DSC_MODE_FORCE_DISABLE) {
ret = NVHDMIPKT_FAIL;
goto done;
}
pDscInfo->type = NV_DSC_INFO_EVO_TYPE_HDMI;
pDscInfo->hdmi.dscMode = b2Heads1Or ?
NV_DSC_EVO_MODE_DUAL : NV_DSC_EVO_MODE_SINGLE;
@@ -2385,6 +2393,7 @@ static NvBool nvHdmiFrlQueryConfigOneBpc(
}
}
done:
return ret == NVHDMIPKT_SUCCESS;
}
@@ -2410,6 +2419,8 @@ NvBool nvHdmiFrlQueryConfig(
HDMI_FRL_CONFIG *pConfig,
NVDscInfoEvoRec *pDscInfo)
{
const NvKmsDpyOutputColorFormatInfo supportedColorFormats =
nvDpyGetOutputColorFormatInfo(pDpyEvo);
NVDpyAttributeColor dpyColor = *pDpyColor;
do {
if (nvHdmiFrlQueryConfigOneBpc(pDpyEvo,
@@ -2423,7 +2434,7 @@ NvBool nvHdmiFrlQueryConfig(
*pDpyColor = dpyColor;
return TRUE;
}
} while(nvDowngradeColorBpc(&dpyColor) &&
} while(nvDowngradeColorBpc(&supportedColorFormats, &dpyColor) &&
(dpyColor.bpc >= NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8));
return FALSE;
}

View File

@@ -541,8 +541,8 @@ static NvBool UpdateLayerFlipEvoHwStateHDRStaticMetadata(
{
if (pParams->layer[layer].hdr.specified) {
if (pParams->layer[layer].hdr.enabled) {
// Don't allow enabling HDR on a layer that doesn't support it.
if (!pDevEvo->caps.layerCaps[layer].supportsHDR) {
// Don't allow enabling HDR on a layer that doesn't support ICtCp.
if (!pDevEvo->caps.layerCaps[layer].supportsICtCp) {
return FALSE;
}
@@ -551,8 +551,8 @@ static NvBool UpdateLayerFlipEvoHwStateHDRStaticMetadata(
}
pHwState->hdrStaticMetadata.enabled = pParams->layer[layer].hdr.enabled;
// Only mark dirty if layer supports HDR, otherwise this is a no-op.
if (pDevEvo->caps.layerCaps[layer].supportsHDR) {
// Only mark dirty if layer supports ICtCp, otherwise this is a no-op.
if (pDevEvo->caps.layerCaps[layer].supportsICtCp) {
pFlipState->dirty.hdrStaticMetadata = TRUE;
}
}
@@ -1273,7 +1273,7 @@ ValidateHDR(const NVDevEvoRec *pDevEvo,
NvU32 layer;
for (layer = 0; layer < pDevEvo->head[head].numLayers; layer++) {
if (pDevEvo->caps.layerCaps[layer].supportsHDR) {
if (pDevEvo->caps.layerCaps[layer].supportsICtCp) {
layerSupportedCount++;
}
@@ -1291,7 +1291,7 @@ ValidateHDR(const NVDevEvoRec *pDevEvo,
}
// Already checked in UpdateLayerFlipEvoHwStateHDRStaticMetadata()
nvAssert(pDevEvo->caps.layerCaps[layer].supportsHDR);
nvAssert(pDevEvo->caps.layerCaps[layer].supportsICtCp);
}
}

View File

@@ -1672,7 +1672,8 @@ static NvBool ValidateMode(NVDpyEvoPtr pDpyEvo,
NvU32 head;
NvBool ret = FALSE;
const NVColorFormatInfoRec supportedColorFormats = nvGetColorFormatInfo(pDpyEvo);
const NvKmsDpyOutputColorFormatInfo supportedColorFormats =
nvDpyGetOutputColorFormatInfo(pDpyEvo);
NVDpyAttributeColor dpyColor;
if (modeName[0] == '\0') {

View File

@@ -247,6 +247,7 @@ GetColorSpaceAndColorRange(
{
enum NvKmsOutputColorimetry colorimetry;
enum NvKmsDpyAttributeColorRangeValue requestedColorRange;
enum NvKmsDpyAttributeColorBpcValue requestedColorBpc;
enum NvKmsDpyAttributeRequestedColorSpaceValue requestedColorSpace;
NVDpyEvoRec *pOneArbitraryDpyEvo =
nvGetOneArbitraryDpyEvo(pRequestHead->dpyIdList, pDispEvo);
@@ -275,6 +276,12 @@ GetColorSpaceAndColorRange(
requestedColorRange = pOneArbitraryDpyEvo->requestedColorRange;
}
if (pRequestHead->colorBpcSpecified) {
requestedColorBpc = pRequestHead->colorBpc;
} else {
requestedColorBpc = NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_UNKNOWN;
}
if (pRequestHead->flip.colorimetry.specified) {
colorimetry = pRequestHead->flip.colorimetry.val;
} else {
@@ -290,6 +297,7 @@ GetColorSpaceAndColorRange(
pRequestHead->mode.timings.yuv420Mode,
colorimetry,
requestedColorSpace,
requestedColorBpc,
requestedColorRange,
&pDpyColor->format,
&pDpyColor->bpc,
@@ -332,6 +340,15 @@ static NvBool AssignProposedModeSetColorSpaceAndColorRangeSpecified(
}
}
/*
* When color bpc is specified in modeset request, it should
* match the proposed color bpc.
*/
if (pRequestHead->colorBpcSpecified &&
(pProposedApiHead->attributes.color.bpc != pRequestHead->colorBpc)) {
return FALSE;
}
/*
* When color range is specified in modeset request, it should
* match the proposed color range.
@@ -342,6 +359,7 @@ static NvBool AssignProposedModeSetColorSpaceAndColorRangeSpecified(
}
pProposedApiHead->colorSpaceSpecified = pRequestHead->colorSpaceSpecified;
pProposedApiHead->colorBpcSpecified = pRequestHead->colorBpcSpecified;
pProposedApiHead->colorRangeSpecified = pRequestHead->colorRangeSpecified;
return TRUE;
}
@@ -417,11 +435,11 @@ static void AdjustHwModeTimingsForVrr(const NVDispEvoRec *pDispEvo,
allowGsync,
allowAdaptiveSync);
nvAdjustHwModeTimingsForVrrEvo(pTimings,
nvAdjustHwModeTimingsForVrrEvo(pDpyEvo,
vrrType,
pDpyEvo->vrr.edidTimeoutMicroseconds,
vrrOverrideMinRefreshRate,
pDpyEvo->vrr.needsSwFramePacing);
pDpyEvo->vrr.needsSwFramePacing,
pTimings);
}
/*
@@ -1539,8 +1557,8 @@ static NvBool DowngradeColorSpaceAndBpcOneHead(
NVDpyEvoRec *pDpyEvo =
nvGetOneArbitraryDpyEvo(pProposedApiHead->dpyIdList,
pDispEvo);
const NVColorFormatInfoRec supportedColorFormats =
nvGetColorFormatInfo(pDpyEvo);
const NvKmsDpyOutputColorFormatInfo supportedColorFormats =
nvDpyGetOutputColorFormatInfo(pDpyEvo);
if (!nvDowngradeColorSpaceAndBpc(&supportedColorFormats, &dpyColor)) {
return FALSE;
@@ -1551,6 +1569,11 @@ static NvBool DowngradeColorSpaceAndBpcOneHead(
return FALSE;
}
if (pProposedApiHead->colorBpcSpecified &&
(dpyColor.bpc != pProposedApiHead->attributes.color.bpc)) {
return FALSE;
}
if (pProposedApiHead->colorSpaceSpecified &&
(dpyColor.format != pProposedApiHead->attributes.color.format)) {
return FALSE;

View File

@@ -82,6 +82,7 @@
#include <ctrl/ctrl2080/ctrl2080unix.h> /* NV2080_CTRL_CMD_OS_UNIX_GC6_BLOCKER_REFCNT */
#include <ctrl/ctrl5070/ctrl5070chnc.h> /* NV5070_CTRL_CMD_SET_RMFREE_FLAGS */
#include <ctrl/ctrl5070/ctrl5070or.h> /* NV5070_CTRL_CMD_SET_DAC_PWR */
#include <ctrl/ctrl0000/ctrl0000system.h> /* NV0000_CTRL_CMD_SYSTEM_GET_APPROVAL_COOKIE */
#include "nvos.h"
@@ -1291,6 +1292,28 @@ static NvBool ProbeDisplayCommonCaps(NVDevEvoPtr pDevEvo)
return TRUE;
}
/*!
* Query the variable refresh rate (G-SYNC) capability of a display.
*/
static void ProbeVRRCaps(NVDispEvoPtr pDispEvo)
{
NV0000_CTRL_SYSTEM_GET_VRR_COOKIE_PRESENT_PARAMS params = { 0 };
NvU32 ret;
ret = nvRmApiControl(nvEvoGlobal.clientHandle,
nvEvoGlobal.clientHandle,
NV0000_CTRL_SYSTEM_GET_VRR_COOKIE_PRESENT,
&params, sizeof(params));
if (ret != NVOS_STATUS_SUCCESS) {
return;
}
pDispEvo->vrr.hasPlatformCookie = params.bIsPresent;
}
static NvBool ReadDPCDReg(NVConnectorEvoPtr pConnectorEvo,
NvU32 dpcdAddr,
NvU8 *dpcdData)
@@ -1766,6 +1789,7 @@ enum NvKmsAllocDeviceStatus nvRmAllocDisplays(NVDevEvoPtr pDevEvo)
goto fail;
}
ProbeVRRCaps(pDispEvo);
}
nvAllocVrrEvo(pDevEvo);

View File

@@ -255,19 +255,86 @@ nvGetAllowedDpyVrrType(const NVDpyEvoRec *pDpyEvo,
return NVKMS_DPY_VRR_TYPE_NONE;
}
static NvBool GetEdidTimeoutMicroseconds(
const NVDpyEvoRec *pDpyEvo,
const NVHwModeTimingsEvo *pTimings,
NvU32 *pEdidTimeoutMicroseconds)
{
const NvU32 rr10kHz = nvGetRefreshRate10kHz(pTimings);
const NVParsedEdidEvoRec *pParsedEdid = &pDpyEvo->parsedEdid;
const NVT_DISPLAYID_2_0_INFO *pDisplayIdInfo = NULL;
const NvU32 nominalRefreshRateHz = rr10kHz / 10000; // XXX round?
NVT_PROTOCOL sinkProtocol = NVT_PROTOCOL_UNKNOWN;
NvU32 fmin;
if (!pParsedEdid->valid) {
return FALSE;
}
// XXX not sufficient; see what DD does in changelist 34157172
if (nvDpyUsesDPLib(pDpyEvo)) {
sinkProtocol = NVT_PROTOCOL_DP;
} else if (nvDpyIsHdmiEvo(pDpyEvo)) {
sinkProtocol = NVT_PROTOCOL_HDMI;
}
fmin = NvTiming_GetVrrFmin(&pParsedEdid->info,
pDisplayIdInfo,
nominalRefreshRateHz,
sinkProtocol);
if (fmin == 0) {
if (pDpyEvo->internal && pDpyEvo->pDispEvo->vrr.hasPlatformCookie) {
/*
* An internal notebook VRR panel must have a non-zero fmin. The
* recommendation from hardware is to use a default of fmin =
* rr/2.4. So, compute timeoutUsec as:
*
* timeoutUsec = 10^6 / fmin
* = 10^6 / (rr/2.4)
* = 10^6 * (2.4/rr)
* = 10^5 * 24 / rr
*/
*pEdidTimeoutMicroseconds = 2400000 / nominalRefreshRateHz;
return TRUE;
}
if (pDpyEvo->vrr.type == NVKMS_DPY_VRR_TYPE_GSYNC) {
/* GSYNC can have fmin==0; i.e., the panel is self-refreshing. */
*pEdidTimeoutMicroseconds = 0;
return TRUE;
}
/* Otherwise, VRR is not possible. */
return FALSE;
}
*pEdidTimeoutMicroseconds = 1000000 / fmin;
return TRUE;
}
/*! Adjust mode timings as necessary for VRR. */
void nvAdjustHwModeTimingsForVrrEvo(NVHwModeTimingsEvoPtr pTimings,
void nvAdjustHwModeTimingsForVrrEvo(const NVDpyEvoRec *pDpyEvo,
const enum NvKmsDpyVRRType vrrType,
const NvU32 edidTimeoutMicroseconds,
const NvU32 vrrOverrideMinRefreshRate,
const NvBool needsSwFramePacing)
const NvBool needsSwFramePacing,
NVHwModeTimingsEvoPtr pTimings)
{
NvU32 timeoutMicroseconds;
NvU32 edidTimeoutMicroseconds;
if (vrrType == NVKMS_DPY_VRR_TYPE_NONE) {
return;
}
if (!GetEdidTimeoutMicroseconds(pDpyEvo,
pTimings,
&edidTimeoutMicroseconds)) {
return;
}
// Allow overriding the EDID min refresh rate on Adaptive-Sync
// displays.
if (nvIsAdaptiveSyncDpyVrrType(vrrType) && vrrOverrideMinRefreshRate) {
@@ -395,7 +462,7 @@ static void SetTimeoutPerFrame(void *dataPtr, NvU32 dataU32)
&(pInputHeadState->vrrFramePacingInfo);
const NvU32 headsMask = pInputHeadState->mergeModeVrrSecondaryHeadMask |
NVBIT(inputHead);
volatile NV0073_CTRL_RM_VRR_SHARED_DATA *pData = pInputVrrFramePacingInfo->pData;
volatile NV0073_CTRL_RM_VRR_SHARED_DATA *pData = pInputVrrFramePacingInfo->pData;
/*
* XXX[2Heads1OR] Implement per api-head frame pacing and remove this
@@ -1078,7 +1145,7 @@ void nvTrackAndDelayFlipForVrrSwFramePacing(NVDispEvoPtr pDispEvo,
const struct NvKmsVrrFramePacingInfo *pVrrFramePacingInfo,
NVFlipChannelEvoHwState *pFlip)
{
volatile NV0073_CTRL_RM_VRR_SHARED_DATA *pData = pVrrFramePacingInfo->pData;
volatile NV0073_CTRL_RM_VRR_SHARED_DATA *pData = pVrrFramePacingInfo->pData;
NvU32 retryCount = MAX_VRR_FLIP_DELAY_TIME_RETRY_COUNT;
NvU64 flipTimeStamp = 0;
NvU64 dataTimeStamp1 = 0, dataTimeStamp2 = 0;
@@ -1216,8 +1283,7 @@ NvS32 nvIncVrrSemaphoreIndex(NVDevEvoPtr pDevEvo)
if (pDevEvo->vrr.active && !pDevEvo->hal->caps.supportsDisplayRate) {
vrrSemaphoreIndex = pDevEvo->vrr.flipCounter++;
if (pDevEvo->vrr.flipCounter >=
NVKMS_VRR_SEMAPHORE_SURFACE_SIZE / sizeof(NvU32)) {
if (pDevEvo->vrr.flipCounter >= NVKMS_VRR_SEMAPHORE_SURFACE_COUNT) {
pDevEvo->vrr.flipCounter = 0;
}
}
@@ -1302,3 +1368,21 @@ void nvTriggerVrrUnstallSetCursorImage(NVDispEvoPtr pDispEvo,
}
}
void nvVrrSignalSemaphore(NVDevEvoPtr pDevEvo, NvS32 vrrSemaphoreIndex)
{
NvU32* pVrrSemaphores = (NvU32*)pDevEvo->vrr.pSemaphores;
if (!pDevEvo->vrr.pSemaphores) {
return;
}
if (vrrSemaphoreIndex < 0) {
return;
}
if (vrrSemaphoreIndex >= NVKMS_VRR_SEMAPHORE_SURFACE_COUNT) {
return;
}
pVrrSemaphores[vrrSemaphoreIndex] = 1;
}

View File

@@ -2694,7 +2694,7 @@ static NvBool RegisterSurface(struct NvKmsPerOpen *pOpen,
nvEvoRegisterSurface(pOpenDev->pDevEvo, pOpenDev, pParams,
NvHsMapPermissionsReadOnly);
return TRUE;
return pParams->reply.surfaceHandle != 0;
}
@@ -4899,6 +4899,24 @@ static NvBool AccelVblankSemControls(
hwHeadMask);
}
static NvBool VrrSignalSemaphore(
struct NvKmsPerOpen *pOpen,
void *pParamsVoid)
{
struct NvKmsPerOpenDev *pOpenDev;
const struct NvKmsVrrSignalSemaphoreParams *pParams = pParamsVoid;
NvS32 vrrSemaphoreIndex = pParams->request.vrrSemaphoreIndex;
pOpenDev = GetPerOpenDev(pOpen, pParams->request.deviceHandle);
if (pOpenDev == NULL) {
return FALSE;
}
nvVrrSignalSemaphore(pOpenDev->pDevEvo, vrrSemaphoreIndex);
return TRUE;
}
/*!
* Perform the ioctl operation requested by the client.
*
@@ -5024,6 +5042,7 @@ NvBool nvKmsIoctl(
ENTRY(NVKMS_IOCTL_ENABLE_VBLANK_SEM_CONTROL, EnableVblankSemControl),
ENTRY(NVKMS_IOCTL_DISABLE_VBLANK_SEM_CONTROL, DisableVblankSemControl),
ENTRY(NVKMS_IOCTL_ACCEL_VBLANK_SEM_CONTROLS, AccelVblankSemControls),
ENTRY(NVKMS_IOCTL_VRR_SIGNAL_SEMAPHORE, VrrSignalSemaphore),
};
struct NvKmsPerOpen *pOpen = pOpenVoid;

View File

@@ -0,0 +1,328 @@
// Generated using 'Offline GLSL Shader Compiler Version 13.0.0.0.545.00.dev/gpu_drv/dev_a-16109'
// WARNING: This file is auto-generated! Do not hand-edit!
// Instead, edit the GLSL shaders and run 'unix-build nvmake @generate'.
#include "nvidia-3d-shaders.h"
#include "g_shader_names.h"
ct_assert(NUM_PROGRAMS == 34);
static const Nv3dProgramInfo BlackwellProgramInfo[NUM_PROGRAMS] = {
// nvidia_headsurface_vertex
{ .offset = 0x00000000,
.registerCount = 15,
.type = NV3D_SHADER_TYPE_VERTEX,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_VERTEX_B,
.bindGroup = NV3D_HW_BIND_GROUP_VERTEX,
},
// nvidia_headsurface_fragment
{ .offset = 0x00000300,
.registerCount = 13,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_customSampling
{ .offset = 0x00000580,
.registerCount = 40,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_overlay
{ .offset = 0x00004680,
.registerCount = 31,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_overlay_customSampling
{ .offset = 0x00005480,
.registerCount = 32,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_offset
{ .offset = 0x00008280,
.registerCount = 15,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_offset_customSampling
{ .offset = 0x00008600,
.registerCount = 40,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_offset_swapped
{ .offset = 0x0000c800,
.registerCount = 16,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_offset_swapped_customSampling
{ .offset = 0x0000cb80,
.registerCount = 40,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_offset_overlay
{ .offset = 0x00010d80,
.registerCount = 32,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_offset_overlay_customSampling
{ .offset = 0x00011c00,
.registerCount = 32,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_offset_overlay_swapped
{ .offset = 0x00014b00,
.registerCount = 31,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_offset_overlay_swapped_customSampling
{ .offset = 0x00015980,
.registerCount = 32,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_blend
{ .offset = 0x00018880,
.registerCount = 15,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_blend_customSampling
{ .offset = 0x00018b80,
.registerCount = 40,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_blend_swapped
{ .offset = 0x0001cd00,
.registerCount = 17,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_blend_swapped_customSampling
{ .offset = 0x0001d080,
.registerCount = 40,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_blend_overlay
{ .offset = 0x00021280,
.registerCount = 32,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_blend_overlay_customSampling
{ .offset = 0x00022100,
.registerCount = 32,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_blend_overlay_swapped
{ .offset = 0x00024f80,
.registerCount = 31,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_blend_overlay_swapped_customSampling
{ .offset = 0x00025e00,
.registerCount = 32,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_blend_offset
{ .offset = 0x00028d00,
.registerCount = 20,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_blend_offset_customSampling
{ .offset = 0x00029100,
.registerCount = 40,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_blend_offset_swapped
{ .offset = 0x0002d380,
.registerCount = 20,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_blend_offset_swapped_customSampling
{ .offset = 0x0002d780,
.registerCount = 40,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_blend_offset_overlay
{ .offset = 0x00031a00,
.registerCount = 35,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_blend_offset_overlay_customSampling
{ .offset = 0x00032880,
.registerCount = 37,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_blend_offset_overlay_swapped
{ .offset = 0x00035780,
.registerCount = 36,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_blend_offset_overlay_swapped_customSampling
{ .offset = 0x00036680,
.registerCount = 37,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_yuv420
{ .offset = 0x00039600,
.registerCount = 56,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_yuv420_overlay
{ .offset = 0x0003b180,
.registerCount = 38,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_pixelShift
{ .offset = 0x0003dc80,
.registerCount = 32,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_overlay_pixelShift
{ .offset = 0x0003e880,
.registerCount = 31,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
// nvidia_headsurface_fragment_reversePrime
{ .offset = 0x0003f780,
.registerCount = 13,
.type = NV3D_SHADER_TYPE_PIXEL,
.constIndex = -1,
.stage = NV3D_HW_SHADER_STAGE_PIXEL,
.bindGroup = NV3D_HW_BIND_GROUP_FRAGMENT,
},
};
static const Nv3dShaderConstBufInfo BlackwellConstBufInfo[] = {
};
static const size_t BlackwellConstBufSize = 0;
static const NvU32 BlackwellConstBufSizeAlign = 256;
// Total shader code size: 254.5 KB
static const size_t BlackwellProgramHeapSize = 260608;
static const size_t BlackwellShaderMaxLocalBytes = 0;
static const size_t BlackwellShaderMaxStackBytes = 0;

Binary file not shown.