mirror of
https://github.com/NVIDIA/open-gpu-kernel-modules.git
synced 2026-02-01 05:59:48 +00:00
560.28.03
This commit is contained in:
@@ -41,6 +41,41 @@
|
||||
nvEvoLogDebug(EVO_LOG_INFO, "[kapi][GPU Id 0x%08x] "__format, \
|
||||
device->gpuId, ##__VA_ARGS__)
|
||||
|
||||
/*
|
||||
* Semaphore values used when using semaphore-based synchronization between
|
||||
* userspace rendering and flips.
|
||||
*/
|
||||
enum NvKmsKapiSemaphoreValues {
|
||||
/*
|
||||
* Initial state on driver init, and the value written by the hardware when
|
||||
* it has completed processing of a frame using this semaphore.
|
||||
*/
|
||||
NVKMS_KAPI_SEMAPHORE_VALUE_DONE = 0xd00dd00d,
|
||||
|
||||
/*
|
||||
* Value of the semaphore when a flip is pending in the display pushbuffer,
|
||||
* but userspace rendering is not yet complete.
|
||||
*/
|
||||
NVKMS_KAPI_SEMAPHORE_VALUE_NOT_READY = 0x13371337,
|
||||
|
||||
/*
|
||||
* Value of the semaphore when userspace rendering is complete and the
|
||||
* pending flip may proceed.
|
||||
*/
|
||||
NVKMS_KAPI_SEMAPHORE_VALUE_READY = 0xf473f473,
|
||||
};
|
||||
|
||||
struct NvKmsKapiNisoSurface {
|
||||
NvU32 hRmHandle;
|
||||
NvKmsSurfaceHandle hKmsHandle;
|
||||
|
||||
NvBool mapped;
|
||||
void *pLinearAddress;
|
||||
|
||||
enum NvKmsNIsoFormat format;
|
||||
|
||||
};
|
||||
|
||||
struct NvKmsKapiDevice {
|
||||
|
||||
NvU32 gpuId;
|
||||
@@ -87,20 +122,15 @@ struct NvKmsKapiDevice {
|
||||
} caps;
|
||||
|
||||
NvU64 supportedSurfaceMemoryFormats[NVKMS_KAPI_LAYER_MAX];
|
||||
NvBool supportsHDR[NVKMS_KAPI_LAYER_MAX];
|
||||
NvBool supportsICtCp[NVKMS_KAPI_LAYER_MAX];
|
||||
|
||||
NvU32 numHeads;
|
||||
NvU32 numLayers[NVKMS_KAPI_MAX_HEADS];
|
||||
|
||||
struct {
|
||||
NvU32 hRmHandle;
|
||||
NvKmsSurfaceHandle hKmsHandle;
|
||||
struct NvKmsKapiNisoSurface notifier;
|
||||
struct NvKmsKapiNisoSurface semaphore;
|
||||
|
||||
NvBool mapped;
|
||||
void *pLinearAddress;
|
||||
|
||||
enum NvKmsNIsoFormat format;
|
||||
} notifier;
|
||||
NvU32 numDisplaySemaphores;
|
||||
|
||||
struct {
|
||||
NvU32 currFlipNotifierIndex;
|
||||
|
||||
@@ -72,8 +72,10 @@ static inline NvU32 NVKMS_KAPI_NOTIFIER_OFFSET(NvU32 head,
|
||||
}
|
||||
|
||||
NvBool nvKmsKapiAllocateNotifiers(struct NvKmsKapiDevice *device, NvBool inVideoMemory);
|
||||
NvBool nvKmsKapiAllocateSemaphores(struct NvKmsKapiDevice *device, NvBool inVideoMemory);
|
||||
|
||||
void nvKmsKapiFreeNotifiers(struct NvKmsKapiDevice *device);
|
||||
void nvKmsKapiFreeNisoSurface(struct NvKmsKapiDevice *device,
|
||||
struct NvKmsKapiNisoSurface *surf);
|
||||
|
||||
NvBool nvKmsKapiIsNotifierFinish(const struct NvKmsKapiDevice *device,
|
||||
const NvU32 head, const NvU32 layer,
|
||||
@@ -82,4 +84,16 @@ NvBool nvKmsKapiIsNotifierFinish(const struct NvKmsKapiDevice *device,
|
||||
void nvKmsKapiNotifierSetNotBegun(struct NvKmsKapiDevice *device,
|
||||
NvU32 head, NvU32 layer, NvU32 index);
|
||||
|
||||
NvBool nvKmsKapiResetDisplaySemaphore(struct NvKmsKapiDevice *device,
|
||||
NvU32 index);
|
||||
|
||||
void nvKmsKapiSignalDisplaySemaphore(struct NvKmsKapiDevice *device,
|
||||
NvU32 index);
|
||||
|
||||
void nvKmsKapiCancelDisplaySemaphore(struct NvKmsKapiDevice *device,
|
||||
NvU32 index);
|
||||
|
||||
NvU32 nvKmsKapiGetDisplaySemaphoreOffset(struct NvKmsKapiDevice *device,
|
||||
NvU32 index);
|
||||
|
||||
#endif /* __NVKMS_KAPI_NOTIFIERS_H__ */
|
||||
|
||||
@@ -158,13 +158,17 @@ struct NvKmsKapiDeviceResourcesInfo {
|
||||
|
||||
NvU32 hasVideoMemory;
|
||||
|
||||
NvU32 numDisplaySemaphores;
|
||||
|
||||
NvU8 genericPageKind;
|
||||
|
||||
NvBool supportsSyncpts;
|
||||
|
||||
NvBool requiresVrrSemaphores;
|
||||
} caps;
|
||||
|
||||
NvU64 supportedSurfaceMemoryFormats[NVKMS_KAPI_LAYER_MAX];
|
||||
NvBool supportsHDR[NVKMS_KAPI_LAYER_MAX];
|
||||
NvBool supportsICtCp[NVKMS_KAPI_LAYER_MAX];
|
||||
};
|
||||
|
||||
#define NVKMS_KAPI_LAYER_MASK(layerType) (1 << (layerType))
|
||||
@@ -210,18 +214,26 @@ struct NvKmsKapiStaticDisplayInfo {
|
||||
NvU32 headMask;
|
||||
};
|
||||
|
||||
struct NvKmsKapiSyncpt {
|
||||
struct NvKmsKapiSyncParams {
|
||||
union {
|
||||
struct {
|
||||
/*!
|
||||
* Possible syncpt use case in kapi.
|
||||
* For pre-syncpt, use only id and value
|
||||
* and for post-syncpt, use only fd.
|
||||
*/
|
||||
NvU32 preSyncptId;
|
||||
NvU32 preSyncptValue;
|
||||
} syncpt;
|
||||
|
||||
/*!
|
||||
* Possible syncpt use case in kapi.
|
||||
* For pre-syncpt, use only id and value
|
||||
* and for post-syncpt, use only fd.
|
||||
*/
|
||||
NvBool preSyncptSpecified;
|
||||
NvU32 preSyncptId;
|
||||
NvU32 preSyncptValue;
|
||||
struct {
|
||||
NvU32 index;
|
||||
} semaphore;
|
||||
} u;
|
||||
|
||||
NvBool postSyncptRequested;
|
||||
NvBool preSyncptSpecified;
|
||||
NvBool postSyncptRequested;
|
||||
NvBool semaphoreSpecified;
|
||||
};
|
||||
|
||||
struct NvKmsKapiLayerConfig {
|
||||
@@ -231,7 +243,7 @@ struct NvKmsKapiLayerConfig {
|
||||
NvU8 surfaceAlpha;
|
||||
} compParams;
|
||||
struct NvKmsRRParams rrParams;
|
||||
struct NvKmsKapiSyncpt syncptParams;
|
||||
struct NvKmsKapiSyncParams syncParams;
|
||||
|
||||
struct {
|
||||
struct NvKmsHDRStaticMetadata val;
|
||||
@@ -319,7 +331,6 @@ struct NvKmsKapiHeadModeSetConfig {
|
||||
|
||||
struct {
|
||||
struct {
|
||||
NvBool specified;
|
||||
NvU32 depth;
|
||||
NvU32 start;
|
||||
NvU32 end;
|
||||
@@ -327,7 +338,6 @@ struct NvKmsKapiHeadModeSetConfig {
|
||||
} input;
|
||||
|
||||
struct {
|
||||
NvBool specified;
|
||||
NvBool enabled;
|
||||
struct NvKmsLutRamps *pRamps;
|
||||
} output;
|
||||
@@ -342,7 +352,8 @@ struct NvKmsKapiHeadRequestedConfig {
|
||||
NvBool modeChanged : 1;
|
||||
NvBool hdrInfoFrameChanged : 1;
|
||||
NvBool colorimetryChanged : 1;
|
||||
NvBool lutChanged : 1;
|
||||
NvBool ilutChanged : 1;
|
||||
NvBool olutChanged : 1;
|
||||
} flags;
|
||||
|
||||
struct NvKmsKapiCursorRequestedConfig cursorRequestedConfig;
|
||||
@@ -368,6 +379,8 @@ struct NvKmsKapiHeadReplyConfig {
|
||||
|
||||
struct NvKmsKapiModeSetReplyConfig {
|
||||
enum NvKmsFlipResult flipResult;
|
||||
NvBool vrrFlip;
|
||||
NvS32 vrrSemaphoreIndex;
|
||||
struct NvKmsKapiHeadReplyConfig
|
||||
headReplyConfig[NVKMS_KAPI_MAX_HEADS];
|
||||
};
|
||||
@@ -1410,6 +1423,87 @@ struct NvKmsKapiFunctionsTable {
|
||||
(
|
||||
NvKmsKapiSuspendResumeCallbackFunc *function
|
||||
);
|
||||
|
||||
/*!
|
||||
* Immediately reset the specified display semaphore to the pending state.
|
||||
*
|
||||
* Must be called prior to applying a mode set that utilizes the specified
|
||||
* display semaphore for synchronization.
|
||||
*
|
||||
* \param [in] device The device which will utilize the semaphore.
|
||||
*
|
||||
* \param [in] semaphoreIndex Index of the desired semaphore within the
|
||||
* NVKMS semaphore pool. Must be less than
|
||||
* NvKmsKapiDeviceResourcesInfo::caps::numDisplaySemaphores
|
||||
* for the specified device.
|
||||
*/
|
||||
NvBool
|
||||
(*resetDisplaySemaphore)
|
||||
(
|
||||
struct NvKmsKapiDevice *device,
|
||||
NvU32 semaphoreIndex
|
||||
);
|
||||
|
||||
/*!
|
||||
* Immediately set the specified display semaphore to the displayable state.
|
||||
*
|
||||
* Must be called after \ref resetDisplaySemaphore to indicate a mode
|
||||
* configuration change that utilizes the specified display semaphore for
|
||||
* synchronization may proceed.
|
||||
*
|
||||
* \param [in] device The device which will utilize the semaphore.
|
||||
*
|
||||
* \param [in] semaphoreIndex Index of the desired semaphore within the
|
||||
* NVKMS semaphore pool. Must be less than
|
||||
* NvKmsKapiDeviceResourcesInfo::caps::numDisplaySemaphores
|
||||
* for the specified device.
|
||||
*/
|
||||
void
|
||||
(*signalDisplaySemaphore)
|
||||
(
|
||||
struct NvKmsKapiDevice *device,
|
||||
NvU32 semaphoreIndex
|
||||
);
|
||||
|
||||
/*!
|
||||
* Immediately cancel use of a display semaphore by resetting its value to
|
||||
* its initial state.
|
||||
*
|
||||
* This can be used by clients to restore a semaphore to a consistent state
|
||||
* when they have prepared it for use by previously calling
|
||||
* \ref resetDisplaySemaphore() on it, but are then prevented from
|
||||
* submitting the associated hardware operations to consume it due to the
|
||||
* subsequent failure of some software or hardware operation.
|
||||
*
|
||||
* \param [in] device The device which will utilize the semaphore.
|
||||
*
|
||||
* \param [in] semaphoreIndex Index of the desired semaphore within the
|
||||
* NVKMS semaphore pool. Must be less than
|
||||
* NvKmsKapiDeviceResourcesInfo::caps::numDisplaySemaphores
|
||||
* for the specified device.
|
||||
*/
|
||||
void
|
||||
(*cancelDisplaySemaphore)
|
||||
(
|
||||
struct NvKmsKapiDevice *device,
|
||||
NvU32 semaphoreIndex
|
||||
);
|
||||
|
||||
/*!
|
||||
* Signal the VRR semaphore at the specified index from the CPU.
|
||||
* If device does not support VRR semaphores, this is a no-op.
|
||||
* Returns true if signal is success or no-op, otherwise returns false.
|
||||
*
|
||||
* \param [in] device A device allocated using allocateDevice().
|
||||
*
|
||||
* \param [in] index The VRR semaphore index to be signalled.
|
||||
*/
|
||||
NvBool
|
||||
(*signalVrrSemaphore)
|
||||
(
|
||||
struct NvKmsKapiDevice *device,
|
||||
NvS32 index
|
||||
);
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -33,14 +33,15 @@
|
||||
NVKMS_MAX_LAYERS_PER_HEAD * \
|
||||
NVKMS_KAPI_MAX_NOTIFERS_PER_LAYER)
|
||||
|
||||
void nvKmsKapiFreeNotifiers(struct NvKmsKapiDevice *device)
|
||||
void nvKmsKapiFreeNisoSurface(struct NvKmsKapiDevice *device,
|
||||
struct NvKmsKapiNisoSurface *surface)
|
||||
{
|
||||
if (device->notifier.hKmsHandle != 0) {
|
||||
if (surface->hKmsHandle != 0) {
|
||||
struct NvKmsUnregisterSurfaceParams paramsUnreg = { };
|
||||
NvBool status;
|
||||
|
||||
paramsUnreg.request.deviceHandle = device->hKmsDevice;
|
||||
paramsUnreg.request.surfaceHandle = device->notifier.hKmsHandle;
|
||||
paramsUnreg.request.surfaceHandle = surface->hKmsHandle;
|
||||
|
||||
status = nvkms_ioctl_from_kapi(device->pKmsOpen,
|
||||
NVKMS_IOCTL_UNREGISTER_SURFACE,
|
||||
@@ -55,13 +56,13 @@ void nvKmsKapiFreeNotifiers(struct NvKmsKapiDevice *device)
|
||||
device->notifier.hKmsHandle = 0;
|
||||
}
|
||||
|
||||
if (device->notifier.mapped) {
|
||||
if (surface->mapped) {
|
||||
NV_STATUS status;
|
||||
|
||||
status = nvRmApiUnmapMemory(device->hRmClient,
|
||||
device->hRmSubDevice,
|
||||
device->notifier.hRmHandle,
|
||||
device->notifier.pLinearAddress,
|
||||
surface->hRmHandle,
|
||||
surface->pLinearAddress,
|
||||
0);
|
||||
|
||||
if (status != NV_OK) {
|
||||
@@ -74,12 +75,12 @@ void nvKmsKapiFreeNotifiers(struct NvKmsKapiDevice *device)
|
||||
device->notifier.mapped = NV_FALSE;
|
||||
}
|
||||
|
||||
if (device->notifier.hRmHandle != 0) {
|
||||
if (surface->hRmHandle != 0) {
|
||||
NvU32 status;
|
||||
|
||||
status = nvRmApiFree(device->hRmClient,
|
||||
device->hRmDevice,
|
||||
device->notifier.hRmHandle);
|
||||
surface->hRmHandle);
|
||||
|
||||
if (status != NVOS_STATUS_SUCCESS) {
|
||||
nvKmsKapiLogDeviceDebug(
|
||||
@@ -88,8 +89,8 @@ void nvKmsKapiFreeNotifiers(struct NvKmsKapiDevice *device)
|
||||
status);
|
||||
}
|
||||
|
||||
nvFreeUnixRmHandle(&device->handleAllocator, device->notifier.hRmHandle);
|
||||
device->notifier.hRmHandle = 0;
|
||||
nvFreeUnixRmHandle(&device->handleAllocator, surface->hRmHandle);
|
||||
surface->hRmHandle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,9 +103,9 @@ static void InitNotifier(struct NvKmsKapiDevice *device,
|
||||
device->notifier.pLinearAddress);
|
||||
}
|
||||
|
||||
#define NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE 0x1000
|
||||
|
||||
NvBool nvKmsKapiAllocateNotifiers(struct NvKmsKapiDevice *device,
|
||||
static NvBool AllocateNisoSurface(struct NvKmsKapiDevice *device,
|
||||
struct NvKmsKapiNisoSurface *surface,
|
||||
NvU64 size,
|
||||
NvBool inVideoMemory)
|
||||
{
|
||||
struct NvKmsRegisterSurfaceParams surfParams = {};
|
||||
@@ -112,19 +113,10 @@ NvBool nvKmsKapiAllocateNotifiers(struct NvKmsKapiDevice *device,
|
||||
NvU8 compressible = 0;
|
||||
NvBool ret;
|
||||
|
||||
ct_assert((NVKMS_KAPI_MAX_NOTIFIERS * NVKMS_KAPI_NOTIFIER_SIZE) <=
|
||||
(NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE));
|
||||
|
||||
ct_assert(NVKMS_KAPI_NOTIFIER_SIZE >= sizeof(NvNotification));
|
||||
nvAssert(NVKMS_KAPI_NOTIFIER_SIZE >=
|
||||
nvKmsSizeOfNotifier(device->notifier.format, TRUE /* overlay */));
|
||||
nvAssert(NVKMS_KAPI_NOTIFIER_SIZE >=
|
||||
nvKmsSizeOfNotifier(device->notifier.format, FALSE /* overlay */));
|
||||
|
||||
device->notifier.hRmHandle =
|
||||
surface->hRmHandle =
|
||||
nvGenerateUnixRmHandle(&device->handleAllocator);
|
||||
|
||||
if (device->notifier.hRmHandle == 0x0) {
|
||||
if (surface->hRmHandle == 0x0) {
|
||||
nvKmsKapiLogDeviceDebug(
|
||||
device,
|
||||
"nvGenerateUnixRmHandle() failed");
|
||||
@@ -133,32 +125,32 @@ NvBool nvKmsKapiAllocateNotifiers(struct NvKmsKapiDevice *device,
|
||||
|
||||
if (inVideoMemory) {
|
||||
ret = nvKmsKapiAllocateVideoMemory(device,
|
||||
device->notifier.hRmHandle,
|
||||
surface->hRmHandle,
|
||||
NvKmsSurfaceMemoryLayoutPitch,
|
||||
NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE,
|
||||
size,
|
||||
NVKMS_KAPI_ALLOCATION_TYPE_NOTIFIER,
|
||||
&compressible);
|
||||
} else {
|
||||
ret = nvKmsKapiAllocateSystemMemory(device,
|
||||
device->notifier.hRmHandle,
|
||||
NvKmsSurfaceMemoryLayoutPitch,
|
||||
NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE,
|
||||
surface->hRmHandle,
|
||||
NvKmsSurfaceMemoryLayoutPitch,
|
||||
size,
|
||||
NVKMS_KAPI_ALLOCATION_TYPE_NOTIFIER,
|
||||
&compressible);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
nvFreeUnixRmHandle(&device->handleAllocator, device->notifier.hRmHandle);
|
||||
device->notifier.hRmHandle = 0x0;
|
||||
nvFreeUnixRmHandle(&device->handleAllocator, surface->hRmHandle);
|
||||
surface->hRmHandle = 0x0;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
status = nvRmApiMapMemory(device->hRmClient,
|
||||
device->hRmSubDevice,
|
||||
device->notifier.hRmHandle,
|
||||
surface->hRmHandle,
|
||||
0,
|
||||
NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE,
|
||||
&device->notifier.pLinearAddress,
|
||||
size,
|
||||
&surface->pLinearAddress,
|
||||
0);
|
||||
|
||||
if (status != NV_OK) {
|
||||
@@ -169,23 +161,22 @@ NvBool nvKmsKapiAllocateNotifiers(struct NvKmsKapiDevice *device,
|
||||
goto failed;
|
||||
}
|
||||
|
||||
device->notifier.mapped = NV_TRUE;
|
||||
surface->mapped = NV_TRUE;
|
||||
|
||||
surfParams.request.deviceHandle = device->hKmsDevice;
|
||||
surfParams.request.useFd = FALSE;
|
||||
surfParams.request.rmClient = device->hRmClient;
|
||||
|
||||
surfParams.request.widthInPixels = NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE;
|
||||
surfParams.request.widthInPixels = size;
|
||||
surfParams.request.heightInPixels = 1;
|
||||
surfParams.request.layout = NvKmsSurfaceMemoryLayoutPitch;
|
||||
surfParams.request.format = NvKmsSurfaceMemoryFormatI8;
|
||||
surfParams.request.log2GobsPerBlockY = 0;
|
||||
surfParams.request.isoType = NVKMS_MEMORY_NISO;
|
||||
|
||||
surfParams.request.planes[0].u.rmObject = device->notifier.hRmHandle;
|
||||
surfParams.request.planes[0].pitch = NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE;
|
||||
surfParams.request.planes[0].rmObjectSizeInBytes =
|
||||
NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE;
|
||||
surfParams.request.planes[0].u.rmObject = surface->hRmHandle;
|
||||
surfParams.request.planes[0].pitch = size;
|
||||
surfParams.request.planes[0].rmObjectSizeInBytes = size;
|
||||
|
||||
if (!nvkms_ioctl_from_kapi(device->pKmsOpen,
|
||||
NVKMS_IOCTL_REGISTER_SURFACE,
|
||||
@@ -196,7 +187,37 @@ NvBool nvKmsKapiAllocateNotifiers(struct NvKmsKapiDevice *device,
|
||||
goto failed;
|
||||
}
|
||||
|
||||
device->notifier.hKmsHandle = surfParams.reply.surfaceHandle;
|
||||
surface->hKmsHandle = surfParams.reply.surfaceHandle;
|
||||
|
||||
return NV_TRUE;
|
||||
|
||||
failed:
|
||||
|
||||
nvKmsKapiFreeNisoSurface(device, surface);
|
||||
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
#define NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE 0x1000
|
||||
|
||||
NvBool nvKmsKapiAllocateNotifiers(struct NvKmsKapiDevice *device,
|
||||
NvBool inVideoMemory)
|
||||
{
|
||||
ct_assert((NVKMS_KAPI_MAX_NOTIFIERS * NVKMS_KAPI_NOTIFIER_SIZE) <=
|
||||
NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE);
|
||||
|
||||
ct_assert(NVKMS_KAPI_NOTIFIER_SIZE >= sizeof(NvNotification));
|
||||
nvAssert(NVKMS_KAPI_NOTIFIER_SIZE >=
|
||||
nvKmsSizeOfNotifier(device->notifier.format, TRUE /* overlay */));
|
||||
nvAssert(NVKMS_KAPI_NOTIFIER_SIZE >=
|
||||
nvKmsSizeOfNotifier(device->notifier.format, FALSE /* overlay */));
|
||||
|
||||
if (!AllocateNisoSurface(device,
|
||||
&device->notifier,
|
||||
NVKMS_KAPI_NOTIFIERS_SURFACE_SIZE,
|
||||
inVideoMemory)) {
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
/* Init Notifiers */
|
||||
|
||||
@@ -218,10 +239,117 @@ NvBool nvKmsKapiAllocateNotifiers(struct NvKmsKapiDevice *device,
|
||||
}
|
||||
|
||||
return NV_TRUE;
|
||||
|
||||
failed:
|
||||
|
||||
nvKmsKapiFreeNotifiers(device);
|
||||
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
static void ResetSemaphore(struct NvKmsKapiDevice *device,
|
||||
NvU32 index,
|
||||
NvU32 payload)
|
||||
{
|
||||
nvKmsResetSemaphore(device->semaphore.format,
|
||||
index,
|
||||
device->semaphore.pLinearAddress,
|
||||
payload);
|
||||
}
|
||||
|
||||
#define NVKMS_KAPI_SEMAPHORE_SURFACE_SIZE 0x1000
|
||||
|
||||
NvBool nvKmsKapiAllocateSemaphores(struct NvKmsKapiDevice *device,
|
||||
NvBool inVideoMemory)
|
||||
{
|
||||
NvU32 index;
|
||||
|
||||
if (!AllocateNisoSurface(device,
|
||||
&device->semaphore,
|
||||
NVKMS_KAPI_SEMAPHORE_SURFACE_SIZE,
|
||||
inVideoMemory)) {
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
/* Init Semaphores */
|
||||
|
||||
device->numDisplaySemaphores = NVKMS_KAPI_SEMAPHORE_SURFACE_SIZE /
|
||||
nvKmsSizeOfSemaphore(device->semaphore.format);
|
||||
|
||||
/*
|
||||
* See the comment in nvKmsKapiSignalDisplaySemaphore() for the full
|
||||
* justification of this requirement. The current implementation requires
|
||||
* only 16 semaphores (2 per window) given a maximum of one outstanding
|
||||
* flip, but this value allows up to 32 outstanding flips, as recommended
|
||||
* by the architecture team in an old hardware bug.
|
||||
*/
|
||||
nvAssert(device->numDisplaySemaphores >= 256);
|
||||
|
||||
for (index = 0; index < device->numDisplaySemaphores; index++) {
|
||||
ResetSemaphore(device, index, NVKMS_KAPI_SEMAPHORE_VALUE_DONE);
|
||||
}
|
||||
|
||||
return NV_TRUE;
|
||||
}
|
||||
|
||||
NvBool nvKmsKapiResetDisplaySemaphore(struct NvKmsKapiDevice *device,
|
||||
NvU32 index)
|
||||
{
|
||||
struct nvKmsParsedSemaphore semParsed;
|
||||
|
||||
nvKmsParseSemaphore(device->semaphore.format,
|
||||
index,
|
||||
device->semaphore.pLinearAddress,
|
||||
&semParsed);
|
||||
|
||||
if (semParsed.payload != NVKMS_KAPI_SEMAPHORE_VALUE_DONE) {
|
||||
nvKmsKapiLogDeviceDebug(
|
||||
device,
|
||||
"Attempt to reuse semaphore at index %u with pending status 0x%08x",
|
||||
index,
|
||||
semParsed.payload);
|
||||
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
ResetSemaphore(device, index, NVKMS_KAPI_SEMAPHORE_VALUE_NOT_READY);
|
||||
|
||||
return NV_TRUE;
|
||||
}
|
||||
|
||||
void nvKmsKapiSignalDisplaySemaphore(struct NvKmsKapiDevice *device,
|
||||
NvU32 index)
|
||||
{
|
||||
/*
|
||||
* Note most users of semaphores use a "ready" value that varies from
|
||||
* frame to frame, citing bug 194936. However, this "bug" simply
|
||||
* notes that the hardware may read ahead and grab semaphore values for
|
||||
* pending semaphore acquires such that two pending frames using the
|
||||
* same semaphore might be signaled "ready" by the same semaphore write.
|
||||
* Given this implementation cycles through at least 256 semaphores,
|
||||
* meaning if all 8 hardware windows were programmed in every flip, there
|
||||
* could be at least 32 frames in-flight without re-using a semaphore
|
||||
* slot, and the code above that initializes a semaphore for each frame
|
||||
* first ensures the prior frame using that semaphore has completed,
|
||||
* this approach is not necessary here. There should be no opportunity
|
||||
* for the hardware to "pre-fetch" a prior frame's semaphore acquire
|
||||
* value from the semaphore here, and hence a constant value is sufficient.
|
||||
*/
|
||||
ResetSemaphore(device, index, NVKMS_KAPI_SEMAPHORE_VALUE_READY);
|
||||
}
|
||||
|
||||
void nvKmsKapiCancelDisplaySemaphore(struct NvKmsKapiDevice *device,
|
||||
NvU32 index)
|
||||
{
|
||||
struct nvKmsParsedSemaphore semParsed;
|
||||
|
||||
nvKmsParseSemaphore(device->semaphore.format,
|
||||
index,
|
||||
device->semaphore.pLinearAddress,
|
||||
&semParsed);
|
||||
|
||||
if (semParsed.payload != NVKMS_KAPI_SEMAPHORE_VALUE_DONE) {
|
||||
nvAssert(semParsed.payload == NVKMS_KAPI_SEMAPHORE_VALUE_NOT_READY);
|
||||
ResetSemaphore(device, index, NVKMS_KAPI_SEMAPHORE_VALUE_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
NvU32 nvKmsKapiGetDisplaySemaphoreOffset(struct NvKmsKapiDevice *device,
|
||||
NvU32 index)
|
||||
{
|
||||
return nvKmsSizeOfSemaphore(device->semaphore.format) * index;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "nvidia-modeset-os-interface.h"
|
||||
|
||||
#include "nvkms-api.h"
|
||||
#include "nvkms-sync.h"
|
||||
#include "nvkms-rmapi.h"
|
||||
#include "nvkms-vrr.h"
|
||||
|
||||
@@ -272,9 +273,10 @@ failed:
|
||||
*/
|
||||
static void KmsFreeDevice(struct NvKmsKapiDevice *device)
|
||||
{
|
||||
/* Free notifier memory */
|
||||
/* Free notifier and semaphore memory */
|
||||
|
||||
nvKmsKapiFreeNotifiers(device);
|
||||
nvKmsKapiFreeNisoSurface(device, &device->semaphore);
|
||||
nvKmsKapiFreeNisoSurface(device, &device->notifier);
|
||||
|
||||
/* Free NVKMS device */
|
||||
|
||||
@@ -398,7 +400,7 @@ static NvBool KmsAllocateDevice(struct NvKmsKapiDevice *device)
|
||||
for (layer = 0; layer < NVKMS_KAPI_LAYER_MAX; layer++) {
|
||||
device->supportedSurfaceMemoryFormats[layer] =
|
||||
paramsAlloc->reply.layerCaps[layer].supportedSurfaceMemoryFormats;
|
||||
device->supportsHDR[layer] = paramsAlloc->reply.layerCaps[layer].supportsHDR;
|
||||
device->supportsICtCp[layer] = paramsAlloc->reply.layerCaps[layer].supportsICtCp;
|
||||
}
|
||||
|
||||
if (paramsAlloc->reply.validNIsoFormatMask &
|
||||
@@ -413,6 +415,15 @@ static NvBool KmsAllocateDevice(struct NvKmsKapiDevice *device)
|
||||
device->notifier.format = NVKMS_NISO_FORMAT_LEGACY;
|
||||
}
|
||||
|
||||
if (paramsAlloc->reply.validNIsoFormatMask &
|
||||
(1 << NVKMS_NISO_FORMAT_FOUR_WORD_NVDISPLAY)) {
|
||||
device->semaphore.format = NVKMS_NISO_FORMAT_FOUR_WORD_NVDISPLAY;
|
||||
} else {
|
||||
nvAssert(paramsAlloc->reply.validNIsoFormatMask &
|
||||
(1 << NVKMS_NISO_FORMAT_LEGACY));
|
||||
device->semaphore.format = NVKMS_NISO_FORMAT_LEGACY;
|
||||
}
|
||||
|
||||
/* XXX Add support for SLI/multiple display engines per device */
|
||||
if (paramsAlloc->reply.numDisps != 1)
|
||||
{
|
||||
@@ -442,6 +453,14 @@ static NvBool KmsAllocateDevice(struct NvKmsKapiDevice *device)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Allocate semaphore memory in video memory whenever available */
|
||||
if (!nvKmsKapiAllocateSemaphores(device, !device->isSOC)) {
|
||||
nvKmsKapiLogDebug(
|
||||
"Failed to allocate Semaphore objects for GPU ID 0x%08x",
|
||||
device->gpuId);
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = NV_TRUE;
|
||||
|
||||
done:
|
||||
@@ -1010,6 +1029,7 @@ static NvBool GetDeviceResourcesInfo
|
||||
|
||||
info->caps.hasVideoMemory = !device->isSOC;
|
||||
info->caps.genericPageKind = device->caps.genericPageKind;
|
||||
info->caps.requiresVrrSemaphores = device->caps.requiresVrrSemaphores;
|
||||
|
||||
if (device->hKmsDevice == 0x0) {
|
||||
info->caps.pitchAlignment = 0x1;
|
||||
@@ -1085,6 +1105,8 @@ static NvBool GetDeviceResourcesInfo
|
||||
info->caps.supportedCursorSurfaceMemoryFormats =
|
||||
NVBIT(NvKmsSurfaceMemoryFormatA8R8G8B8);
|
||||
|
||||
info->caps.numDisplaySemaphores = device->numDisplaySemaphores;
|
||||
|
||||
ct_assert(sizeof(info->supportedSurfaceMemoryFormats) ==
|
||||
sizeof(device->supportedSurfaceMemoryFormats));
|
||||
|
||||
@@ -1092,12 +1114,12 @@ static NvBool GetDeviceResourcesInfo
|
||||
device->supportedSurfaceMemoryFormats,
|
||||
sizeof(device->supportedSurfaceMemoryFormats));
|
||||
|
||||
ct_assert(sizeof(info->supportsHDR) ==
|
||||
sizeof(device->supportsHDR));
|
||||
ct_assert(sizeof(info->supportsICtCp) ==
|
||||
sizeof(device->supportsICtCp));
|
||||
|
||||
nvkms_memcpy(info->supportsHDR,
|
||||
device->supportsHDR,
|
||||
sizeof(device->supportsHDR));
|
||||
nvkms_memcpy(info->supportsICtCp,
|
||||
device->supportsICtCp,
|
||||
sizeof(device->supportsICtCp));
|
||||
done:
|
||||
|
||||
return status;
|
||||
@@ -1319,7 +1341,7 @@ static NvBool GetDynamicDisplayInfo(
|
||||
sizeof(params->edid.buffer));
|
||||
|
||||
params->edid.bufferSize = pParamsDpyDynamic->reply.edid.bufferSize;
|
||||
params->vrrSupported = (vrrSupported && !device->caps.requiresVrrSemaphores) ? NV_TRUE : NV_FALSE;
|
||||
params->vrrSupported = vrrSupported;
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -2471,25 +2493,48 @@ static NvBool AssignSyncObjectConfig(
|
||||
struct NvKmsChannelSyncObjects *pSyncObject)
|
||||
{
|
||||
if (!device->supportsSyncpts) {
|
||||
if (pLayerConfig->syncptParams.preSyncptSpecified ||
|
||||
pLayerConfig->syncptParams.postSyncptRequested) {
|
||||
if (pLayerConfig->syncParams.preSyncptSpecified ||
|
||||
pLayerConfig->syncParams.postSyncptRequested) {
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Syncpt and Semaphore usage are mutually exclusive. */
|
||||
if (pLayerConfig->syncParams.semaphoreSpecified &&
|
||||
(pLayerConfig->syncParams.preSyncptSpecified ||
|
||||
pLayerConfig->syncParams.postSyncptRequested)) {
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
pSyncObject->useSyncpt = FALSE;
|
||||
|
||||
if (pLayerConfig->syncptParams.preSyncptSpecified) {
|
||||
if (pLayerConfig->syncParams.preSyncptSpecified) {
|
||||
pSyncObject->useSyncpt = TRUE;
|
||||
|
||||
pSyncObject->u.syncpts.pre.type = NVKMS_SYNCPT_TYPE_RAW;
|
||||
pSyncObject->u.syncpts.pre.u.raw.id = pLayerConfig->syncptParams.preSyncptId;
|
||||
pSyncObject->u.syncpts.pre.u.raw.value = pLayerConfig->syncptParams.preSyncptValue;
|
||||
pSyncObject->u.syncpts.pre.u.raw.id = pLayerConfig->syncParams.u.syncpt.preSyncptId;
|
||||
pSyncObject->u.syncpts.pre.u.raw.value = pLayerConfig->syncParams.u.syncpt.preSyncptValue;
|
||||
} else if (pLayerConfig->syncParams.semaphoreSpecified) {
|
||||
pSyncObject->u.semaphores.release.surface.surfaceHandle =
|
||||
pSyncObject->u.semaphores.acquire.surface.surfaceHandle =
|
||||
device->semaphore.hKmsHandle;
|
||||
pSyncObject->u.semaphores.release.surface.format =
|
||||
pSyncObject->u.semaphores.acquire.surface.format =
|
||||
device->semaphore.format;
|
||||
pSyncObject->u.semaphores.release.surface.offsetInWords =
|
||||
pSyncObject->u.semaphores.acquire.surface.offsetInWords =
|
||||
nvKmsKapiGetDisplaySemaphoreOffset(
|
||||
device,
|
||||
pLayerConfig->syncParams.u.semaphore.index) >> 2;
|
||||
pSyncObject->u.semaphores.acquire.value =
|
||||
NVKMS_KAPI_SEMAPHORE_VALUE_READY;
|
||||
pSyncObject->u.semaphores.release.value =
|
||||
NVKMS_KAPI_SEMAPHORE_VALUE_DONE;
|
||||
}
|
||||
|
||||
if (pLayerConfig->syncptParams.postSyncptRequested) {
|
||||
if (pLayerConfig->syncParams.postSyncptRequested) {
|
||||
pSyncObject->useSyncpt = TRUE;
|
||||
|
||||
pSyncObject->u.syncpts.requestedPostType = NVKMS_SYNCPT_TYPE_FD;
|
||||
}
|
||||
return NV_TRUE;
|
||||
@@ -2581,7 +2626,7 @@ static NvBool NvKmsKapiOverlayLayerConfigToKms(
|
||||
params->layer[layer].colorSpace.specified = TRUE;
|
||||
}
|
||||
|
||||
if (layerRequestedConfig->flags.cscChanged) {
|
||||
if (layerRequestedConfig->flags.cscChanged || bFromKmsSetMode) {
|
||||
params->layer[layer].csc.specified = NV_TRUE;
|
||||
params->layer[layer].csc.useMain = layerConfig->cscUseMain;
|
||||
if (!layerConfig->cscUseMain) {
|
||||
@@ -2709,7 +2754,7 @@ static NvBool NvKmsKapiPrimaryLayerConfigToKms(
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (layerRequestedConfig->flags.cscChanged) {
|
||||
if (layerRequestedConfig->flags.cscChanged || bFromKmsSetMode) {
|
||||
nvAssert(!layerConfig->cscUseMain);
|
||||
|
||||
params->layer[NVKMS_MAIN_LAYER].csc.specified = NV_TRUE;
|
||||
@@ -2795,25 +2840,32 @@ static NvBool NvKmsKapiLayerConfigToKms(
|
||||
}
|
||||
|
||||
static void NvKmsKapiHeadLutConfigToKms(
|
||||
const struct NvKmsKapiHeadModeSetConfig *modeSetConfig,
|
||||
struct NvKmsSetLutCommonParams *lutParams)
|
||||
const struct NvKmsKapiHeadRequestedConfig *headRequestedConfig,
|
||||
struct NvKmsSetLutCommonParams *lutParams,
|
||||
NvBool bFromKmsSetMode)
|
||||
{
|
||||
const struct NvKmsKapiHeadModeSetConfig *modeSetConfig =
|
||||
&headRequestedConfig->modeSetConfig;
|
||||
struct NvKmsSetInputLutParams *input = &lutParams->input;
|
||||
struct NvKmsSetOutputLutParams *output = &lutParams->output;
|
||||
|
||||
/* input LUT */
|
||||
input->specified = modeSetConfig->lut.input.specified;
|
||||
input->depth = modeSetConfig->lut.input.depth;
|
||||
input->start = modeSetConfig->lut.input.start;
|
||||
input->end = modeSetConfig->lut.input.end;
|
||||
if (headRequestedConfig->flags.ilutChanged || bFromKmsSetMode) {
|
||||
input->specified = NV_TRUE;
|
||||
input->depth = modeSetConfig->lut.input.depth;
|
||||
input->start = modeSetConfig->lut.input.start;
|
||||
input->end = modeSetConfig->lut.input.end;
|
||||
|
||||
input->pRamps = nvKmsPointerToNvU64(modeSetConfig->lut.input.pRamps);
|
||||
input->pRamps = nvKmsPointerToNvU64(modeSetConfig->lut.input.pRamps);
|
||||
}
|
||||
|
||||
/* output LUT */
|
||||
output->specified = modeSetConfig->lut.output.specified;
|
||||
output->enabled = modeSetConfig->lut.output.enabled;
|
||||
if (headRequestedConfig->flags.olutChanged || bFromKmsSetMode) {
|
||||
output->specified = NV_TRUE;
|
||||
output->enabled = modeSetConfig->lut.output.enabled;
|
||||
|
||||
output->pRamps = nvKmsPointerToNvU64(modeSetConfig->lut.output.pRamps);
|
||||
output->pRamps = nvKmsPointerToNvU64(modeSetConfig->lut.output.pRamps);
|
||||
}
|
||||
}
|
||||
|
||||
static NvBool AnyLayerTransferFunctionChanged(
|
||||
@@ -2925,9 +2977,9 @@ static NvBool NvKmsKapiRequestedModeSetConfigToKms(
|
||||
|
||||
NvKmsKapiDisplayModeToKapi(&headModeSetConfig->mode, ¶msHead->mode);
|
||||
|
||||
if (headRequestedConfig->flags.lutChanged) {
|
||||
NvKmsKapiHeadLutConfigToKms(headModeSetConfig, ¶msHead->flip.lut);
|
||||
}
|
||||
NvKmsKapiHeadLutConfigToKms(headRequestedConfig,
|
||||
¶msHead->flip.lut,
|
||||
NV_TRUE /* bFromKmsSetMode */);
|
||||
|
||||
NvKmsKapiCursorConfigToKms(&headRequestedConfig->cursorRequestedConfig,
|
||||
¶msHead->flip,
|
||||
@@ -2975,13 +3027,8 @@ static NvBool NvKmsKapiRequestedModeSetConfigToKms(
|
||||
paramsHead->viewPortSizeIn.height =
|
||||
headModeSetConfig->mode.timings.vVisible;
|
||||
|
||||
if (device->caps.requiresVrrSemaphores) {
|
||||
paramsHead->allowGsync = NV_FALSE;
|
||||
paramsHead->allowAdaptiveSync = NVKMS_ALLOW_ADAPTIVE_SYNC_DISABLED;
|
||||
} else {
|
||||
paramsHead->allowGsync = NV_TRUE;
|
||||
paramsHead->allowAdaptiveSync = NVKMS_ALLOW_ADAPTIVE_SYNC_ALL;
|
||||
}
|
||||
paramsHead->allowGsync = NV_TRUE;
|
||||
paramsHead->allowAdaptiveSync = NVKMS_ALLOW_ADAPTIVE_SYNC_ALL;
|
||||
}
|
||||
|
||||
return NV_TRUE;
|
||||
@@ -3189,9 +3236,10 @@ static NvBool KmsFlip(
|
||||
if (headModeSetConfig->vrrEnabled) {
|
||||
params->request.allowVrr = NV_TRUE;
|
||||
}
|
||||
if (headRequestedConfig->flags.lutChanged) {
|
||||
NvKmsKapiHeadLutConfigToKms(headModeSetConfig, &flipParams->lut);
|
||||
}
|
||||
|
||||
NvKmsKapiHeadLutConfigToKms(headRequestedConfig,
|
||||
&flipParams->lut,
|
||||
NV_FALSE /* bFromKmsSetMode */);
|
||||
}
|
||||
|
||||
if (params->request.numFlipHeads == 0) {
|
||||
@@ -3216,6 +3264,9 @@ static NvBool KmsFlip(
|
||||
}
|
||||
|
||||
/*! fill back flip reply */
|
||||
replyConfig->vrrFlip = params->reply.vrrFlipType;
|
||||
replyConfig->vrrSemaphoreIndex = params->reply.vrrSemaphoreIndex;
|
||||
|
||||
for (i = 0; i < params->request.numFlipHeads; i++) {
|
||||
const struct NvKmsKapiHeadRequestedConfig *headRequestedConfig =
|
||||
&requestedConfig->headRequestedConfig[pFlipHead[i].head];
|
||||
@@ -3246,7 +3297,7 @@ static NvBool KmsFlip(
|
||||
|
||||
/*! initialize explicitly to -1 as 0 is valid file descriptor */
|
||||
layerReplyConfig->postSyncptFd = -1;
|
||||
if (layerRequestedConfig->syncptParams.postSyncptRequested) {
|
||||
if (layerRequestedConfig->syncParams.postSyncptRequested) {
|
||||
layerReplyConfig->postSyncptFd =
|
||||
flipParams->layer[layer].postSyncpt.u.fd;
|
||||
}
|
||||
@@ -3457,6 +3508,25 @@ static void nvKmsKapiSetSuspendResumeCallback
|
||||
pSuspendResumeFunc = function;
|
||||
}
|
||||
|
||||
static NvBool SignalVrrSemaphore
|
||||
(
|
||||
struct NvKmsKapiDevice *device,
|
||||
NvS32 index
|
||||
)
|
||||
{
|
||||
NvBool status = NV_TRUE;
|
||||
struct NvKmsVrrSignalSemaphoreParams params = { };
|
||||
params.request.deviceHandle = device->hKmsDevice;
|
||||
params.request.vrrSemaphoreIndex = index;
|
||||
status = nvkms_ioctl_from_kapi(device->pKmsOpen,
|
||||
NVKMS_IOCTL_VRR_SIGNAL_SEMAPHORE,
|
||||
¶ms, sizeof(params));
|
||||
if (!status) {
|
||||
nvKmsKapiLogDeviceDebug(device, "NVKMS VrrSignalSemaphore failed");
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
NvBool nvKmsKapiGetFunctionsTableInternal
|
||||
(
|
||||
struct NvKmsKapiFunctionsTable *funcsTable
|
||||
@@ -3537,5 +3607,10 @@ NvBool nvKmsKapiGetFunctionsTableInternal
|
||||
nvKmsKapiSetSemaphoreSurfaceValue;
|
||||
funcsTable->setSuspendResumeCallback = nvKmsKapiSetSuspendResumeCallback;
|
||||
|
||||
funcsTable->resetDisplaySemaphore = nvKmsKapiResetDisplaySemaphore;
|
||||
funcsTable->signalDisplaySemaphore = nvKmsKapiSignalDisplaySemaphore;
|
||||
funcsTable->cancelDisplaySemaphore = nvKmsKapiCancelDisplaySemaphore;
|
||||
funcsTable->signalVrrSemaphore = SignalVrrSemaphore;
|
||||
|
||||
return NV_TRUE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user