550.40.07

This commit is contained in:
Bernhard Stoeckner
2024-01-24 17:51:53 +01:00
parent bb2dac1f20
commit 91676d6628
1411 changed files with 261367 additions and 145959 deletions

View File

@@ -98,6 +98,13 @@ ifeq ($(TARGET_ARCH),aarch64)
CONDITIONAL_CFLAGS += $(call TEST_CC_ARG, -mno-outline-atomics)
endif
ifeq ($(TARGET_ARCH),riscv64)
CFLAGS += -march=rv64imac_zicsr_zifencei
CFLAGS += -mabi=lp64
CFLAGS += -mcmodel=medany
CFLAGS += -mno-relax
endif
CFLAGS += -fno-pic
CFLAGS += -fno-common
CFLAGS += -fomit-frame-pointer

View File

@@ -188,6 +188,8 @@ NvBool nvDowngradeColorSpaceAndBpc(
NvBool nvDPValidateModeEvo(NVDpyEvoPtr pDpyEvo,
NVHwModeTimingsEvoPtr pTimings,
enum NvKmsDpyAttributeCurrentColorSpaceValue *pColorSpace,
enum NvKmsDpyAttributeColorBpcValue *pColorBpc,
const NvBool b2Heads1Or,
NVDscInfoEvoRec *pDscInfo,
const struct NvKmsModeValidationParams *pParams);
@@ -402,6 +404,10 @@ NvBool nvEvoUse2Heads1OR(const NVDpyEvoRec *pDpyEvo,
NvU32 nvGetRefreshRate10kHz(const NVHwModeTimingsEvo *pTimings);
NvBool nvIsLockGroupFlipLocked(const NVLockGroup *pLockGroup);
NvBool nvEvoIsConsoleActive(const NVDevEvoRec *pDevEvo);
#ifdef __cplusplus
};
#endif

View File

@@ -38,7 +38,7 @@ void nvUpdateHdmiInfoFrames(const NVDispEvoRec *pDispEvo,
void nvDpyUpdateHdmiPreModesetEvo(NVDpyEvoPtr pDpyEvo);
void nvDpyUpdateHdmiVRRCaps(NVDpyEvoPtr pDpyEvo);
void nvUpdateHdmiCaps(NVDpyEvoPtr pDpyEvo);
void nvSendHdmiCapsToRm(NVDpyEvoPtr pDpyEvo);
void nvLogEdidCea861InfoEvo(NVDpyEvoPtr pDpyEvo,
NVEvoInfoStringPtr pInfoString);

View File

@@ -28,10 +28,14 @@
extern "C" {
#endif
#include <nvlimits.h>
#include "nvkms-types.h"
#include <class/cl0092.h> /* NV0092_REGISTER_RG_LINE_CALLBACK_FN */
#include <class/cl9010.h> /* OSVBLANKCALLBACKPROC */
#define NVKMS_RM_HANDLE_SPACE_DEVICE(_i) ((_i) + 1)
#define NVKMS_RM_HANDLE_SPACE_FRAMELOCK(_i) (NV_MAX_DEVICES + (_i) + 1)
NvBool nvWriteDPCDReg(NVConnectorEvoPtr pConnectorEvo,
NvU32 dpcdAddr,
NvU8 dpcdData);

View File

@@ -72,6 +72,22 @@ void nvEvoUnregisterDeferredRequestFifo(
NVDevEvoPtr pDevEvo,
NVDeferredRequestFifoRec *pDeferredRequestFifo);
NVVblankSemControl *nvEvoEnableVblankSemControl(
NVDevEvoRec *pDevEvo,
NVDispEvoRec *pDispEvo,
NvU32 hwHead,
NVSurfaceEvoRec *pSurfaceEvo,
NvU64 surfaceOffset);
NvBool nvEvoDisableVblankSemControl(
NVDevEvoRec *pDevEvo,
NVVblankSemControl *pVblankSemControl);
NvBool nvEvoAccelVblankSemControls(
NVDevEvoPtr pDevEvo,
NvU32 dispIndex,
NvU32 hwHeadMask);
static inline NvBool nvEvoIsSurfaceOwner(const NVSurfaceEvoRec *pSurfaceEvo,
const struct NvKmsPerOpenDev *pOpenDev,
NvKmsSurfaceHandle surfaceHandle)

View File

@@ -151,6 +151,7 @@ typedef struct _NVDeferredRequestFifoRec *NVDeferredRequestFifoPtr;
typedef struct _NVSwapGroupRec *NVSwapGroupPtr;
typedef struct _NVEvoModesetUpdateState NVEvoModesetUpdateState;
typedef struct _NVLockGroup NVLockGroup;
typedef struct _NVVblankSemControl *NVVblankSemControlPtr;
/*
* _NVHs*EvoRec are defined in nvkms-headsurface-priv.h; they are intentionally
@@ -882,7 +883,6 @@ typedef struct {
NvBool supportsHDMI20 :1;
NvBool inputLutAppliesToBase :1;
NvU8 validNIsoFormatMask;
NvU8 genericPageKind;
NvU32 maxPitchValue;
int maxWidthInBytes;
int maxWidthInPixels;
@@ -1128,6 +1128,12 @@ typedef struct _NVEvoDevRec {
*/
NvBool isHeadSurfaceSupported : 1;
/*
* vblank Sem Control requires support in resman; that support is not
* currently available on Tegra.
*/
NvBool supportsVblankSemControl : 1;
nvkms_timer_handle_t *postFlipIMPTimer;
nvkms_timer_handle_t *consoleRestoreTimer;
@@ -1266,29 +1272,6 @@ typedef struct _NVEvoDevRec {
} apiHead[NVKMS_MAX_HEADS_PER_DISP];
} NVDevEvoRec;
static inline NvBool nvEvoIsConsoleActive(const NVDevEvoRec *pDevEvo)
{
/*
* If (pDevEvo->modesetOwner == NULL) that means either the vbios
* console or the NVKMS console might be active.
*/
if (pDevEvo->modesetOwner == NULL) {
return TRUE;
}
/*
* If (pDevEvo->modesetOwner != NULL) but
* pDevEvo->modesetOwnerChanged is TRUE, that means the modeset
* ownership is grabbed by the external client but it hasn't
* performed any modeset and the console is still active.
*/
if ((pDevEvo->modesetOwner != NULL) && pDevEvo->modesetOwnerChanged) {
return TRUE;
}
return FALSE;
}
/*
* The NVHwModeTimingsEvo structure stores all the values necessary to
* perform a modeset with EVO
@@ -2535,6 +2518,8 @@ typedef struct _NVFrameLockEvo {
enum NvKmsFrameLockAttributeMulDivModeValue mulDivMode;
NvBool testMode;
NVUnixRmHandleAllocatorRec handleAllocator;
} NVFrameLockEvoRec;
/*!
@@ -3185,6 +3170,13 @@ static inline void nvAssignHwHeadsMaskApiHeadState(
nvPopCount32(hwHeadsMask);
}
typedef struct _NVVblankSemControl {
NvU32 dispIndex;
NvU32 hwHead;
NvU64 surfaceOffset;
NVSurfaceEvoRec *pSurfaceEvo;
} NVVblankSemControl;
#ifdef __cplusplus
};
#endif

View File

@@ -55,6 +55,11 @@ static inline NvBool A_plus_B_greater_than_C_U16(NvU16 a, NvU16 b, NvU16 c)
return (NV_U16_MAX - a < b) || ((a + b) > c);
}
static inline NvBool A_plus_B_greater_than_C_U64(NvU64 a, NvU64 b, NvU64 c)
{
return (NV_U64_MAX - a < b) || ((a + b) > c);
}
static inline NvS32 clamp_S32(NvS32 val, NvS32 lo, NvS32 hi)
{
if (val < lo) {

View File

@@ -58,6 +58,7 @@ typedef NvU32 NvKmsFrameLockHandle;
typedef NvU32 NvKmsDeferredRequestFifoHandle;
typedef NvU32 NvKmsSwapGroupHandle;
typedef NvU32 NvKmsVblankSyncObjectHandle;
typedef NvU32 NvKmsVblankSemControlHandle;
struct NvKmsSize {
NvU16 width;

View File

@@ -268,6 +268,9 @@ enum NvKmsIoctlCommand {
NVKMS_IOCTL_DISABLE_VBLANK_SYNC_OBJECT,
NVKMS_IOCTL_NOTIFY_VBLANK,
NVKMS_IOCTL_SET_FLIPLOCK_GROUP,
NVKMS_IOCTL_ENABLE_VBLANK_SEM_CONTROL,
NVKMS_IOCTL_DISABLE_VBLANK_SEM_CONTROL,
NVKMS_IOCTL_ACCEL_VBLANK_SEM_CONTROLS,
};
@@ -1121,12 +1124,6 @@ struct NvKmsAllocDeviceReply {
NvU32 maxHeightInPixels;
NvU32 maxCursorSize;
/*!
* The page kind used by the GPU's MMU for uncompressed block-linear color
* formats.
*/
NvU8 genericPageKind;
/*!
* Describes the supported Color Key selects and blending modes for match
* and nomatch cursor pixels.
@@ -1180,6 +1177,18 @@ struct NvKmsAllocDeviceReply {
* generator sync objects that signal at vblank.
*/
NvBool supportsVblankSyncObjects;
/*!
* 'supportsVblankSemControl' indicates whether the VBlank Semaphore Control
* interface:
*
* NVKMS_IOCTL_ENABLE_VBLANK_SEM_CONTROL,
* NVKMS_IOCTL_DISABLE_VBLANK_SEM_CONTROL,
* NVKMS_IOCTL_ACCEL_VBLANK_SEM_CONTROLS,
*
* is supported.
*/
NvBool supportsVblankSemControl;
};
struct NvKmsAllocDeviceParams {
@@ -2739,7 +2748,6 @@ enum NvKmsDispAttribute {
NV_KMS_DISP_ATTRIBUTE_FRAMELOCK_TEST_SIGNAL,
NV_KMS_DISP_ATTRIBUTE_FRAMELOCK_RESET,
NV_KMS_DISP_ATTRIBUTE_FRAMELOCK_SET_SWAP_BARRIER,
NV_KMS_DISP_ATTRIBUTE_ALLOW_FLIPLOCK,
NV_KMS_DISP_ATTRIBUTE_QUERY_DP_AUX_LOG,
};
@@ -4079,4 +4087,79 @@ struct NvKmsSetFlipLockGroupParams {
struct NvKmsSetFlipLockGroupReply reply; /*! out */
};
/*
* NVKMS_IOCTL_ENABLE_VBLANK_SEM_CONTROL
* NVKMS_IOCTL_DISABLE_VBLANK_SEM_CONTROL
* NVKMS_IOCTL_ACCEL_VBLANK_SEM_CONTROLS
*
* Enable or disable vblank semaphore control for the given head using the
* specified surface and surface offset. The memory at that location is
* interpreted as an NV0073_CTRL_CMD_SYSTEM_VBLANK_SEM_CONTROL_DATA. See the
* RMAPI documentation for NV0073_CTRL_CMD_SYSTEM_VBLANK_SEM_CONTROL_DATA for
* details of the semantics of that interface.
*
* It is the responsibility of the nvkms client(s) to coordinate at modeset
* time: the mapping of nvkms apiHeads to underlying hwHeads may change during a
* modeset, such that a registered vblank sem control will no longer receive
* vblank callbacks if the head is shutdown. Before a modeset shuts down a
* head, nvkms clients should ensure that all in-flight semaphore acquires are
* satisfied, and then after the modeset the vblank sem controls should be
* re-enabled.
*
* NVKMS_IOCTL_ACCEL_VBLANK_SEM_CONTROLS can be used, specifying a particular
* set of heads, to set all vblank sem controls on those heads to have their
* semaphore set to the value in their respective
* NV0073_CTRL_CMD_SYSTEM_VBLANK_SEM_CONTROL_DATA::requestCounterAccel fields.
*
* These ioctls are only available when
* NvKmsAllocDeviceReply::supportsVblankSemControl is true.
*/
struct NvKmsEnableVblankSemControlRequest {
NvKmsDeviceHandle deviceHandle;
NvKmsDispHandle dispHandle;
NvU32 head;
NvKmsSurfaceHandle surfaceHandle;
NvU64 surfaceOffset NV_ALIGN_BYTES(8);
};
struct NvKmsEnableVblankSemControlReply {
NvKmsVblankSemControlHandle vblankSemControlHandle;
};
struct NvKmsEnableVblankSemControlParams {
struct NvKmsEnableVblankSemControlRequest request;
struct NvKmsEnableVblankSemControlReply reply;
};
struct NvKmsDisableVblankSemControlRequest {
NvKmsDeviceHandle deviceHandle;
NvKmsDispHandle dispHandle;
NvKmsVblankSemControlHandle vblankSemControlHandle;
};
struct NvKmsDisableVblankSemControlReply {
NvU32 padding;
};
struct NvKmsDisableVblankSemControlParams {
struct NvKmsDisableVblankSemControlRequest request;
struct NvKmsDisableVblankSemControlReply reply;
};
struct NvKmsAccelVblankSemControlsRequest {
NvKmsDeviceHandle deviceHandle;
NvKmsDispHandle dispHandle;
NvU32 headMask;
};
struct NvKmsAccelVblankSemControlsReply {
NvU32 padding;
};
struct NvKmsAccelVblankSemControlsParams {
struct NvKmsAccelVblankSemControlsRequest request;
struct NvKmsAccelVblankSemControlsReply reply;
};
#endif /* NVKMS_API_H */

View File

@@ -490,6 +490,8 @@ typedef enum NvKmsKapiRegisterWaiterResultRec {
NVKMS_KAPI_REG_WAITER_ALREADY_SIGNALLED,
} NvKmsKapiRegisterWaiterResult;
typedef void NvKmsKapiSuspendResumeCallbackFunc(NvBool suspend);
struct NvKmsKapiFunctionsTable {
/*!
@@ -1399,6 +1401,15 @@ struct NvKmsKapiFunctionsTable {
NvU64 index,
NvU64 new_value
);
/*!
* Set the callback function for suspending and resuming the display system.
*/
void
(*setSuspendResumeCallback)
(
NvKmsKapiSuspendResumeCallbackFunc *function
);
};
/** @} */

View File

@@ -383,9 +383,6 @@ static NvBool KmsAllocateDevice(struct NvKmsKapiDevice *device)
device->caps.maxHeightInPixels = paramsAlloc->reply.maxHeightInPixels;
device->caps.maxCursorSizeInPixels = paramsAlloc->reply.maxCursorSize;
device->caps.requiresVrrSemaphores = paramsAlloc->reply.requiresVrrSemaphores;
/* The generic page kind was determined during RM device allocation,
* but it should match what NVKMS reports */
nvAssert(device->caps.genericPageKind == paramsAlloc->reply.genericPageKind);
/* XXX Add LUT support */
@@ -3436,6 +3433,30 @@ static NvBool GetCRC32
return NV_TRUE;
}
static NvKmsKapiSuspendResumeCallbackFunc *pSuspendResumeFunc;
void nvKmsKapiSuspendResume
(
NvBool suspend
)
{
if (pSuspendResumeFunc) {
pSuspendResumeFunc(suspend);
}
}
static void nvKmsKapiSetSuspendResumeCallback
(
NvKmsKapiSuspendResumeCallbackFunc *function
)
{
if (pSuspendResumeFunc && function) {
nvKmsKapiLogDebug("Kapi suspend/resume callback function already registered");
}
pSuspendResumeFunc = function;
}
NvBool nvKmsKapiGetFunctionsTableInternal
(
struct NvKmsKapiFunctionsTable *funcsTable
@@ -3514,6 +3535,7 @@ NvBool nvKmsKapiGetFunctionsTableInternal
nvKmsKapiUnregisterSemaphoreSurfaceCallback;
funcsTable->setSemaphoreSurfaceValue =
nvKmsKapiSetSemaphoreSurfaceValue;
funcsTable->setSuspendResumeCallback = nvKmsKapiSetSuspendResumeCallback;
return NV_TRUE;
}

View File

@@ -100,6 +100,8 @@ NvBool nvkms_output_rounding_fix(void);
NvBool nvkms_disable_hdmi_frl(void);
NvBool nvkms_disable_vrr_memclk_switch(void);
NvBool nvkms_hdmi_deepcolor(void);
NvBool nvkms_vblank_sem_control(void);
NvBool nvkms_opportunistic_display_sync(void);
void nvkms_call_rm (void *ops);
void* nvkms_alloc (size_t size,

View File

@@ -103,6 +103,8 @@ NvBool nvKmsKapiGetFunctionsTableInternal
struct NvKmsKapiFunctionsTable *funcsTable
);
void nvKmsKapiSuspendResume(NvBool suspend);
NvBool nvKmsGetBacklight(NvU32 display_id, void *drv_priv, NvU32 *brightness);
NvBool nvKmsSetBacklight(NvU32 display_id, void *drv_priv, NvU32 brightness);

View File

@@ -95,6 +95,7 @@
#include "nvkms-rm.h"
#include "nvkms-rmapi.h"
#include "nvkms-utils.h"
#include "nvkms-evo.h"
#include "nvidia-push-init.h"
#include "nvidia-push-methods.h"
@@ -275,11 +276,23 @@ NvU32 nvDIFRPrefetchSurfaces(NVDIFRStateEvoPtr pDifr, size_t l2CacheSize)
NvU32 status;
/*
* If DIFR is disabled it's because we know we were or will be flipping, or
* if console is active then the scanout surfaces will get updated by the
* OS console driver without any knowledge of NVKMS.
* If the console is active then the scanout surfaces will get updated by
* the OS console driver without any knowledge of NVKMS, DIFR should not be
* enabled in that case.
*/
if (pDifr->hwDisabled || nvEvoIsConsoleActive(pDevEvo)) {
if (nvEvoIsConsoleActive(pDevEvo)) {
/*
* NV2080_CTRL_LPWR_DIFR_PREFETCH_FAIL_INSUFFICIENT_L2_SIZE: Despite
* what the name suggests this will actually tell RM (and further PMU)
* to disable DIFR until the next modeset.
*/
return NV2080_CTRL_LPWR_DIFR_PREFETCH_FAIL_INSUFFICIENT_L2_SIZE;
}
/*
* If DIFR is disabled it's because we know we were or will be flipping.
*/
if (pDifr->hwDisabled) {
return NV2080_CTRL_LPWR_DIFR_PREFETCH_FAIL_OS_FLIPS_ENABLED;
}
@@ -845,8 +858,17 @@ static void IdleTimerProc(void *dataPtr, NvU32 dataU32)
pDifr->idleTimer = NULL;
if (now - pDifr->lastFlipTime >= idlePeriod) {
/* Enough time has passed with no new flips, enable DIFR. */
SetDisabledState(pDifr, FALSE);
/*
* Enough time has passed with no new flips, enable DIFR if the console
* is not active. If the console is active then the scanout surfaces
* will get updated by the OS console driver without any knowledge of
* NVKMS, DIFR can not be enabled in that case; the idle timer will get
* scheduled by nvDIFRNotifyFlip() on next modeset/flip, till then DIFR
* will remain disabled.
*/
if (!nvEvoIsConsoleActive(pDifr->pDevEvo)) {
SetDisabledState(pDifr, FALSE);
}
} else {
/* New flips have happened since the original, reset idle timer. */
EnsureIdleTimer(pDifr);

View File

@@ -71,7 +71,7 @@ static NvBool ValidateEdid (const NVDpyEvoRec *pDpyEvo,
const NvBool ignoreEdidChecksum);
static void LogEdid (NVDpyEvoPtr pDpyEvo,
NVEvoInfoStringPtr pInfoString);
static void ClearEdid (NVDpyEvoPtr pDpyEvo);
static void ClearEdid (NVDpyEvoPtr pDpyEvo, const NvBool bSendHdmiCapsToRm);
static void ClearCustomEdid (const NVDpyEvoRec *pDpyEvo);
static void WriteEdidToResman (const NVDpyEvoRec *pDpyEvo,
const NVEdidRec *pEdid);
@@ -90,14 +90,14 @@ static void AssignDpyEvoName (NVDpyEvoPtr pDpyEvo);
static NvBool IsConnectorTMDS (NVConnectorEvoPtr);
static void DpyDisconnectEvo(NVDpyEvoPtr pDpyEvo)
static void DpyDisconnectEvo(NVDpyEvoPtr pDpyEvo, const NvBool bSendHdmiCapsToRm)
{
NVDispEvoPtr pDispEvo = pDpyEvo->pDispEvo;
pDispEvo->connectedDisplays =
nvDpyIdListMinusDpyId(pDispEvo->connectedDisplays, pDpyEvo->id);
ClearEdid(pDpyEvo);
ClearEdid(pDpyEvo, bSendHdmiCapsToRm);
}
static NvBool DpyConnectEvo(
@@ -353,6 +353,7 @@ static void ApplyNewEdid(
NVDpyEvoPtr pDpyEvo,
const NVEdidRec *pEdid,
const NVParsedEdidEvoRec *pParsedEdid,
const NvBool bSendHdmiCapsToRm,
NVEvoInfoStringPtr pInfoString)
{
if (pDpyEvo->edid.buffer != NULL) {
@@ -394,7 +395,9 @@ static void ApplyNewEdid(
DpyAssignColorSpaceCaps(pDpyEvo, pInfoString);
}
nvUpdateHdmiCaps(pDpyEvo);
if (bSendHdmiCapsToRm) {
nvSendHdmiCapsToRm(pDpyEvo);
}
nvDpyProbeMaxPixelClock(pDpyEvo);
@@ -656,7 +659,8 @@ static void ReadAndApplyEdidEvo(
* worrying that this request has different parameters (like CustomEdid
* or mode validation overrides).
*/
ApplyNewEdid(pDpyEvo, &edid, pParsedEdid, &infoString);
ApplyNewEdid(pDpyEvo, &edid, pParsedEdid, TRUE /* bSendHdmiCapsToRm */,
&infoString);
} else {
nvFree(edid.buffer);
}
@@ -1917,14 +1921,15 @@ static void LogEdid(NVDpyEvoPtr pDpyEvo, NVEvoInfoStringPtr pInfoString)
* structure.
*/
static void ClearEdid(NVDpyEvoPtr pDpyEvo)
static void ClearEdid(NVDpyEvoPtr pDpyEvo, const NvBool bSendHdmiCapsToRm)
{
NVEdidRec edid = { };
NVEvoInfoStringRec infoString;
nvInitInfoString(&infoString, NULL, 0);
if (EdidHasChanged(pDpyEvo, &edid, NULL)) {
ApplyNewEdid(pDpyEvo, &edid, NULL, &infoString);
ApplyNewEdid(pDpyEvo, &edid, NULL,
bSendHdmiCapsToRm, &infoString);
}
}
@@ -2358,7 +2363,7 @@ void nvFreeDpyEvo(NVDispEvoPtr pDispEvo, NVDpyEvoPtr pDpyEvo)
{
nvCancelSDRTransitionTimer(pDpyEvo);
DpyDisconnectEvo(pDpyEvo);
DpyDisconnectEvo(pDpyEvo, FALSE /* bSendHdmiCapsToRm */);
// Let the DP library host implementation handle deleting a pDpy as if the
// library had notified it of a lost device.
@@ -2952,7 +2957,7 @@ NvBool nvDpyGetDynamicData(
return FALSE;
}
} else {
DpyDisconnectEvo(pDpyEvo);
DpyDisconnectEvo(pDpyEvo, TRUE /* bSendHdmiCapsToRm */);
}
if (nvConnectorUsesDPLib(pConnectorEvo)) {

View File

@@ -1837,8 +1837,11 @@ static NvBool ProhibitLockIfNecessary(NVDispEvoRec *pDispEvo)
/*
* Prohibit locking if necessary for the active configuration.
*
* Set up rasterlock between heads on a single GPU, if certain conditions are met:
* - Locking is not prohibited due to the active configuration
* - Opportunistic display sync is not disabled via kernel module parameter
* - All active heads have identical mode timings
*
* Set pDispEvo->pRasterLockPossible to indicate whether rasterlock is possible
@@ -1866,7 +1869,12 @@ static void FinishModesetOneDisp(
pDispEvo->rasterLockPossible = FALSE;
if (ProhibitLockIfNecessary(pDispEvo)) {
/* If locking is prohibited, do not attempt to lock heads. */
/* If all locking is prohibited, do not attempt rasterlock. */
return;
}
if (!nvkms_opportunistic_display_sync()) {
/* If opportunistic display sync is disabled, do not attempt rasterlock. */
return;
}
@@ -6663,35 +6671,41 @@ static NvBool GetDfpProtocol(const NVDpyEvoRec *pDpyEvo,
if (nvDpyIsHdmiEvo(pDpyEvo) &&
/* If we don't require boot clocks... */
((overrides & NVKMS_MODE_VALIDATION_REQUIRE_BOOT_CLOCKS) == 0) &&
/* If FRL is supported, use it for 10 BPC if needed. */
((nvHdmiDpySupportsFrl(pDpyEvo) &&
nvDpyIsHdmiDepth30Evo(pDpyEvo) &&
/* If FRL is supported... */
nvHdmiDpySupportsFrl(pDpyEvo) &&
/* Use FRL for 10 BPC if needed. */
((nvDpyIsHdmiDepth30Evo(pDpyEvo) &&
nvHdmiTimingsNeedFrl(pDpyEvo, pTimings, HDMI_BPC10)) ||
/* Fall back to 8 BPC, use FRL if needed. */
/* Use FRL for 8 BPC if needed. */
nvHdmiTimingsNeedFrl(pDpyEvo, pTimings, HDMI_BPC8))) {
/* If FRL is needed for 8 BPC, but not supported, fail. */
if (!nvHdmiDpySupportsFrl(pDpyEvo)) {
return FALSE;
}
nvAssert(nvDpyIsHdmiEvo(pDpyEvo));
nvAssert(rmProtocol == NV0073_CTRL_SPECIFIC_OR_PROTOCOL_SOR_SINGLE_TMDS_A ||
rmProtocol == NV0073_CTRL_SPECIFIC_OR_PROTOCOL_SOR_SINGLE_TMDS_B);
timingsProtocol = NVKMS_PROTOCOL_SOR_HDMI_FRL;
} else {
/* If HDMI FRL is needed for 8 BPC, but not supported, fail. */
if (nvDpyIsHdmiEvo(pDpyEvo) &&
nvHdmiTimingsNeedFrl(pDpyEvo, pTimings, HDMI_BPC8) &&
((overrides & NVKMS_MODE_VALIDATION_NO_MAX_PCLK_CHECK) == 0)) {
nvAssert(!nvHdmiDpySupportsFrl(pDpyEvo));
return FALSE;
}
switch (rmProtocol) {
default:
nvAssert(!"unrecognized SOR RM protocol");
return FALSE;
case NV0073_CTRL_SPECIFIC_OR_PROTOCOL_SOR_SINGLE_TMDS_A:
if (nvDpyRequiresDualLinkEvo(pDpyEvo, pTimings)) {
if (nvDpyRequiresDualLinkEvo(pDpyEvo, pTimings) &&
((overrides & NVKMS_MODE_VALIDATION_NO_MAX_PCLK_CHECK) == 0)) {
return FALSE;
}
timingsProtocol = NVKMS_PROTOCOL_SOR_SINGLE_TMDS_A;
break;
case NV0073_CTRL_SPECIFIC_OR_PROTOCOL_SOR_SINGLE_TMDS_B:
if (nvDpyRequiresDualLinkEvo(pDpyEvo, pTimings)) {
if (nvDpyRequiresDualLinkEvo(pDpyEvo, pTimings) &&
((overrides & NVKMS_MODE_VALIDATION_NO_MAX_PCLK_CHECK) == 0)) {
return FALSE;
}
timingsProtocol = NVKMS_PROTOCOL_SOR_SINGLE_TMDS_B;
@@ -6874,13 +6888,15 @@ NvBool nvDowngradeColorSpaceAndBpc(
NvBool nvDPValidateModeEvo(NVDpyEvoPtr pDpyEvo,
NVHwModeTimingsEvoPtr pTimings,
enum NvKmsDpyAttributeCurrentColorSpaceValue *pColorSpace,
enum NvKmsDpyAttributeColorBpcValue *pColorBpc,
const NvBool b2Heads1Or,
NVDscInfoEvoRec *pDscInfo,
const struct NvKmsModeValidationParams *pParams)
{
NVConnectorEvoPtr pConnectorEvo = pDpyEvo->pConnectorEvo;
enum NvKmsDpyAttributeCurrentColorSpaceValue colorSpace;
enum NvKmsDpyAttributeColorBpcValue colorBpc;
enum NvKmsDpyAttributeCurrentColorSpaceValue colorSpace = *pColorSpace;
enum NvKmsDpyAttributeColorBpcValue colorBpc = *pColorBpc;
enum NvKmsDpyAttributeColorRangeValue colorRange;
const NVColorFormatInfoRec supportedColorFormats =
nvGetColorFormatInfo(pDpyEvo);
@@ -6895,14 +6911,6 @@ NvBool nvDPValidateModeEvo(NVDpyEvoPtr pDpyEvo,
return TRUE;
}
if (pTimings->yuv420Mode != NV_YUV420_MODE_NONE) {
colorSpace = NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr420;
colorBpc = NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
} else if (!nvGetDefaultColorSpace(&supportedColorFormats, &colorSpace,
&colorBpc)) {
return FALSE;
}
if (colorSpace != NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_RGB) {
colorRange = NV_KMS_DPY_ATTRIBUTE_COLOR_RANGE_LIMITED;
} else {
@@ -6928,6 +6936,8 @@ NvBool nvDPValidateModeEvo(NVDpyEvoPtr pDpyEvo,
return FALSE;
}
*pColorSpace = colorSpace;
*pColorBpc = colorBpc;
return TRUE;
}
@@ -9405,6 +9415,7 @@ void nvEvoEnableMergeModePreModeset(NVDispEvoRec *pDispEvo,
pHC->serverLock = NV_EVO_RASTER_LOCK;
pHC->serverLockPin = NV_EVO_LOCK_PIN_INTERNAL(primaryHead);
pHC->setLockOffsetX = TRUE;
pHC->crashLockUnstallMode = FALSE;
} else {
pHC->clientLock = NV_EVO_RASTER_LOCK;
pHC->clientLockPin = NV_EVO_LOCK_PIN_INTERNAL(primaryHead);
@@ -9415,11 +9426,10 @@ void nvEvoEnableMergeModePreModeset(NVDispEvoRec *pDispEvo,
} else {
pHC->clientLockoutWindow = 2;
}
pHC->crashLockUnstallMode =
(pTimings->vrr.type != NVKMS_DPY_VRR_TYPE_NONE);
}
if (pTimings->vrr.type != NVKMS_DPY_VRR_TYPE_NONE) {
pHC->crashLockUnstallMode = TRUE;
}
pHC->stereoLocked = FALSE;
EvoUpdateHeadParams(pDispEvo, head, pUpdateState);
@@ -9584,3 +9594,42 @@ NvBool nvEvoUse2Heads1OR(const NVDpyEvoRec *pDpyEvo,
* maximum pixel clock support by a head. */
return (pTimings->pixelClock > pHeadCaps->maxPClkKHz);
}
NvBool nvIsLockGroupFlipLocked(const NVLockGroup *pLockGroup)
{
return pLockGroup->flipLockEnabled;
}
NvBool nvEvoIsConsoleActive(const NVDevEvoRec *pDevEvo)
{
/*
* The actual console state can be known only after allocation of core
* channel, if core channel is not allocated yet then assume that console
* is active.
*/
if (pDevEvo->core == NULL) {
return TRUE;
}
/*
* If (pDevEvo->modesetOwner == NULL) that means either the vbios
* console or the NVKMS console might be active.
*
* If (pDevEvo->modesetOwner != NULL) but
* pDevEvo->modesetOwnerChanged is TRUE, that means the modeset
* ownership is grabbed by the external client but it hasn't
* performed any modeset and the console is still active.
*/
if ((pDevEvo->modesetOwner == NULL) || pDevEvo->modesetOwnerChanged) {
NvU32 sd;
const NVDispEvoRec *pDispEvo;
FOR_ALL_EVO_DISPLAYS(pDispEvo, sd, pDevEvo) {
if (nvGetActiveHeadMask(pDispEvo) != 0x0) {
return TRUE;
}
}
}
return FALSE;
}

View File

@@ -3585,15 +3585,12 @@ EvoProgramSemaphore6(NVDevEvoPtr pDevEvo,
const NVFlipNIsoSurfaceEvoHwState *pNIso;
/*! Program Acq-only semaphore */
pSurfaceDesc = NULL;
offset = acqMode = relMode = value = 0;
if (pHwState->syncObject.usingSyncpt) {
if (pHwState->syncObject.u.syncpts.isPreSyncptSpecified) {
NvU32 id = pHwState->syncObject.u.syncpts.preSyncpt;
pSurfaceDesc = &pDevEvo->preSyncptTable[id].surfaceDesc;
} else {
pSurfaceDesc = NULL;
}
offset = 0;
if (pHwState->syncObject.usingSyncpt &&
pHwState->syncObject.u.syncpts.isPreSyncptSpecified) {
NvU32 id = pHwState->syncObject.u.syncpts.preSyncpt;
pSurfaceDesc = &pDevEvo->preSyncptTable[id].surfaceDesc;
acqMode = DRF_DEF(C67E, _SET_ACQ_SEMAPHORE_CONTROL, _ACQ_MODE, _CGEQ);
value = pHwState->syncObject.u.syncpts.preValue;
} else {
@@ -3617,16 +3614,14 @@ EvoProgramSemaphore6(NVDevEvoPtr pDevEvo,
/*! Program Rel-only semaphore */
pSurfaceDesc = NULL;
offset = acqMode = relMode = value = 0;
if (pHwState->syncObject.usingSyncpt) {
if (pHwState->syncObject.usingSyncpt &&
pHwState->syncObject.u.syncpts.isPostSyncptSpecified) {
pSurfaceDesc = &pHwState->syncObject.u.syncpts.surfaceDesc;
offset = 0;
acqMode = DRF_DEF(C67E, _SET_SEMAPHORE_CONTROL, _SKIP_ACQ, _TRUE);
relMode = DRF_DEF(C67E, _SET_SEMAPHORE_CONTROL, _REL_MODE, _WRITE);
value = pHwState->syncObject.u.syncpts.postValue;
/*! increase local max val as well */
if (pHwState->syncObject.u.syncpts.isPostSyncptSpecified) {
pChannel->postSyncpt.syncptMaxVal++;
}
pChannel->postSyncpt.syncptMaxVal++;
} else {
if (pHwState->syncObject.u.semaphores.releaseSurface.pSurfaceEvo != NULL) {
pNIso = &pHwState->syncObject.u.semaphores.releaseSurface;
@@ -6771,12 +6766,19 @@ static void EvoSetStallLockC3(NVDispEvoPtr pDispEvo, const int head,
NVEvoChannelPtr pChannel = pDevEvo->core;
NVEvoSubDevPtr pEvoSubDev = &pDevEvo->gpus[pDispEvo->displayOwner];
NVEvoHeadControlPtr pHC = &pEvoSubDev->headControl[head];
NvU32 data = 0x0;
nvUpdateUpdateState(pDevEvo, updateState, pChannel);
if (pHC->crashLockUnstallMode) {
data |= DRF_DEF(C37D, _HEAD_SET_STALL_LOCK, _UNSTALL_MODE, _CRASH_LOCK);
} else {
data |= DRF_DEF(C37D, _HEAD_SET_STALL_LOCK, _UNSTALL_MODE, _LINE_LOCK);
}
if (enable) {
NvU32 data = DRF_DEF(C37D, _HEAD_SET_STALL_LOCK, _ENABLE, _TRUE) |
DRF_DEF(C37D, _HEAD_SET_STALL_LOCK, _MODE, _ONE_SHOT);
data |= DRF_DEF(C37D, _HEAD_SET_STALL_LOCK, _ENABLE, _TRUE) |
DRF_DEF(C37D, _HEAD_SET_STALL_LOCK, _MODE, _ONE_SHOT);
if (!pHC->useStallLockPin) {
data |= DRF_DEF(C37D, _HEAD_SET_STALL_LOCK, _LOCK_PIN, _LOCK_PIN_NONE);
@@ -6789,20 +6791,12 @@ static void EvoSetStallLockC3(NVDispEvoPtr pDispEvo, const int head,
data |= DRF_NUM(C37D, _HEAD_SET_STALL_LOCK, _LOCK_PIN,
NVC37D_HEAD_SET_STALL_LOCK_LOCK_PIN_LOCK_PIN(pin));
}
if (pHC->crashLockUnstallMode) {
data |= DRF_DEF(C37D, _HEAD_SET_STALL_LOCK, _UNSTALL_MODE, _CRASH_LOCK);
} else {
data |= DRF_DEF(C37D, _HEAD_SET_STALL_LOCK, _UNSTALL_MODE, _LINE_LOCK);
}
nvDmaSetStartEvoMethod(pChannel, NVC37D_HEAD_SET_STALL_LOCK(head), 1);
nvDmaSetEvoMethodData(pChannel, data);
} else {
nvDmaSetStartEvoMethod(pChannel, NVC37D_HEAD_SET_STALL_LOCK(head), 1);
nvDmaSetEvoMethodData(pChannel,
DRF_DEF(C37D, _HEAD_SET_STALL_LOCK, _ENABLE, _FALSE));
data |= DRF_DEF(C37D, _HEAD_SET_STALL_LOCK, _ENABLE, _FALSE);
}
nvDmaSetStartEvoMethod(pChannel, NVC37D_HEAD_SET_STALL_LOCK(head), 1);
nvDmaSetEvoMethodData(pChannel, data);
}
static NvBool GetChannelState(NVDevEvoPtr pDevEvo,

View File

@@ -368,8 +368,7 @@ static NvBool GpuIdInDevEvo(NVDevEvoPtr pDevEvo, NvU32 gpuId)
/*!
* Free the pFrameLock object.
*/
static void FreeFrameLockEvo(NVDevEvoPtr pDevEvo,
NVFrameLockEvoPtr pFrameLockEvo)
static void FreeFrameLockEvo(NVFrameLockEvoPtr pFrameLockEvo)
{
if (pFrameLockEvo == NULL) {
return;
@@ -380,13 +379,15 @@ static void FreeFrameLockEvo(NVDevEvoPtr pDevEvo,
nvEvoGlobal.clientHandle,
pFrameLockEvo->device);
nvFreeUnixRmHandle(&pDevEvo->handleAllocator,
nvFreeUnixRmHandle(&pFrameLockEvo->handleAllocator,
pFrameLockEvo->device);
pFrameLockEvo->device = 0;
}
nvAssert(pFrameLockEvo->nGpuIds == 0);
nvTearDownUnixRmHandleAllocator(&pFrameLockEvo->handleAllocator);
nvListDel(&pFrameLockEvo->frameLockListEntry);
nvFree(pFrameLockEvo);
@@ -395,8 +396,8 @@ static void FreeFrameLockEvo(NVDevEvoPtr pDevEvo,
/*!
* Allocate and initialize a new pFrameLock object.
*/
static NVFrameLockEvoPtr AllocFrameLockEvo(NVDevEvoPtr pDevEvo,
int instance, NvU32 gsyncId)
static NVFrameLockEvoPtr AllocFrameLockEvo(int instance, NvU32 gsyncId,
NvBool *pBadFirmware)
{
NV30F1_ALLOC_PARAMETERS gsyncAllocParams = { 0 };
NV30F1_CTRL_GSYNC_GET_CAPS_PARAMS gsyncGetCapsParams = { 0 };
@@ -404,6 +405,8 @@ static NVFrameLockEvoPtr AllocFrameLockEvo(NVDevEvoPtr pDevEvo,
nvAssert(FindFrameLock(gsyncId) == NULL);
*pBadFirmware = FALSE;
pFrameLockEvo = nvCalloc(1, sizeof(NVFrameLockEvoRec));
if (pFrameLockEvo == NULL) {
@@ -412,7 +415,16 @@ static NVFrameLockEvoPtr AllocFrameLockEvo(NVDevEvoPtr pDevEvo,
nvListInit(&pFrameLockEvo->frameLockListEntry);
pFrameLockEvo->device = nvGenerateUnixRmHandle(&pDevEvo->handleAllocator);
if (!nvInitUnixRmHandleAllocator(
&pFrameLockEvo->handleAllocator,
nvEvoGlobal.clientHandle,
NVKMS_RM_HANDLE_SPACE_FRAMELOCK(instance))) {
nvEvoLog(EVO_LOG_ERROR, "Failed to initialize framelock handles");
goto fail;
}
pFrameLockEvo->device =
nvGenerateUnixRmHandle(&pFrameLockEvo->handleAllocator);
gsyncAllocParams.gsyncInstance = instance;
@@ -456,13 +468,8 @@ static NVFrameLockEvoPtr AllocFrameLockEvo(NVDevEvoPtr pDevEvo,
/* Check if the Quadro Sync card has a firmware
* version compatible with the GPUs connected to it.
*/
pDevEvo->badFramelockFirmware = gsyncGetCapsParams.isFirmwareRevMismatch;
if (gsyncGetCapsParams.isFirmwareRevMismatch) {
nvEvoLogDev(pDevEvo, EVO_LOG_ERROR, "The firmware on this Quadro Sync "
"card is not compatible with the GPUs connected to it."
" Please visit "
"<https://www.nvidia.com/object/quadro-sync.html> "
"for instructions on installing the correct firmware.");
*pBadFirmware = TRUE;
goto fail;
}
@@ -514,7 +521,7 @@ static NVFrameLockEvoPtr AllocFrameLockEvo(NVDevEvoPtr pDevEvo,
fail:
FreeFrameLockEvo(pDevEvo, pFrameLockEvo);
FreeFrameLockEvo(pFrameLockEvo);
return NULL;
}
@@ -617,8 +624,8 @@ void nvAllocFrameLocksEvo(NVDevEvoPtr pDevEvo)
}
for (i = 0; i < ARRAY_LEN(attachedGsyncParams.gsyncIds); i++) {
NVFrameLockEvoPtr pFrameLockEvo;
NvBool badFirmware = FALSE;
if (attachedGsyncParams.gsyncIds[i] == NV0000_CTRL_GSYNC_INVALID_ID) {
continue;
@@ -627,11 +634,20 @@ void nvAllocFrameLocksEvo(NVDevEvoPtr pDevEvo)
pFrameLockEvo = FindFrameLock(attachedGsyncParams.gsyncIds[i]);
if (pFrameLockEvo == NULL) {
pFrameLockEvo = AllocFrameLockEvo(pDevEvo, i,
attachedGsyncParams.gsyncIds[i]);
pFrameLockEvo = AllocFrameLockEvo(i,
attachedGsyncParams.gsyncIds[i],
&badFirmware);
}
if (pFrameLockEvo == NULL) {
if (badFirmware) {
nvEvoLogDev(pDevEvo, EVO_LOG_ERROR,
"The firmware on this Quadro Sync card is not compatible "
"with the GPUs connected to it. Please visit "
"<https://www.nvidia.com/object/quadro-sync.html> "
"for instructions on installing the correct firmware.");
pDevEvo->badFramelockFirmware = TRUE;
}
continue;
}
@@ -654,7 +670,7 @@ void nvFreeFrameLocksEvo(NVDevEvoPtr pDevEvo)
UnBindFrameLockFromDevEvo(pFrameLockEvo, pDevEvo);
if (pFrameLockEvo->nGpuIds == 0) {
FreeFrameLockEvo(pDevEvo, pFrameLockEvo);
FreeFrameLockEvo(pFrameLockEvo);
}
}
}
@@ -2009,11 +2025,6 @@ static const struct {
.get = NULL,
.type = NV_KMS_ATTRIBUTE_TYPE_BOOLEAN,
},
[NV_KMS_DISP_ATTRIBUTE_ALLOW_FLIPLOCK] = {
.set = nvAllowFlipLockEvo,
.get = NULL,
.type = NV_KMS_ATTRIBUTE_TYPE_BOOLEAN,
},
[NV_KMS_DISP_ATTRIBUTE_QUERY_DP_AUX_LOG] = {
.set = NULL,
.get = nvRmQueryDpAuxLog,

View File

@@ -61,7 +61,6 @@ enum NvKmsAllocDeviceStatus nvAssignEvoCaps(NVDevEvoPtr pDevEvo)
_supportsDP13, \
_supportsHDMI20, \
_inputLutAppliesToBase, \
_genericPageKind, \
_dpYCbCr422MaxBpc, \
_hdmiYCbCr422MaxBpc, \
_validNIsoFormatMask, \
@@ -90,7 +89,6 @@ enum NvKmsAllocDeviceStatus nvAssignEvoCaps(NVDevEvoPtr pDevEvo)
.maxWidthInBytes = _maxWidthInBytes, \
.maxWidthInPixels = _maxWidthInPixels, \
.maxHeight = _maxHeight, \
.genericPageKind = _genericPageKind, \
.maxRasterWidth = DRF_MASK(NV ## _classPrefix ## 7D_HEAD_SET_RASTER_SIZE_WIDTH), \
.maxRasterHeight = DRF_MASK(NV ## _classPrefix ## 7D_HEAD_SET_RASTER_SIZE_HEIGHT),\
.dpYCbCr422MaxBpc = _dpYCbCr422MaxBpc, \
@@ -136,28 +134,6 @@ enum NvKmsAllocDeviceStatus nvAssignEvoCaps(NVDevEvoPtr pDevEvo)
*/
#define NVD_CORE_CHANNEL_DMA_ARMED_SIZE 0x8000
/*
* The file
* https://github.com/NVIDIA/open-gpu-doc/blob/master/manuals/turing/tu104/dev_mmu.ref.txt
* defines:
*
* #define NV_MMU_PTE_KIND_GENERIC_MEMORY 0x06
*
* The file
* https://github.com/NVIDIA/open-gpu-doc/blob/master/manuals/volta/gv100/dev_mmu.ref.txt
* defines:
*
* #define NV_MMU_PTE_KIND_GENERIC_16BX2 0xfe
*
* Which correspond to the "generic" page kind used for non-compressed single-
* sample blocklinear color images on Turing+ and pre-Turing GPUs respectively.
* This is the only blocklinear memory layout display ever cares about.
*/
#define TURING_GENERIC_KIND 0x06
#define FERMI_GENERIC_KIND 0xfe
/* NVDisplay and later entries */
#define ENTRY_NVD(_coreClassPrefix, _windowClassPrefix, ...) \
ENTRY(_coreClassPrefix, __VA_ARGS__, \
@@ -177,33 +153,32 @@ enum NvKmsAllocDeviceStatus nvAssignEvoCaps(NVDevEvoPtr pDevEvo)
const NVEvoCapsRec evoCaps;
} dispTable[] = {
/*
* hdmiYCbCr422MaxBpc-----------------------------------------+
* dpYCbCr422MaxBpc---------------------------------------+ |
* genericPageKind---------------------+ | |
* inputLutAppliesToBase ---------+ | | |
* supportsHDMI20 -------------+ | | | |
* supportsDP13 ------------+ | | | | |
* pEvoHal --------------+ | | | | | |
* windowClassPrefix | | | | | | |
* classPrefix | | | | | | | |
* | | | | | | | | |
* hdmiYCbCr422MaxBpc--------------------+
* dpYCbCr422MaxBpc------------------+ |
* inputLutAppliesToBase ---------+ | |
* supportsHDMI20 -------------+ | | |
* supportsDP13 ------------+ | | | |
* pEvoHal --------------+ | | | | |
* windowClassPrefix | | | | | |
* classPrefix | | | | | | |
* | | | | | | | |
*/
/* Ada */
ENTRY_NVD(C7, C6, &nvEvoC6, 1, 1, 0, TURING_GENERIC_KIND, 12, 12),
ENTRY_NVD(C7, C6, &nvEvoC6, 1, 1, 0, 12, 12),
/* Ampere */
ENTRY_NVD(C6, C6, &nvEvoC6, 1, 1, 0, TURING_GENERIC_KIND, 12, 12),
ENTRY_NVD(C6, C6, &nvEvoC6, 1, 1, 0, 12, 12),
/* Turing */
ENTRY_NVD(C5, C5, &nvEvoC5, 1, 1, 0, TURING_GENERIC_KIND, 12, 12),
ENTRY_NVD(C5, C5, &nvEvoC5, 1, 1, 0, 12, 12),
/* Volta */
ENTRY_NVD(C3, C3, &nvEvoC3, 1, 1, 0, FERMI_GENERIC_KIND, 12, 12),
ENTRY_NVD(C3, C3, &nvEvoC3, 1, 1, 0, 12, 12),
/* gp10x */
ENTRY_EVO(98, &nvEvo94, 1, 1, 1, FERMI_GENERIC_KIND, 12, 12),
ENTRY_EVO(98, &nvEvo94, 1, 1, 1, 12, 12),
/* gp100 */
ENTRY_EVO(97, &nvEvo94, 1, 1, 1, FERMI_GENERIC_KIND, 12, 12),
ENTRY_EVO(97, &nvEvo94, 1, 1, 1, 12, 12),
/* gm20x */
ENTRY_EVO(95, &nvEvo94, 0, 1, 1, FERMI_GENERIC_KIND, 8, 0),
ENTRY_EVO(95, &nvEvo94, 0, 1, 1, 8, 0),
/* gm10x */
ENTRY_EVO(94, &nvEvo94, 0, 0, 1, FERMI_GENERIC_KIND, 8, 0),
ENTRY_EVO(94, &nvEvo94, 0, 0, 1, 8, 0),
};
int i;

View File

@@ -238,7 +238,7 @@ NvBool nvDpyIsHdmiDepth30Evo(const NVDpyEvoRec *pDpyEvo)
/*!
* Updates the display's HDMI 2.0 capabilities to the RM.
*/
void nvUpdateHdmiCaps(NVDpyEvoPtr pDpyEvo)
void nvSendHdmiCapsToRm(NVDpyEvoPtr pDpyEvo)
{
NV0073_CTRL_SPECIFIC_SET_HDMI_SINK_CAPS_PARAMS params = { 0 };
NVParsedEdidEvoPtr pParsedEdid = &pDpyEvo->parsedEdid;
@@ -256,7 +256,7 @@ void nvUpdateHdmiCaps(NVDpyEvoPtr pDpyEvo)
params.caps = 0;
/*
* nvUpdateHdmiCaps() gets called on dpy's connect/disconnect events
* nvSendHdmiCapsToRm() gets called on dpy's connect/disconnect events
* to set/clear capabilities, clear capabilities if parsed edid
* is not valid.
*/
@@ -1835,15 +1835,11 @@ NvBool nvHdmi204k60HzRGB444Allowed(const NVDpyEvoRec *pDpyEvo,
void nvHdmiSetVRR(NVDispEvoPtr pDispEvo, NvU32 head, NvBool enable)
{
NVT_EXTENDED_METADATA_PACKET_INFOFRAME empInfoFrame;
NVT_EXTENDED_METADATA_PACKET_INFOFRAME_CTRL empCtrl;
NVT_EXTENDED_METADATA_PACKET_INFOFRAME_CTRL empCtrl = { 0 };
NVHDMIPKT_TC transmitControl;
NVT_STATUS status;
nvkms_memset(&empCtrl, NVT_INFOFRAME_CTRL_DONTCARE,
sizeof(empCtrl));
empCtrl.EnableVRR = enable;
empCtrl.EnableQMS = FALSE;
status = NvTiming_ConstructExtendedMetadataPacketInfoframe(&empCtrl,
&empInfoFrame);

View File

@@ -1646,6 +1646,10 @@ static NvBool ValidateMode(NVDpyEvoPtr pDpyEvo,
NvU8 hdmiFrlBpc;
NvBool ret = FALSE;
const NVColorFormatInfoRec supportedColorFormats = nvGetColorFormatInfo(pDpyEvo);
enum NvKmsDpyAttributeCurrentColorSpaceValue colorSpace;
enum NvKmsDpyAttributeColorBpcValue colorBpc;
if (modeName[0] == '\0') {
nvBuildModeName(pModeTimings->hVisible, pModeTimings->vVisible,
localModeName, sizeof(localModeName));
@@ -1702,6 +1706,16 @@ static NvBool ValidateMode(NVDpyEvoPtr pDpyEvo,
b2Heads1Or = nvEvoUse2Heads1OR(pDpyEvo, pTimingsEvo, pParams);
if (pTimingsEvo->yuv420Mode != NV_YUV420_MODE_NONE) {
colorSpace = NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_YCbCr420;
colorBpc = NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_BPC_8;
} else if (!nvGetDefaultColorSpace(&supportedColorFormats, &colorSpace,
&colorBpc)) {
LogModeValidationEnd(pDispEvo, pInfoString,
"Failed to get default color space and Bpc");
goto done;
}
if (nvDpyIsHdmiEvo(pDpyEvo)) {
if (!nvHdmiFrlQueryConfig(pDpyEvo,
&pKmsMode->timings,
@@ -1716,8 +1730,8 @@ static NvBool ValidateMode(NVDpyEvoPtr pDpyEvo,
goto done;
}
} else {
if (!nvDPValidateModeEvo(pDpyEvo, pTimingsEvo, b2Heads1Or, pDscInfo,
pParams)) {
if (!nvDPValidateModeEvo(pDpyEvo, pTimingsEvo, &colorSpace, &colorBpc,
b2Heads1Or, pDscInfo, pParams)) {
LogModeValidationEnd(pDispEvo,
pInfoString, "DP Bandwidth check failed");
goto done;
@@ -1736,28 +1750,20 @@ static NvBool ValidateMode(NVDpyEvoPtr pDpyEvo,
/* Run the raster timings through IMP checking. */
{
const NVColorFormatInfoRec colorFormats =
nvGetColorFormatInfo(pDpyEvo);
enum NvKmsDpyAttributeCurrentColorSpaceValue colorSpace;
enum NvKmsDpyAttributeColorBpcValue colorBpc;
if (!nvGetDefaultColorSpace(&colorFormats, &colorSpace, &colorBpc) ||
!nvConstructHwModeTimingsImpCheckEvo(pDpyEvo->pConnectorEvo,
pTimingsEvo,
(pDscInfo->type !=
NV_DSC_INFO_EVO_TYPE_DISABLED),
b2Heads1Or,
colorSpace,
colorBpc,
pParams,
impOutTimings,
&impOutNumHeads,
pInfoString)) {
LogModeValidationEnd(pDispEvo, pInfoString,
"GPU extended capability check failed");
goto done;
}
if (!nvConstructHwModeTimingsImpCheckEvo(pDpyEvo->pConnectorEvo,
pTimingsEvo,
(pDscInfo->type !=
NV_DSC_INFO_EVO_TYPE_DISABLED),
b2Heads1Or,
colorSpace,
colorBpc,
pParams,
impOutTimings,
&impOutNumHeads,
pInfoString)) {
LogModeValidationEnd(pDispEvo, pInfoString,
"GPU extended capability check failed");
goto done;
}
nvAssert(impOutNumHeads > 0);

View File

@@ -199,6 +199,9 @@ static NvBool QueryGpuCapabilities(NVDevEvoPtr pDevEvo)
/* TODO: This cap bit should be queried from RM */
pDevEvo->requiresAllAllocationsInSysmem = pDevEvo->isSOCDisplay;
pDevEvo->supportsVblankSemControl =
!pDevEvo->isSOCDisplay && nvkms_vblank_sem_control();
/* ctxDma{,Non}CoherentAllowed */
if (!pDevEvo->isSOCDisplay) {
@@ -4250,9 +4253,10 @@ NvBool nvRmAllocDeviceEvo(NVDevEvoPtr pDevEvo,
goto failure;
}
if (!nvInitUnixRmHandleAllocator(&pDevEvo->handleAllocator,
nvEvoGlobal.clientHandle,
pRequest->deviceId + 1)) {
if (!nvInitUnixRmHandleAllocator(
&pDevEvo->handleAllocator,
nvEvoGlobal.clientHandle,
NVKMS_RM_HANDLE_SPACE_DEVICE(pRequest->deviceId))) {
nvEvoLogDev(pDevEvo, EVO_LOG_ERROR, "Failed to initialize handles");
goto failure;
}

View File

@@ -1225,3 +1225,111 @@ void nvEvoUnregisterDeferredRequestFifo(
nvFree(pDeferredRequestFifo);
}
static NvBool UpdateVblankSemControl(
NVDevEvoRec *pDevEvo,
NVVblankSemControl *pVblankSemControl,
NvBool enable)
{
NV0073_CTRL_CMD_SYSTEM_VBLANK_SEM_CONTROL_PARAMS params = { };
params.subDeviceInstance = pVblankSemControl->dispIndex;
params.head = pVblankSemControl->hwHead;
params.hMemory = pVblankSemControl->pSurfaceEvo->planes[0].rmHandle;
params.memoryOffset = pVblankSemControl->surfaceOffset;
params.bEnable = enable;
return nvRmApiControl(nvEvoGlobal.clientHandle,
pDevEvo->displayCommonHandle,
NV0073_CTRL_CMD_SYSTEM_VBLANK_SEM_CONTROL,
&params, sizeof(params)) == NVOS_STATUS_SUCCESS;
}
NVVblankSemControl *nvEvoEnableVblankSemControl(
NVDevEvoRec *pDevEvo,
NVDispEvoRec *pDispEvo,
NvU32 hwHead,
NVSurfaceEvoRec *pSurfaceEvo,
NvU64 surfaceOffset)
{
NVVblankSemControl *pVblankSemControl;
if (!pDevEvo->supportsVblankSemControl) {
return NULL;
}
/*
* We cannot enable VblankSemControl if the requested offset within the
* surface is too large.
*/
if (A_plus_B_greater_than_C_U64(
surfaceOffset,
sizeof(NV0073_CTRL_CMD_SYSTEM_VBLANK_SEM_CONTROL_DATA),
pSurfaceEvo->planes[0].rmObjectSizeInBytes)) {
return NULL;
}
if (nvEvoSurfaceRefCntsTooLarge(pSurfaceEvo)) {
return NULL;
}
pVblankSemControl = nvCalloc(1, sizeof(*pVblankSemControl));
if (pVblankSemControl == NULL) {
return NULL;
}
pVblankSemControl->hwHead = hwHead;
pVblankSemControl->dispIndex = pDispEvo->displayOwner;
pVblankSemControl->surfaceOffset = surfaceOffset;
pVblankSemControl->pSurfaceEvo = pSurfaceEvo;
if (UpdateVblankSemControl(pDevEvo,
pVblankSemControl,
TRUE /* enable */)) {
nvEvoIncrementSurfaceRefCnts(pSurfaceEvo);
return pVblankSemControl;
} else {
nvFree(pVblankSemControl);
return NULL;
}
}
NvBool nvEvoDisableVblankSemControl(
NVDevEvoRec *pDevEvo,
NVVblankSemControl *pVblankSemControl)
{
if (!pDevEvo->supportsVblankSemControl) {
return FALSE;
}
if (UpdateVblankSemControl(pDevEvo,
pVblankSemControl,
FALSE /* enable */)) {
nvEvoDecrementSurfaceRefCnts(pDevEvo, pVblankSemControl->pSurfaceEvo);
nvFree(pVblankSemControl);
return TRUE;
} else {
return FALSE;
}
}
NvBool nvEvoAccelVblankSemControls(
NVDevEvoPtr pDevEvo,
NvU32 dispIndex,
NvU32 hwHeadMask)
{
NV0073_CTRL_CMD_SYSTEM_ACCEL_VBLANK_SEM_CONTROLS_PARAMS params = { };
if (!pDevEvo->supportsVblankSemControl) {
return FALSE;
}
params.subDeviceInstance = dispIndex;
params.headMask = hwHeadMask;
return nvRmApiControl(nvEvoGlobal.clientHandle,
pDevEvo->displayCommonHandle,
NV0073_CTRL_CMD_SYSTEM_ACCEL_VBLANK_SEM_CONTROLS,
&params, sizeof(params)) == NVOS_STATUS_SUCCESS;
}

View File

@@ -262,21 +262,12 @@ void nvAdjustHwModeTimingsForVrrEvo(NVHwModeTimingsEvoPtr pTimings,
const NvU32 vrrOverrideMinRefreshRate,
const NvBool needsSwFramePacing)
{
NvU32 timeoutMicroseconds;
if (vrrType == NVKMS_DPY_VRR_TYPE_NONE) {
return;
}
/*
* On G-SYNC panels, the back porch extension is used to indicate to
* the monitor that VRR is enabled. It is not necessary on
* Adaptive-Sync displays.
*/
if (vrrType == NVKMS_DPY_VRR_TYPE_GSYNC) {
pTimings->rasterSize.y += 2;
pTimings->rasterBlankEnd.y += 2;
pTimings->rasterBlankStart.y += 2;
}
// Allow overriding the EDID min refresh rate on Adaptive-Sync
// displays.
if (nvIsAdaptiveSyncDpyVrrType(vrrType) && vrrOverrideMinRefreshRate) {
@@ -295,11 +286,30 @@ void nvAdjustHwModeTimingsForVrrEvo(NVHwModeTimingsEvoPtr pTimings,
clampedMinRefreshRate =
NV_MIN(clampedMinRefreshRate, maxMinRefreshRate);
pTimings->vrr.timeoutMicroseconds = 1000000 /
clampedMinRefreshRate;
timeoutMicroseconds = 1000000 / clampedMinRefreshRate;
} else {
pTimings->vrr.timeoutMicroseconds = edidTimeoutMicroseconds;
timeoutMicroseconds = edidTimeoutMicroseconds;
}
// Disallow VRR if the refresh rate is less than 110% of the VRR minimum
// refresh rate.
if (nvGetRefreshRate10kHz(pTimings) <
(((NvU64) 1000000 * 11000) / timeoutMicroseconds)) {
return;
}
/*
* On G-SYNC panels, the back porch extension is used to indicate to
* the monitor that VRR is enabled. It is not necessary on
* Adaptive-Sync displays.
*/
if (vrrType == NVKMS_DPY_VRR_TYPE_GSYNC) {
pTimings->rasterSize.y += 2;
pTimings->rasterBlankEnd.y += 2;
pTimings->rasterBlankStart.y += 2;
}
pTimings->vrr.timeoutMicroseconds = timeoutMicroseconds;
pTimings->vrr.needsSwFramePacing = needsSwFramePacing;
pTimings->vrr.type = vrrType;
}

View File

@@ -145,6 +145,7 @@ struct NvKmsPerOpenDisp {
struct NvKmsPerOpenConnector connector[NVKMS_MAX_CONNECTORS_PER_DISP];
NVEvoApiHandlesRec vblankSyncObjectHandles[NVKMS_MAX_HEADS_PER_DISP];
NVEvoApiHandlesRec vblankCallbackHandles[NVKMS_MAX_HEADS_PER_DISP];
NVEvoApiHandlesRec vblankSemControlHandles;
};
struct NvKmsPerOpenDev {
@@ -697,6 +698,8 @@ static void ClearPerOpenDisp(
nvEvoDestroyApiHandles(&pOpenDisp->vblankCallbackHandles[i]);
}
nvEvoDestroyApiHandles(&pOpenDisp->vblankSemControlHandles);
nvEvoDestroyApiHandle(&pOpenDev->dispHandles, pOpenDisp->nvKmsApiHandle);
nvkms_memset(pOpenDisp, 0, sizeof(*pOpenDisp));
@@ -762,8 +765,8 @@ static NvBool InitPerOpenDisp(
/* Initialize the vblankCallbackHandles for each head.
*
* The limit of VBLANK_SYNC_OBJECTS_PER_HEAD doesn't really apply here, but
* we need something. */
* The initial value of VBLANK_SYNC_OBJECTS_PER_HEAD doesn't really apply
* here, but we need something. */
for (NvU32 i = 0; i < NVKMS_MAX_HEADS_PER_DISP; i++) {
if (!nvEvoInitApiHandles(&pOpenDisp->vblankCallbackHandles[i],
NVKMS_MAX_VBLANK_SYNC_OBJECTS_PER_HEAD)) {
@@ -771,6 +774,15 @@ static NvBool InitPerOpenDisp(
}
}
/* Initialize the vblankSemControlHandles.
*
* The initial value of VBLANK_SYNC_OBJECTS_PER_HEAD doesn't really apply
* here, but we need something. */
if (!nvEvoInitApiHandles(&pOpenDisp->vblankSemControlHandles,
NVKMS_MAX_VBLANK_SYNC_OBJECTS_PER_HEAD)) {
goto fail;
}
if (!AllocPerOpenFrameLock(pOpen, pOpenDisp)) {
goto fail;
}
@@ -1444,7 +1456,6 @@ static NvBool AllocDevice(struct NvKmsPerOpen *pOpen,
pParams->reply.maxWidthInPixels = pDevEvo->caps.maxWidthInPixels;
pParams->reply.maxHeightInPixels = pDevEvo->caps.maxHeight;
pParams->reply.cursorCompositionCaps = pDevEvo->caps.cursorCompositionCaps;
pParams->reply.genericPageKind = pDevEvo->caps.genericPageKind;
pParams->reply.maxCursorSize = pDevEvo->cursorHal->caps.maxSize;
@@ -1470,6 +1481,8 @@ static NvBool AllocDevice(struct NvKmsPerOpen *pOpen,
pParams->reply.supportsVblankSyncObjects =
pDevEvo->hal->caps.supportsVblankSyncObjects;
pParams->reply.supportsVblankSemControl = pDevEvo->supportsVblankSemControl;
pParams->reply.status = NVKMS_ALLOC_DEVICE_STATUS_SUCCESS;
return TRUE;
@@ -1554,12 +1567,46 @@ static void DisableRemainingVblankSyncObjects(struct NvKmsPerOpen *pOpen,
}
}
static void DisableRemainingVblankSemControls(
struct NvKmsPerOpen *pOpen,
struct NvKmsPerOpenDev *pOpenDev)
{
struct NvKmsPerOpenDisp *pOpenDisp;
NvKmsGenericHandle dispHandle;
NVDevEvoPtr pDevEvo = pOpenDev->pDevEvo;
nvAssert(pOpen->type == NvKmsPerOpenTypeIoctl);
FOR_ALL_POINTERS_IN_EVO_API_HANDLES(&pOpenDev->dispHandles,
pOpenDisp,
dispHandle) {
NVVblankSemControl *pVblankSemControl;
NvKmsGenericHandle vblankSemControlHandle;
FOR_ALL_POINTERS_IN_EVO_API_HANDLES(&pOpenDisp->vblankSemControlHandles,
pVblankSemControl,
vblankSemControlHandle) {
NvBool ret =
nvEvoDisableVblankSemControl(pDevEvo, pVblankSemControl);
if (!ret) {
nvAssert(!"implicit disable of vblank sem control failed.");
}
nvEvoDestroyApiHandle(&pOpenDisp->vblankSemControlHandles,
vblankSemControlHandle);
}
}
}
static void FreeDeviceReference(struct NvKmsPerOpen *pOpen,
struct NvKmsPerOpenDev *pOpenDev)
{
/* Disable all client-owned vblank sync objects that still exist. */
DisableRemainingVblankSyncObjects(pOpen, pOpenDev);
DisableRemainingVblankSemControls(pOpen, pOpenDev);
FreeSwapGroups(pOpenDev);
UnregisterDeferredRequestFifos(pOpenDev);
@@ -4667,6 +4714,150 @@ static NvBool SetFlipLockGroup(
return nvSetFlipLockGroup(pDevEvo, pRequest);
}
static NvBool EnableVblankSemControl(
struct NvKmsPerOpen *pOpen,
void *pParamsVoid)
{
struct NvKmsEnableVblankSemControlParams *pParams = pParamsVoid;
struct NvKmsPerOpenDev *pOpenDev;
struct NvKmsPerOpenDisp *pOpenDisp;
NVDevEvoPtr pDevEvo;
NVDispEvoRec *pDispEvo;
NVSurfaceEvoPtr pSurfaceEvo;
NVVblankSemControl *pVblankSemControl;
NvKmsVblankSemControlHandle vblankSemControlHandle;
NvU32 hwHead;
if (!GetPerOpenDevAndDisp(pOpen,
pParams->request.deviceHandle,
pParams->request.dispHandle,
&pOpenDev,
&pOpenDisp)) {
return FALSE;
}
pDevEvo = pOpenDev->pDevEvo;
pDispEvo = pOpenDisp->pDispEvo;
pSurfaceEvo =
nvEvoGetSurfaceFromHandleNoDispHWAccessOk(
pDevEvo,
&pOpenDev->surfaceHandles,
pParams->request.surfaceHandle);
if (pSurfaceEvo == NULL) {
return FALSE;
}
hwHead = nvGetPrimaryHwHead(pDispEvo, pParams->request.head);
if (hwHead == NV_INVALID_HEAD) {
return FALSE;
}
pVblankSemControl = nvEvoEnableVblankSemControl(
pDevEvo,
pDispEvo,
hwHead,
pSurfaceEvo,
pParams->request.surfaceOffset);
if (pVblankSemControl == NULL) {
return FALSE;
}
vblankSemControlHandle =
nvEvoCreateApiHandle(&pOpenDisp->vblankSemControlHandles,
pVblankSemControl);
if (vblankSemControlHandle == 0) {
(void)nvEvoDisableVblankSemControl(pDevEvo, pVblankSemControl);
return FALSE;
}
pParams->reply.vblankSemControlHandle = vblankSemControlHandle;
return TRUE;
}
static NvBool DisableVblankSemControl(
struct NvKmsPerOpen *pOpen,
void *pParamsVoid)
{
const struct NvKmsDisableVblankSemControlParams *pParams = pParamsVoid;
struct NvKmsPerOpenDev *pOpenDev;
struct NvKmsPerOpenDisp *pOpenDisp;
NVDevEvoPtr pDevEvo;
NVVblankSemControl *pVblankSemControl;
NvBool ret;
if (!GetPerOpenDevAndDisp(pOpen,
pParams->request.deviceHandle,
pParams->request.dispHandle,
&pOpenDev,
&pOpenDisp)) {
return FALSE;
}
pDevEvo = pOpenDev->pDevEvo;
pVblankSemControl =
nvEvoGetPointerFromApiHandle(&pOpenDisp->vblankSemControlHandles,
pParams->request.vblankSemControlHandle);
if (pVblankSemControl == NULL) {
return FALSE;
}
ret = nvEvoDisableVblankSemControl(pDevEvo, pVblankSemControl);
if (ret) {
nvEvoDestroyApiHandle(&pOpenDisp->vblankSemControlHandles,
pParams->request.vblankSemControlHandle);
}
return ret;
}
static NvBool AccelVblankSemControls(
struct NvKmsPerOpen *pOpen,
void *pParamsVoid)
{
const struct NvKmsAccelVblankSemControlsParams *pParams = pParamsVoid;
struct NvKmsPerOpenDev *pOpenDev;
struct NvKmsPerOpenDisp *pOpenDisp;
NVDevEvoPtr pDevEvo;
const NVDispEvoRec *pDispEvo;
NvU32 apiHead, hwHeadMask = 0;
if (!GetPerOpenDevAndDisp(pOpen,
pParams->request.deviceHandle,
pParams->request.dispHandle,
&pOpenDev,
&pOpenDisp)) {
return FALSE;
}
if (!nvKmsOpenDevHasSubOwnerPermissionOrBetter(pOpenDev)) {
return FALSE;
}
pDevEvo = pOpenDev->pDevEvo;
pDispEvo = pOpenDisp->pDispEvo;
FOR_ALL_HEADS(apiHead, pParams->request.headMask) {
NvU32 hwHead = nvGetPrimaryHwHead(pDispEvo, apiHead);
if (hwHead != NV_INVALID_HEAD) {
hwHeadMask |= NVBIT(hwHead);
}
}
return nvEvoAccelVblankSemControls(
pDevEvo,
pDispEvo->displayOwner,
hwHeadMask);
}
/*!
* Perform the ioctl operation requested by the client.
*
@@ -4789,6 +4980,9 @@ NvBool nvKmsIoctl(
ENTRY(NVKMS_IOCTL_DISABLE_VBLANK_SYNC_OBJECT, DisableVblankSyncObject),
ENTRY(NVKMS_IOCTL_NOTIFY_VBLANK, NotifyVblank),
ENTRY(NVKMS_IOCTL_SET_FLIPLOCK_GROUP, SetFlipLockGroup),
ENTRY(NVKMS_IOCTL_ENABLE_VBLANK_SEM_CONTROL, EnableVblankSemControl),
ENTRY(NVKMS_IOCTL_DISABLE_VBLANK_SEM_CONTROL, DisableVblankSemControl),
ENTRY(NVKMS_IOCTL_ACCEL_VBLANK_SEM_CONTROLS, AccelVblankSemControls),
};
struct NvKmsPerOpen *pOpen = pOpenVoid;
@@ -5702,11 +5896,21 @@ ProcFsPrintHeads(
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);
nvEvoLogInfoString(&infoString,
" pLockGroup : %p",
pLockGroup);
nvEvoLogInfoString(&infoString,
" flipLock : %s",
flipLocked ? "yes" : "no");
}
outString(data, buffer);
if (pDevEvo->coreInitMethodsPending) {