mirror of
https://github.com/NVIDIA/open-gpu-kernel-modules.git
synced 2026-02-06 16:19:58 +00:00
545.23.06
This commit is contained in:
@@ -174,4 +174,41 @@ void
|
||||
nvKmsKapiFreeChannelEvent(struct NvKmsKapiDevice *device,
|
||||
struct NvKmsKapiChannelEvent *cb);
|
||||
|
||||
struct NvKmsKapiSemaphoreSurface*
|
||||
nvKmsKapiImportSemaphoreSurface(struct NvKmsKapiDevice *device,
|
||||
NvU64 nvKmsParamsUser,
|
||||
NvU64 nvKmsParamsSize,
|
||||
void **pSemaphoreMap,
|
||||
void **pMaxSubmittedMap);
|
||||
|
||||
void
|
||||
nvKmsKapiFreeSemaphoreSurface(struct NvKmsKapiDevice *device,
|
||||
struct NvKmsKapiSemaphoreSurface *ss);
|
||||
|
||||
NvKmsKapiRegisterWaiterResult
|
||||
nvKmsKapiRegisterSemaphoreSurfaceCallback(
|
||||
struct NvKmsKapiDevice *device,
|
||||
struct NvKmsKapiSemaphoreSurface *semaphoreSurface,
|
||||
NvKmsSemaphoreSurfaceCallbackProc *pCallback,
|
||||
void *pData,
|
||||
NvU64 index,
|
||||
NvU64 wait_value,
|
||||
NvU64 new_value,
|
||||
struct NvKmsKapiSemaphoreSurfaceCallback **pCallbackHandle);
|
||||
|
||||
NvBool
|
||||
nvKmsKapiUnregisterSemaphoreSurfaceCallback(
|
||||
struct NvKmsKapiDevice *device,
|
||||
struct NvKmsKapiSemaphoreSurface *semaphoreSurface,
|
||||
NvU64 index,
|
||||
NvU64 wait_value,
|
||||
struct NvKmsKapiSemaphoreSurfaceCallback *callbackHandle);
|
||||
|
||||
NvBool
|
||||
nvKmsKapiSetSemaphoreSurfaceValue(
|
||||
struct NvKmsKapiDevice *device,
|
||||
struct NvKmsKapiSemaphoreSurface *semaphoreSurface,
|
||||
NvU64 index,
|
||||
NvU64 new_value);
|
||||
|
||||
#endif /* __NVKMS_KAPI_INTERNAL_H__ */
|
||||
|
||||
@@ -58,4 +58,10 @@ struct NvKmsKapiPrivExportMemoryParams {
|
||||
int memFd;
|
||||
};
|
||||
|
||||
struct NvKmsKapiPrivImportSemaphoreSurfaceParams {
|
||||
NvHandle hClient;
|
||||
NvHandle hSemaphoreSurface;
|
||||
NvU64 semaphoreSurfaceSize;
|
||||
};
|
||||
|
||||
#endif /* !defined(__NVKMS_KAPI_PRIVATE_H__) */
|
||||
|
||||
@@ -49,6 +49,8 @@ struct NvKmsKapiDevice;
|
||||
struct NvKmsKapiMemory;
|
||||
struct NvKmsKapiSurface;
|
||||
struct NvKmsKapiChannelEvent;
|
||||
struct NvKmsKapiSemaphoreSurface;
|
||||
struct NvKmsKapiSemaphoreSurfaceCallback;
|
||||
|
||||
typedef NvU32 NvKmsKapiConnector;
|
||||
typedef NvU32 NvKmsKapiDisplay;
|
||||
@@ -67,6 +69,14 @@ typedef NvU32 NvKmsKapiDisplay;
|
||||
*/
|
||||
typedef void NvKmsChannelEventProc(void *dataPtr, NvU32 dataU32);
|
||||
|
||||
/*
|
||||
* Note: Same as above, this function must not call back into NVKMS-KAPI, nor
|
||||
* directly into RM. Doing so could cause deadlocks given the notification
|
||||
* function will most likely be called from within RM's interrupt handler
|
||||
* callchain.
|
||||
*/
|
||||
typedef void NvKmsSemaphoreSurfaceCallbackProc(void *pData);
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@@ -126,6 +136,11 @@ struct NvKmsKapiDeviceResourcesInfo {
|
||||
NvU32 validCursorCompositionModes;
|
||||
NvU64 supportedCursorSurfaceMemoryFormats;
|
||||
|
||||
struct {
|
||||
NvU64 maxSubmittedOffset;
|
||||
NvU64 stride;
|
||||
} semsurf;
|
||||
|
||||
struct {
|
||||
NvU16 validRRTransforms;
|
||||
NvU32 validCompositionModes;
|
||||
@@ -218,8 +233,10 @@ struct NvKmsKapiLayerConfig {
|
||||
struct NvKmsRRParams rrParams;
|
||||
struct NvKmsKapiSyncpt syncptParams;
|
||||
|
||||
struct NvKmsHDRStaticMetadata hdrMetadata;
|
||||
NvBool hdrMetadataSpecified;
|
||||
struct {
|
||||
struct NvKmsHDRStaticMetadata val;
|
||||
NvBool enabled;
|
||||
} hdrMetadata;
|
||||
|
||||
enum NvKmsOutputTf tf;
|
||||
|
||||
@@ -233,16 +250,21 @@ struct NvKmsKapiLayerConfig {
|
||||
NvU16 dstWidth, dstHeight;
|
||||
|
||||
enum NvKmsInputColorSpace inputColorSpace;
|
||||
struct NvKmsCscMatrix csc;
|
||||
NvBool cscUseMain;
|
||||
};
|
||||
|
||||
struct NvKmsKapiLayerRequestedConfig {
|
||||
struct NvKmsKapiLayerConfig config;
|
||||
struct {
|
||||
NvBool surfaceChanged : 1;
|
||||
NvBool srcXYChanged : 1;
|
||||
NvBool srcWHChanged : 1;
|
||||
NvBool dstXYChanged : 1;
|
||||
NvBool dstWHChanged : 1;
|
||||
NvBool surfaceChanged : 1;
|
||||
NvBool srcXYChanged : 1;
|
||||
NvBool srcWHChanged : 1;
|
||||
NvBool dstXYChanged : 1;
|
||||
NvBool dstWHChanged : 1;
|
||||
NvBool cscChanged : 1;
|
||||
NvBool tfChanged : 1;
|
||||
NvBool hdrMetadataChanged : 1;
|
||||
} flags;
|
||||
};
|
||||
|
||||
@@ -286,14 +308,41 @@ struct NvKmsKapiHeadModeSetConfig {
|
||||
struct NvKmsKapiDisplayMode mode;
|
||||
|
||||
NvBool vrrEnabled;
|
||||
|
||||
struct {
|
||||
NvBool enabled;
|
||||
enum NvKmsInfoFrameEOTF eotf;
|
||||
struct NvKmsHDRStaticMetadata staticMetadata;
|
||||
} hdrInfoFrame;
|
||||
|
||||
enum NvKmsOutputColorimetry colorimetry;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
NvBool specified;
|
||||
NvU32 depth;
|
||||
NvU32 start;
|
||||
NvU32 end;
|
||||
struct NvKmsLutRamps *pRamps;
|
||||
} input;
|
||||
|
||||
struct {
|
||||
NvBool specified;
|
||||
NvBool enabled;
|
||||
struct NvKmsLutRamps *pRamps;
|
||||
} output;
|
||||
} lut;
|
||||
};
|
||||
|
||||
struct NvKmsKapiHeadRequestedConfig {
|
||||
struct NvKmsKapiHeadModeSetConfig modeSetConfig;
|
||||
struct {
|
||||
NvBool activeChanged : 1;
|
||||
NvBool displaysChanged : 1;
|
||||
NvBool modeChanged : 1;
|
||||
NvBool activeChanged : 1;
|
||||
NvBool displaysChanged : 1;
|
||||
NvBool modeChanged : 1;
|
||||
NvBool hdrInfoFrameChanged : 1;
|
||||
NvBool colorimetryChanged : 1;
|
||||
NvBool lutChanged : 1;
|
||||
} flags;
|
||||
|
||||
struct NvKmsKapiCursorRequestedConfig cursorRequestedConfig;
|
||||
@@ -318,6 +367,7 @@ struct NvKmsKapiHeadReplyConfig {
|
||||
};
|
||||
|
||||
struct NvKmsKapiModeSetReplyConfig {
|
||||
enum NvKmsFlipResult flipResult;
|
||||
struct NvKmsKapiHeadReplyConfig
|
||||
headReplyConfig[NVKMS_KAPI_MAX_HEADS];
|
||||
};
|
||||
@@ -434,6 +484,12 @@ enum NvKmsKapiAllocationType {
|
||||
NVKMS_KAPI_ALLOCATION_TYPE_OFFSCREEN = 2,
|
||||
};
|
||||
|
||||
typedef enum NvKmsKapiRegisterWaiterResultRec {
|
||||
NVKMS_KAPI_REG_WAITER_FAILED,
|
||||
NVKMS_KAPI_REG_WAITER_SUCCESS,
|
||||
NVKMS_KAPI_REG_WAITER_ALREADY_SIGNALLED,
|
||||
} NvKmsKapiRegisterWaiterResult;
|
||||
|
||||
struct NvKmsKapiFunctionsTable {
|
||||
|
||||
/*!
|
||||
@@ -519,8 +575,8 @@ struct NvKmsKapiFunctionsTable {
|
||||
);
|
||||
|
||||
/*!
|
||||
* Revoke permissions previously granted. Only one (dispIndex, head,
|
||||
* display) is currently supported.
|
||||
* Revoke modeset permissions previously granted. Only one (dispIndex,
|
||||
* head, display) is currently supported.
|
||||
*
|
||||
* \param [in] device A device returned by allocateDevice().
|
||||
*
|
||||
@@ -537,6 +593,34 @@ struct NvKmsKapiFunctionsTable {
|
||||
NvKmsKapiDisplay display
|
||||
);
|
||||
|
||||
/*!
|
||||
* Grant modeset sub-owner permissions to fd. This is used by clients to
|
||||
* convert drm 'master' permissions into nvkms sub-owner permission.
|
||||
*
|
||||
* \param [in] fd fd from opening /dev/nvidia-modeset.
|
||||
*
|
||||
* \param [in] device A device returned by allocateDevice().
|
||||
*
|
||||
* \return NV_TRUE on success, NV_FALSE on failure.
|
||||
*/
|
||||
NvBool (*grantSubOwnership)
|
||||
(
|
||||
NvS32 fd,
|
||||
struct NvKmsKapiDevice *device
|
||||
);
|
||||
|
||||
/*!
|
||||
* Revoke sub-owner permissions previously granted.
|
||||
*
|
||||
* \param [in] device A device returned by allocateDevice().
|
||||
*
|
||||
* \return NV_TRUE on success, NV_FALSE on failure.
|
||||
*/
|
||||
NvBool (*revokeSubOwnership)
|
||||
(
|
||||
struct NvKmsKapiDevice *device
|
||||
);
|
||||
|
||||
/*!
|
||||
* Registers for notification, via
|
||||
* NvKmsKapiAllocateDeviceParams::eventCallback, of the events specified
|
||||
@@ -1122,6 +1206,199 @@ struct NvKmsKapiFunctionsTable {
|
||||
NvP64 dmaBuf,
|
||||
NvU32 limit);
|
||||
|
||||
/*!
|
||||
* Import a semaphore surface allocated elsewhere to NVKMS and return a
|
||||
* handle to the new object.
|
||||
*
|
||||
* \param [in] device A device allocated using allocateDevice().
|
||||
*
|
||||
* \param [in] nvKmsParamsUser Userspace pointer to driver-specific
|
||||
* parameters describing the semaphore
|
||||
* surface being imported.
|
||||
*
|
||||
* \param [in] nvKmsParamsSize Size of the driver-specific parameter
|
||||
* struct.
|
||||
*
|
||||
* \param [out] pSemaphoreMap Returns a CPU mapping of the semaphore
|
||||
* surface's semaphore memory to the client.
|
||||
*
|
||||
* \param [out] pMaxSubmittedMap Returns a CPU mapping of the semaphore
|
||||
* surface's semaphore memory to the client.
|
||||
*
|
||||
* \return struct NvKmsKapiSemaphoreSurface* on success, NULL on failure.
|
||||
*/
|
||||
struct NvKmsKapiSemaphoreSurface* (*importSemaphoreSurface)
|
||||
(
|
||||
struct NvKmsKapiDevice *device,
|
||||
NvU64 nvKmsParamsUser,
|
||||
NvU64 nvKmsParamsSize,
|
||||
void **pSemaphoreMap,
|
||||
void **pMaxSubmittedMap
|
||||
);
|
||||
|
||||
/*!
|
||||
* Free an imported semaphore surface.
|
||||
*
|
||||
* \param [in] device The device passed to
|
||||
* importSemaphoreSurface() when creating
|
||||
* semaphoreSurface.
|
||||
*
|
||||
* \param [in] semaphoreSurface A semaphore surface returned by
|
||||
* importSemaphoreSurface().
|
||||
*/
|
||||
void (*freeSemaphoreSurface)
|
||||
(
|
||||
struct NvKmsKapiDevice *device,
|
||||
struct NvKmsKapiSemaphoreSurface *semaphoreSurface
|
||||
);
|
||||
|
||||
/*!
|
||||
* Register a callback to be called when a semaphore reaches a value.
|
||||
*
|
||||
* The callback will be called when the semaphore at index in
|
||||
* semaphoreSurface reaches the value wait_value. The callback will
|
||||
* be called at most once and is automatically unregistered when called.
|
||||
* It may also be unregistered (i.e., cancelled) explicitly using the
|
||||
* unregisterSemaphoreSurfaceCallback() function. To avoid leaking the
|
||||
* memory used to track the registered callback, callers must ensure one
|
||||
* of these methods of unregistration is used for every successful
|
||||
* callback registration that returns a non-NULL pCallbackHandle.
|
||||
*
|
||||
* \param [in] device The device passed to
|
||||
* importSemaphoreSurface() when creating
|
||||
* semaphoreSurface.
|
||||
*
|
||||
* \param [in] semaphoreSurface A semaphore surface returned by
|
||||
* importSemaphoreSurface().
|
||||
*
|
||||
* \param [in] pCallback A pointer to the function to call when
|
||||
* the specified value is reached. NULL
|
||||
* means no callback.
|
||||
*
|
||||
* \param [in] pData Arbitrary data to be passed back to the
|
||||
* callback as its sole parameter.
|
||||
*
|
||||
* \param [in] index The index of the semaphore within
|
||||
* semaphoreSurface.
|
||||
*
|
||||
* \param [in] wait_value The value the semaphore must reach or
|
||||
* exceed before the callback is called.
|
||||
*
|
||||
* \param [in] new_value The value the semaphore will be set to
|
||||
* when it reaches or exceeds <wait_value>.
|
||||
* 0 means do not update the value.
|
||||
*
|
||||
* \param [out] pCallbackHandle On success, the value pointed to will
|
||||
* contain an opaque handle to the
|
||||
* registered callback that may be used to
|
||||
* cancel it if needed. Unused if pCallback
|
||||
* is NULL.
|
||||
*
|
||||
* \return NVKMS_KAPI_REG_WAITER_SUCCESS if the waiter was registered or if
|
||||
* no callback was requested and the semaphore at <index> has
|
||||
* already reached or exceeded <wait_value>
|
||||
*
|
||||
* NVKMS_KAPI_REG_WAITER_ALREADY_SIGNALLED if a callback was
|
||||
* requested and the semaphore at <index> has already reached or
|
||||
* exceeded <wait_value>
|
||||
*
|
||||
* NVKMS_KAPI_REG_WAITER_FAILED if waiter registration failed.
|
||||
*/
|
||||
NvKmsKapiRegisterWaiterResult
|
||||
(*registerSemaphoreSurfaceCallback)
|
||||
(
|
||||
struct NvKmsKapiDevice *device,
|
||||
struct NvKmsKapiSemaphoreSurface *semaphoreSurface,
|
||||
NvKmsSemaphoreSurfaceCallbackProc *pCallback,
|
||||
void *pData,
|
||||
NvU64 index,
|
||||
NvU64 wait_value,
|
||||
NvU64 new_value,
|
||||
struct NvKmsKapiSemaphoreSurfaceCallback **pCallbackHandle
|
||||
);
|
||||
|
||||
/*!
|
||||
* Unregister a callback registered via registerSemaphoreSurfaceCallback()
|
||||
*
|
||||
* If the callback has not yet been called, this function will cancel the
|
||||
* callback and free its associated resources.
|
||||
*
|
||||
* Note this function treats the callback handle as a pointer. While this
|
||||
* function does not dereference that pointer itself, the underlying call
|
||||
* to RM does within a properly guarded critical section that first ensures
|
||||
* it is not in the process of being used within a callback. This means
|
||||
* the callstack must take into consideration that pointers are not in
|
||||
* general unique handles if they may have been freed, since a subsequent
|
||||
* malloc could return the same pointer value at that point. This callchain
|
||||
* avoids that by leveraging the behavior of the underlying RM APIs:
|
||||
*
|
||||
* 1) A callback handle is referenced relative to its corresponding
|
||||
* (semaphore surface, index, wait_value) tuple here and within RM. It
|
||||
* is not a valid handle outside of that scope.
|
||||
*
|
||||
* 2) A callback can not be registered against an already-reached value
|
||||
* for a given semaphore surface index.
|
||||
*
|
||||
* 3) A given callback handle can not be registered twice against the same
|
||||
* (semaphore surface, index, wait_value) tuple, so unregistration will
|
||||
* never race with registration at the RM level, and would only race at
|
||||
* a higher level if used incorrectly. Since this is kernel code, we
|
||||
* can safely assume there won't be malicious clients purposely misuing
|
||||
* the API, but the burden is placed on the caller to ensure its usage
|
||||
* does not lead to races at higher levels.
|
||||
*
|
||||
* These factors considered together ensure any valid registered handle is
|
||||
* either still in the relevant waiter list and refers to the same event/
|
||||
* callback as when it was registered, or has been removed from the list
|
||||
* as part of a critical section that also destroys the list itself and
|
||||
* makes future lookups in that list impossible, and hence eliminates the
|
||||
* chance of comparing a stale handle with a new handle of the same value
|
||||
* as part of a lookup.
|
||||
*
|
||||
* \param [in] device The device passed to
|
||||
* importSemaphoreSurface() when creating
|
||||
* semaphoreSurface.
|
||||
*
|
||||
* \param [in] semaphoreSurface The semaphore surface passed to
|
||||
* registerSemaphoreSurfaceCallback() when
|
||||
* registering the callback.
|
||||
*
|
||||
* \param [in] index The index passed to
|
||||
* registerSemaphoreSurfaceCallback() when
|
||||
* registering the callback.
|
||||
*
|
||||
* \param [in] wait_value The wait_value passed to
|
||||
* registerSemaphoreSurfaceCallback() when
|
||||
* registering the callback.
|
||||
*
|
||||
* \param [in] callbackHandle The callback handle returned by
|
||||
* registerSemaphoreSurfaceCallback().
|
||||
*/
|
||||
NvBool
|
||||
(*unregisterSemaphoreSurfaceCallback)
|
||||
(
|
||||
struct NvKmsKapiDevice *device,
|
||||
struct NvKmsKapiSemaphoreSurface *semaphoreSurface,
|
||||
NvU64 index,
|
||||
NvU64 wait_value,
|
||||
struct NvKmsKapiSemaphoreSurfaceCallback *callbackHandle
|
||||
);
|
||||
|
||||
/*!
|
||||
* Update the value of a semaphore surface from the CPU.
|
||||
*
|
||||
* Update the semaphore value at the specified index from the CPU, then
|
||||
* wake up any pending CPU waiters associated with that index that are
|
||||
* waiting on it reaching a value <= the new value.
|
||||
*/
|
||||
NvBool
|
||||
(*setSemaphoreSurfaceValue)
|
||||
(
|
||||
struct NvKmsKapiDevice *device,
|
||||
struct NvKmsKapiSemaphoreSurface *semaphoreSurface,
|
||||
NvU64 index,
|
||||
NvU64 new_value
|
||||
);
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -29,7 +29,9 @@
|
||||
#include "nvkms-kapi-private.h"
|
||||
#include "nvkms-kapi-internal.h"
|
||||
|
||||
#include "class/cl0000.h"
|
||||
#include "class/cl0005.h"
|
||||
#include "ctrl/ctrl00da.h"
|
||||
|
||||
struct NvKmsKapiChannelEvent {
|
||||
struct NvKmsKapiDevice *device;
|
||||
@@ -168,3 +170,402 @@ fail:
|
||||
nvKmsKapiFreeChannelEvent(device, cb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct NvKmsKapiSemaphoreSurface {
|
||||
NvHandle hSemaphoreSurface;
|
||||
|
||||
NvHandle hSemaphoreMem;
|
||||
NvHandle hMaxSubmittedMem;
|
||||
};
|
||||
|
||||
struct NvKmsKapiSemaphoreSurface*
|
||||
nvKmsKapiImportSemaphoreSurface
|
||||
(
|
||||
struct NvKmsKapiDevice *device,
|
||||
NvU64 nvKmsParamsUser,
|
||||
NvU64 nvKmsParamsSize,
|
||||
void **pSemaphoreMap,
|
||||
void **pMaxSubmittedMap
|
||||
)
|
||||
{
|
||||
struct NvKmsKapiSemaphoreSurface *ss = NULL;
|
||||
struct NvKmsKapiPrivImportSemaphoreSurfaceParams p, *pHeap;
|
||||
NV_SEMAPHORE_SURFACE_CTRL_REF_MEMORY_PARAMS refParams = {};
|
||||
NvU32 ret;
|
||||
int status;
|
||||
|
||||
/* Verify the driver-private params size and copy it in from userspace */
|
||||
|
||||
if (nvKmsParamsSize != sizeof(p)) {
|
||||
nvKmsKapiLogDebug(
|
||||
"NVKMS semaphore surface import parameter size mismatch - expected: 0x%llx, caller specified: 0x%llx",
|
||||
(NvU64)sizeof(p), nvKmsParamsSize);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use a heap allocation as the destination pointer passed to
|
||||
* nvkms_copyin; stack allocations created within core NVKMS may not
|
||||
* be recognizable to the Linux kernel's CONFIG_HARDENED_USERCOPY
|
||||
* checker, triggering false errors. But then save the result to a
|
||||
* variable on the stack, so that we can free the heap memory
|
||||
* immediately and not worry about its lifetime.
|
||||
*/
|
||||
|
||||
pHeap = nvKmsKapiCalloc(1, sizeof(*pHeap));
|
||||
if (pHeap == NULL) {
|
||||
nvKmsKapiLogDebug(
|
||||
"NVKMS failed to allocate semaphore surface parameter struct of size: %ld",
|
||||
(long)sizeof(*pHeap));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
status = nvkms_copyin(pHeap, nvKmsParamsUser, sizeof(*pHeap));
|
||||
|
||||
p = *pHeap;
|
||||
nvKmsKapiFree(pHeap);
|
||||
|
||||
if (status != 0) {
|
||||
nvKmsKapiLogDebug(
|
||||
"NVKMS semaphore surface import parameters could not be read from userspace");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ss = nvKmsKapiCalloc(1, sizeof(*ss));
|
||||
if (ss == NULL) {
|
||||
nvKmsKapiLogDeviceDebug(
|
||||
device,
|
||||
"Failed to allocate memory for NVKMS semaphore surface while importing (0x%08x, 0x%08x)",
|
||||
p.hClient, p.hSemaphoreSurface);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = nvRmApiDupObject2(device->hRmClient,
|
||||
device->hRmSubDevice,
|
||||
&ss->hSemaphoreSurface,
|
||||
p.hClient,
|
||||
p.hSemaphoreSurface,
|
||||
0);
|
||||
|
||||
if (ret != NVOS_STATUS_SUCCESS) {
|
||||
nvKmsKapiLogDeviceDebug(
|
||||
device,
|
||||
"Failed to dup RM semaphore surface object (0x%08x, 0x%08x)",
|
||||
p.hClient, p.hSemaphoreSurface);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = nvRmApiControl(device->hRmClient,
|
||||
ss->hSemaphoreSurface,
|
||||
NV_SEMAPHORE_SURFACE_CTRL_CMD_REF_MEMORY,
|
||||
&refParams,
|
||||
sizeof(refParams));
|
||||
|
||||
if (ret != NVOS_STATUS_SUCCESS) {
|
||||
nvKmsKapiLogDeviceDebug(
|
||||
device,
|
||||
"Failed to ref RM semaphore surface memory objects (0x%08x, 0x%08x)",
|
||||
p.hClient, p.hSemaphoreSurface);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ss->hSemaphoreMem = refParams.hSemaphoreMem;
|
||||
ss->hMaxSubmittedMem = refParams.hMaxSubmittedMem;
|
||||
|
||||
ret = nvRmApiMapMemory(device->hRmClient,
|
||||
device->hRmDevice,
|
||||
ss->hSemaphoreMem,
|
||||
0,
|
||||
p.semaphoreSurfaceSize,
|
||||
pSemaphoreMap,
|
||||
0);
|
||||
|
||||
if (ret != NVOS_STATUS_SUCCESS) {
|
||||
nvKmsKapiLogDeviceDebug(
|
||||
device,
|
||||
"Failed to map RM semaphore surface semaphore memory (0x%08x, 0x%08x)",
|
||||
p.hClient, p.hSemaphoreSurface);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ss->hMaxSubmittedMem != NV01_NULL_OBJECT) {
|
||||
if (ss->hMaxSubmittedMem != ss->hSemaphoreMem) {
|
||||
ret = nvRmApiMapMemory(device->hRmClient,
|
||||
device->hRmDevice,
|
||||
ss->hMaxSubmittedMem,
|
||||
0,
|
||||
p.semaphoreSurfaceSize,
|
||||
pMaxSubmittedMap,
|
||||
0);
|
||||
if (ret != NVOS_STATUS_SUCCESS) {
|
||||
nvKmsKapiLogDeviceDebug(
|
||||
device,
|
||||
"Failed to map RM semaphore surface max submitted memory (0x%08x, 0x%08x)",
|
||||
p.hClient, p.hSemaphoreSurface);
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
*pMaxSubmittedMap = *pSemaphoreMap;
|
||||
}
|
||||
} else {
|
||||
*pMaxSubmittedMap = NULL;
|
||||
}
|
||||
|
||||
return ss;
|
||||
|
||||
fail:
|
||||
if (ss && ss->hSemaphoreSurface) {
|
||||
if ((ss->hMaxSubmittedMem != NV01_NULL_OBJECT) &&
|
||||
(ss->hMaxSubmittedMem != ss->hSemaphoreMem)) {
|
||||
nvRmApiFree(device->hRmClient,
|
||||
device->hRmDevice,
|
||||
ss->hMaxSubmittedMem);
|
||||
}
|
||||
|
||||
if (ss->hSemaphoreMem != NV01_NULL_OBJECT) {
|
||||
nvRmApiFree(device->hRmClient,
|
||||
device->hRmDevice,
|
||||
ss->hSemaphoreMem);
|
||||
}
|
||||
|
||||
nvRmApiFree(device->hRmClient,
|
||||
device->hRmDevice,
|
||||
ss->hSemaphoreSurface);
|
||||
}
|
||||
nvKmsKapiFree(ss);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void nvKmsKapiFreeSemaphoreSurface
|
||||
(
|
||||
struct NvKmsKapiDevice *device,
|
||||
struct NvKmsKapiSemaphoreSurface *ss
|
||||
)
|
||||
{
|
||||
if (device == NULL || ss == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ss->hMaxSubmittedMem != NV01_NULL_OBJECT) &&
|
||||
(ss->hMaxSubmittedMem != ss->hSemaphoreMem)) {
|
||||
nvRmApiFree(device->hRmClient,
|
||||
device->hRmDevice,
|
||||
ss->hMaxSubmittedMem);
|
||||
}
|
||||
|
||||
nvRmApiFree(device->hRmClient,
|
||||
device->hRmDevice,
|
||||
ss->hSemaphoreMem);
|
||||
|
||||
nvRmApiFree(device->hRmClient,
|
||||
device->hRmSubDevice,
|
||||
ss->hSemaphoreSurface);
|
||||
|
||||
nvKmsKapiFree(ss);
|
||||
}
|
||||
|
||||
struct NvKmsKapiSemaphoreSurfaceCallback {
|
||||
NvKmsSemaphoreSurfaceCallbackProc *pCallback;
|
||||
void *pData;
|
||||
|
||||
NVOS10_EVENT_KERNEL_CALLBACK_EX rmCallback;
|
||||
};
|
||||
|
||||
static void SemaphoreSurfaceKapiCallback(void *arg1, void *arg2, NvHandle hEvent,
|
||||
NvU32 data, NvU32 status)
|
||||
{
|
||||
struct NvKmsKapiSemaphoreSurfaceCallback *cb = arg1;
|
||||
cb->pCallback(cb->pData);
|
||||
nvKmsKapiFree(cb);
|
||||
}
|
||||
|
||||
NvKmsKapiRegisterWaiterResult
|
||||
nvKmsKapiRegisterSemaphoreSurfaceCallback(
|
||||
struct NvKmsKapiDevice *device,
|
||||
struct NvKmsKapiSemaphoreSurface *semaphoreSurface,
|
||||
NvKmsSemaphoreSurfaceCallbackProc *pCallback,
|
||||
void *pData,
|
||||
NvU64 index,
|
||||
NvU64 wait_value,
|
||||
NvU64 new_value,
|
||||
struct NvKmsKapiSemaphoreSurfaceCallback **pCallbackHandle)
|
||||
{
|
||||
NvU32 ret;
|
||||
|
||||
struct NvKmsKapiSemaphoreSurfaceCallback *cb = NULL;
|
||||
NV_SEMAPHORE_SURFACE_CTRL_REGISTER_WAITER_PARAMS waiterParams = { };
|
||||
|
||||
if (device == NULL) {
|
||||
nvKmsKapiLogDebug(
|
||||
"Invalid device while registering semaphore surface callback");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((semaphoreSurface == NULL) ||
|
||||
((pCallback == NULL) && (new_value == 0))) {
|
||||
nvKmsKapiLogDeviceDebug(
|
||||
device,
|
||||
"Invalid parameter while registering semaphore surface callback");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
waiterParams.index = index;
|
||||
waiterParams.waitValue = wait_value;
|
||||
waiterParams.newValue = new_value;
|
||||
|
||||
if (pCallback) {
|
||||
cb = nvKmsKapiCalloc(1, sizeof(*cb));
|
||||
if (cb == NULL) {
|
||||
nvKmsKapiLogDeviceDebug(
|
||||
device,
|
||||
"Failed to allocate memory for semaphore surface (0x%08x, 0x%08x) callback on index %" NvU64_fmtu " for value %" NvU64_fmtx,
|
||||
device->hRmClient, semaphoreSurface->hSemaphoreSurface,
|
||||
index, wait_value);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
cb->pCallback = pCallback;
|
||||
cb->pData = pData;
|
||||
cb->rmCallback.func = SemaphoreSurfaceKapiCallback;
|
||||
cb->rmCallback.arg = cb;
|
||||
|
||||
waiterParams.notificationHandle = (NvUPtr)&cb->rmCallback;
|
||||
}
|
||||
|
||||
ret = nvRmApiControl(device->hRmClient,
|
||||
semaphoreSurface->hSemaphoreSurface,
|
||||
NV_SEMAPHORE_SURFACE_CTRL_CMD_REGISTER_WAITER,
|
||||
&waiterParams,
|
||||
sizeof(waiterParams));
|
||||
|
||||
switch (ret) {
|
||||
case NVOS_STATUS_SUCCESS:
|
||||
if (pCallback) {
|
||||
*pCallbackHandle = cb;
|
||||
}
|
||||
return NVKMS_KAPI_REG_WAITER_SUCCESS;
|
||||
case NVOS_STATUS_ERROR_ALREADY_SIGNALLED:
|
||||
return NVKMS_KAPI_REG_WAITER_ALREADY_SIGNALLED;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fail:
|
||||
nvKmsKapiFree(cb);
|
||||
return NVKMS_KAPI_REG_WAITER_FAILED;
|
||||
}
|
||||
|
||||
NvBool
|
||||
nvKmsKapiUnregisterSemaphoreSurfaceCallback(
|
||||
struct NvKmsKapiDevice *device,
|
||||
struct NvKmsKapiSemaphoreSurface *semaphoreSurface,
|
||||
NvU64 index,
|
||||
NvU64 wait_value,
|
||||
struct NvKmsKapiSemaphoreSurfaceCallback *callbackHandle)
|
||||
{
|
||||
NV_SEMAPHORE_SURFACE_CTRL_UNREGISTER_WAITER_PARAMS waiterParams = { };
|
||||
NvU32 ret;
|
||||
|
||||
|
||||
if (device == NULL) {
|
||||
nvKmsKapiLogDebug(
|
||||
"Invalid device while unregistering semaphore surface callback");
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
if ((semaphoreSurface == NULL) || (callbackHandle == NULL) ||
|
||||
(wait_value == 0)) {
|
||||
nvKmsKapiLogDeviceDebug(
|
||||
device,
|
||||
"Invalid parameter while unregistering semaphore surface callback");
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note this function does not actually dereference callbackHandle before
|
||||
* making the RM control call. This is important, as there may exist a race
|
||||
* such that the client is calling this function while another thread is
|
||||
* running the callback and freeing its handle.
|
||||
*
|
||||
* The existance of this race seems to imply there is an additional hazard
|
||||
* where a new callback may be registered against the same wait value during
|
||||
* the first race, which this call would then mistakenly delete. That is
|
||||
* impossible because the RM semaphore surface code would detect that such a
|
||||
* waiter is already signaled and return without adding it to the waiter
|
||||
* list.
|
||||
*/
|
||||
waiterParams.index = index;
|
||||
waiterParams.waitValue = wait_value;
|
||||
|
||||
/*
|
||||
* Manually perform the equivalent of &callbackHandle->rmCallback, but with
|
||||
* semantics that make it clearer there is no access of the memory pointed
|
||||
* to by callbackHandle.
|
||||
*/
|
||||
waiterParams.notificationHandle = (NvUPtr)callbackHandle +
|
||||
offsetof(struct NvKmsKapiSemaphoreSurfaceCallback, rmCallback);
|
||||
|
||||
ret = nvRmApiControl(device->hRmClient,
|
||||
semaphoreSurface->hSemaphoreSurface,
|
||||
NV_SEMAPHORE_SURFACE_CTRL_CMD_UNREGISTER_WAITER,
|
||||
&waiterParams,
|
||||
sizeof(waiterParams));
|
||||
|
||||
switch (ret) {
|
||||
case NVOS_STATUS_SUCCESS:
|
||||
/*
|
||||
* The callback was successfully unregistered, and will never run. Free
|
||||
* its associated data.
|
||||
*/
|
||||
nvKmsKapiFree(callbackHandle);
|
||||
return NV_TRUE;
|
||||
|
||||
default:
|
||||
/*
|
||||
* This code must assume failure to unregister for any reason indicates
|
||||
* the callback is being run right now, or is on a list of pending
|
||||
* callbacks which will be run in finite time. Do not free its data.
|
||||
*/
|
||||
return NV_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
NvBool
|
||||
nvKmsKapiSetSemaphoreSurfaceValue(
|
||||
struct NvKmsKapiDevice *device,
|
||||
struct NvKmsKapiSemaphoreSurface *semaphoreSurface,
|
||||
NvU64 index,
|
||||
NvU64 new_value)
|
||||
{
|
||||
NvU32 ret;
|
||||
|
||||
NV_SEMAPHORE_SURFACE_CTRL_SET_VALUE_PARAMS setParams = { };
|
||||
|
||||
if (device == NULL) {
|
||||
nvKmsKapiLogDebug(
|
||||
"Invalid device used to set semaphore surface value");
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
if (semaphoreSurface == NULL) {
|
||||
nvKmsKapiLogDeviceDebug(
|
||||
device,
|
||||
"Attempt to set value on Invalid semaphore surface");
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
setParams.index = index;
|
||||
setParams.newValue = new_value;
|
||||
|
||||
ret = nvRmApiControl(device->hRmClient,
|
||||
semaphoreSurface->hSemaphoreSurface,
|
||||
NV_SEMAPHORE_SURFACE_CTRL_CMD_SET_VALUE,
|
||||
&setParams,
|
||||
sizeof(setParams));
|
||||
|
||||
if (ret != NVOS_STATUS_SUCCESS) {
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
return NV_TRUE;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <ctrl/ctrl0000/ctrl0000client.h> /* NV0000_CTRL_CMD_CLIENT_GET_ADDR_SPACE_TYPE_VIDMEM */
|
||||
#include <ctrl/ctrl0080/ctrl0080gpu.h> /* NV0080_CTRL_CMD_GPU_GET_NUM_SUBDEVICES */
|
||||
#include <ctrl/ctrl0080/ctrl0080fb.h> /* NV0080_CTRL_CMD_FB_GET_CAPS_V2 */
|
||||
#include <ctrl/ctrl2080/ctrl2080fb.h> /* NV2080_CTRL_CMD_FB_GET_SEMAPHORE_SURFACE_LAYOUT */
|
||||
#include <ctrl/ctrl2080/ctrl2080unix.h> /* NV2080_CTRL_CMD_OS_UNIX_GC6_BLOCKER_REFCNT */
|
||||
|
||||
#include "ctrl/ctrl003e.h" /* NV003E_CTRL_CMD_GET_SURFACE_PHYS_PAGES */
|
||||
@@ -914,6 +915,51 @@ static NvBool RevokePermissions
|
||||
sizeof(paramsRevoke));
|
||||
}
|
||||
|
||||
static NvBool GrantSubOwnership
|
||||
(
|
||||
NvS32 fd,
|
||||
struct NvKmsKapiDevice *device
|
||||
)
|
||||
{
|
||||
struct NvKmsGrantPermissionsParams paramsGrant = { };
|
||||
struct NvKmsPermissions *perm = ¶msGrant.request.permissions;
|
||||
|
||||
if (device->hKmsDevice == 0x0) {
|
||||
return NV_TRUE;
|
||||
}
|
||||
|
||||
perm->type = NV_KMS_PERMISSIONS_TYPE_SUB_OWNER;
|
||||
|
||||
paramsGrant.request.fd = fd;
|
||||
paramsGrant.request.deviceHandle = device->hKmsDevice;
|
||||
|
||||
return nvkms_ioctl_from_kapi(device->pKmsOpen,
|
||||
NVKMS_IOCTL_GRANT_PERMISSIONS, ¶msGrant,
|
||||
sizeof(paramsGrant));
|
||||
}
|
||||
|
||||
static NvBool RevokeSubOwnership
|
||||
(
|
||||
struct NvKmsKapiDevice *device
|
||||
)
|
||||
{
|
||||
struct NvKmsRevokePermissionsParams paramsRevoke = { };
|
||||
|
||||
if (device->hKmsDevice == 0x0) {
|
||||
return NV_TRUE;
|
||||
}
|
||||
|
||||
paramsRevoke.request.permissionsTypeBitmask =
|
||||
NVBIT(NV_KMS_PERMISSIONS_TYPE_FLIPPING) |
|
||||
NVBIT(NV_KMS_PERMISSIONS_TYPE_MODESET) |
|
||||
NVBIT(NV_KMS_PERMISSIONS_TYPE_SUB_OWNER);
|
||||
paramsRevoke.request.deviceHandle = device->hKmsDevice;
|
||||
|
||||
return nvkms_ioctl_from_kapi(device->pKmsOpen,
|
||||
NVKMS_IOCTL_REVOKE_PERMISSIONS, ¶msRevoke,
|
||||
sizeof(paramsRevoke));
|
||||
}
|
||||
|
||||
static NvBool DeclareEventInterest
|
||||
(
|
||||
const struct NvKmsKapiDevice *device,
|
||||
@@ -941,12 +987,30 @@ static NvBool GetDeviceResourcesInfo
|
||||
)
|
||||
{
|
||||
struct NvKmsQueryDispParams paramsDisp = { };
|
||||
NV2080_CTRL_FB_GET_SEMAPHORE_SURFACE_LAYOUT_PARAMS semsurfLayoutParams = { };
|
||||
NvBool status = NV_FALSE;
|
||||
NvU32 ret;
|
||||
|
||||
NvU32 i;
|
||||
|
||||
nvkms_memset(info, 0, sizeof(*info));
|
||||
|
||||
ret = nvRmApiControl(device->hRmClient,
|
||||
device->hRmSubDevice,
|
||||
NV2080_CTRL_CMD_FB_GET_SEMAPHORE_SURFACE_LAYOUT,
|
||||
&semsurfLayoutParams,
|
||||
sizeof(semsurfLayoutParams));
|
||||
|
||||
if (ret == NVOS_STATUS_SUCCESS) {
|
||||
info->caps.semsurf.stride = semsurfLayoutParams.size;
|
||||
info->caps.semsurf.maxSubmittedOffset =
|
||||
semsurfLayoutParams.maxSubmittedSemaphoreValueOffset;
|
||||
} else {
|
||||
/* Non-fatal. No semaphore surface support. */
|
||||
info->caps.semsurf.stride = 0;
|
||||
info->caps.semsurf.maxSubmittedOffset = 0;
|
||||
}
|
||||
|
||||
info->caps.hasVideoMemory = !device->isSOC;
|
||||
info->caps.genericPageKind = device->caps.genericPageKind;
|
||||
|
||||
@@ -2436,16 +2500,18 @@ static NvBool AssignSyncObjectConfig(
|
||||
|
||||
static void AssignHDRMetadataConfig(
|
||||
const struct NvKmsKapiLayerConfig *layerConfig,
|
||||
const struct NvKmsKapiLayerRequestedConfig *layerRequestedConfig,
|
||||
const NvU32 layer,
|
||||
struct NvKmsFlipCommonParams *params)
|
||||
struct NvKmsFlipCommonParams *params,
|
||||
NvBool bFromKmsSetMode)
|
||||
{
|
||||
if (layerConfig->hdrMetadataSpecified) {
|
||||
params->layer[layer].hdr.enabled = TRUE;
|
||||
params->layer[layer].hdr.specified = TRUE;
|
||||
params->layer[layer].hdr.staticMetadata = layerConfig->hdrMetadata;
|
||||
} else {
|
||||
params->layer[layer].hdr.enabled = FALSE;
|
||||
params->layer[layer].hdr.specified = TRUE;
|
||||
params->layer[layer].hdr.specified =
|
||||
bFromKmsSetMode || layerRequestedConfig->flags.hdrMetadataChanged;
|
||||
params->layer[layer].hdr.enabled =
|
||||
layerConfig->hdrMetadata.enabled;
|
||||
if (layerConfig->hdrMetadata.enabled) {
|
||||
params->layer[layer].hdr.staticMetadata =
|
||||
layerConfig->hdrMetadata.val;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2513,15 +2579,30 @@ static NvBool NvKmsKapiOverlayLayerConfigToKms(
|
||||
params->layer[layer].compositionParams.specified = TRUE;
|
||||
params->layer[layer].minPresentInterval =
|
||||
layerConfig->minPresentInterval;
|
||||
|
||||
params->layer[layer].colorSpace.val = layerConfig->inputColorSpace;
|
||||
params->layer[layer].colorSpace.specified = TRUE;
|
||||
}
|
||||
|
||||
params->layer[layer].sizeIn.val.width = layerConfig->srcWidth;
|
||||
params->layer[layer].sizeIn.val.height = layerConfig->srcHeight;
|
||||
params->layer[layer].sizeIn.specified = TRUE;
|
||||
if (layerRequestedConfig->flags.cscChanged) {
|
||||
params->layer[layer].csc.specified = NV_TRUE;
|
||||
params->layer[layer].csc.useMain = layerConfig->cscUseMain;
|
||||
if (!layerConfig->cscUseMain) {
|
||||
params->layer[layer].csc.matrix = layerConfig->csc;
|
||||
}
|
||||
}
|
||||
|
||||
params->layer[layer].sizeOut.val.width = layerConfig->dstWidth;
|
||||
params->layer[layer].sizeOut.val.height = layerConfig->dstHeight;
|
||||
params->layer[layer].sizeOut.specified = TRUE;
|
||||
if (layerRequestedConfig->flags.srcWHChanged || bFromKmsSetMode) {
|
||||
params->layer[layer].sizeIn.val.width = layerConfig->srcWidth;
|
||||
params->layer[layer].sizeIn.val.height = layerConfig->srcHeight;
|
||||
params->layer[layer].sizeIn.specified = TRUE;
|
||||
}
|
||||
|
||||
if (layerRequestedConfig->flags.dstWHChanged || bFromKmsSetMode) {
|
||||
params->layer[layer].sizeOut.val.width = layerConfig->dstWidth;
|
||||
params->layer[layer].sizeOut.val.height = layerConfig->dstHeight;
|
||||
params->layer[layer].sizeOut.specified = TRUE;
|
||||
}
|
||||
|
||||
if (layerRequestedConfig->flags.dstXYChanged || bFromKmsSetMode) {
|
||||
params->layer[layer].outputPosition.val.x = layerConfig->dstX;
|
||||
@@ -2530,10 +2611,8 @@ static NvBool NvKmsKapiOverlayLayerConfigToKms(
|
||||
params->layer[layer].outputPosition.specified = NV_TRUE;
|
||||
}
|
||||
|
||||
params->layer[layer].colorspace.val = layerConfig->inputColorSpace;
|
||||
params->layer[layer].colorspace.specified = TRUE;
|
||||
|
||||
AssignHDRMetadataConfig(layerConfig, layer, params);
|
||||
AssignHDRMetadataConfig(layerConfig, layerRequestedConfig, layer,
|
||||
params, bFromKmsSetMode);
|
||||
|
||||
if (commit) {
|
||||
NvU32 nextIndex = NVKMS_KAPI_INC_NOTIFIER_INDEX(
|
||||
@@ -2619,6 +2698,9 @@ static NvBool NvKmsKapiPrimaryLayerConfigToKms(
|
||||
}
|
||||
}
|
||||
|
||||
params->layer[NVKMS_MAIN_LAYER].colorSpace.val = layerConfig->inputColorSpace;
|
||||
params->layer[NVKMS_MAIN_LAYER].colorSpace.specified = TRUE;
|
||||
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
@@ -2630,10 +2712,18 @@ static NvBool NvKmsKapiPrimaryLayerConfigToKms(
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
params->layer[NVKMS_MAIN_LAYER].colorspace.val = layerConfig->inputColorSpace;
|
||||
params->layer[NVKMS_MAIN_LAYER].colorspace.specified = TRUE;
|
||||
if (layerRequestedConfig->flags.cscChanged) {
|
||||
nvAssert(!layerConfig->cscUseMain);
|
||||
|
||||
AssignHDRMetadataConfig(layerConfig, NVKMS_MAIN_LAYER, params);
|
||||
params->layer[NVKMS_MAIN_LAYER].csc.specified = NV_TRUE;
|
||||
params->layer[NVKMS_MAIN_LAYER].csc.useMain = FALSE;
|
||||
params->layer[NVKMS_MAIN_LAYER].csc.matrix = layerConfig->csc;
|
||||
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
AssignHDRMetadataConfig(layerConfig, layerRequestedConfig, NVKMS_MAIN_LAYER,
|
||||
params, bFromKmsSetMode);
|
||||
|
||||
if (commit && changed) {
|
||||
NvU32 nextIndex = NVKMS_KAPI_INC_NOTIFIER_INDEX(
|
||||
@@ -2707,6 +2797,47 @@ static NvBool NvKmsKapiLayerConfigToKms(
|
||||
bFromKmsSetMode);
|
||||
}
|
||||
|
||||
static void NvKmsKapiHeadLutConfigToKms(
|
||||
const struct NvKmsKapiHeadModeSetConfig *modeSetConfig,
|
||||
struct NvKmsSetLutCommonParams *lutParams)
|
||||
{
|
||||
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;
|
||||
|
||||
input->pRamps = nvKmsPointerToNvU64(modeSetConfig->lut.input.pRamps);
|
||||
|
||||
/* output LUT */
|
||||
output->specified = modeSetConfig->lut.output.specified;
|
||||
output->enabled = modeSetConfig->lut.output.enabled;
|
||||
|
||||
output->pRamps = nvKmsPointerToNvU64(modeSetConfig->lut.output.pRamps);
|
||||
}
|
||||
|
||||
static NvBool AnyLayerTransferFunctionChanged(
|
||||
const struct NvKmsKapiHeadRequestedConfig *headRequestedConfig)
|
||||
{
|
||||
NvU32 layer;
|
||||
|
||||
for (layer = 0;
|
||||
layer < ARRAY_LEN(headRequestedConfig->layerRequestedConfig);
|
||||
layer++) {
|
||||
const struct NvKmsKapiLayerRequestedConfig *layerRequestedConfig =
|
||||
&headRequestedConfig->layerRequestedConfig[layer];
|
||||
|
||||
if (layerRequestedConfig->flags.tfChanged) {
|
||||
return NV_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
static NvBool GetOutputTransferFunction(
|
||||
const struct NvKmsKapiHeadRequestedConfig *headRequestedConfig,
|
||||
enum NvKmsOutputTf *tf)
|
||||
@@ -2724,7 +2855,7 @@ static NvBool GetOutputTransferFunction(
|
||||
const struct NvKmsKapiLayerConfig *layerConfig =
|
||||
&layerRequestedConfig->config;
|
||||
|
||||
if (layerConfig->hdrMetadataSpecified) {
|
||||
if (layerConfig->hdrMetadata.enabled) {
|
||||
if (!found) {
|
||||
*tf = layerConfig->tf;
|
||||
found = NV_TRUE;
|
||||
@@ -2797,6 +2928,10 @@ static NvBool NvKmsKapiRequestedModeSetConfigToKms(
|
||||
|
||||
NvKmsKapiDisplayModeToKapi(&headModeSetConfig->mode, ¶msHead->mode);
|
||||
|
||||
if (headRequestedConfig->flags.lutChanged) {
|
||||
NvKmsKapiHeadLutConfigToKms(headModeSetConfig, ¶msHead->flip.lut);
|
||||
}
|
||||
|
||||
NvKmsKapiCursorConfigToKms(&headRequestedConfig->cursorRequestedConfig,
|
||||
¶msHead->flip,
|
||||
NV_TRUE /* bFromKmsSetMode */);
|
||||
@@ -2825,6 +2960,19 @@ static NvBool NvKmsKapiRequestedModeSetConfigToKms(
|
||||
paramsHead->flip.tf.val = tf;
|
||||
paramsHead->flip.tf.specified = NV_TRUE;
|
||||
|
||||
paramsHead->flip.hdrInfoFrame.specified = NV_TRUE;
|
||||
paramsHead->flip.hdrInfoFrame.enabled =
|
||||
headModeSetConfig->hdrInfoFrame.enabled;
|
||||
if (headModeSetConfig->hdrInfoFrame.enabled) {
|
||||
paramsHead->flip.hdrInfoFrame.eotf =
|
||||
headModeSetConfig->hdrInfoFrame.eotf;
|
||||
paramsHead->flip.hdrInfoFrame.staticMetadata =
|
||||
headModeSetConfig->hdrInfoFrame.staticMetadata;
|
||||
}
|
||||
|
||||
paramsHead->flip.colorimetry.specified = NV_TRUE;
|
||||
paramsHead->flip.colorimetry.val = headModeSetConfig->colorimetry;
|
||||
|
||||
paramsHead->viewPortSizeIn.width =
|
||||
headModeSetConfig->mode.timings.hVisible;
|
||||
paramsHead->viewPortSizeIn.height =
|
||||
@@ -2846,6 +2994,7 @@ static NvBool NvKmsKapiRequestedModeSetConfigToKms(
|
||||
static NvBool KmsSetMode(
|
||||
struct NvKmsKapiDevice *device,
|
||||
const struct NvKmsKapiRequestedModeSetConfig *requestedConfig,
|
||||
struct NvKmsKapiModeSetReplyConfig *replyConfig,
|
||||
const NvBool commit)
|
||||
{
|
||||
struct NvKmsSetModeParams *params = NULL;
|
||||
@@ -2868,6 +3017,11 @@ static NvBool KmsSetMode(
|
||||
NVKMS_IOCTL_SET_MODE,
|
||||
params, sizeof(*params));
|
||||
|
||||
replyConfig->flipResult =
|
||||
(params->reply.status == NVKMS_SET_MODE_STATUS_SUCCESS) ?
|
||||
NV_KMS_FLIP_RESULT_SUCCESS :
|
||||
NV_KMS_FLIP_RESULT_INVALID_PARAMS;
|
||||
|
||||
if (!status) {
|
||||
nvKmsKapiLogDeviceDebug(
|
||||
device,
|
||||
@@ -2966,7 +3120,6 @@ static NvBool KmsFlip(
|
||||
&requestedConfig->headRequestedConfig[head];
|
||||
const struct NvKmsKapiHeadModeSetConfig *headModeSetConfig =
|
||||
&headRequestedConfig->modeSetConfig;
|
||||
enum NvKmsOutputTf tf;
|
||||
|
||||
struct NvKmsFlipCommonParams *flipParams = NULL;
|
||||
|
||||
@@ -3006,17 +3159,42 @@ static NvBool KmsFlip(
|
||||
}
|
||||
}
|
||||
|
||||
status = GetOutputTransferFunction(headRequestedConfig, &tf);
|
||||
if (status != NV_TRUE) {
|
||||
goto done;
|
||||
flipParams->tf.specified =
|
||||
AnyLayerTransferFunctionChanged(headRequestedConfig);
|
||||
if (flipParams->tf.specified) {
|
||||
enum NvKmsOutputTf tf;
|
||||
status = GetOutputTransferFunction(headRequestedConfig, &tf);
|
||||
if (status != NV_TRUE) {
|
||||
goto done;
|
||||
}
|
||||
flipParams->tf.val = tf;
|
||||
}
|
||||
|
||||
flipParams->tf.val = tf;
|
||||
flipParams->tf.specified = NV_TRUE;
|
||||
flipParams->hdrInfoFrame.specified =
|
||||
headRequestedConfig->flags.hdrInfoFrameChanged;
|
||||
if (flipParams->hdrInfoFrame.specified) {
|
||||
flipParams->hdrInfoFrame.enabled =
|
||||
headModeSetConfig->hdrInfoFrame.enabled;
|
||||
if (headModeSetConfig->hdrInfoFrame.enabled) {
|
||||
flipParams->hdrInfoFrame.eotf =
|
||||
headModeSetConfig->hdrInfoFrame.eotf;
|
||||
flipParams->hdrInfoFrame.staticMetadata =
|
||||
headModeSetConfig->hdrInfoFrame.staticMetadata;
|
||||
}
|
||||
}
|
||||
|
||||
flipParams->colorimetry.specified =
|
||||
headRequestedConfig->flags.colorimetryChanged;
|
||||
if (flipParams->colorimetry.specified) {
|
||||
flipParams->colorimetry.val = headModeSetConfig->colorimetry;
|
||||
}
|
||||
|
||||
if (headModeSetConfig->vrrEnabled) {
|
||||
params->request.allowVrr = NV_TRUE;
|
||||
}
|
||||
if (headRequestedConfig->flags.lutChanged) {
|
||||
NvKmsKapiHeadLutConfigToKms(headModeSetConfig, &flipParams->lut);
|
||||
}
|
||||
}
|
||||
|
||||
if (params->request.numFlipHeads == 0) {
|
||||
@@ -3027,6 +3205,8 @@ static NvBool KmsFlip(
|
||||
NVKMS_IOCTL_FLIP,
|
||||
params, sizeof(*params));
|
||||
|
||||
replyConfig->flipResult = params->reply.flipResult;
|
||||
|
||||
if (!status) {
|
||||
nvKmsKapiLogDeviceDebug(
|
||||
device,
|
||||
@@ -3129,12 +3309,16 @@ static NvBool ApplyModeSetConfig(
|
||||
}
|
||||
|
||||
if (bRequiredModeset) {
|
||||
return KmsSetMode(device, requestedConfig, commit);
|
||||
return KmsSetMode(device, requestedConfig, replyConfig, commit);
|
||||
}
|
||||
|
||||
return KmsFlip(device, requestedConfig, replyConfig, commit);
|
||||
}
|
||||
|
||||
/*
|
||||
* This executes without the nvkms_lock held. The lock will be grabbed
|
||||
* during the kapi dispatching contained in this function.
|
||||
*/
|
||||
void nvKmsKapiHandleEventQueueChange
|
||||
(
|
||||
struct NvKmsKapiDevice *device
|
||||
@@ -3279,6 +3463,8 @@ NvBool nvKmsKapiGetFunctionsTableInternal
|
||||
|
||||
funcsTable->grantPermissions = GrantPermissions;
|
||||
funcsTable->revokePermissions = RevokePermissions;
|
||||
funcsTable->grantSubOwnership = GrantSubOwnership;
|
||||
funcsTable->revokeSubOwnership = RevokeSubOwnership;
|
||||
|
||||
funcsTable->declareEventInterest = DeclareEventInterest;
|
||||
|
||||
@@ -3320,5 +3506,14 @@ NvBool nvKmsKapiGetFunctionsTableInternal
|
||||
|
||||
funcsTable->isMemoryValidForDisplay = IsMemoryValidForDisplay;
|
||||
|
||||
funcsTable->importSemaphoreSurface = nvKmsKapiImportSemaphoreSurface;
|
||||
funcsTable->freeSemaphoreSurface = nvKmsKapiFreeSemaphoreSurface;
|
||||
funcsTable->registerSemaphoreSurfaceCallback =
|
||||
nvKmsKapiRegisterSemaphoreSurfaceCallback;
|
||||
funcsTable->unregisterSemaphoreSurfaceCallback =
|
||||
nvKmsKapiUnregisterSemaphoreSurfaceCallback;
|
||||
funcsTable->setSemaphoreSurfaceValue =
|
||||
nvKmsKapiSetSemaphoreSurfaceValue;
|
||||
|
||||
return NV_TRUE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user