560.28.03

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

View File

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

View File

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

View File

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

View File

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

View File

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