mirror of
https://github.com/NVIDIA/open-gpu-kernel-modules.git
synced 2026-02-05 23:59:59 +00:00
550.40.07
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -58,6 +58,7 @@ typedef NvU32 NvKmsFrameLockHandle;
|
||||
typedef NvU32 NvKmsDeferredRequestFifoHandle;
|
||||
typedef NvU32 NvKmsSwapGroupHandle;
|
||||
typedef NvU32 NvKmsVblankSyncObjectHandle;
|
||||
typedef NvU32 NvKmsVblankSemControlHandle;
|
||||
|
||||
struct NvKmsSize {
|
||||
NvU16 width;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
);
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
¶ms, 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,
|
||||
¶ms, sizeof(params)) == NVOS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user