520.61.05

This commit is contained in:
Andy Ritger
2022-10-10 14:59:24 -07:00
parent fe0728787f
commit 90eb10774f
758 changed files with 88383 additions and 26493 deletions

View File

@@ -38,3 +38,4 @@ void nvEvoStateStartNoLock(NVEvoSubDevPtr);
#endif
#endif /* __EVO_STATE_H__ */

View File

@@ -44,9 +44,6 @@ void nvUpdateInfoFrames(const NVDispEvoRec *pDispEvo, const NvU32 head);
NvBool nvDpyRequiresDualLinkEvo(const NVDpyEvoRec *pDpyEvo,
const NVHwModeTimingsEvo *pTimings);
NVHwModeTimingsEvoPtr
nvGetCurrentModeTimingsForDpyEvo(const NVDpyEvoRec *pDpyEvo);
NVDpyEvoPtr nvGetDpyEvoFromDispEvo(const NVDispEvoRec *pDispEvo, NVDpyId dpyId);
NVDpyEvoPtr nvGetDPMSTDpyEvo(NVConnectorEvoPtr pConnectorEvo,

View File

@@ -222,6 +222,8 @@ void nvChooseCurrentColorSpaceAndRangeEvo(
void nvUpdateCurrentHardwareColorSpaceAndRangeEvo(
NVDispEvoPtr pDispEvo,
const NvU32 head,
const enum NvKmsDpyAttributeCurrentColorSpaceValue colorSpace,
const enum NvKmsDpyAttributeColorRangeValue colorRange,
NVEvoUpdateState *pUpdateState);
void nvSetColorSpaceAndRangeEvo(

View File

@@ -35,8 +35,7 @@ typedef struct {
NvU32 activeRmId;
struct NvKmsSetLutCommonParams lut;
NvU8 allowFlipLockGroup;
enum NvKmsDpyAttributeCurrentColorSpaceValue colorSpace;
enum NvKmsDpyAttributeColorRangeValue colorRange;
NVAttributesSetEvoRec attributes;
struct NvKmsModeValidationParams modeValidationParams;
NvBool changed : 1;
NvBool allowGsync : 1;

View File

@@ -43,6 +43,14 @@ typedef NvBool (*NVShutDownHeadsTestFunc)(
void nvShutDownHeads(NVDevEvoPtr pDevEvo, NVShutDownHeadsTestFunc pTestFunc);
NVVBlankCallbackPtr nvRegisterVBlankCallback(NVDispEvoPtr pDispEvo,
NvU32 head,
NVVBlankCallbackProc pCallback,
void *pUserData);
void nvUnregisterVBlankCallback(NVDispEvoPtr pDispEvo,
NvU32 head,
NVVBlankCallbackPtr pCallback);
#ifdef __cplusplus
};
#endif

View File

@@ -134,6 +134,7 @@ typedef struct _NVVblankSyncObjectRec *NVVblankSyncObjectPtr;
typedef struct _NVDispHeadStateEvoRec *NVDispHeadStateEvoPtr;
typedef struct _NVDispEvoRec *NVDispEvoPtr;
typedef struct _NVParsedEdidEvoRec *NVParsedEdidEvoPtr;
typedef struct _NVVBlankCallbackRec *NVVBlankCallbackPtr;
typedef struct _NVDpyEvoRec *NVDpyEvoPtr;
typedef struct _NVLutSurfaceEvo *NVLutSurfaceEvoPtr;
typedef struct _NVFrameLockEvo *NVFrameLockEvoPtr;
@@ -841,7 +842,6 @@ typedef struct _NVEvoDevRec {
NvU32 deviceHandle;
struct NvKmsPerOpenDev *pNvKmsOpenDev;
/* SLI Info */
struct {
NvBool mosaic;
@@ -1141,6 +1141,13 @@ typedef struct _NVHwModeViewPortEvo {
struct NvKmsUsageBounds guaranteedUsage;
} NVHwModeViewPortEvo;
static inline NvBool nvIsImageSharpeningAvailable(
const NVHwModeViewPortEvo *pViewPort)
{
return (pViewPort->out.width != pViewPort->in.width) ||
(pViewPort->out.height != pViewPort->in.height);
}
enum nvKmsPixelDepth {
NVKMS_PIXEL_DEPTH_18_444,
NVKMS_PIXEL_DEPTH_24_444,
@@ -1324,6 +1331,22 @@ static inline struct NvKmsRect nvEvoViewPortOutClientView(
return viewPortOut;
}
/*
* The ELD contains a subset of the digital display device's EDID
* information related to audio capabilities. The GPU driver sends the
* ELD to hardware and the audio driver reads it by issuing the ELD
* command verb.
*/
#define NV_MAX_AUDIO_DEVICE_ENTRIES \
(NV0073_CTRL_DFP_ELD_AUDIO_CAPS_DEVICE_ENTRY_3 + 1)
typedef enum {
NV_ELD_PRE_MODESET = 0,
NV_ELD_POST_MODESET,
NV_ELD_POWER_ON_RESET,
} NvEldCase;
/* OR indices are per OR-type. The maximum OR index for each type
* on each GPU is:
*
@@ -1390,6 +1413,8 @@ typedef struct _NVConnectorEvoRec {
NvBool ycbcr422Capable;
NvBool ycbcr444Capable;
} colorSpaceCaps;
NvEldCase audioDevEldCase[NV_MAX_AUDIO_DEVICE_ENTRIES];
} NVConnectorEvoRec;
static inline NvU32 nvConnectorGetAttachedHeadMaskEvo(
@@ -1513,9 +1538,6 @@ typedef struct _NVDispHeadStateEvoRec {
NVAttributesSetEvoRec attributes;
NVEvoScalerTaps hTaps;
NVEvoScalerTaps vTaps;
/*! Cached, to preserve across modesets. */
struct NvKmsModeValidationParams modeValidationParams;
@@ -1567,6 +1589,9 @@ typedef struct _NVDispHeadStateEvoRec {
NvU8 numVblankSyncObjectsCreated;
NVVblankSyncObjectRec vblankSyncObjects[NVKMS_MAX_VBLANK_SYNC_OBJECTS_PER_HEAD];
NVDispHeadAudioStateEvoRec audio;
NvU32 rmVBlankCallbackHandle;
NVListRec vblankCallbackList;
} NVDispHeadStateEvoRec;
typedef struct _NVDispEvoRec {
@@ -1662,6 +1687,15 @@ typedef struct _NVDispEvoRec {
struct nvkms_backlight_device *backlightDevice;
} NVDispEvoRec;
/*
* XXX[2Head1OR] Remove nvHardwareHeadToApiHead(), before implementing logic to
* map multiple hardware heads onto the single api head.
*/
static inline NvU32 nvHardwareHeadToApiHead(const NvU32 head)
{
return head;
}
typedef enum {
NV_EVO_PASSIVE_DP_DONGLE_UNUSED,
NV_EVO_PASSIVE_DP_DONGLE_DP2DVI,
@@ -1682,14 +1716,23 @@ typedef struct _NVParsedEdidEvoRec {
char serialNumberString[NVT_EDID_LDD_PAYLOAD_SIZE+1];
} NVParsedEdidEvoRec;
typedef void (*NVVBlankCallbackProc)(NVDispEvoRec *pDispEvo,
const NvU32 head,
NVVBlankCallbackPtr pCallbackData);
typedef struct _NVVBlankCallbackRec {
NVListRec vblankCallbackListEntry;
NVVBlankCallbackProc pCallback;
void *pUserData;
} NVVBlankCallbackRec;
typedef struct _NVDpyEvoRec {
NVListRec dpyListEntry;
NVDpyId id;
char name[NVKMS_DPY_NAME_SIZE];
/* The hardware head to use with this dpy. */
NvU32 head;
NvU32 apiHead;
struct _NVDispEvoRec *pDispEvo;
NVConnectorEvoPtr pConnectorEvo;
@@ -1907,7 +1950,7 @@ static inline NvBool nvDpyUsesDPLib(const NVDpyEvoRec *pDpyEvo)
*/
static inline NvBool nvDpyEvoIsActive(const NVDpyEvoRec *pDpyEvo)
{
return (pDpyEvo->head != NV_INVALID_HEAD);
return (pDpyEvo->apiHead != NV_INVALID_HEAD);
}
/*
@@ -2252,6 +2295,14 @@ struct _NVSurfaceEvoRec {
NvBool procFsFlag;
#endif
/*
* Disallow DIFR if display caching is forbidden. This will be set for
* CPU accessible surfaces.
*/
NvBool noDisplayCaching;
/* Keep track of prefetched surfaces. */
NvU32 difrLastPrefetchPass;
};
typedef struct _NVDeferredRequestFifoRec {

View File

@@ -2430,6 +2430,15 @@ struct NvKmsRegisterSurfaceRequest {
NvBool noDisplayHardwareAccess;
/*
* This flag should be set if the surface can potentially be updated
* directly on the screen after the flip. For example, this is the case
* if the surface is CPU mapped, accessible by more than one GPU, or in
* a similar situation. If this flag is set NVKMS knows not to consider
* the surface content cacheable between flips.
*/
NvBool noDisplayCaching;
/*
* If isoType == NVKMS_MEMORY_NISO, NVKMS will create CPU and GPU mappings
* for the surface memory.

View File

@@ -118,12 +118,6 @@ struct NvKmsKapiSurface {
NvKmsSurfaceHandle hKmsHandle;
};
enum NvKmsKapiAllocationType {
NVKMS_KAPI_ALLOCATION_TYPE_SCANOUT = 0,
NVKMS_KAPI_ALLOCATION_TYPE_NOTIFIER = 1,
};
static inline void *nvKmsKapiCalloc(size_t nmem, size_t size)
{
return nvInternalAlloc(nmem * size, NV_TRUE);

View File

@@ -416,6 +416,12 @@ struct NvKmsKapiCreateSurfaceParams {
NvU8 log2GobsPerBlockY;
};
enum NvKmsKapiAllocationType {
NVKMS_KAPI_ALLOCATION_TYPE_SCANOUT = 0,
NVKMS_KAPI_ALLOCATION_TYPE_NOTIFIER = 1,
NVKMS_KAPI_ALLOCATION_TYPE_OFFSCREEN = 2,
};
struct NvKmsKapiFunctionsTable {
/*!
@@ -609,6 +615,8 @@ struct NvKmsKapiFunctionsTable {
* \param [in] device A device allocated using allocateDevice().
*
* \param [in] layout BlockLinear or Pitch.
*
* \param [in] type Allocation type.
*
* \param [in] size Size, in bytes, of the memory to allocate.
*
@@ -624,6 +632,7 @@ struct NvKmsKapiFunctionsTable {
(
struct NvKmsKapiDevice *device,
enum NvKmsSurfaceMemoryLayout layout,
enum NvKmsKapiAllocationType type,
NvU64 size,
NvU8 *compressible
);
@@ -637,6 +646,8 @@ struct NvKmsKapiFunctionsTable {
* \param [in] device A device allocated using allocateDevice().
*
* \param [in] layout BlockLinear or Pitch.
*
* \param [in] type Allocation type.
*
* \param [in] size Size, in bytes, of the memory to allocate.
*
@@ -652,6 +663,7 @@ struct NvKmsKapiFunctionsTable {
(
struct NvKmsKapiDevice *device,
enum NvKmsSurfaceMemoryLayout layout,
enum NvKmsKapiAllocationType type,
NvU64 size,
NvU8 *compressible
);

View File

@@ -452,7 +452,7 @@ NvBool nvKmsKapiAllocateSystemMemory(struct NvKmsKapiDevice *device,
{
NvU32 ret;
NV_MEMORY_ALLOCATION_PARAMS memAllocParams = { };
const NvKmsDispIOCoherencyModes *pIOCoherencyModes;
const NvKmsDispIOCoherencyModes *pIOCoherencyModes = NULL;
memAllocParams.owner = NVKMS_RM_HEAP_ID;
memAllocParams.size = size;
@@ -521,6 +521,9 @@ NvBool nvKmsKapiAllocateSystemMemory(struct NvKmsKapiDevice *device,
pIOCoherencyModes = &device->nisoIOCoherencyModes;
break;
case NVKMS_KAPI_ALLOCATION_TYPE_OFFSCREEN:
memAllocParams.flags |= NVOS32_ALLOC_FLAGS_NO_SCANOUT;
break;
default:
nvKmsKapiLogDeviceDebug(device, "Unknown Allocation Type");
@@ -532,7 +535,7 @@ NvBool nvKmsKapiAllocateSystemMemory(struct NvKmsKapiDevice *device,
memAllocParams.attr2 = FLD_SET_DRF(OS32, _ATTR2, _GPU_CACHEABLE, _NO,
memAllocParams.attr2);
if (!pIOCoherencyModes->coherent) {
if (pIOCoherencyModes == NULL || !pIOCoherencyModes->coherent) {
memAllocParams.attr = FLD_SET_DRF(OS32, _ATTR, _COHERENCY,
_WRITE_COMBINE, memAllocParams.attr);
} else {
@@ -673,6 +676,15 @@ NvBool nvKmsKapiAllocateVideoMemory(struct NvKmsKapiDevice *device,
memAllocParams.attr);
break;
case NVKMS_KAPI_ALLOCATION_TYPE_OFFSCREEN:
memAllocParams.type = NVOS32_TYPE_IMAGE;
memAllocParams.flags |=
NVOS32_ALLOC_FLAGS_NO_SCANOUT |
NVOS32_ALLOC_FLAGS_FORCE_MEM_GROWS_UP;
memAllocParams.attr =
FLD_SET_DRF(OS32, _ATTR, _PHYSICALITY, _NONCONTIGUOUS,
memAllocParams.attr);
break;
default:
nvKmsKapiLogDeviceDebug(device, "Unknown Allocation Type");
return NV_FALSE;
@@ -1219,6 +1231,7 @@ static struct NvKmsKapiMemory* AllocateVideoMemory
(
struct NvKmsKapiDevice *device,
enum NvKmsSurfaceMemoryLayout layout,
enum NvKmsKapiAllocationType type,
NvU64 size,
NvU8 *compressible
)
@@ -1236,7 +1249,7 @@ static struct NvKmsKapiMemory* AllocateVideoMemory
hRmHandle,
layout,
size,
NVKMS_KAPI_ALLOCATION_TYPE_SCANOUT,
type,
compressible)) {
nvKmsKapiFreeRmHandle(device, hRmHandle);
FreeMemory(device, memory);
@@ -1258,6 +1271,7 @@ static struct NvKmsKapiMemory* AllocateSystemMemory
(
struct NvKmsKapiDevice *device,
enum NvKmsSurfaceMemoryLayout layout,
enum NvKmsKapiAllocationType type,
NvU64 size,
NvU8 *compressible
)
@@ -1275,7 +1289,7 @@ static struct NvKmsKapiMemory* AllocateSystemMemory
hRmHandle,
layout,
size,
NVKMS_KAPI_ALLOCATION_TYPE_SCANOUT,
type,
compressible)) {
nvKmsKapiFreeRmHandle(device, hRmHandle);
FreeMemory(device, memory);

View File

@@ -155,7 +155,8 @@ static NvBool GetScanLine(const NVDpyEvoRec *pDpyEvo, NvS64 *pScanLine)
NVDispEvoPtr pDispEvo = pDpyEvo->pDispEvo;
NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
NvU32 ret;
const NvU32 head = pDpyEvo->head;
/* XXX[2Heads1OR] Get scanline of the primary hardware head. */
const NvU32 head = pDpyEvo->apiHead;
if (head == NV_INVALID_HEAD) {
return FALSE;
@@ -189,7 +190,7 @@ static NvBool GetScanLine(const NVDpyEvoRec *pDpyEvo, NvS64 *pScanLine)
*/
static NvBool GetHead(const NVDpyEvoRec *pDpyEvo, NvS64 *pHead)
{
*pHead = (NvS64)pDpyEvo->head;
*pHead = (NvS64)pDpyEvo->apiHead;
return TRUE;
}
@@ -205,12 +206,13 @@ static void SetDitheringCommon(NVDpyEvoPtr pDpyEvo)
{
NVEvoUpdateState updateState = { };
if (pDpyEvo->head == NV_INVALID_HEAD) {
if (pDpyEvo->apiHead == NV_INVALID_HEAD) {
return;
}
/* XXX[2Heads1OR] Broadcast dithering to the hardware heads. */
nvSetDitheringEvo(pDpyEvo->pDispEvo,
pDpyEvo->head,
pDpyEvo->apiHead,
pDpyEvo->requestedDithering.state,
pDpyEvo->requestedDithering.depth,
pDpyEvo->requestedDithering.mode,
@@ -425,6 +427,7 @@ static NvBool DigitalVibranceAvailable(const NVDpyEvoRec *pDpyEvo)
static NvBool SetDigitalVibrance(NVDpyEvoRec *pDpyEvo, NvS64 dvc)
{
NVEvoUpdateState updateState = { };
NVDispEvoRec *pDispEvo = pDpyEvo->pDispEvo;
if (!DigitalVibranceAvailable(pDpyEvo)) {
return FALSE;
@@ -433,12 +436,15 @@ static NvBool SetDigitalVibrance(NVDpyEvoRec *pDpyEvo, NvS64 dvc)
dvc = NV_MAX(dvc, NV_EVO_DVC_MIN);
dvc = NV_MIN(dvc, NV_EVO_DVC_MAX);
/* XXX[2Heads1OR] Broadcast vibrance setting to the hardware heads. */
nvSetDVCEvo(pDpyEvo->pDispEvo,
pDpyEvo->head, dvc, &updateState);
pDpyEvo->apiHead, dvc, &updateState);
nvEvoUpdateAndKickOff(pDpyEvo->pDispEvo, FALSE, &updateState,
TRUE /* releaseElv */);
pDispEvo->headState[pDpyEvo->apiHead].attributes.dvc = dvc;
return TRUE;
}
@@ -497,12 +503,16 @@ static NvBool SetImageSharpening(NVDpyEvoRec *pDpyEvo, NvS64 imageSharpening)
imageSharpening = NV_MAX(imageSharpening, NV_EVO_IMAGE_SHARPENING_MIN);
imageSharpening = NV_MIN(imageSharpening, NV_EVO_IMAGE_SHARPENING_MAX);
/* XXX[2Heads1OR] Broadcast image sharpening setting to the hardware heads */
nvSetImageSharpeningEvo(pDispEvo,
pDpyEvo->head, imageSharpening, &updateState);
pDpyEvo->apiHead, imageSharpening, &updateState);
nvEvoUpdateAndKickOff(pDispEvo, FALSE, &updateState,
TRUE /* releaseElv */);
pDispEvo->headState[pDpyEvo->apiHead].attributes.imageSharpening.value =
imageSharpening;
return TRUE;
}
@@ -569,23 +579,24 @@ static void DpyPostColorSpaceOrRangeSetEvo(NVDpyEvoPtr pDpyEvo)
{
NVEvoUpdateState updateState = { };
if (pDpyEvo->head == NV_INVALID_HEAD) {
if (pDpyEvo->apiHead == NV_INVALID_HEAD) {
return;
}
/* XXX[2Heads1OR] Broadcast color space settings to the hardware heads. */
/*
* Recompute the current ColorSpace and ColorRange, given updated requested
* values, and program any changes in EVO hardware.
*/
nvSetColorSpaceAndRangeEvo(
pDpyEvo->pDispEvo,
pDpyEvo->head,
pDpyEvo->apiHead,
pDpyEvo->requestedColorSpace,
pDpyEvo->requestedColorRange,
&updateState);
/* Update InfoFrames as needed. */
nvUpdateInfoFrames(pDpyEvo->pDispEvo, pDpyEvo->head);
nvUpdateInfoFrames(pDpyEvo->pDispEvo, pDpyEvo->apiHead);
// Kick off
nvEvoUpdateAndKickOff(pDpyEvo->pDispEvo, FALSE, &updateState,
@@ -798,13 +809,21 @@ static NvBool GetDigitalLinkType(const NVDpyEvoRec *pDpyEvo, NvS64 *pValue)
if (nvConnectorUsesDPLib(pDpyEvo->pConnectorEvo)) {
*pValue = nvRMLaneCountToNvKms(pDpyEvo->dp.laneCount);
} else {
const NVHwModeTimingsEvo *pTimings =
nvGetCurrentModeTimingsForDpyEvo(pDpyEvo);
const NVHwModeTimingsEvo *pTimings;
const NVDispEvoRec *pDispEvo = pDpyEvo->pDispEvo;
/*
* XXX[2Heads1OR] Track DIGITAL_LINK_TYPE as per head
* attributes set which get mirrored into NVDpyEvoRec::attributes
* after modeset.
*/
const NvU32 head = pDpyEvo->apiHead;
if (pTimings == NULL) {
if (head == NV_INVALID_HEAD) {
return FALSE;
}
pTimings = &pDispEvo->headState[head].timings;
*pValue = nvDpyRequiresDualLinkEvo(pDpyEvo, pTimings) ?
NV_KMS_DPY_ATTRIBUTE_DIGITAL_LINK_TYPE_DUAL :
NV_KMS_DPY_ATTRIBUTE_DIGITAL_LINK_TYPE_SINGLE;
@@ -953,20 +972,22 @@ static NvBool SetStereoEvo(NVDpyEvoPtr pDpyEvo, NvS64 value)
{
NvBool enable = !!value;
if (pDpyEvo->head == NV_INVALID_HEAD) {
if (pDpyEvo->apiHead == NV_INVALID_HEAD) {
return FALSE;
}
return nvSetStereoEvo(pDpyEvo->pDispEvo, pDpyEvo->head, enable);
/* XXX[2Heads1OR] Broadcast the stereo setting to the hardware heads. */
return nvSetStereoEvo(pDpyEvo->pDispEvo, pDpyEvo->apiHead, enable);
}
static NvBool GetStereoEvo(const NVDpyEvoRec *pDpyEvo, NvS64 *pValue)
{
if (pDpyEvo->head == NV_INVALID_HEAD) {
if (pDpyEvo->apiHead == NV_INVALID_HEAD) {
return FALSE;
}
*pValue = !!nvGetStereoEvo(pDpyEvo->pDispEvo, pDpyEvo->head);
/* XXX[2Heads1OR] Loop over hardware heads to determine stereo status. */
*pValue = !!nvGetStereoEvo(pDpyEvo->pDispEvo, pDpyEvo->apiHead);
return TRUE;
}
@@ -1188,7 +1209,7 @@ NvBool nvSetDpyAttributeEvo(NVDpyEvoPtr pDpyEvo,
return FALSE;
}
if (pDpyEvo->head != NV_INVALID_HEAD) {
if (pDpyEvo->apiHead != NV_INVALID_HEAD) {
NVDispEvoRec *pDispEvo = pDpyEvo->pDispEvo;
NVDpyEvoRec *pClonedDpyEvo;
@@ -1200,7 +1221,7 @@ NvBool nvSetDpyAttributeEvo(NVDpyEvoPtr pDpyEvo,
* apiHead -> pDpyEvo mapping will get implemented.
*/
FOR_ALL_EVO_DPYS(pClonedDpyEvo, pDispEvo->validDisplays, pDispEvo) {
if (pClonedDpyEvo->head != pDpyEvo->head) {
if (pClonedDpyEvo->apiHead != pDpyEvo->apiHead) {
continue;
}
nvDpyUpdateCurrentAttributes(pClonedDpyEvo);

View File

@@ -757,7 +757,7 @@ NvBool nvEvoRestoreConsole(NVDevEvoPtr pDevEvo, const NvBool allowMST)
FOR_ALL_EVO_DPYS(pDpyEvo, candidateDpys, pDispEvo) {
NvBool isTiledDisplayFound = FALSE;
TiledDisplayInfo tiledDisplayInfo = { 0 };
TiledDisplayInfo tiledDisplayInfo = { };
NvBool isTiledDisplayEnable = FALSE;
const NVT_DISPLAYID_INFO *pDpyDisplayIdInfo =
pDpyEvo->parsedEdid.valid ?

View File

@@ -24,8 +24,6 @@
/* this source file contains routines for setting and moving the cursor.
* NV50 specific */
#include "nvkms-cursor.h"
#include "nvkms-types.h"
#include "nvkms-dma.h"

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2005-2013 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2005-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -56,6 +56,7 @@ DpyGetPassiveDpDongleType(const NVDpyEvoRec *pDpyEvo,
NvU32 *passiveDpDongleMaxPclkKHz);
static void
CreateParsedEdidFromNVT_TIMING(NVT_TIMING *pTimings,
NvU8 bpc,
NVParsedEdidEvoPtr pParsedEdid);
static NvBool ReadEdidFromDP (const NVDpyEvoRec *pDpyEvo,
@@ -81,7 +82,8 @@ static void ReadAndApplyEdidEvo (NVDpyEvoPtr pDpyEvo,
struct NvKmsQueryDpyDynamicDataParams *pParams);
static NvBool GetFixedModeTimings (NVDpyEvoPtr pDpyEvo);
static NvBool ReadDSITimingsFromResman (const NVDpyEvoRec *pDpyEvo,
NVT_TIMING *pTimings);
NVT_TIMING *pTimings,
NvU8 *pBpc);
static void AssignDpyEvoName (NVDpyEvoPtr pDpyEvo);
static NvBool IsConnectorTMDS (NVConnectorEvoPtr);
@@ -116,8 +118,9 @@ static NvBool DpyConnectEvo(
ReadAndApplyEdidEvo(pDpyEvo, pParams);
}
if (pDpyEvo->head != NV_INVALID_HEAD) {
nvUpdateInfoFrames(pDpyEvo->pDispEvo, pDpyEvo->head);
if (pDpyEvo->apiHead != NV_INVALID_HEAD) {
/* XXX[2Heads1OR] Info frames should get programmed onky for the primary head. */
nvUpdateInfoFrames(pDpyEvo->pDispEvo, pDpyEvo->apiHead);
}
return TRUE;
@@ -404,17 +407,11 @@ static void ApplyNewEdid(
*/
static NvBool ReadDSITimingsFromResman(
const NVDpyEvoRec *pDpyEvo,
NVT_TIMING *pTimings)
NVT_TIMING *pTimings,
NvU8 *pBpc)
{
NvU32 ret;
NV0073_CTRL_CMD_DFP_GET_DSI_MODE_TIMING_PARAMS dsiModeTimingParams = { 0 };
// Values are currently hardcoded while waiting for full RM support
NvU32 hFrontPorch = 8;
NvU32 vFrontPorch = 2;
NvU32 hBackPorch = 56;
NvU32 vBackPorch = 51;
NvU32 hSyncWidth = 96;
NvU32 vSyncWidth = 2;
NVDispEvoPtr pDispEvo = pDpyEvo->pDispEvo;
NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
@@ -442,31 +439,37 @@ static NvBool ReadDSITimingsFromResman(
// Converts refresh (Hz) into appropriate units for rr1k (units of 0.001Hz)
pTimings->etc.rrx1k = dsiModeTimingParams.refresh * 1000;
pTimings->HVisible = dsiModeTimingParams.hActive;
pTimings->HFrontPorch = hFrontPorch;
pTimings->HSyncWidth = hSyncWidth;
pTimings->HFrontPorch = dsiModeTimingParams.hFrontPorch;
pTimings->HSyncWidth = dsiModeTimingParams.hSyncWidth;
pTimings->HTotal = dsiModeTimingParams.hActive +
hFrontPorch + hSyncWidth + hBackPorch;
dsiModeTimingParams.hFrontPorch +
dsiModeTimingParams.hSyncWidth +
dsiModeTimingParams.hBackPorch;
pTimings->VVisible = dsiModeTimingParams.vActive;
pTimings->VFrontPorch = vFrontPorch;
pTimings->VSyncWidth = vSyncWidth;
pTimings->VFrontPorch = dsiModeTimingParams.vFrontPorch;
pTimings->VSyncWidth = dsiModeTimingParams.vSyncWidth;
pTimings->VTotal = dsiModeTimingParams.vActive +
vFrontPorch + vSyncWidth + vBackPorch;
dsiModeTimingParams.vFrontPorch +
dsiModeTimingParams.vSyncWidth +
dsiModeTimingParams.vBackPorch;
pTimings->pclk = HzToKHz(pTimings->VTotal *
pTimings->HTotal *
dsiModeTimingParams.refresh) / 10;
pTimings->pclk = HzToKHz(dsiModeTimingParams.pclkHz) / 10;
// DSI only supports RGB444
*pBpc = dsiModeTimingParams.bpp / 3;
return TRUE;
}
static NvBool ReadDPSerializerTimings(
const NVDpyEvoRec *pDpyEvo,
NVT_TIMING *pTimings)
NVT_TIMING *pTimings,
NvU8 *pBpc)
{
/*
* TODO Add RM control call that will return the fixed timings
* that can be used with a given display.
* and bpc that can be used with a given display.
*/
pTimings->HVisible = 1920;
pTimings->VVisible = 1080;
@@ -481,6 +484,7 @@ static NvBool ReadDPSerializerTimings(
pTimings->interlaced = 0;
pTimings->pclk = 14850;
pTimings->etc.rrx1k = 60000;
*pBpc = 0;
return TRUE;
}
@@ -490,18 +494,20 @@ static NvBool GetFixedModeTimings(
{
NVT_TIMING timings = { };
NvBool ret = FALSE;
NvU8 bpc;
if (pDpyEvo->pConnectorEvo->signalFormat == NVKMS_CONNECTOR_SIGNAL_FORMAT_DSI) {
ret = ReadDSITimingsFromResman(pDpyEvo, &timings);
ret = ReadDSITimingsFromResman(pDpyEvo, &timings, &bpc);
} else if (nvConnectorIsDPSerializer(pDpyEvo->pConnectorEvo)) {
ret = ReadDPSerializerTimings(pDpyEvo, &timings);
ret = ReadDPSerializerTimings(pDpyEvo, &timings, &bpc);
}
if (!ret) {
return ret;
}
CreateParsedEdidFromNVT_TIMING(&timings, &pDpyEvo->parsedEdid);
CreateParsedEdidFromNVT_TIMING(&timings, bpc, &pDpyEvo->parsedEdid);
AssignDpyEvoName(pDpyEvo);
nvDpyProbeMaxPixelClock(pDpyEvo);
@@ -1982,6 +1988,7 @@ static void PrePatchEdid(const NVDpyEvoRec *pDpyEvo, NVEdidPtr pEdid,
*/
static void CreateParsedEdidFromNVT_TIMING(
NVT_TIMING *pTimings,
NvU8 bpc,
NVParsedEdidEvoPtr pParsedEdid)
{
nvkms_memset(pParsedEdid, 0, sizeof(*pParsedEdid));
@@ -1991,6 +1998,7 @@ static void CreateParsedEdidFromNVT_TIMING(
pParsedEdid->info.u.feature_ver_1_4_digital.continuous_frequency = FALSE;
pParsedEdid->info.version = NVT_EDID_VER_1_4;
pParsedEdid->info.input.isDigital = TRUE;
pParsedEdid->info.input.u.digital.bpc = bpc;
pParsedEdid->limits.min_h_rate_hz = 1;
pParsedEdid->limits.min_v_rate_hzx1k = 1;
pParsedEdid->limits.max_h_rate_hz = NV_U32_MAX;
@@ -2192,7 +2200,7 @@ NVDpyEvoPtr nvAllocDpyEvo(NVDispEvoPtr pDispEvo,
pDpyEvo->pDispEvo = pDispEvo;
pDpyEvo->pConnectorEvo = pConnectorEvo;
pDpyEvo->head = NV_INVALID_HEAD;
pDpyEvo->apiHead = NV_INVALID_HEAD;
pDpyEvo->id = dpyId;
nvListAdd(&pDpyEvo->dpyListEntry, &pDispEvo->dpyList);
@@ -2428,34 +2436,6 @@ NvBool nvDpyRequiresDualLinkEvo(const NVDpyEvoRec *pDpyEvo,
return (pTimings->pixelClock > pDpyEvo->maxSingleLinkPixelClockKHz);
}
/*!
* Return EVO mode timings currently used with the given pDpyEvo.
*
* \param[in] pDpyEvo dpy whose mode timings should be returned.
*
* \return NULL if pDpyEvo is not active. Otherwise, return the mode
* timings programmed in the head that is driving the dpy.
*/
NVHwModeTimingsEvoPtr
nvGetCurrentModeTimingsForDpyEvo(const NVDpyEvoRec *pDpyEvo)
{
NVDispEvoPtr pDispEvo = pDpyEvo->pDispEvo;
NVDispHeadStateEvoPtr pHeadState = NULL;
const NvU32 head = pDpyEvo->head;
if (head == NV_INVALID_HEAD) {
return NULL;
}
pHeadState = &pDispEvo->headState[head];
nvAssert(nvDpyIdIsInDpyIdList(pDpyEvo->id, pHeadState->activeDpys));
return &pHeadState->timings;
}
/*!
* Return the NVDpyEvoPtr that corresponds to the given dpyId, on the
* given NVDispEvoPtr, or NULL if no matching NVDpyEvoPtr can be
@@ -2738,9 +2718,10 @@ void nvDpyUpdateCurrentAttributes(NVDpyEvoRec *pDpyEvo)
{
NVAttributesSetEvoRec newAttributes = pDpyEvo->currentAttributes;
if (pDpyEvo->head != NV_INVALID_HEAD) {
if (pDpyEvo->apiHead != NV_INVALID_HEAD) {
/* XXX[2Heads1OR] attributes should get stored in the api-head state. */
newAttributes =
pDpyEvo->pDispEvo->headState[pDpyEvo->head].attributes;
pDpyEvo->pDispEvo->headState[pDpyEvo->apiHead].attributes;
} else {
newAttributes.dithering.enabled = FALSE;
newAttributes.dithering.depth = NV_KMS_DPY_ATTRIBUTE_CURRENT_DITHERING_DEPTH_NONE;

View File

@@ -1707,14 +1707,12 @@ done:
void nvUpdateCurrentHardwareColorSpaceAndRangeEvo(
NVDispEvoPtr pDispEvo,
const NvU32 head,
const enum NvKmsDpyAttributeCurrentColorSpaceValue colorSpace,
const enum NvKmsDpyAttributeColorRangeValue colorRange,
NVEvoUpdateState *pUpdateState)
{
NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
const enum NvKmsDpyAttributeCurrentColorSpaceValue colorSpace =
pHeadState->attributes.colorSpace;
const enum NvKmsDpyAttributeColorRangeValue colorRange =
pHeadState->attributes.colorRange;
const NVConnectorEvoRec *pConnectorEvo = pHeadState->pConnectorEvo;
nvAssert(pConnectorEvo != NULL);
@@ -1858,7 +1856,11 @@ void nvSetColorSpaceAndRangeEvo(
&pHeadState->attributes.colorRange);
/* Update hardware's current colorSpace and colorRange */
nvUpdateCurrentHardwareColorSpaceAndRangeEvo(pDispEvo, head, pUpdateState);
nvUpdateCurrentHardwareColorSpaceAndRangeEvo(pDispEvo,
head,
pHeadState->attributes.colorSpace,
pHeadState->attributes.colorRange,
pUpdateState);
}
void nvEvoHeadSetControlOR(NVDispEvoPtr pDispEvo,
@@ -2974,7 +2976,11 @@ NvBool nvQueryRasterLockEvo(const NVDpyEvoRec *pDpyEvo, NvS64 *val)
NVDispEvoPtr pDispEvo = pDpyEvo->pDispEvo;
NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
NVEvoSubDevPtr pEvoSubDev;
const NvU32 head = pDpyEvo->head;
/*
* XXX[2Heads1OR] Loop over hardware heads to determine if this api-head
* is rasterlocked with any other api-head.
*/
const NvU32 head = pDpyEvo->apiHead;
NVEvoHeadControlPtr pHC;
if ((head == NV_INVALID_HEAD) || (pDevEvo->gpus == NULL)) {
@@ -3136,7 +3142,12 @@ static NvBool UpdateFlipLock50(const NVDpyEvoRec *pDpyEvo,
NvU32 *val, NvBool set)
{
NVDispEvoPtr pDispEvo = pDpyEvo->pDispEvo;
const NvU32 head = pDpyEvo->head;
/*
* XXX[2Heads1OR] Loop over hardware heads to determine is this api-head
* is rasterlocked with any other api-head and flip lock is not prohibited
* on its corresponding hardware heads.
*/
const NvU32 head = pDpyEvo->apiHead;
NVEvoUpdateState updateState = { };
NvBool ret;
@@ -3359,18 +3370,6 @@ void nvSetViewPortsEvo(NVDispEvoPtr pDispEvo,
NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
const NVHwModeViewPortEvo *pViewPort = &pHeadState->timings.viewPort;
// Image sharpening is available when scaling is enabled.
pHeadState->attributes.imageSharpening.available =
(pViewPort->out.width != pViewPort->in.width) ||
(pViewPort->out.height != pViewPort->in.height);
// cache HEAD_SET_CONTROL_OUTPUT_SCALER H/V taps for use in
// SetOutputScaler(). This is needed because SetOutputScaler may be called
// from nvSetImageSharpeningEvo where the NVHwModeViewPortEvo
// isn't as easily accessible.
pHeadState->hTaps = pViewPort->hTaps;
pHeadState->vTaps = pViewPort->vTaps;
nvPushEvoSubDevMaskDisp(pDispEvo);
pDevEvo->hal->SetViewportInOut(pDevEvo, head,
pViewPort, pViewPort, pViewPort,
@@ -4111,8 +4110,6 @@ void nvSetDVCEvo(NVDispEvoPtr pDispEvo,
NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
pHeadState->attributes.dvc = dvc;
nvAssert(dvc >= NV_EVO_DVC_MIN);
nvAssert(dvc <= NV_EVO_DVC_MAX);
@@ -4139,9 +4136,6 @@ void nvSetImageSharpeningEvo(NVDispEvoRec *pDispEvo, const NvU32 head,
NvU32 value, NVEvoUpdateState *updateState)
{
NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
pHeadState->attributes.imageSharpening.value = value;
/*
* Evo values are from -128 to 127, with a default of 0.
@@ -5300,13 +5294,23 @@ NvBool nvConstructHwModeTimingsEvo(const NVDpyEvoRec *pDpyEvo,
} else if (pConnectorEvo->legacyType ==
NV0073_CTRL_SPECIFIC_DISPLAY_TYPE_DFP) {
/* TMDS default, also acceptable for DSI */
pTimings->pixelDepth = NVKMS_PIXEL_DEPTH_24_444;
/* Pick displayport pixel depths for raster timings */
if (nvConnectorUsesDPLib(pDpyEvo->pConnectorEvo)) {
if (pConnectorEvo->signalFormat == NVKMS_CONNECTOR_SIGNAL_FORMAT_DSI) {
switch (pDpyEvo->parsedEdid.info.input.u.digital.bpc) {
case 10:
pTimings->pixelDepth = NVKMS_PIXEL_DEPTH_30_444;
break;
case 6:
pTimings->pixelDepth = NVKMS_PIXEL_DEPTH_18_444;
break;
default:
nvAssert(!"Invalid Pixel Depth for DSI");
// fall through
case 8:
pTimings->pixelDepth = NVKMS_PIXEL_DEPTH_24_444;
break;
}
} else if (nvConnectorUsesDPLib(pDpyEvo->pConnectorEvo)) {
// Pick displayport pixel depths for raster timings.
// Start off picking best possible depth based on monitor caps
// If the monitor doesn't have an EDID version 1.4 or higher, assume
// it's 8.
@@ -5319,6 +5323,9 @@ NvBool nvConstructHwModeTimingsEvo(const NVDpyEvoRec *pDpyEvo,
pTimings->pixelDepth = NVKMS_PIXEL_DEPTH_18_444;
}
}
} else {
/* TMDS default */
pTimings->pixelDepth = NVKMS_PIXEL_DEPTH_24_444;
}
}

View File

@@ -2008,7 +2008,7 @@ static void EvoFlip90(NVDevEvoPtr pDevEvo,
sd,
head,
pHwState->pSurfaceEvo[NVKMS_LEFT])) {
const struct NvKmsCscMatrix zeroCscMatrix = { 0 };
const struct NvKmsCscMatrix zeroCscMatrix = { };
nvPushEvoSubDevMask(pDevEvo, NVBIT(sd));
EvoPushSetCoreSurfaceMethodsForOneSd(pDevEvo, sd, head,
@@ -2768,6 +2768,7 @@ static void EvoSetOutputScaler90(const NVDispEvoRec *pDispEvo, const NvU32 head,
NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
NVEvoChannelPtr pChannel = pDevEvo->core;
const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
const NVHwModeViewPortEvo *pViewPort = &pHeadState->timings.viewPort;
NvU32 setControlOutputScaler = 0;
NvU32 vTapsHw = 0, hTapsHw = 0;
@@ -2775,7 +2776,7 @@ static void EvoSetOutputScaler90(const NVDispEvoRec *pDispEvo, const NvU32 head,
nvAssert(pDevEvo->subDevMaskStackDepth > 0);
nvUpdateUpdateState(pDevEvo, updateState, pChannel);
switch (pHeadState->vTaps) {
switch (pViewPort->vTaps) {
case NV_EVO_SCALER_5TAPS:
vTapsHw = NV917D_HEAD_SET_CONTROL_OUTPUT_SCALER_VERTICAL_TAPS_TAPS_5;
break;
@@ -2793,7 +2794,7 @@ static void EvoSetOutputScaler90(const NVDispEvoRec *pDispEvo, const NvU32 head,
vTapsHw = NV917D_HEAD_SET_CONTROL_OUTPUT_SCALER_VERTICAL_TAPS_TAPS_1;
break;
}
switch (pHeadState->hTaps) {
switch (pViewPort->hTaps) {
case NV_EVO_SCALER_8TAPS:
hTapsHw = NV917D_HEAD_SET_CONTROL_OUTPUT_SCALER_HORIZONTAL_TAPS_TAPS_8;
break;
@@ -2814,7 +2815,7 @@ static void EvoSetOutputScaler90(const NVDispEvoRec *pDispEvo, const NvU32 head,
DRF_NUM(917D, _HEAD_SET_CONTROL_OUTPUT_SCALER, _VERTICAL_TAPS,
vTapsHw);
if (pHeadState->attributes.imageSharpening.available) {
if (nvIsImageSharpeningAvailable(&pHeadState->timings.viewPort)) {
setControlOutputScaler =
FLD_SET_DRF_NUM(917D, _HEAD_SET_CONTROL_OUTPUT_SCALER,
_HRESPONSE_BIAS, imageSharpeningValue,
@@ -3601,7 +3602,7 @@ static void EvoGetScanLine90(const NVDispEvoRec *pDispEvo,
static NvU32 EvoGetActiveViewportOffset94(NVDispEvoRec *pDispEvo, NvU32 head)
{
NV5070_CTRL_CMD_GET_ACTIVE_VIEWPORT_BASE_PARAMS params = {0};
NV5070_CTRL_CMD_GET_ACTIVE_VIEWPORT_BASE_PARAMS params = { };
NvU32 ret;
NVDevEvoRec *pDevEvo = pDispEvo->pDevEvo;
@@ -3626,13 +3627,13 @@ EvoClearSurfaceUsage91(NVDevEvoPtr pDevEvo, NVSurfaceEvoPtr pSurfaceEvo)
{
NvU32 sd;
NvBool kickOff = FALSE;
NVEvoUpdateState updateState = { 0 };
NVEvoUpdateState updateState = { };
for (sd = 0; sd < pDevEvo->numSubDevices; sd++) {
NvU32 head;
for (head = 0; head < pDevEvo->numHeads; head++) {
const struct NvKmsCscMatrix zeroCscMatrix = { 0 };
const struct NvKmsCscMatrix zeroCscMatrix = { };
const NVEvoSubDevHeadStateRec *pSdHeadState =
&pDevEvo->gpus[sd].headState[head];

View File

@@ -5176,16 +5176,17 @@ static void EvoSetOutputScalerC3(const NVDispEvoRec *pDispEvo, const NvU32 head,
NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
NVEvoChannelPtr pChannel = pDevEvo->core;
const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
const NVHwModeViewPortEvo *pViewPort = &pHeadState->timings.viewPort;
/* These methods should only apply to a single pDpyEvo */
nvAssert(pDevEvo->subDevMaskStackDepth > 0);
nvUpdateUpdateState(pDevEvo, updateState, pChannel);
NvU32 vTaps = pHeadState->vTaps > NV_EVO_SCALER_2TAPS ?
NvU32 vTaps = pViewPort->vTaps > NV_EVO_SCALER_2TAPS ?
NVC37D_HEAD_SET_CONTROL_OUTPUT_SCALER_VERTICAL_TAPS_TAPS_5 :
NVC37D_HEAD_SET_CONTROL_OUTPUT_SCALER_VERTICAL_TAPS_TAPS_2;
NvU32 hTaps = pHeadState->hTaps > NV_EVO_SCALER_2TAPS ?
NvU32 hTaps = pViewPort->hTaps > NV_EVO_SCALER_2TAPS ?
NVC37D_HEAD_SET_CONTROL_OUTPUT_SCALER_HORIZONTAL_TAPS_TAPS_5 :
NVC37D_HEAD_SET_CONTROL_OUTPUT_SCALER_HORIZONTAL_TAPS_TAPS_2;
@@ -6675,7 +6676,7 @@ EvoEnableMidFrameAndDWCFWatermarkC5(NVDevEvoPtr pDevEvo,
static NvU32 EvoGetActiveViewportOffsetC3(NVDispEvoRec *pDispEvo, NvU32 head)
{
NVC372_CTRL_CMD_GET_ACTIVE_VIEWPORT_POINT_IN_PARAMS params = {0};
NVC372_CTRL_CMD_GET_ACTIVE_VIEWPORT_POINT_IN_PARAMS params = { };
NvU32 ret;
NVDevEvoRec *pDevEvo = pDispEvo->pDevEvo;

View File

@@ -1933,6 +1933,7 @@ void nvFlipEvoOneHead(
}
nvPushEvoSubDevMask(pDevEvo, subDeviceMask);
pDevEvo->hal->Flip(pDevEvo,
pDevEvo->head[head].layer[layer],
&pFlipState->layer[layer],

View File

@@ -1129,7 +1129,8 @@ static NvBool FrameLockDpyCanBeServer(const NVDpyEvoRec *pDpyEvo)
NV30F1_CTRL_GSYNC_GET_CONTROL_SYNC_PARAMS gsyncGetControlSyncParams = { 0 };
NVDispEvoPtr pDispEvo = pDpyEvo->pDispEvo;
NVFrameLockEvoPtr pFrameLockEvo = pDispEvo->pFrameLockEvo;
const NvU32 head = pDpyEvo->head;
/* XXX[2Heads1OR] Get the primary hardware head. */
const NvU32 head = pDpyEvo->apiHead;
const NVDispHeadStateEvoRec *pHeadState;
NvU32 ret;
@@ -2171,7 +2172,8 @@ NvU32 nvGetFramelockServerHead(const NVDispEvoRec *pDispEvo)
{
const NVDpyEvoRec *pDpyEvo =
nvGetDpyEvoFromDispEvo(pDispEvo, pDispEvo->framelock.server);
return (pDpyEvo != NULL) ? pDpyEvo->head : NV_INVALID_HEAD;
/* XXX[2Heads1OR] Get the primary hardware head. */
return (pDpyEvo != NULL) ? pDpyEvo->apiHead : NV_INVALID_HEAD;
}
NvU32 nvGetFramelockClientHeadsMask(const NVDispEvoRec *pDispEvo)
@@ -2179,11 +2181,15 @@ NvU32 nvGetFramelockClientHeadsMask(const NVDispEvoRec *pDispEvo)
NvU32 headsMask = 0x0;
const NVDpyEvoRec *pDpyEvo;
/*
* XXX[2Heads1OR] Translate api-head -> hardware-heads, and make sure to
* include the secondary hardware-head of the server dpy.
*/
FOR_ALL_EVO_DPYS(pDpyEvo, pDispEvo->framelock.clients, pDispEvo) {
if (pDpyEvo->head == NV_INVALID_HEAD) {
if (pDpyEvo->apiHead == NV_INVALID_HEAD) {
continue;
}
headsMask |= NVBIT(pDpyEvo->head);
headsMask |= NVBIT(pDpyEvo->apiHead);
}
return headsMask;
}
@@ -2199,7 +2205,8 @@ void nvUpdateGLSFramelock(const NVDispEvoRec *pDispEvo, const NvU32 head,
* apiHead -> pDpyEvo mapping will get implemented.
*/
FOR_ALL_EVO_DPYS(pDpyEvo, pDispEvo->validDisplays, pDispEvo) {
if (pDpyEvo->head != head) {
/* XXX[2Heads1OR] Get the primary hardware head. */
if (pDpyEvo->apiHead != head) {
continue;
}

View File

@@ -21,12 +21,13 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "nvkms-types.h"
#include "nvkms-cursor.h"
#include "nvkms-hal.h"
#include "nvkms-rm.h"
#include "class/cl9470.h" // NV9470_DISPLAY
#include "class/cl9570.h" // NV9570_DISPLAY
#include "class/cl9770.h" // NV9770_DISPLAY
@@ -34,6 +35,7 @@
#include "class/clc370.h" // NVC370_DISPLAY
#include "class/clc570.h" // NVC570_DISPLAY
#include "class/clc670.h" // NVC670_DISPLAY
#include "class/clc770.h" // NVC770_DISPLAY
#include "class/cl947d.h" // NV947D_CORE_CHANNEL_DMA
#include "class/cl957d.h" // NV957D_CORE_CHANNEL_DMA
@@ -45,6 +47,7 @@
#include "class/clc57e.h" // NVC57E_WINDOW_CHANNEL_DMA
#include "class/clc67d.h" // NVC67D_CORE_CHANNEL_DMA
#include "class/clc67e.h" // NVC67E_WINDOW_CHANNEL_DMA
#include "class/clc77d.h" // NVC67D_CORE_CHANNEL_DMA
extern NVEvoHAL nvEvo94;
extern NVEvoHAL nvEvoC3;
@@ -155,14 +158,14 @@ enum NvKmsAllocDeviceStatus nvAssignEvoCaps(NVDevEvoPtr pDevEvo)
/* NVDisplay and later entries */
#define ENTRY_NVD(_classPrefix, ...) \
ENTRY(_classPrefix, __VA_ARGS__, \
#define ENTRY_NVD(_coreClassPrefix, _windowClassPrefix, ...) \
ENTRY(_coreClassPrefix, __VA_ARGS__, \
(1 << NVKMS_NISO_FORMAT_FOUR_WORD_NVDISPLAY), \
DRF_MASK(NV ## _classPrefix ## 7E_SET_PLANAR_STORAGE_PITCH), \
DRF_MASK(NV ## _classPrefix ## 7E_SET_PLANAR_STORAGE_PITCH) * \
DRF_MASK(NV ## _windowClassPrefix ## 7E_SET_PLANAR_STORAGE_PITCH), \
DRF_MASK(NV ## _windowClassPrefix ## 7E_SET_PLANAR_STORAGE_PITCH) * \
NVKMS_BLOCK_LINEAR_GOB_WIDTH, \
DRF_MASK(NV ## _classPrefix ## 7E_SET_SIZE_IN_WIDTH), \
DRF_MASK(NV ## _classPrefix ## 7E_SET_SIZE_IN_WIDTH), \
DRF_MASK(NV ## _windowClassPrefix ## 7E_SET_SIZE_IN_WIDTH), \
DRF_MASK(NV ## _windowClassPrefix ## 7E_SET_SIZE_IN_WIDTH), \
NVD_CORE_CHANNEL_DMA_ARMED_OFFSET, \
NVD_CORE_CHANNEL_DMA_ARMED_SIZE)
@@ -173,22 +176,24 @@ enum NvKmsAllocDeviceStatus nvAssignEvoCaps(NVDevEvoPtr pDevEvo)
const NVEvoCapsRec evoCaps;
} dispTable[] = {
/*
* genericPageKind--------------------+
* inputLutAppliesToBase --------+ |
* supportsHDMI20 ------------+ | |
* supportsDP13 -----------+ | | |
* inbandStereoSignaling+ | | | |
* pEvoHal ----------+ | | | | |
* classPrefix | | | | | |
* | | | | | | |
* genericPageKind------------------------+
* inputLutAppliesToBase ------------+ |
* supportsHDMI20 ----------------+ | |
* supportsDP13 ---------------+ | | |
* inbandStereoSignaling----+ | | | |
* pEvoHal --------------+ | | | | |
* windowClassPrefix | | | | | |
* classPrefix | | | | | | |
* | | | | | | | |
*/
ENTRY_NVD(C6, &nvEvoC6, 1, 1, 1, 0, TURING_GENERIC_KIND),
ENTRY_NVD(C5, &nvEvoC5, 1, 1, 1, 0, TURING_GENERIC_KIND),
ENTRY_NVD(C3, &nvEvoC3, 1, 1, 1, 0, FERMI_GENERIC_KIND),
ENTRY_EVO(98, &nvEvo94, 1, 1, 1, 1, FERMI_GENERIC_KIND),
ENTRY_EVO(97, &nvEvo94, 1, 1, 1, 1, FERMI_GENERIC_KIND),
ENTRY_EVO(95, &nvEvo94, 1, 0, 1, 1, FERMI_GENERIC_KIND),
ENTRY_EVO(94, &nvEvo94, 1, 0, 0, 1, FERMI_GENERIC_KIND),
ENTRY_NVD(C7, C6, &nvEvoC6, 1, 1, 1, 0, TURING_GENERIC_KIND),
ENTRY_NVD(C6, C6, &nvEvoC6, 1, 1, 1, 0, TURING_GENERIC_KIND),
ENTRY_NVD(C5, C5, &nvEvoC5, 1, 1, 1, 0, TURING_GENERIC_KIND),
ENTRY_NVD(C3, C3, &nvEvoC3, 1, 1, 1, 0, FERMI_GENERIC_KIND),
ENTRY_EVO(98, &nvEvo94, 1, 1, 1, 1, FERMI_GENERIC_KIND),
ENTRY_EVO(97, &nvEvo94, 1, 1, 1, 1, FERMI_GENERIC_KIND),
ENTRY_EVO(95, &nvEvo94, 1, 0, 1, 1, FERMI_GENERIC_KIND),
ENTRY_EVO(94, &nvEvo94, 1, 0, 0, 1, FERMI_GENERIC_KIND),
};
int i;

View File

@@ -928,9 +928,6 @@ void nvHdmiDpConstructHeadAudioState(const NvU32 displayId,
}
}
#define MAX_AUDIO_DEVICE_ENTRIES \
(NV0073_CTRL_DFP_ELD_AUDIO_CAPS_DEVICE_ENTRY_3 + 1)
/*
* Returns audio device entry of connector, which should
* be attached to given head. Returns NONE if head is inactive.
@@ -955,7 +952,7 @@ static NvU32 GetAudioDeviceEntry(const NVDispEvoRec *pDispEvo, const NvU32 head)
return NV0073_CTRL_DFP_ELD_AUDIO_CAPS_DEVICE_ENTRY_NONE;
}
ct_assert(MAX_AUDIO_DEVICE_ENTRIES == NVKMS_MAX_HEADS_PER_DISP);
ct_assert(NV_MAX_AUDIO_DEVICE_ENTRIES == NVKMS_MAX_HEADS_PER_DISP);
if (nvConnectorUsesDPLib(pConnectorEvo) &&
(nvDPGetActiveLinkMode(pConnectorEvo->pDpLibConnector) ==
@@ -966,66 +963,10 @@ static NvU32 GetAudioDeviceEntry(const NVDispEvoRec *pDispEvo, const NvU32 head)
return NV0073_CTRL_DFP_ELD_AUDIO_CAPS_DEVICE_ENTRY_0;
}
static NvBool IsAudioDeviceEntryActive(
const NVConnectorEvoRec *pConnectorEvo, const NvU32 deviceEntry)
{
NvU32 primaryOrIndex;
NvU32 head, headsCount = 0;
NvBool isInMSTMode, isConnectorActive;
if ((pConnectorEvo->or.mask == 0x0) ||
(deviceEntry >= MAX_AUDIO_DEVICE_ENTRIES)) {
return FALSE;
}
primaryOrIndex = nvEvoConnectorGetPrimaryOr(pConnectorEvo);
isInMSTMode = FALSE;
isConnectorActive = FALSE;
FOR_EACH_INDEX_IN_MASK(
32,
head,
pConnectorEvo->or.ownerHeadMask[primaryOrIndex]) {
const NVDispEvoRec *pDispEvo = pConnectorEvo->pDispEvo;
const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
NVDpyEvoRec *pDpyEvo = nvGetOneArbitraryDpyEvo(
pHeadState->activeDpys, pDispEvo);
if (headsCount == 0) {
isInMSTMode = nvDpyEvoIsDPMST(pDpyEvo);
} else {
nvAssert(isInMSTMode == nvDpyEvoIsDPMST(pDpyEvo));
}
headsCount++;
isConnectorActive = TRUE;
} FOR_EACH_INDEX_IN_MASK_END
if (!isConnectorActive) {
return FALSE;
}
nvAssert(isInMSTMode || headsCount == 1);
if (isInMSTMode) {
return (NVBIT(deviceEntry) &
pConnectorEvo->or.ownerHeadMask[primaryOrIndex]) ? TRUE : FALSE;
} else if (!isInMSTMode && deviceEntry == 0) {
return TRUE;
}
return FALSE;
}
/*!
* Send EDID-Like-Data (ELD) to RM.
*
* The ELD contains a subset of the digital display device's EDID
* information related to audio capabilities. The GPU driver sends the
* ELD to hardware and the audio driver reads it by issuing the ELD
* command verb. The ELD should be updated under the following
* situations:
* ELD should be updated under the following situations:
*
* 1. Power on reset
* 2. Pre modeset
@@ -1042,6 +983,15 @@ static NvBool IsAudioDeviceEntryActive(
* NV_ELD_PRE_MODESET : isPD = 1, isELDV = 0
* NV_ELD_POST_MODESET : isPD = 1, isELDV = 1
*
* The initial ELD case of each audio device entry in hardware is unknown.
* Fortunately, NVConnectorEvoRec::audioDevEldCase[] is zero-initialized,
* which means each audioDevEldCase[] array element will have initial
* value NV_ELD_PRE_MODESET=0.
*
* That ensures that nvRemoveUnusedHdmiDpAudioDevice(), during
* the first modeset, will reset all unused audio device entries to
* NV_ELD_POWER_ON_RESET.
*
* \param[in] pDispEvo The disp of the displayId
* \param[in] displayId The display device whose ELD should be updated.
* This should be NVDispHeadStateEvoRec::activeRmId
@@ -1054,14 +1004,11 @@ static NvBool IsAudioDeviceEntryActive(
* extracted.
* \param[in] eldCase The condition that requires updating the ELD.
*/
typedef enum {
NV_ELD_POWER_ON_RESET,
NV_ELD_PRE_MODESET,
NV_ELD_POST_MODESET,
} NvEldCase;
static void RmSetELDAudioCaps(
const NVDispEvoRec *pDispEvo, const NvU32 displayId,
const NVDispEvoRec *pDispEvo,
NVConnectorEvoRec *pConnectorEvo,
const NvU32 displayId,
const NvU32 deviceEntry,
const NvU32 maxFreqSupported, const NVEldEvoRec *pEld,
const NvEldCase eldCase)
@@ -1072,6 +1019,8 @@ static void RmSetELDAudioCaps(
NvBool isPD, isELDV;
NvU32 ret;
pConnectorEvo->audioDevEldCase[deviceEntry] = eldCase;
/* setup the ctrl flag */
switch(eldCase) {
case NV_ELD_POWER_ON_RESET :
@@ -1154,7 +1103,7 @@ void nvHdmiDpEnableDisableAudio(const NVDispEvoRec *pDispEvo,
const NvU32 head, const NvBool enable)
{
const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
const NVConnectorEvoRec *pConnectorEvo = pHeadState->pConnectorEvo;
NVConnectorEvoRec *pConnectorEvo = pHeadState->pConnectorEvo;
const NvU32 deviceEntry = GetAudioDeviceEntry(pDispEvo, head);
/*
@@ -1173,6 +1122,7 @@ void nvHdmiDpEnableDisableAudio(const NVDispEvoRec *pDispEvo,
if (enable) {
/* Make sure to remove corresponding audio device */
RmSetELDAudioCaps(pDispEvo,
pConnectorEvo,
nvDpyIdToNvU32(pConnectorEvo->displayId),
deviceEntry,
0 /* maxFreqSupported */,
@@ -1188,6 +1138,7 @@ void nvHdmiDpEnableDisableAudio(const NVDispEvoRec *pDispEvo,
/* Invalidate ELD buffer before disabling audio */
if (!enable) {
RmSetELDAudioCaps(pDispEvo,
pConnectorEvo,
pHeadState->activeRmId,
deviceEntry,
0 /* maxFreqSupported */,
@@ -1206,6 +1157,7 @@ void nvHdmiDpEnableDisableAudio(const NVDispEvoRec *pDispEvo,
/* Populate ELD buffer after enabling audio */
if (enable) {
RmSetELDAudioCaps(pDispEvo,
pConnectorEvo,
pHeadState->activeRmId,
deviceEntry,
pHeadState->audio.maxFreqSupported,
@@ -1235,7 +1187,7 @@ void nvDpyUpdateHdmiVRRCaps(NVDpyEvoPtr pDpyEvo)
void nvRemoveUnusedHdmiDpAudioDevice(const NVDispEvoRec *pDispEvo)
{
const NVConnectorEvoRec *pConnectorEvo;
NVConnectorEvoRec *pConnectorEvo;
const NvU32 activeSorMask = nvGetActiveSorMask(pDispEvo);
FOR_ALL_EVO_CONNECTORS(pConnectorEvo, pDispEvo) {
@@ -1258,14 +1210,24 @@ void nvRemoveUnusedHdmiDpAudioDevice(const NVDispEvoRec *pDispEvo)
}
for (deviceEntry = 0;
deviceEntry < MAX_AUDIO_DEVICE_ENTRIES;
deviceEntry < NV_MAX_AUDIO_DEVICE_ENTRIES;
deviceEntry++) {
if (IsAudioDeviceEntryActive(pConnectorEvo, deviceEntry)) {
/*
* Skip if the audio device is enabled (ELD case is set to
* NV_ELD_POST_MODESET by nvHdmiDpEnableDisableAudio()), or if the
* audio device is already disabled (ELD case is set to
* NV_ELD_POWER_ON_RESET).
*/
if ((pConnectorEvo->audioDevEldCase[deviceEntry] ==
NV_ELD_POST_MODESET) ||
(pConnectorEvo->audioDevEldCase[deviceEntry] ==
NV_ELD_POWER_ON_RESET)) {
continue;
}
RmSetELDAudioCaps(pDispEvo,
pConnectorEvo,
nvDpyIdToNvU32(pConnectorEvo->displayId),
deviceEntry,
0 /* maxFreqSupported */,
@@ -2114,10 +2076,4 @@ void nvHdmiFrlSetConfig(NVDispEvoRec *pDispEvo, NvU32 head)
"HDMI FRL link training retried %d times.",
retries);
}
nvAssert(pHeadState->attributes.digitalSignal ==
NV_KMS_DPY_ATTRIBUTE_DIGITAL_SIGNAL_TMDS);
pHeadState->attributes.digitalSignal =
NV_KMS_DPY_ATTRIBUTE_DIGITAL_SIGNAL_HDMI_FRL;
}

View File

@@ -276,15 +276,15 @@ GetColorSpaceAndColorRange(
nvChooseCurrentColorSpaceAndRangeEvo(&pProposedHead->timings,
requestedColorSpace,
requestedColorRange,
&pProposedHead->colorSpace,
&pProposedHead->colorRange);
&pProposedHead->attributes.colorSpace,
&pProposedHead->attributes.colorRange);
/*
* When colorspace is specified in modeset request, it should
* match the proposed colorspace.
*/
if (pRequestHead->colorSpaceSpecified) {
NvBool ret = FALSE;
switch (pProposedHead->colorSpace) {
switch (pProposedHead->attributes.colorSpace) {
case NV_KMS_DPY_ATTRIBUTE_CURRENT_COLOR_SPACE_RGB:
ret = (pRequestHead->colorSpace ==
NV_KMS_DPY_ATTRIBUTE_REQUESTED_COLOR_SPACE_RGB);
@@ -310,7 +310,7 @@ GetColorSpaceAndColorRange(
* match the proposed color range.
*/
if (pRequestHead->colorRangeSpecified &&
(pProposedHead->colorRange != pRequestHead->colorRange)) {
(pProposedHead->attributes.colorRange != pRequestHead->colorRange)) {
return FALSE;
}
@@ -381,8 +381,7 @@ AssignProposedModeSetHwState(NVDevEvoRec *pDevEvo,
pProposedHead->allowFlipLockGroup = pHeadState->allowFlipLockGroup;
pProposedHead->modeValidationParams =
pHeadState->modeValidationParams;
pProposedHead->colorSpace = pHeadState->attributes.colorSpace;
pProposedHead->colorRange = pHeadState->attributes.colorRange;
pProposedHead->attributes = pHeadState->attributes;
pProposedHead->changed = FALSE;
pProposedHead->hs10bpcHint = pHeadState->hs10bpcHint;
pProposedHead->audio = pHeadState->audio;
@@ -518,6 +517,31 @@ AssignProposedModeSetHwState(NVDevEvoRec *pDevEvo,
continue;
}
pProposedHead->attributes.digitalSignal =
nvGetDefaultDpyAttributeDigitalSignalValue(pProposedHead->pConnectorEvo);
if (pProposedHead->timings.hdmiFrlConfig.frlRate !=
HDMI_FRL_DATA_RATE_NONE) {
nvAssert(pProposedHead->attributes.digitalSignal ==
NV_KMS_DPY_ATTRIBUTE_DIGITAL_SIGNAL_TMDS);
pProposedHead->attributes.digitalSignal =
NV_KMS_DPY_ATTRIBUTE_DIGITAL_SIGNAL_HDMI_FRL;
}
{
NVDpyEvoRec *pDpyEvo =
nvGetOneArbitraryDpyEvo(pProposedHead->dpyIdList,
pDispEvo);
pProposedHead->attributes.dvc =
pDpyEvo->currentAttributes.dvc;
/* Image sharpening is available when scaling is enabled. */
pProposedHead->attributes.imageSharpening.available =
nvIsImageSharpeningAvailable(&pProposedHead->timings.viewPort);
pProposedHead->attributes.imageSharpening.value =
pDpyEvo->currentAttributes.imageSharpening.value;
}
/*
* modesetOwnerChanged implies that there was a modeset
* ownership change since the last modeset. If input/output lut not
@@ -833,7 +857,7 @@ static NvBool DowngradeDpPixelDepth(
if ((pProposedHead->pConnectorEvo == pConnectorEvo) &&
nvDowngradeHwModeTimingsDpPixelDepthEvo(
pTimings,
pProposedHead->colorSpace)) {
pProposedHead->attributes.colorSpace)) {
return TRUE;
}
}
@@ -879,7 +903,7 @@ tryAgain:
head,
pProposedHead->activeRmId,
pProposedHead->dpyIdList,
pProposedHead->colorSpace,
pProposedHead->attributes.colorSpace,
&pProposedHead->modeValidationParams,
pTimings);
@@ -921,7 +945,7 @@ tryAgain:
head,
pProposedHead->activeRmId,
pProposedHead->dpyIdList,
pProposedHead->colorSpace,
pProposedHead->attributes.colorSpace,
&pProposedHead->timings);
if (pProposedHead->pDpLibModesetState == NULL) {
return FALSE;
@@ -932,7 +956,35 @@ tryAgain:
return bResult;
}
static void VBlankCallbackDeferredWork(void *dataPtr, NvU32 data32)
{
NVVBlankCallbackPtr pVBlankCallbackTmp = NULL;
NVVBlankCallbackPtr pVBlankCallback = NULL;
NVDispEvoPtr pDispEvo = dataPtr;
NvU32 head = data32;
if (!nvHeadIsActive(pDispEvo, head)) {
return;
}
nvListForEachEntry_safe(pVBlankCallback,
pVBlankCallbackTmp,
&pDispEvo->headState[head].vblankCallbackList,
vblankCallbackListEntry) {
pVBlankCallback->pCallback(pDispEvo, head, pVBlankCallback);
}
}
static void VBlankCallback(void *pParam1, void *pParam2)
{
const NvU32 head = (NvU32)(NvUPtr)pParam2;
(void) nvkms_alloc_timer_with_ref_ptr(
VBlankCallbackDeferredWork,
pParam1, /* ref_ptr to pDispEvo */
head, /* dataU32 */
0); /* timeout: schedule the work immediately */
}
/*!
* Validate the proposed configuration on the specified disp.
@@ -1415,7 +1467,7 @@ ApplyProposedModeSetHwStateOneHeadShutDown(
nvkms_memset(&pDevEvo->gpus[sd].headState[head], 0,
sizeof(pDevEvo->gpus[sd].headState[head]));
pDpyEvo->head = NV_INVALID_HEAD;
pDpyEvo->apiHead = NV_INVALID_HEAD;
}
static void
@@ -1532,7 +1584,7 @@ ApplyProposedModeSetHwStateOneHeadPreUpdate(
return;
}
pDpyEvo->head = head;
pDpyEvo->apiHead = nvHardwareHeadToApiHead(head);
AssignSor(pWorkArea, pProposedHead->pConnectorEvo);
@@ -1583,9 +1635,11 @@ ApplyProposedModeSetHwStateOneHeadPreUpdate(
nvEvoHeadSetControlOR(pDispEvo, head, updateState);
/* Update hardware's current colorSpace and colorRange */
pHeadState->attributes.colorSpace = pProposedHead->colorSpace;
pHeadState->attributes.colorRange = pProposedHead->colorRange;
nvUpdateCurrentHardwareColorSpaceAndRangeEvo(pDispEvo, head, updateState);
nvUpdateCurrentHardwareColorSpaceAndRangeEvo(pDispEvo,
head,
pProposedHead->attributes.colorSpace,
pProposedHead->attributes.colorRange,
updateState);
nvEvoAttachConnector(pProposedHead->pConnectorEvo,
head,
@@ -1597,18 +1651,15 @@ ApplyProposedModeSetHwStateOneHeadPreUpdate(
nvSetImageSharpeningEvo(
pDispEvo,
head,
pDpyEvo->currentAttributes.imageSharpening.value,
pProposedHead->attributes.imageSharpening.value,
updateState);
nvSetDVCEvo(pDispEvo, head,
pDpyEvo->currentAttributes.dvc,
pProposedHead->attributes.dvc,
updateState);
pHeadState->attributes.digitalSignal =
nvGetDefaultDpyAttributeDigitalSignalValue(pDpyEvo->pConnectorEvo);
/* If required, nvHdmiFrlSetConfig() overrides attributes.digitalSignal */
nvHdmiFrlSetConfig(pDispEvo, head);
/*
@@ -1617,6 +1668,16 @@ ApplyProposedModeSetHwStateOneHeadPreUpdate(
*/
ReenableActiveCoreRGSyncObjects(pDispEvo->pDevEvo, pHeadState, head,
updateState);
pHeadState->attributes.digitalSignal =
pProposedHead->attributes.digitalSignal;
pHeadState->attributes.dvc = pProposedHead->attributes.dvc;
pHeadState->attributes.imageSharpening.available =
pProposedHead->attributes.imageSharpening.available;
pHeadState->attributes.imageSharpening.value =
pProposedHead->attributes.imageSharpening.value;
pHeadState->attributes.colorSpace = pProposedHead->attributes.colorSpace;
pHeadState->attributes.colorRange = pProposedHead->attributes.colorRange;
}
@@ -2625,6 +2686,71 @@ done:
return ret;
}
/*!
* Register a callback to activate when vblank is reached on a given head.
*
* \param[in,out] pDispEvo The display engine to register the callback on.
* \param[in] head The head to register the callback on.
* \param[in] pCallback The function to call when vblank is reached on the
* provided pDispEvo+head combination.
* \param[in] pUserData A pointer to caller-provided custom data.
*
* \return Returns a pointer to a NVVBlankCallbackRec structure if the
* registration was successful. Otherwise, return NULL.
*/
NVVBlankCallbackPtr nvRegisterVBlankCallback(NVDispEvoPtr pDispEvo,
NvU32 head,
NVVBlankCallbackProc pCallback,
void *pUserData)
{
NVVBlankCallbackPtr pVBlankCallback = NULL;
pVBlankCallback = nvCalloc(1, sizeof(*pVBlankCallback));
if (pVBlankCallback == NULL) {
return NULL;
}
pVBlankCallback->pCallback = pCallback;
pVBlankCallback->pUserData = pUserData;
nvListAppend(&pVBlankCallback->vblankCallbackListEntry,
&pDispEvo->headState[head].vblankCallbackList);
// If this is the first entry in the list, register the vblank callback
if (pDispEvo->headState[head].rmVBlankCallbackHandle == 0) {
pDispEvo->headState[head].rmVBlankCallbackHandle =
nvRmAddVBlankCallback(pDispEvo,
head,
VBlankCallback);
}
return pVBlankCallback;
}
/*!
* Un-register a vblank callback for a given head.
*
* \param[in,out] pDispEvo The display engine to register the callback on.
* \param[in] head The head to register the callback on.
* \param[in] pCallback A pointer to the NVVBlankCallbackRec to un-register.
*
*/
void nvUnregisterVBlankCallback(NVDispEvoPtr pDispEvo,
NvU32 head,
NVVBlankCallbackPtr pCallback)
{
nvListDel(&pCallback->vblankCallbackListEntry);
nvFree(pCallback);
// If there are no more callbacks, disable the RM-level callback
if (nvListIsEmpty(&pDispEvo->headState[head].vblankCallbackList)) {
nvRmRemoveVBlankCallback(pDispEvo,
pDispEvo->headState[head].rmVBlankCallbackHandle);
pDispEvo->headState[head].rmVBlankCallbackHandle = 0;
}
}
/*!
* Perform a modeset that disables some or all heads.
*

View File

@@ -238,6 +238,7 @@ static void FreeDisplay(NVDispEvoPtr pDispEvo)
for (head = 0; head < ARRAY_LEN(pDispEvo->pSwapGroup); head++) {
nvAssert(pDispEvo->pSwapGroup[head] == NULL);
nvAssert(nvListIsEmpty(&pDispEvo->headState[head].vblankCallbackList));
}
nvAssert(nvListIsEmpty(&pDispEvo->dpyList));
@@ -269,6 +270,7 @@ static inline NVDispEvoPtr AllocDisplay(NVDevEvoPtr pDevEvo)
for (head = 0; head < ARRAY_LEN(pDispEvo->headState); head++) {
pDispEvo->headState[head].activeDpys = nvEmptyDpyIdList();
pDispEvo->headState[head].attributes = NV_EVO_DEFAULT_ATTRIBUTES_SET;
nvListInit(&pDispEvo->headState[head].vblankCallbackList);
}
pDispEvo->ref_ptr = nvkms_alloc_ref_ptr(pDispEvo);
@@ -1035,10 +1037,10 @@ static void MarkConnectorBootHeadActive(NVDispEvoPtr pDispEvo, NvU32 head)
pHeadState = &pDispEvo->headState[head];
nvAssert(pDpyEvo->head == NV_INVALID_HEAD);
nvAssert(pDpyEvo->apiHead == NV_INVALID_HEAD);
nvAssert(!nvHeadIsActive(pDispEvo, head));
pDpyEvo->head = head;
pDpyEvo->apiHead = nvHardwareHeadToApiHead(head);
pHeadState->activeDpys =
nvAddDpyIdToEmptyDpyIdList(pConnectorEvo->displayId);

View File

@@ -504,6 +504,7 @@ void nvEvoRegisterSurface(NVDevEvoPtr pDevEvo,
}
pSurfaceEvo->requireCtxDma = !pRequest->noDisplayHardwareAccess;
pSurfaceEvo->noDisplayCaching = pRequest->noDisplayCaching;
/*
* Map the first plane of the surface only into the CPU's address space.

View File

@@ -110,6 +110,15 @@ enum NvKmsPerOpenType {
NvKmsPerOpenTypeUndefined,
};
enum NvKmsUnicastEventType {
/* Used by:
* NVKMS_IOCTL_JOIN_SWAP_GROUP */
NvKmsUnicastEventTypeDeferredRequest,
/* Undefined, this indicates the unicast fd is available for use. */
NvKmsUnicastEventTypeUndefined,
};
struct NvKmsPerOpenConnector {
NVConnectorEvoPtr pConnectorEvo;
NvKmsConnectorHandle nvKmsApiHandle;
@@ -183,13 +192,13 @@ struct NvKmsPerOpen {
* that object can generate events on the unicast event. Store a
* pointer to that object, so that we can clear the pointer when the
* unicast event NvKmsPerOpen is closed.
*
* So far, deferred request fifos with swap groups are the only
* users of unicast events. When we add more users, we can add an
* enum or similar to know which object type is using this unicast
* event.
*/
NVDeferredRequestFifoPtr pDeferredRequestFifo;
enum NvKmsUnicastEventType type;
union {
struct {
NVDeferredRequestFifoPtr pDeferredRequestFifo;
} deferred;
} e;
} unicastEvent;
};
};
@@ -3701,6 +3710,17 @@ static const char *ProcFsPerOpenTypeString(
return "unknown";
}
static const char *ProcFsUnicastEventTypeString(
enum NvKmsUnicastEventType type)
{
switch (type) {
case NvKmsUnicastEventTypeDeferredRequest: return "DeferredRequest";
case NvKmsUnicastEventTypeUndefined: return "undefined";
}
return "unknown";
}
static const char *ProcFsPerOpenClientTypeString(
enum NvKmsClientType clientType)
{
@@ -3851,10 +3871,18 @@ ProcFsPrintClients(
pOpen->grantSwapGroup.pSwapGroup);
} else if (pOpen->type == NvKmsPerOpenTypeUnicastEvent) {
nvEvoLogInfoString(&infoString,
" pDeferredRequestFifo : %p",
pOpen->unicastEvent.pDeferredRequestFifo);
" unicastEvent type : %s",
ProcFsUnicastEventTypeString(pOpen->unicastEvent.type));
switch(pOpen->unicastEvent.type) {
case NvKmsUnicastEventTypeDeferredRequest:
nvEvoLogInfoString(&infoString,
" pDeferredRequestFifo : %p",
pOpen->unicastEvent.e.deferred.pDeferredRequestFifo);
break;
default:
break;
}
}
nvEvoLogInfoString(&infoString, "");
@@ -4612,6 +4640,7 @@ void nvSendUnicastEvent(struct NvKmsPerOpen *pOpen)
}
nvAssert(pOpen->type == NvKmsPerOpenTypeUnicastEvent);
nvAssert(pOpen->unicastEvent.type != NvKmsUnicastEventTypeUndefined);
nvkms_event_queue_changed(pOpen->pOpenKernel, TRUE);
}
@@ -4626,12 +4655,21 @@ void nvRemoveUnicastEvent(struct NvKmsPerOpen *pOpen)
nvAssert(pOpen->type == NvKmsPerOpenTypeUnicastEvent);
pDeferredRequestFifo = pOpen->unicastEvent.pDeferredRequestFifo;
switch(pOpen->unicastEvent.type)
{
case NvKmsUnicastEventTypeDeferredRequest:
pDeferredRequestFifo =
pOpen->unicastEvent.e.deferred.pDeferredRequestFifo;
if (pDeferredRequestFifo != NULL) {
pDeferredRequestFifo->swapGroup.pOpenUnicastEvent = NULL;
pOpen->unicastEvent.pDeferredRequestFifo = NULL;
pDeferredRequestFifo->swapGroup.pOpenUnicastEvent = NULL;
pOpen->unicastEvent.e.deferred.pDeferredRequestFifo = NULL;
break;
default:
nvAssert("Invalid Unicast Event Type!");
break;
}
pOpen->unicastEvent.type = NvKmsUnicastEventTypeUndefined;
}
static void AllocSurfaceCtxDmasForAllOpens(NVDevEvoRec *pDevEvo)

View File

@@ -124,6 +124,7 @@ SRCS += ../common/modeset/hdmipacket/nvhdmipkt_9471.c
SRCS += ../common/modeset/hdmipacket/nvhdmipkt_9571.c
SRCS += ../common/modeset/hdmipacket/nvhdmipkt_C371.c
SRCS += ../common/modeset/hdmipacket/nvhdmipkt_C671.c
SRCS += ../common/modeset/hdmipacket/nvhdmipkt_C771.c
SRCS += ../common/modeset/timing/nvt_cvt.c
SRCS += ../common/modeset/timing/nvt_displayid20.c
SRCS += ../common/modeset/timing/nvt_dmt.c