570.86.15

This commit is contained in:
Bernhard Stoeckner
2025-01-27 19:36:56 +01:00
parent 9d0b0414a5
commit 54d69484da
1166 changed files with 318863 additions and 182687 deletions

View File

@@ -48,6 +48,12 @@
#include "class/clc670.h"
#include "class/clc67d.h"
#include "class/clc770.h"
#include "class/clc870.h"
#include "class/clc87d.h"
#include "class/clc970.h"
#include "class/clc97d.h"
#include "class/clca70.h"
#include "class/clca7d.h"
#include "hdmi_spec.h"
@@ -181,6 +187,36 @@ static const NVHDMIPKT_CLASS_HIERARCHY hierarchy[] =
NVC770_DISPLAY, // displayClass
NVC67D_CORE_CHANNEL_DMA // coreDmaClass
},
[NVHDMIPKT_C871_CLASS] = {// Index 9==NVHDMIPKT_C871_CLASS
NVHDMIPKT_C871_CLASS, // classId
NVHDMIPKT_C671_CLASS, // parentClassId
NV_FALSE, // isRootClass
initializeHdmiPktInterfaceC871, // initInterface
hdmiConstructorC871, // constructor
hdmiDestructorC871, // destructor
NVC870_DISPLAY, // displayClass
NVC87D_CORE_CHANNEL_DMA // coreDmaClass
},
[NVHDMIPKT_C971_CLASS] = {// Index 10==NVHDMIPKT_C971_CLASS
NVHDMIPKT_C971_CLASS, // classId
NVHDMIPKT_C871_CLASS, // parentClassId
NV_FALSE, // isRootClass
initializeHdmiPktInterfaceC971, // initInterface
hdmiConstructorC971, // constructor
hdmiDestructorC971, // destructor
NVC970_DISPLAY, // displayClass
NVC97D_CORE_CHANNEL_DMA // coreDmaClass
},
[NVHDMIPKT_CA71_CLASS] = {// Index 11==NVHDMIPKT_CA71_CLASS
NVHDMIPKT_CA71_CLASS, // classId
NVHDMIPKT_C971_CLASS, // parentClassId
NV_FALSE, // isRootClass
initializeHdmiPktInterfaceCA71, // initInterface
hdmiConstructorCA71, // constructor
hdmiDestructorCA71, // destructor
NVCA70_DISPLAY, // displayClass
NVCA7D_CORE_CHANNEL_DMA // coreDmaClass
},
};
/********************************** HDMI Library interfaces *************************************/
@@ -262,6 +298,61 @@ NvHdmiPkt_PacketWrite(NvHdmiPkt_Handle libHandle,
pPacket);
}
/*
* NvHdmiPkt_PacketRead
*/
NVHDMIPKT_RESULT
NvHdmiPkt_PacketRead(NvHdmiPkt_Handle libHandle,
NvU32 subDevice,
NvU32 head,
NVHDMIPKT_TYPE packetReg,
NvU32 bufferLen,
NvU8 *const pOutPktBuffer)
{
if (libHandle == NVHDMIPKT_INVALID_HANDLE)
{
return NVHDMIPKT_LIBRARY_INIT_FAIL;
}
NVHDMIPKT_CLASS* pClass = fromHdmiPktHandle(libHandle);
if ((pOutPktBuffer == NULL) || (bufferLen == 0))
{
return NVHDMIPKT_INVALID_ARG;
}
return pClass->hdmiPacketRead(pClass,
subDevice,
head,
packetReg,
bufferLen,
pOutPktBuffer);
}
/*
* NvHdmiPkt_SetupAdvancedInfoframe
*/
NVHDMIPKT_RESULT
NvHdmiPkt_SetupAdvancedInfoframe(NvHdmiPkt_Handle libHandle,
NvU32 subDevice,
NvU32 head,
NVHDMIPKT_TYPE packetReg,
ADVANCED_INFOFRAME const *pInfoframe)
{
if (libHandle == NVHDMIPKT_INVALID_HANDLE)
{
return NVHDMIPKT_LIBRARY_INIT_FAIL;
}
NVHDMIPKT_CLASS* pClass = fromHdmiPktHandle(libHandle);
return pClass->programAdvancedInfoframe(pClass,
subDevice,
head,
packetReg,
pInfoframe);
}
NVHDMIPKT_RESULT
NvHdmi_AssessLinkCapabilities(NvHdmiPkt_Handle libHandle,
NvU32 subDevice,

View File

@@ -57,6 +57,8 @@ typedef enum
NVHDMIPKT_ERR_GENERAL = 5,
NVHDMIPKT_INSUFFICIENT_BANDWIDTH = 6,
NVHDMIPKT_RETRY = 7,
NVHDMIPKT_INSUFFICIENT_BUFFER = 8,
NVHDMIPKT_DSC_PPS_ERROR = 9
} NVHDMIPKT_RESULT;
// NVHDMIPKT_TYPE: HDMI Packet Enums
@@ -75,7 +77,11 @@ typedef enum _NVHDMIPKT_TYPE
NVHDMIPKT_TYPE_SHARED_GENERIC4 = 9,
NVHDMIPKT_TYPE_SHARED_GENERIC5 = 10,
NVHDMIPKT_TYPE_SHARED_GENERIC6 = 11,
NVHDMIPKT_INVALID_PKT_TYPE = 12
NVHDMIPKT_TYPE_SHARED_GENERIC7 = 12,
NVHDMIPKT_TYPE_SHARED_GENERIC8 = 13,
NVHDMIPKT_TYPE_SHARED_GENERIC9 = 14,
NVHDMIPKT_TYPE_SHARED_GENERIC10 = 15,
NVHDMIPKT_INVALID_PKT_TYPE = 16
} NVHDMIPKT_TYPE;
// Hdmi packet TransmitControl defines. These definitions reflect the
@@ -173,6 +179,23 @@ typedef enum _NVHDMIPKT_TC
DRF_DEF(_HDMI_PKT, _TRANSMIT_CTRL, _LOC, _VBLANK)),
} NVHDMIPKT_TC;
typedef enum _INFOFRAME_CTRL_RUN_MODE
{
INFOFRAME_CTRL_RUN_MODE_ALWAYS = 0,
INFOFRAME_CTRL_RUN_MODE_ONCE,
INFOFRAME_CTRL_RUN_MODE_FID_ALWAYS,
INFOFRAME_CTRL_RUN_MODE_FID_ONCE,
INFOFRAME_CTRL_RUN_MODE_FID_TRIGGER
} INFOFRAME_CTRL_RUN_MODE;
typedef enum _INFOFRAME_CTRL_LOC
{
INFOFRAME_CTRL_LOC_VBLANK = 0,
INFOFRAME_CTRL_LOC_VSYNC,
INFOFRAME_CTRL_LOC_LINE,
INFOFRAME_CTRL_LOC_LOADV
} INFOFRAME_CTRL_LOC;
// RM client handles. Used when client chooses that hdmi library make RM calls.
// NOTE: NVHDMIPKT_RM_CALLS_INTERNAL macro should be define to use it.
typedef struct tagNVHDMIPKT_RM_CLIENT_HANDLES
@@ -260,6 +283,39 @@ typedef struct _tagNVHDMIPKT_CALLBACK
} NVHDMIPKT_CALLBACK;
/************************************************************************************************
* runMode - specify one of the modes of operation*
* location - vsync/line/vblank *
* flipId - client to provide if FID mode of operation, 0 otherwise *
* lineNum - if infoframe is sent at line border specify lineNum. 0 is default *
* *
* T239 chip more infoframe support *
************************************************************************************************/
typedef struct tagADVANCED_INFOFRAME
{
INFOFRAME_CTRL_RUN_MODE runMode;
INFOFRAME_CTRL_LOC location;
NvU32 flipId;
NvU32 lineNum;
NvU32 numAdditionalInfoframes;
NvU32 packetLen; // client is expected to fill in 9 DWs for each infoframe, leaving unused bytes 0
NvU8 const * pPacket; // (4 bytes header, 32 bytes max payload per infoframe) For SIZE > 0, pPacket is
// continuous array of multiple infoframes each 9DW in size
// flags
NvU32 isLargeInfoframe : 1; // set if client wants SIZE > 0. Default 0 = normal infoframe
NvU32 lineIdReversed : 1; // set if client wants line Id reversed. Default 0 = not reversed
NvU32 crcOverride : 1; // set if client uses CRC override. Default 0 = CRC override not used
NvU32 asSdpOverride : 1; // set if client wants to enable AS SDP override in infoframe HW
NvU32 hwChecksum : 1; // set if client wants HW checksum. Default 0 = SW checksum
NvU32 matchFidMethodArmState : 1; // set if client wants HW to send infoframe when FID method's ARM state matches. Default 0 = send only when FID method Active state
NvU32 winMethodCyaBroadcast : 1; // set if client will set up CYA reg for SF to decode directly. Default 0 = private precalc decode (SF decodes from precalc)
NvU32 highAudioPriority : 1; // set if client wants high priority for audio. Default 0 = audio low priority
NvU32 reserved : 24;
} ADVANCED_INFOFRAME;
/*********************** HDMI Library interface to write hdmi ctrl/packet ***********************/
typedef void* NvHdmiPkt_Handle;
#define NVHDMIPKT_INVALID_HANDLE ((NvHdmiPkt_Handle)0)
@@ -307,6 +363,44 @@ NvHdmiPkt_PacketWrite(NvHdmiPkt_Handle libHandle,
NvU8 const *const pPacket);
/************************************************************************************************
* NvHdmiPkt_PacketRead - Returns HDMI NVHDMIPKT_RESULT. *
* *
* Parameters: *
* libHandle - Hdmi library handle, provided on initializing the library. *
* subDevice - Sub Device ID. *
* head - Head number. *
* packetReg - One of the NVHDMIPKT_TYPE types. *
* bufferLen - Size of the client provided read out buffer *
* pOutPktBuffer - buffer into which read packet data is to be written. *
************************************************************************************************/
NVHDMIPKT_RESULT
NvHdmiPkt_PacketRead(NvHdmiPkt_Handle libHandle,
NvU32 subDevice,
NvU32 head,
NVHDMIPKT_TYPE packetReg,
NvU32 bufferLen,
NvU8 *const pOutPktBuffer);
/************************************************************************************************
* NvHdmiPkt_SetupAdvancedInfoframe - Returns HDMI NVHDMIPKT_RESULT. *
* *
* Parameters: *
* libHandle - Hdmi library handle, provided on initializing the library. *
* subDevice - Sub Device ID. *
* head - Head number. *
* packetType - One of the NVHDMIPKT_TYPE types. *
* pInfoframe - details about infoframe to be programmed - run mode/loc/etc and pkt bytes *
************************************************************************************************/
NVHDMIPKT_RESULT
NvHdmiPkt_SetupAdvancedInfoframe(NvHdmiPkt_Handle libHandle,
NvU32 subDevice,
NvU32 head,
NVHDMIPKT_TYPE packetReg,
ADVANCED_INFOFRAME const *pInfoframe);
/***************************** Interface to initialize HDMI Library *****************************/
/************************************************************************************************

View File

@@ -359,6 +359,33 @@ hdmiClearFRLConfigDummy(NVHDMIPKT_CLASS *pThis,
return NVHDMIPKT_SUCCESS;
}
NVHDMIPKT_RESULT
hdmiPacketReadDummy(NVHDMIPKT_CLASS* pThis,
NvU32 subDevice,
NvU32 head,
NVHDMIPKT_TYPE packetReg,
NvU32 bufferLen,
NvU8 *const pOutPktBuffer)
{
NvHdmiPkt_Print(pThis, "ERROR - Dummy function hdmiPacketReadDummy called. "
"Should never be called.");
NvHdmiPkt_Assert(0);
return NVHDMIPKT_SUCCESS;
}
NVHDMIPKT_RESULT
programAdvancedInfoframeDummy(NVHDMIPKT_CLASS* pThis,
NvU32 subDevice,
NvU32 head,
NVHDMIPKT_TYPE packetReg,
const ADVANCED_INFOFRAME* pInfoframe)
{
NvHdmiPkt_Print(pThis, "ERROR - Dummy function programAdvancedInfoframeDummy called. "
"Should never be called.");
NvHdmiPkt_Assert(0);
return NVHDMIPKT_SUCCESS;
}
/*
* initializeHdmiPktInterface0073
*/
@@ -389,4 +416,7 @@ initializeHdmiPktInterface0073(NVHDMIPKT_CLASS* pClass)
pClass->hdmiSetFRLConfig = hdmiSetFRLConfigDummy;
pClass->hdmiClearFRLConfig = hdmiClearFRLConfigDummy;
// More (generic) infoframe support on T239+
pClass->hdmiPacketRead = hdmiPacketReadDummy;
pClass->programAdvancedInfoframe = programAdvancedInfoframeDummy;
}

View File

@@ -828,4 +828,7 @@ initializeHdmiPktInterface9171(NVHDMIPKT_CLASS* pClass)
pClass->hdmiSetFRLConfig = hdmiSetFRLConfigDummy;
pClass->hdmiClearFRLConfig = hdmiClearFRLConfigDummy;
// T239+
pClass->hdmiPacketRead = hdmiPacketReadDummy;
pClass->programAdvancedInfoframe = programAdvancedInfoframeDummy;
}

View File

@@ -360,7 +360,12 @@ static void populateDscCaps(HDMI_SRC_CAPS const * const pSrcCaps,
pDscInfo->sinkCaps.algorithmRevision.versionMajor = 1;
pDscInfo->sinkCaps.algorithmRevision.versionMinor = 2;
pDscInfo->sinkCaps.peakThroughputMode0 = peakThroughput;
pDscInfo->sinkCaps.peakThroughputMode1 = peakThroughput * 2;
// Per DSC v1.2 spec, native 422/420 per-slice peak throughput is approximately twice of RGB/444 peak throughput
// HDMI has only one throughput cap reporting, no separate 422/420 throughput cap unlike for DP, so just double 444's value here.
pDscInfo->sinkCaps.peakThroughputMode1 = (peakThroughput == DSC_DECODER_PEAK_THROUGHPUT_MODE0_340) ?
DSC_DECODER_PEAK_THROUGHPUT_MODE1_650 : // closest approximation to 680Mhz
DSC_DECODER_PEAK_THROUGHPUT_MODE1_800;
}
// Fill in mode related info for DSC lib
@@ -790,7 +795,7 @@ hdmiQueryFRLConfigC671(NVHDMIPKT_CLASS *pThis,
(pClientCtrl->forceBppx16 && ((pClientCtrl->bitsPerPixelX16 < bppMinX16) || (pClientCtrl->bitsPerPixelX16 > bppMaxX16))) ||
(pClientCtrl->forceBppx16 && !pSinkCaps->pHdmiForumInfo->dsc_All_bpp))
{
return NVHDMIPKT_FAIL;
return NVHDMIPKT_INVALID_ARG;
}
bTryUncompressedMode = (bCanUseDSC && (pClientCtrl->enableDSC ||
@@ -1185,8 +1190,9 @@ frlQuery_Success:
{
NvHdmiPkt_Print(pThis, "ERROR - DSC PPS calculation failed.");
NvHdmiPkt_Assert(0);
result = NVHDMIPKT_FAIL;
result = NVHDMIPKT_DSC_PPS_ERROR;
}
if (pDscScratchBuffer != NULL)
{
pThis->callback.free(pThis->cbHandle, pDscScratchBuffer);

View File

@@ -0,0 +1,641 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* File: nvhdmipkt_C871.c
*
*/
#include "nvhdmipkt_common.h"
/*
* Purpose: Provides packet write functions for HDMI library for T23+ chips
*/
#include "nvhdmipkt_class.h"
#include "nvhdmipkt_internal.h"
#include "hdmi_spec.h"
#include "class/clc871.h"
#include "ctrl/ctrl0073/ctrl0073specific.h"
#define NVHDMIPKT_C871_MAX_PKT_BYTES_AVI 21 // 3 bytes header + 18 bytes payload
extern void hdmiWriteAviPacket9171(NVHDMIPKT_CLASS* pThis,
NvU32* pBaseReg,
NvU32 head,
NvU32 packetLen,
NvU8 const *const pPacket);
/*
* translatePacketTypeC871
*/
static NvU32
translatePacketTypeC871(NVHDMIPKT_CLASS* pThis,
NVHDMIPKT_TYPE packetType)
{
NvU32 typeC871 = NVHDMIPKT_INVALID_PKT_TYPE; // initialize to an invalid type enum
switch (packetType)
{
case NVHDMIPKT_TYPE_AVI_INFOFRAME:
typeC871 = NVC871_SF_HDMI_INFO_IDX_AVI_INFOFRAME;
break;
case NVHDMIPKT_TYPE_GENERAL_CONTROL:
typeC871 = NVC871_SF_HDMI_INFO_IDX_GCP;
break;
case NVHDMIPKT_TYPE_AUDIO_INFOFRAME:
default:
NvHdmiPkt_Print(pThis, "ERROR - translatePacketType wrong packet type for class C871: %0x.",
packetType);
NvHdmiPkt_Assert(0);
break;
}
return typeC871;
}
/*
* hdmiWriteAviPacketC871
*/
static void
hdmiWriteAviPacketC871(NVHDMIPKT_CLASS* pThis,
NvU32* pBaseReg,
NvU32 head,
NvU32 packetLen,
NvU8 const *const pPacket)
{
NvU32 data = 0;
if (packetLen > NVHDMIPKT_C871_MAX_PKT_BYTES_AVI)
{
NvHdmiPkt_Print(pThis, "ERROR - input AVI packet length incorrect. Write will be capped to max allowable bytes");
NvHdmiPkt_Assert(0);
}
data = REG_RD32(pBaseReg, NVC871_SF_HDMI_AVI_INFOFRAME_SUBPACK2_LOW(head));
data = FLD_SET_DRF_NUM(C871, _SF_HDMI_AVI_INFOFRAME_SUBPACK2_LOW, _PB14, pPacket[17], data);
data = FLD_SET_DRF_NUM(C871, _SF_HDMI_AVI_INFOFRAME_SUBPACK2_LOW, _PB15, pPacket[18], data);
data = FLD_SET_DRF_NUM(C871, _SF_HDMI_AVI_INFOFRAME_SUBPACK2_LOW, _PB16, pPacket[19], data);
data = FLD_SET_DRF_NUM(C871, _SF_HDMI_AVI_INFOFRAME_SUBPACK2_LOW, _PB17, pPacket[20], data);
REG_WR32(pBaseReg, NVC871_SF_HDMI_AVI_INFOFRAME_SUBPACK2_LOW(head), data);
// the lower 17 bytes remain the same as in 9171 class, call 9171 packet write function to program them
hdmiWriteAviPacket9171(pThis,
pBaseReg,
head,
17, // HB0-2 and PB0-14
pPacket);
return;
}
/*
* hdmiWriteGeneralCtrlPacketC871
*/
static void
hdmiWriteGeneralCtrlPacketC871(NVHDMIPKT_CLASS* pThis,
NvU32* pBaseReg,
NvU32 head,
NvU32 packetLen,
NvU8 const *const pPacket)
{
NvU32 data = 0;
// orIndexer info is ignored.
data = REG_RD32(pBaseReg, NVC871_SF_HDMI_GCP_SUBPACK(head));
data = FLD_SET_DRF_NUM(C871, _SF_HDMI_GCP_SUBPACK, _SB0, pPacket[3], data);
data = FLD_SET_DRF_NUM(C871, _SF_HDMI_GCP_SUBPACK, _SB1, pPacket[4], data);
data = FLD_SET_DRF_NUM(C871, _SF_HDMI_GCP_SUBPACK, _SB2, pPacket[5], data);
REG_WR32(pBaseReg, NVC871_SF_HDMI_GCP_SUBPACK(head), data);
return;
}
/*
* hdmiPacketWriteC871
*/
static NVHDMIPKT_RESULT
hdmiPacketWriteC871(NVHDMIPKT_CLASS* pThis,
NvU32 subDevice,
NvU32 displayId,
NvU32 head,
NVHDMIPKT_TYPE packetType,
NVHDMIPKT_TC transmitControl,
NvU32 packetLen,
NvU8 const *const pPacketIn)
{
NVHDMIPKT_RESULT result = NVHDMIPKT_SUCCESS;
NvU32* pBaseReg = (NvU32*)pThis->memMap[subDevice].pMemBase;
NvU32 pktTypeC871 = pThis->translatePacketType(pThis, packetType);
NvU32 tc = pThis->translateTransmitControl(pThis, transmitControl);
NV0073_CTRL_SPECIFIC_CTRL_HDMI_PARAMS params = {0};
// packetIn can be of varying size. Use a fixed max size buffer for programing hw units to prevent out of bounds access
NvU8 pPacket[NVHDMIPKT_CTAIF_MAX_PKT_BYTES] = {0};
if (pBaseReg == 0 || head >= NVC871_SF_HDMI_AVI_INFOFRAME_CTRL__SIZE_1 ||
packetLen == 0 || pPacketIn == 0 || pktTypeC871 == NVHDMIPKT_INVALID_PKT_TYPE)
{
result = NVHDMIPKT_INVALID_ARG;
NvHdmiPkt_Print(pThis, "Invalid arg");
goto hdmiPacketWriteC871_exit;
}
if (packetLen > NVHDMIPKT_CTAIF_MAX_PKT_BYTES)
{
NvHdmiPkt_Print(pThis, "ERROR - input packet length incorrect %d Packet write will be capped to max allowable bytes", packetLen);
packetLen = NVHDMIPKT_CTAIF_MAX_PKT_BYTES;
NvHdmiPkt_Assert(0);
}
// input packet looks ok to use, copy over the bytes
NVMISC_MEMCPY(pPacket, pPacketIn, packetLen);
// acquire mutex
pThis->callback.acquireMutex(pThis->cbHandle);
// Disable this packet type.
pThis->hdmiWritePacketCtrl(pThis, pBaseReg, head, pktTypeC871, tc, NV_TRUE);
// write the packet
switch (pktTypeC871)
{
case NVC871_SF_HDMI_INFO_IDX_AVI_INFOFRAME:
pThis->hdmiWriteAviPacket(pThis, pBaseReg, head, packetLen, pPacket);
break;
case NVC871_SF_HDMI_INFO_IDX_GCP:
// Check whether the GCP packet is AVMute DISABLE or AvMute ENABLE
// Enable HDMI only on GCP unmute i.e. AVMUTE DISABLE
if (pPacket[HDMI_PKT_HDR_SIZE] == HDMI_GENCTRL_PACKET_MUTE_DISABLE)
{
// Enable HDMI.
NVMISC_MEMSET(&params, 0, sizeof(params));
params.subDeviceInstance = (NvU8)subDevice;
params.displayId = displayId;
params.bEnable = NV0073_CTRL_SPECIFIC_CTRL_HDMI_ENABLE;
#if NVHDMIPKT_RM_CALLS_INTERNAL
if (CALL_DISP_RM(NvRmControl)(pThis->clientHandles.hClient,
pThis->clientHandles.hDisplay,
NV0073_CTRL_CMD_SPECIFIC_CTRL_HDMI,
&params,
sizeof(params)) != NVOS_STATUS_SUCCESS)
#else // !NVHDMIPKT_RM_CALLS_INTERNAL
NvBool bSuccess = pThis->callback.rmDispControl2(pThis->cbHandle,
params.subDeviceInstance,
NV0073_CTRL_CMD_SPECIFIC_CTRL_HDMI,
&params,
sizeof(params));
if (bSuccess == NV_FALSE)
#endif // NVHDMIPKT_RM_CALLS_INTERNAL
{
NvHdmiPkt_Print(pThis, "ERROR - RM call to enable hdmi ctrl failed.");
NvHdmiPkt_Assert(0);
result = NVHDMIPKT_FAIL;
}
}
pThis->hdmiWriteGeneralCtrlPacket(pThis, pBaseReg, head, packetLen, pPacket);
break;
default:
result = NVHDMIPKT_INVALID_ARG;
break;
}
// Enable this infoframe.
pThis->hdmiWritePacketCtrl(pThis, pBaseReg, head, pktTypeC871, tc, NV_FALSE);
// release mutex
pThis->callback.releaseMutex(pThis->cbHandle);
hdmiPacketWriteC871_exit:
return result;
}
NvBool
isInfoframeOffsetAvailable(NvU32* pBaseReg,
NvU32 head,
NvU32 requestedInfoframe)
{
NvU32 regAddr, regData = 0;
NvU32 ifIndex, size;
NvBool bResult = NV_TRUE;
for (ifIndex = 0; ifIndex < NVC871_SF_GENERIC_INFOFRAME_CTRL__SIZE_2; ifIndex++)
{
regAddr = NVC871_SF_GENERIC_INFOFRAME_CTRL(head, ifIndex);
regData = REG_RD32(pBaseReg, regAddr);
size = DRF_VAL(C871, _SF_GENERIC_INFOFRAME_CTRL, _SIZE, regData);
// if an infoframe is enabled and it's occupying the offset the requested infoframe would use,
// we cannot allow programming this requested infoframe
if (FLD_TEST_DRF(C871, _SF_GENERIC_INFOFRAME_CTRL, _ENABLE, _YES, regData) && (size > 0))
{
if ((ifIndex + size) > requestedInfoframe)
{
bResult = NV_FALSE;
break;
}
}
}
return bResult;
}
/*
* disableInfoframeC871
*/
NVHDMIPKT_RESULT
disableInfoframeC871(NVHDMIPKT_CLASS* pThis,
NvU32* pBaseReg,
NvU32 head,
NvU32 ifIndex)
{
NVHDMIPKT_RESULT result = NVHDMIPKT_TIMEOUT;
NvU32 regAddr, regData;
regAddr = NVC871_SF_GENERIC_INFOFRAME_CTRL(head, ifIndex);
regData = REG_RD32(pBaseReg, regAddr);
// if infoframe is already disabled nothing to do
if (FLD_TEST_DRF(C871, _SF_GENERIC_INFOFRAME_CTRL, _ENABLE, _NO, regData))
{
return NVHDMIPKT_SUCCESS;
}
// engage timer callbacks to wait for HW register status change if timer callbacks are provided
NvBool bWaitForIdle = NV_FALSE;
if ((pThis->callback.setTimeout != 0) && (pThis->callback.checkTimeout != 0))
{
// wait until BUSY _NO if timer could be engaged successfully
bWaitForIdle = (pThis->callback.setTimeout(pThis->cbHandle, NVHDMIPKT_STATUS_READ_TIMEOUT_IN_us) == NV_TRUE);
}
// write ENABLE_NO
regData = FLD_SET_DRF(C871, _SF_GENERIC_INFOFRAME_CTRL, _ENABLE, _NO, regData);
REG_WR32(pBaseReg, regAddr, regData);
// if timer callbacks are available poll for disable done
if (bWaitForIdle)
{
regData = REG_RD32(pBaseReg, regAddr);
while(FLD_TEST_DRF(C871, _SF_GENERIC_INFOFRAME_CTRL, _BUSY, _YES, regData))
{
if (pThis->callback.checkTimeout(pThis->cbHandle) == NV_TRUE)
{
// timeout waiting for infoframe to get disabled
NvHdmiPkt_Print(pThis, "MoreInfoframe: timeout waiting for infoframe to get disabled");
goto disableInfoframe_exit;
}
regData = REG_RD32(pBaseReg, regAddr);
}
NvHdmiPkt_Assert(FLD_TEST_DRF(C871, _SF_GENERIC_INFOFRAME_CTRL, _BUSY, _NO, regData));
}
else
{
NvHdmiPkt_Print(pThis, "MoreInfoframe: Clients must ideally provide timer callbacks to wait for enable/disable infoframes");
NvHdmiPkt_Assert(0);
}
result = NVHDMIPKT_SUCCESS;
disableInfoframe_exit:
return result;
}
/*
* programAdvancedInfoframeC871
*/
static NVHDMIPKT_RESULT
programAdvancedInfoframeC871(NVHDMIPKT_CLASS *pThis,
NvU32 subDevice,
NvU32 head,
NVHDMIPKT_TYPE packetReg,
const ADVANCED_INFOFRAME *pInfoframe)
{
NVHDMIPKT_RESULT result = NVHDMIPKT_SUCCESS;
NvU32* pBaseReg = (NvU32*)pThis->memMap[subDevice].pMemBase;
if ((packetReg < NVHDMIPKT_TYPE_SHARED_GENERIC1) || (packetReg >= NVHDMIPKT_INVALID_PKT_TYPE))
{
return NVHDMIPKT_INVALID_ARG;
}
NvU32 ifIndex = packetReg - NVHDMIPKT_TYPE_SHARED_GENERIC1;
NvU32 ifNum, dwordNum;
NvU32 regAddr = 0;
NvU32 regData = 0;
NvU32 numOfInfoframes = pInfoframe->isLargeInfoframe ? (pInfoframe->numAdditionalInfoframes + 1) : 1;
if (NV_FALSE == isInfoframeOffsetAvailable(pBaseReg, head, ifIndex))
{
NvHdmiPkt_Print(pThis, "MoreInfoframe: Client requested overwriting an active infoframe");
}
// acquire mutex
pThis->callback.acquireMutex(pThis->cbHandle);
// disable and wait for infoframe HW unit to be ready
result = disableInfoframeC871(pThis, pBaseReg, head, ifIndex);
if (result != NVHDMIPKT_SUCCESS)
{
return result;
}
// write DATA_CTRL
regData = 0;
regAddr = NVC871_SF_GENERIC_INFOFRAME_DATA_CTRL(head);
regData = FLD_SET_DRF_NUM(C871, _SF_GENERIC_INFOFRAME_DATA_CTRL, _OFFSET, ifIndex, regData);
REG_WR32(pBaseReg, regAddr, regData);
// send header + payload
NvHdmiPkt_Assert(pInfoframe->packetLen == (9 * sizeof(NvU32) * numOfInfoframes));
for (ifNum = 0; ifNum < numOfInfoframes; ifNum++)
{
const NvU8 *pPayload = pInfoframe->pPacket + (ifNum * 9 * sizeof(NvU32));
for (dwordNum = 0; dwordNum < 9; dwordNum++) // each infoframe is 9 DWORDs including the header
{
regData = 0;
regData = FLD_SET_DRF_NUM(C871, _SF_GENERIC_INFOFRAME_DATA, _BYTE0, pPayload[4*dwordNum + 0], regData);
regData = FLD_SET_DRF_NUM(C871, _SF_GENERIC_INFOFRAME_DATA, _BYTE1, pPayload[4*dwordNum + 1], regData);
regData = FLD_SET_DRF_NUM(C871, _SF_GENERIC_INFOFRAME_DATA, _BYTE2, pPayload[4*dwordNum + 2], regData);
regData = FLD_SET_DRF_NUM(C871, _SF_GENERIC_INFOFRAME_DATA, _BYTE3, pPayload[4*dwordNum + 3], regData);
REG_WR32(pBaseReg, NVC871_SF_GENERIC_INFOFRAME_DATA(head), regData);
}
}
// write GENERIC_CONFIG
regData = 0;
regAddr = NVC871_SF_GENERIC_INFOFRAME_CONFIG(head, ifIndex);
regData = FLD_SET_DRF_NUM(C871, _SF_GENERIC_INFOFRAME_CONFIG, _FID, pInfoframe->flipId, regData);
if (pInfoframe->location == INFOFRAME_CTRL_LOC_LINE)
{
regData = FLD_SET_DRF_NUM(C871, _SF_GENERIC_INFOFRAME_CONFIG, _LINE_ID, pInfoframe->lineNum, regData);
regData = (pInfoframe->lineIdReversed) ?
FLD_SET_DRF(C871, _SF_GENERIC_INFOFRAME_CONFIG, _LINE_ID_REVERSED, _YES, regData) :
FLD_SET_DRF(C871, _SF_GENERIC_INFOFRAME_CONFIG, _LINE_ID_REVERSED, _NO, regData);
}
regData = (pInfoframe->crcOverride) ?
FLD_SET_DRF(C871, _SF_GENERIC_INFOFRAME_CONFIG, _CRC_OVERRIDE, _YES, regData) :
FLD_SET_DRF(C871, _SF_GENERIC_INFOFRAME_CONFIG, _CRC_OVERRIDE, _NO, regData);
regData = (pInfoframe->matchFidMethodArmState) ?
FLD_SET_DRF(C871, _SF_GENERIC_INFOFRAME_CONFIG, _MTD_STATE_CTRL, _ARM, regData) : // send Infoframe at LOC when matching FID found at channel's FID method's ARM state
FLD_SET_DRF(C871, _SF_GENERIC_INFOFRAME_CONFIG, _MTD_STATE_CTRL, _ACT, regData); // default is when FID method is at ACTIVE state
// write reg
REG_WR32(pBaseReg, regAddr, regData);
// ENABLE_YES to GENERIC_CTRL
regData = 0;
regAddr = NVC871_SF_GENERIC_INFOFRAME_CTRL(head, ifIndex);
regData = FLD_SET_DRF_NUM(C871, _SF_GENERIC_INFOFRAME_CTRL, _RUN_MODE, pInfoframe->runMode, regData);
regData = FLD_SET_DRF_NUM(C871, _SF_GENERIC_INFOFRAME_CTRL, _LOC, pInfoframe->location, regData);
regData = FLD_SET_DRF_NUM(C871, _SF_GENERIC_INFOFRAME_CTRL, _OFFSET, ifIndex, regData);
regData = FLD_SET_DRF_NUM(C871, _SF_GENERIC_INFOFRAME_CTRL, _SIZE, pInfoframe->numAdditionalInfoframes, regData);
regData = FLD_SET_DRF (C871, _SF_GENERIC_INFOFRAME_CTRL, _ENABLE, _YES, regData);
// write reg
REG_WR32(pBaseReg, regAddr, regData);
NvHdmiPkt_Print(pThis, "MoreInfoframe: Sent infoframe of length %d bytes, transmit ctrl 0x%x at offset %d head=%x subdev=%d",
pInfoframe->packetLen, regData, ifIndex, head, subDevice);
// setup MSC_CTRL
regData = 0;
regAddr = NVC871_SF_GENERIC_INFOFRAME_MISC_CTRL(head);
regData = pInfoframe->winMethodCyaBroadcast ?
FLD_SET_DRF(C871, _SF_GENERIC_INFOFRAME_MISC_CTRL, _WIN_CHN_SEL, _PUBLIC, regData) :
FLD_SET_DRF(C871, _SF_GENERIC_INFOFRAME_MISC_CTRL, _WIN_CHN_SEL, _PRIVATE, regData) ;
regData = pInfoframe->highAudioPriority ?
FLD_SET_DRF(C871, _SF_GENERIC_INFOFRAME_MISC_CTRL, _AUDIO_PRIORITY, _HIGH, regData) :
FLD_SET_DRF(C871, _SF_GENERIC_INFOFRAME_MISC_CTRL, _AUDIO_PRIORITY, _LOW, regData);
// write reg
REG_WR32(pBaseReg, regAddr, regData);
// release mutex
pThis->callback.releaseMutex(pThis->cbHandle);
return result;
}
/*
* hdmiWritePacketCtrlC871
*/
static NVHDMIPKT_RESULT
hdmiWritePacketCtrlLegacyPktsC871(NVHDMIPKT_CLASS* pThis,
NvU32* pBaseReg,
NvU32 head,
NvU32 pktTypeC871,
NvU32 transmitControl,
NvBool bDisable)
{
NVHDMIPKT_RESULT result = NVHDMIPKT_INVALID_ARG;
NvU32 regOffset = 0;
NvU32 hdmiCtrl = 0;
if (pBaseReg == 0 || head >= NVC871_SF_HDMI_INFO_CTRL__SIZE_1)
{
return result;
}
switch (pktTypeC871)
{
case NVC871_SF_HDMI_INFO_IDX_AVI_INFOFRAME:
case NVC871_SF_HDMI_INFO_IDX_GCP:
regOffset = NVC871_SF_HDMI_INFO_CTRL(head, pktTypeC871);
hdmiCtrl = REG_RD32(pBaseReg, regOffset);
hdmiCtrl = (bDisable == NV_TRUE) ?
(FLD_SET_DRF(C871, _SF_HDMI_INFO_CTRL, _ENABLE, _DIS, hdmiCtrl)) :
(transmitControl);
REG_WR32(pBaseReg, regOffset, hdmiCtrl);
result = NVHDMIPKT_SUCCESS;
break;
default:
NvHdmiPkt_Assert(0 && "Invalid pkt type!");
break;
}
return result;
}
/*
* hdmiPacketReadC871
*/
static NVHDMIPKT_RESULT
hdmiPacketReadC871(NVHDMIPKT_CLASS* pThis,
NvU32 subDevice,
NvU32 head,
NVHDMIPKT_TYPE packetReg,
NvU32 bufferLen,
NvU8 *const pOutPktBuffer)
{
NvU32 ifIndex, ifNum, dw, regAddr, regData, numOfInfoframes;
NVHDMIPKT_RESULT result = NVHDMIPKT_SUCCESS;
NvU32* pBaseReg = (NvU32*)pThis->memMap[subDevice].pMemBase;
if ((packetReg < NVHDMIPKT_TYPE_SHARED_GENERIC1) || (packetReg >= NVHDMIPKT_INVALID_PKT_TYPE))
{
return NVHDMIPKT_INVALID_ARG;
}
ifIndex = packetReg - NVHDMIPKT_TYPE_SHARED_GENERIC1;
// write infoframe Offset to DATA_CTRL
regData = 0;
regAddr = NVC871_SF_GENERIC_INFOFRAME_DATA_CTRL(head);
regData = FLD_SET_DRF_NUM(C871, _SF_GENERIC_INFOFRAME_DATA_CTRL, _OFFSET, ifIndex, regData);
REG_WR32(pBaseReg, regAddr, regData);
// read size of infoframe programmed at this Offset
regAddr = NVC871_SF_GENERIC_INFOFRAME_CTRL(head, ifIndex);
regData = REG_RD32(pBaseReg, regAddr);
numOfInfoframes = DRF_VAL(C871, _SF_GENERIC_INFOFRAME_CTRL, _SIZE, regData) + 1; // total size is 1 more than SIZE field
NvU32 remainingBufSize = bufferLen;
NvU8 *pBuffer = pOutPktBuffer;
for (ifNum = 0; ifNum < numOfInfoframes; ifNum++)
{
if (remainingBufSize == 0)
{
NvHdmiPkt_Assert(0 && "MoreInfoframe: Buffer size insufficient to copy read packet data");
result = NVHDMIPKT_INSUFFICIENT_BUFFER;
break;
}
// a temporary buffer to read a 36 byte chunk of this infoframe
NvU8 pktBytes[9 * sizeof(NvU32)];
for (dw = 0; dw < 9; dw++) // each infoframe is 9 DWORDs including the header
{
regData = REG_RD32(pBaseReg, NVC871_SF_GENERIC_INFOFRAME_DATA(head));
pktBytes[dw*4 + 0] = DRF_VAL(C871, _SF_GENERIC_INFOFRAME_DATA, _BYTE0, regData);
pktBytes[dw*4 + 1] = DRF_VAL(C871, _SF_GENERIC_INFOFRAME_DATA, _BYTE1, regData);
pktBytes[dw*4 + 2] = DRF_VAL(C871, _SF_GENERIC_INFOFRAME_DATA, _BYTE2, regData);
pktBytes[dw*4 + 3] = DRF_VAL(C871, _SF_GENERIC_INFOFRAME_DATA, _BYTE3, regData);
}
NvU32 bytesCopied = (remainingBufSize > 36) ? 36 : remainingBufSize;
NVMISC_MEMCPY(pBuffer, &pktBytes, bytesCopied);
// move out buffer ptr by the copied bytes
pBuffer += bytesCopied;
// reduce remaining buffer size by the amount we copied
remainingBufSize = remainingBufSize - bytesCopied;
}
return result;
}
/*
* hdmiPacketCtrlC871
*/
static NVHDMIPKT_RESULT
hdmiPacketCtrlC871(NVHDMIPKT_CLASS* pThis,
NvU32 subDevice,
NvU32 displayId,
NvU32 head,
NVHDMIPKT_TYPE packetType,
NVHDMIPKT_TC transmitControl)
{
NvU32* pBaseReg = (NvU32*)pThis->memMap[subDevice].pMemBase;
NvU32 tc = pThis->translateTransmitControl(pThis, transmitControl);
if ((pBaseReg == 0) || (head >= NVC871_SF_GENERIC_INFOFRAME_CTRL__SIZE_1) ||
(packetType >= NVHDMIPKT_INVALID_PKT_TYPE))
{
return NVHDMIPKT_INVALID_ARG;
}
if ((packetType == NVHDMIPKT_TYPE_VENDOR_SPECIFIC_INFOFRAME) ||
(packetType == NVHDMIPKT_TYPE_GENERIC))
{
NvHdmiPkt_Print(pThis, "Generic and VSI registers removed in C871 HW. Call NvHdmiPkt_SetupAdvancedInfoframe to use one of the generic registers!");
NvHdmiPkt_Assert(0);
return NVHDMIPKT_INVALID_ARG;
}
if (packetType >= NVHDMIPKT_TYPE_SHARED_GENERIC1 && packetType <= NVHDMIPKT_TYPE_SHARED_GENERIC10)
{
// client is only expected to call packet ctrl interface to disable the infoframe, no support for other packet ctrl options
// to reprogram/change run mode of a packet, call NvHdmiPkt_SetupAdvancedInfoframe interface
NvHdmiPkt_Assert(FLD_TEST_DRF(_HDMI_PKT, _TRANSMIT_CTRL, _ENABLE, _DIS, transmitControl));
return disableInfoframeC871(pThis, pBaseReg, head, (packetType - NVHDMIPKT_TYPE_SHARED_GENERIC1));
}
NvU32 pktTypeC871 = pThis->translatePacketType(pThis, packetType);
return pThis->hdmiWritePacketCtrl(pThis, pBaseReg, head, pktTypeC871, tc, NV_FALSE);
}
// non-HW - class utility/maintenance functions
/*
* hdmiConstructorC871
*/
NvBool
hdmiConstructorC871(NVHDMIPKT_CLASS* pThis)
{
NvBool result = NV_TRUE;
return result;
}
/*
* hdmiDestructorC871
*/
void
hdmiDestructorC871(NVHDMIPKT_CLASS* pThis)
{
return;
}
/*
* initializeHdmiPktInterfaceC871
*/
void
initializeHdmiPktInterfaceC871(NVHDMIPKT_CLASS* pClass)
{
// Update SF_USER data
pClass->dispSfUserClassId = NVC871_DISP_SF_USER;
pClass->dispSfUserSize = sizeof(NvC871DispSfUserMap);
pClass->translatePacketType = translatePacketTypeC871;
pClass->hdmiWriteAviPacket = hdmiWriteAviPacketC871;
pClass->hdmiWriteGeneralCtrlPacket = hdmiWriteGeneralCtrlPacketC871;
pClass->hdmiPacketWrite = hdmiPacketWriteC871;
pClass->hdmiPacketCtrl = hdmiPacketCtrlC871;
pClass->hdmiWritePacketCtrl = hdmiWritePacketCtrlLegacyPktsC871;
// generic infoframe (shareable by DP and HDMI)
pClass->hdmiPacketRead = hdmiPacketReadC871;
pClass->programAdvancedInfoframe = programAdvancedInfoframeC871;
}

View File

@@ -0,0 +1,204 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* File: nvhdmipkt_C971.c
*
*/
#include "nvhdmipkt_common.h"
/*
* Purpose: Provides packet write functions for HDMI library for NVD5.0 chips
*/
#include "nvhdmipkt_class.h"
#include "nvhdmipkt_internal.h"
#include "class/clc971.h"
/*
* programAdvancedInfoframeC971
*/
static NVHDMIPKT_RESULT
programAdvancedInfoframeC971(NVHDMIPKT_CLASS *pThis,
NvU32 subDevice,
NvU32 head,
NVHDMIPKT_TYPE packetReg,
const ADVANCED_INFOFRAME *pInfoframe)
{
NVHDMIPKT_RESULT result = NVHDMIPKT_SUCCESS;
NvU32* pBaseReg = (NvU32*)pThis->memMap[subDevice].pMemBase;
if ((packetReg < NVHDMIPKT_TYPE_SHARED_GENERIC1) || (packetReg >= NVHDMIPKT_INVALID_PKT_TYPE))
{
return NVHDMIPKT_INVALID_ARG;
}
NvU32 ifIndex = packetReg - NVHDMIPKT_TYPE_SHARED_GENERIC1;
NvU32 ifNum, dwordNum;
NvU32 regAddr = 0;
NvU32 regData = 0;
NvU32 numOfInfoframes = pInfoframe->isLargeInfoframe ? (pInfoframe->numAdditionalInfoframes + 1) : 1;
if (NV_FALSE == isInfoframeOffsetAvailable(pBaseReg, head, ifIndex))
{
NvHdmiPkt_Print(pThis, "MoreInfoframe: Client requested overwriting an active infoframe");
}
NvHdmiPkt_Assert((pInfoframe->crcOverride == 0) &&
"CRC Override bit not supported in Nvd 5.0");
NvHdmiPkt_Assert((pInfoframe->winMethodCyaBroadcast == 0) &&
"window channel priv reg control not supported in Nvd5.0");
NvHdmiPkt_Assert((pInfoframe->location != INFOFRAME_CTRL_LOC_LOADV) &&
"LoadV location not supported in Nvd5.0");
// acquire mutex
pThis->callback.acquireMutex(pThis->cbHandle);
// disable and wait for infoframe HW unit to be ready
// Note, C971 HW provides Clear option for SENT field, so we don't have to disable
// just to make sure new data sending is successful. But we disable Infoframe
// before reprogramming to avoid corrupting a payload that is actively being sent
result = disableInfoframeC871(pThis, pBaseReg, head, ifIndex);
if (result != NVHDMIPKT_SUCCESS)
{
return result;
}
// write SENT bit to clear the SENT field
regAddr = NVC971_SF_GENERIC_INFOFRAME_CTRL(head, ifIndex);
regData = REG_RD32(pBaseReg, regAddr);
regData = FLD_SET_DRF(C971, _SF_GENERIC_INFOFRAME_CTRL, _SENT, _CLEAR, regData);
REG_WR32(pBaseReg, regAddr, regData);
// write DATA_CTRL
regData = 0;
regAddr = NVC971_SF_GENERIC_INFOFRAME_DATA_CTRL(head);
regData = FLD_SET_DRF_NUM(C971, _SF_GENERIC_INFOFRAME_DATA_CTRL, _OFFSET, ifIndex, regData);
REG_WR32(pBaseReg, regAddr, regData);
// send header + payload
NvHdmiPkt_Assert(pInfoframe->packetLen == (9 * sizeof(NvU32) * numOfInfoframes));
for (ifNum = 0; ifNum < numOfInfoframes; ifNum++)
{
const NvU8 *pPayload = pInfoframe->pPacket + (ifNum * 9 * sizeof(NvU32));
for (dwordNum = 0; dwordNum < 9; dwordNum++) // each infoframe is 9 DWORDs including the header
{
regData = 0;
regData = FLD_SET_DRF_NUM(C971, _SF_GENERIC_INFOFRAME_DATA, _BYTE0, pPayload[4*dwordNum + 0], regData);
regData = FLD_SET_DRF_NUM(C971, _SF_GENERIC_INFOFRAME_DATA, _BYTE1, pPayload[4*dwordNum + 1], regData);
regData = FLD_SET_DRF_NUM(C971, _SF_GENERIC_INFOFRAME_DATA, _BYTE2, pPayload[4*dwordNum + 2], regData);
regData = FLD_SET_DRF_NUM(C971, _SF_GENERIC_INFOFRAME_DATA, _BYTE3, pPayload[4*dwordNum + 3], regData);
REG_WR32(pBaseReg, NVC971_SF_GENERIC_INFOFRAME_DATA(head), regData);
}
}
// write GENERIC_CONFIG
regData = 0;
regAddr = NVC971_SF_GENERIC_INFOFRAME_CONFIG(head, ifIndex);
regData = FLD_SET_DRF_NUM(C971, _SF_GENERIC_INFOFRAME_CONFIG, _FID, pInfoframe->flipId, regData);
if (pInfoframe->location == INFOFRAME_CTRL_LOC_LINE)
{
regData = FLD_SET_DRF_NUM(C971, _SF_GENERIC_INFOFRAME_CONFIG, _LINE_ID, pInfoframe->lineNum, regData);
regData = (pInfoframe->lineIdReversed) ?
FLD_SET_DRF(C971, _SF_GENERIC_INFOFRAME_CONFIG, _LINE_ID_REVERSED, _YES, regData) :
FLD_SET_DRF(C971, _SF_GENERIC_INFOFRAME_CONFIG, _LINE_ID_REVERSED, _NO, regData);
}
regData = (pInfoframe->asSdpOverride) ?
FLD_SET_DRF(C971, _SF_GENERIC_INFOFRAME_CONFIG, _AS_SDP_OVERRIDE_EN, _YES, regData) :
FLD_SET_DRF(C971, _SF_GENERIC_INFOFRAME_CONFIG, _AS_SDP_OVERRIDE_EN, _NO, regData);
regData = (pInfoframe->matchFidMethodArmState) ?
FLD_SET_DRF(C971, _SF_GENERIC_INFOFRAME_CONFIG, _MTD_STATE_CTRL, _ARM, regData) :
// send Infoframe at LOC when matching FID found at channel's FID method's ARM state
FLD_SET_DRF(C971, _SF_GENERIC_INFOFRAME_CONFIG, _MTD_STATE_CTRL, _ACT, regData);
// default is when FID method is at ACTIVE state
// write reg
REG_WR32(pBaseReg, regAddr, regData);
// ENABLE_YES to GENERIC_CTRL
regData = 0;
regAddr = NVC971_SF_GENERIC_INFOFRAME_CTRL(head, ifIndex);
regData = FLD_SET_DRF_NUM(C971, _SF_GENERIC_INFOFRAME_CTRL, _RUN_MODE, pInfoframe->runMode, regData);
regData = FLD_SET_DRF_NUM(C971, _SF_GENERIC_INFOFRAME_CTRL, _LOC, pInfoframe->location, regData);
regData = FLD_SET_DRF_NUM(C971, _SF_GENERIC_INFOFRAME_CTRL, _OFFSET, ifIndex, regData);
regData = FLD_SET_DRF_NUM(C971, _SF_GENERIC_INFOFRAME_CTRL, _SIZE, pInfoframe->numAdditionalInfoframes, regData);
regData = FLD_SET_DRF (C971, _SF_GENERIC_INFOFRAME_CTRL, _ENABLE, _YES, regData);
// write reg
REG_WR32(pBaseReg, regAddr, regData);
NvHdmiPkt_Print(pThis, "MoreInfoframe: Sent infoframe of length %d bytes, transmit ctrl 0x%x at offset %d head=%x subdev=%d",
pInfoframe->packetLen, regData, ifIndex, head, subDevice);
// setup MSC_CTRL
regData = 0;
regAddr = NVC971_SF_GENERIC_INFOFRAME_MISC_CTRL(head);
regData = pInfoframe->highAudioPriority ?
FLD_SET_DRF(C971, _SF_GENERIC_INFOFRAME_MISC_CTRL, _AUDIO_PRIORITY, _HIGH, regData) :
FLD_SET_DRF(C971, _SF_GENERIC_INFOFRAME_MISC_CTRL, _AUDIO_PRIORITY, _LOW, regData);
// write reg
REG_WR32(pBaseReg, regAddr, regData);
// release mutex
pThis->callback.releaseMutex(pThis->cbHandle);
return result;
}
// non-HW - class utility/maintenance functions
/*
* hdmiConstructorC971
*/
NvBool
hdmiConstructorC971(NVHDMIPKT_CLASS* pThis)
{
NvBool result = NV_TRUE;
return result;
}
/*
* hdmiDestructorC971
*/
void
hdmiDestructorC971(NVHDMIPKT_CLASS* pThis)
{
return;
}
/*
* initializeHdmiPktInterfaceC971
*/
void
initializeHdmiPktInterfaceC971(NVHDMIPKT_CLASS* pClass)
{
// Update SF_USER data
pClass->dispSfUserClassId = NVC971_DISP_SF_USER;
pClass->dispSfUserSize = sizeof(NvC971DispSfUserMap);
// generic infoframe (shareable by DP and HDMI)
pClass->programAdvancedInfoframe = programAdvancedInfoframeC971;
}

View File

@@ -0,0 +1,65 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* File: nvhdmipkt_CA71.c
*
*/
#include "nvhdmipkt_common.h"
/*
* Purpose: Provides packet write functions for HDMI library for NVD5.0 chips
*/
#include "nvhdmipkt_class.h"
#include "nvhdmipkt_internal.h"
#include "class/clca71.h"
// non-HW - class utility/maintenance functions
/*
* hdmiConstructorCA71
*/
NvBool
hdmiConstructorCA71(NVHDMIPKT_CLASS* pThis)
{
NvBool result = NV_TRUE;
return result;
}
/*
* hdmiDestructorCA71
*/
void
hdmiDestructorCA71(NVHDMIPKT_CLASS* pThis)
{
return;
}
/*
* initializeHdmiPktInterfaceCA71
*/
void
initializeHdmiPktInterfaceCA71(NVHDMIPKT_CLASS* pClass)
{
// Update SF_USER data
pClass->dispSfUserClassId = NVCA71_DISP_SF_USER;
pClass->dispSfUserSize = sizeof(NvCA71DispSfUserMap);
}

View File

@@ -48,6 +48,9 @@ typedef enum
NVHDMIPKT_C571_CLASS = 6, // TU102
NVHDMIPKT_C671_CLASS = 7, // GA102, T234D
NVHDMIPKT_C771_CLASS = 8, // AD10X
NVHDMIPKT_C871_CLASS = 9, // T239
NVHDMIPKT_C971_CLASS = 10, // NVD5.0
NVHDMIPKT_CA71_CLASS = 11,
NVHDMIPKT_INVALID_CLASS // Not to be used by client, and always the last entry here.
} NVHDMIPKT_CLASS_ID;
@@ -85,6 +88,21 @@ struct tagNVHDMIPKT_CLASS
NvU32 packetLen,
NvU8 const *const pPacket);
NVHDMIPKT_RESULT
(*hdmiPacketRead) (NVHDMIPKT_CLASS* pThis,
NvU32 subDevice,
NvU32 head,
NVHDMIPKT_TYPE packetReg,
NvU32 bufferLen,
NvU8 *const pOutPktBuffer);
NVHDMIPKT_RESULT
(*programAdvancedInfoframe) (NVHDMIPKT_CLASS* pThis,
NvU32 subDevice,
NvU32 head,
NVHDMIPKT_TYPE packetReg,
const ADVANCED_INFOFRAME* pInfoframe);
// HW functions - that read/write registers
NvBool
(*hdmiReadPacketStatus) (NVHDMIPKT_CLASS* pThis,

View File

@@ -51,7 +51,9 @@ typedef struct tagNVHDMIPKT_MEM_MAP NVHDMIPKT_MEM_MAP;
#define REG_WR32(reg, offset, data) ((*(((volatile NvU32*)(reg)) + ((offset)/4))) = (data))
#define NVHDMIPKT_INVALID_SUBDEV (0xFFFFFFFF)
#if !defined (WINNT) && !defined(NVHDMIPKT_NVKMS)
#define NVHDMIPKT_DONT_USE_TIMER
#endif
#define NVHDMIPKT_STATUS_READ_TIMEOUT_IN_us (1*1000*1000) /* us - micro second */
// Disp SF User memory map and handle structure
@@ -110,4 +112,17 @@ extern NVHDMIPKT_RESULT hdmiClearFRLConfigDummy(NVHDMIPKT_CLASS *pThis,
NvU32 subDevice,
NvU32 displayId);
extern NVHDMIPKT_RESULT hdmiPacketReadDummy(NVHDMIPKT_CLASS* pThis,
NvU32 subDevice,
NvU32 head,
NVHDMIPKT_TYPE packetReg,
NvU32 bufferLen,
NvU8 *const pOutPktBuffer);
extern NVHDMIPKT_RESULT programAdvancedInfoframeDummy(NVHDMIPKT_CLASS* pThis,
NvU32 subDevice,
NvU32 head,
NVHDMIPKT_TYPE packetReg,
const ADVANCED_INFOFRAME* pInfoframe);
#endif //_NVHDMIPKT_COMMON_H_

View File

@@ -45,6 +45,9 @@ extern void initializeHdmiPktInterface9571(NVHDMIPKT_CLASS*);
extern void initializeHdmiPktInterfaceC371(NVHDMIPKT_CLASS*);
extern void initializeHdmiPktInterfaceC671(NVHDMIPKT_CLASS*);
extern void initializeHdmiPktInterfaceC771(NVHDMIPKT_CLASS*);
extern void initializeHdmiPktInterfaceC871(NVHDMIPKT_CLASS*);
extern void initializeHdmiPktInterfaceC971(NVHDMIPKT_CLASS*);
extern void initializeHdmiPktInterfaceCA71(NVHDMIPKT_CLASS*);
extern NvBool hdmiConstructor0073(NVHDMIPKT_CLASS*);
extern void hdmiDestructor0073 (NVHDMIPKT_CLASS*);
@@ -62,5 +65,18 @@ extern NvBool hdmiConstructorC671(NVHDMIPKT_CLASS*);
extern void hdmiDestructorC671 (NVHDMIPKT_CLASS*);
extern NvBool hdmiConstructorC771(NVHDMIPKT_CLASS*);
extern void hdmiDestructorC771 (NVHDMIPKT_CLASS*);
extern NvBool hdmiConstructorC871(NVHDMIPKT_CLASS*);
extern void hdmiDestructorC871 (NVHDMIPKT_CLASS*);
extern NvBool isInfoframeOffsetAvailable(NvU32* pBaseReg,
NvU32 head,
NvU32 requestedInfoframe);
extern NVHDMIPKT_RESULT disableInfoframeC871(NVHDMIPKT_CLASS* pThis,
NvU32* pBaseReg,
NvU32 head,
NvU32 ifIndex);
extern NvBool hdmiConstructorC971(NVHDMIPKT_CLASS*);
extern void hdmiDestructorC971 (NVHDMIPKT_CLASS*);
extern NvBool hdmiConstructorCA71(NVHDMIPKT_CLASS*);
extern void hdmiDestructorCA71 (NVHDMIPKT_CLASS*);
#endif //_NVHDMIPKT_INTERNAL_H_

View File

@@ -49,7 +49,7 @@ const NvU32 NVT_CVT_H_SYNC_PER = 8; // HSYNC percentage (8%)
const NvU32 NVT_CVT_RB_HBLANK_CELLS = 20; // 160 fixed hblank for RB
const NvU32 NVT_CVT_RB_HFPORCH_CELLS = 6; // 48 fixed hfporch for RB
const NvU32 NVT_CVT_RB_HSYNCW_CELLS = 4; // 32 fixed hsyncwidth for RB
const NvU32 NVT_CVT_RB_MIN_VBLANK = 23; // 460 lines (or 460 us?) [1000000:460 = 50000:23]
const NvU32 NVT_CVT_RB_MIN_VBLANK = 23; // 460 line s (or 460 us?) [1000000:460 = 50000:23]
const NvU32 NVT_CVT_MIN_V_BPORCH = 6; // Minimum vertical back porch.
@@ -154,6 +154,7 @@ NVT_STATUS NvTiming_CalcCVT(NvU32 width, NvU32 height, NvU32 rr, NvU32 flag, NVT
pT->etc.status = NVT_STATUS_CVT;
// For 1, 2, 3, 4 in Computation of common parameters
// H_PIXELS_RND = ROUNDDOWN(H_PIXELS / CELL_GRAN_RND,0) * CELL_GRAN_RND
if ((width % NVT_CVT_CELL_GRAN)!=0)
{
@@ -178,7 +179,8 @@ NVT_STATUS NvTiming_CalcCVT(NvU32 width, NvU32 height, NvU32 rr, NvU32 flag, NVT
dwIdealDutyCycle_DEN = dwHPeroidEstimate_DEN;
dwIdealDutyCycle_NUM = NVT_CVT_C_PRIME * dwHPeroidEstimate_DEN - NVT_CVT_M_PRIME_D_20 * dwHPeriodEstimate_NUM;
if (dwIdealDutyCycle_NUM < dwIdealDutyCycle_DEN * 20)
if (dwIdealDutyCycle_NUM < dwIdealDutyCycle_DEN * 20 ||
(NVT_CVT_C_PRIME * dwHPeroidEstimate_DEN < NVT_CVT_M_PRIME_D_20 * dwHPeriodEstimate_NUM))
{
dwIdealDutyCycle_NUM=20;
dwIdealDutyCycle_DEN=1;
@@ -211,7 +213,8 @@ NVT_STATUS NvTiming_CalcCVT(NvU32 width, NvU32 height, NvU32 rr, NvU32 flag, NVT
pT->VFrontPorch = (NvU16)(NVT_CVT_V_PORCH);
pT->VSyncWidth = getCVTVSync(dwXCells * NVT_CVT_CELL_GRAN, height);
pT->pclk = dwPClk;
pT->pclk = dwPClk;
pT->pclk1khz = (dwPClk << 3) + (dwPClk << 1); // *10
pT->HSyncPol = NVT_H_SYNC_NEGATIVE;
pT->VSyncPol = NVT_V_SYNC_POSITIVE;
@@ -411,6 +414,7 @@ NVT_STATUS NvTiming_CalcCVT_RB2(NvU32 width, NvU32 height, NvU32 rr, NvBool is10
pT->VSyncWidth = NVT_CVT_RB2_V_SYNC_WIDTH;
pT->VFrontPorch = (NvU16)(act_vbi_lines - NVT_CVT_RB2_V_SYNC_WIDTH - NVT_CVT_RB2_MIN_V_BPORCH);
pT->pclk = (act_pixel_freq_khz + 5) / 10; //convert to 10Khz
pT->pclk1khz = act_pixel_freq_khz;
pT->HSyncPol = NVT_H_SYNC_POSITIVE;
pT->VSyncPol = NVT_V_SYNC_NEGATIVE;
pT->HBorder = pT->VBorder = 0; // not supported
@@ -610,6 +614,7 @@ NVT_STATUS NvTiming_CalcCVT_RB3(NvU32 width,
pT->VSyncWidth = NVT_CVT_RB3_V_SYNC_WIDTH;
pT->VFrontPorch = (NvU16)(act_v_blank_lines - NVT_CVT_RB3_V_SYNC_WIDTH - v_back_porch);
pT->pclk = ((NvU32)act_pixel_freq_khz + 5) / 10; //convert to 10Khz
pT->pclk1khz = act_pixel_freq_khz;
pT->HSyncPol = NVT_H_SYNC_POSITIVE;
pT->VSyncPol = NVT_V_SYNC_NEGATIVE;
pT->HBorder = pT->VBorder = 0; // not supported

View File

@@ -1552,9 +1552,9 @@ parseDisplayId20Timing7Descriptor(
pDescriptor = (const DISPLAYID_2_0_TIMING_7_DESCRIPTOR *)pVoidDescriptor;
// pclk is in 1Khz
pTiming->pclk = ((pDescriptor->pixel_clock[2] << 16 |
pDescriptor->pixel_clock[1] << 8 |
pDescriptor->pixel_clock[0]) + 1);
pTiming->pclk1khz = ((pDescriptor->pixel_clock[2] << 16 |
pDescriptor->pixel_clock[1] << 8 |
pDescriptor->pixel_clock[0]) + 1);
pTiming->HBorder = 0;
pTiming->VBorder = 0;
@@ -1637,17 +1637,17 @@ parseDisplayId20Timing7Descriptor(
pTiming->etc.aspect = 0;
}
pTiming->etc.rr = NvTiming_CalcRR(pTiming->pclk,
pTiming->etc.rr = NvTiming_CalcRR(pTiming->pclk1khz,
pTiming->interlaced,
pTiming->HTotal,
pTiming->VTotal) / 10;
pTiming->etc.rrx1k = NvTiming_CalcRRx1k(pTiming->pclk,
pTiming->etc.rrx1k = NvTiming_CalcRRx1k(pTiming->pclk1khz,
pTiming->interlaced,
pTiming->HTotal,
pTiming->VTotal) / 10;
// pclk change to 10k
pTiming->pclk /= 10;
// pclk change to 10kHz
pTiming->pclk = pTiming->pclk1khz / 10;
pTiming->etc.status = NVT_STATUS_DISPLAYID_7N(++count);

View File

@@ -37,13 +37,13 @@ PUSH_SEGMENTS
// DMT table 2-1
// Macro to declare a TIMING initializer for given parameters without border
#define DMT_TIMING(hv,hfp,hsw,ht,hsp,vv,vfp,vsw,vt,vsp,rr,pclk,id) \
{hv,0,hfp,hsw,ht,(hsp)=='-',vv,0,vfp,vsw,vt,(vsp)=='-',NVT_PROGRESSIVE,pclk,{0,rr,set_rrx1k(pclk,ht,vt),0,0x1,{0},{0},{0},{0},NVT_DEF_TIMING_STATUS(NVT_TYPE_DMT,id),"VESA DMT"}}
{hv,0,hfp,hsw,ht,(hsp)=='-',vv,0,vfp,vsw,vt,(vsp)=='-',NVT_PROGRESSIVE,pclk,((pclk<<3)+(pclk<<1)),{0,rr,set_rrx1k(pclk,ht,vt),0,0x1,{0},{0},{0},{0},NVT_DEF_TIMING_STATUS(NVT_TYPE_DMT,id),"VESA DMT"}}
#define DMTRB_TIMING(hv,hfp,hsw,ht,hsp,vv,vfp,vsw,vt,vsp,rr,pclk,id) \
{hv,0,hfp,hsw,ht,(hsp)=='-',vv,0,vfp,vsw,vt,(vsp)=='-',NVT_PROGRESSIVE,pclk,{0,rr,set_rrx1k(pclk,ht,vt),0,0x1,{0},{0},{0},{0},NVT_DEF_TIMING_STATUS(NVT_TYPE_DMT_RB,id),"VESA DMT/RB"}}
{hv,0,hfp,hsw,ht,(hsp)=='-',vv,0,vfp,vsw,vt,(vsp)=='-',NVT_PROGRESSIVE,pclk,((pclk<<3)+(pclk<<1)),{0,rr,set_rrx1k(pclk,ht,vt),0,0x1,{0},{0},{0},{0},NVT_DEF_TIMING_STATUS(NVT_TYPE_DMT_RB,id),"VESA DMT/RB"}}
#define DMTRB_2_TIMING(hv,hfp,hsw,ht,hsp,vv,vfp,vsw,vt,vsp,rr,pclk,id) \
{hv,0,hfp,hsw,ht,(hsp)=='-',vv,0,vfp,vsw,vt,(vsp)=='-',NVT_PROGRESSIVE,pclk,{0,rr,set_rrx1k(pclk,ht,vt),0,0x1,{0},{0},{0},{0},NVT_DEF_TIMING_STATUS(NVT_TYPE_DMT_RB_2,id),"VESA DMT/RB2"}}
{hv,0,hfp,hsw,ht,(hsp)=='-',vv,0,vfp,vsw,vt,(vsp)=='-',NVT_PROGRESSIVE,pclk,((pclk<<3)+(pclk<<1)),{0,rr,set_rrx1k(pclk,ht,vt),0,0x1,{0},{0},{0},{0},NVT_DEF_TIMING_STATUS(NVT_TYPE_DMT_RB_2,id),"VESA DMT/RB2"}}
DATA_SEGMENT(PAGE_DATA)
@@ -56,7 +56,7 @@ static NVT_TIMING DMT[] =
DMT_TIMING ( 720, 36, 72, 936,'-', 400, 1, 3, 446,'+', 85, 3550, 0x03),
DMT_TIMING ( 640, 8, 96, 800,'-', 480, 2, 2, 525,'-', 60, 2518, 0x04),
// 640x480x72Hz (VESA) - this entry have borders
{640,8,16,40,832,NVT_H_SYNC_NEGATIVE,480,8,1,3,520,NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE,3150,{0,72,72000,0,1,{0},{0},{0},{0},NVT_DEF_TIMING_STATUS(NVT_TYPE_DMT,5),"VESA DMT"}},
{640,8,16,40,832,NVT_H_SYNC_NEGATIVE,480,8,1,3,520,NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE,3150,31500,{0,72,72000,0,1,{0},{0},{0},{0},NVT_DEF_TIMING_STATUS(NVT_TYPE_DMT,5),"VESA DMT"}},
DMT_TIMING ( 640, 16, 64, 840,'-', 480, 1, 3, 500,'-', 75, 3150, 0x06),
DMT_TIMING ( 640, 56, 56, 832,'-', 480, 1, 3, 509,'-', 85, 3600, 0x07),
DMT_TIMING ( 800, 24, 72,1024,'+', 600, 1, 2, 625,'+', 56, 3600, 0x08),

View File

@@ -33,6 +33,7 @@
#include "nvt_dsc_pps.h"
#include "nvmisc.h"
#include "displayport/displayport.h"
#include "displayport/displayport2x.h"
#include "nvctassert.h"
#include <stddef.h>
@@ -104,6 +105,7 @@ typedef struct
NvU32 multi_tile; // 1 = Multi-tile architecture, 0 = dsc single or dual mode without multi-tile
NvU32 peak_throughput_mode0; // peak throughput supported by the sink for 444 and simple 422 modes.
NvU32 peak_throughput_mode1; // peak throughput supported by the sink for native 422 and 420 modes.
NvU32 eDP; // 1 = connector type is eDP, 0 otherwise.
} DSC_INPUT_PARAMS;
//output pps parameters after calculation
@@ -989,7 +991,6 @@ DSC_PpsCalcBase
out->pps_identifier = 0;
ENUM3_CHECK("bits_per_component", in->bits_per_component, 8, 10, 12);
out->bits_per_component = in->bits_per_component;
RANGE_CHECK("bits_per_pixelx16", in->bits_per_pixel, 8 * BPP_UNIT, (out->bits_per_component * 3) * BPP_UNIT);
out->bits_per_pixel = in->bits_per_pixel;
RANGE_CHECK("linebuf_depth", in->linebuf_depth, DSC_DECODER_LINE_BUFFER_BIT_DEPTH_MIN, DSC_DECODER_LINE_BUFFER_BIT_DEPTH_MAX);
out->linebuf_depth = in->linebuf_depth;
@@ -1598,22 +1599,74 @@ DSC_PpsCheckSliceHeight(DSC_OUTPUT_PARAMS *out)
* NVT_STATUS_ERR if unsuccessful;
*/
static NVT_STATUS
Dsc_PpsCalcHeight(DSC_OUTPUT_PARAMS *out)
Dsc_PpsCalcHeight
(
const DSC_INPUT_PARAMS *in,
DSC_OUTPUT_PARAMS *out
)
{
if(out->slice_height == 0)
//
// From Blackwell and later, eDP we will try to use smallest slice height
// if client has not asked for a specific slice height. Multi-tile is enabled
// from Blackwell and so here we will use that condition for deciding on
// slice height calculation. Minimum slice height will help with power savings
// when eDP1.5 Selective Update is enabled.
//
if (in->multi_tile && in->eDP)
{
NvU32 i;
for (i = 1 ; i <= 16; i++)
if (out->slice_height == 0U)
{
out->slice_height = out->pic_height / i;
if (out->pic_height != out->slice_height * i )
continue;
// Minimum area of slice should be 15000 as per VESA spec
out->slice_height = (NvU32)NV_CEIL(15000U,(out->slice_width));
while (out->pic_height > out->slice_height)
{
if (out->pic_height % out->slice_height == 0U)
{
if (DSC_PpsCheckSliceHeight(out) == NVT_STATUS_SUCCESS)
{
return NVT_STATUS_SUCCESS;
}
else
{
out->slice_height++;
}
}
else
{
out->slice_height++;
}
if (DSC_PpsCheckSliceHeight(out) == NVT_STATUS_SUCCESS)
return NVT_STATUS_SUCCESS;
if (out->pic_height == out->slice_height)
{
if(DSC_PpsCheckSliceHeight(out) == NVT_STATUS_SUCCESS)
{
return NVT_STATUS_SUCCESS;
}
else
{
return NVT_STATUS_PPS_SLICE_HEIGHT_ERROR;
}
}
}
}
}
else
{
if(out->slice_height == 0)
{
NvU32 i;
for (i = 1 ; i <= 16; i++)
{
out->slice_height = out->pic_height / i;
if (out->pic_height != out->slice_height * i )
continue;
if (DSC_PpsCheckSliceHeight(out) == NVT_STATUS_SUCCESS)
return NVT_STATUS_SUCCESS;
}
// Error! can't find valid slice_height
return NVT_STATUS_PPS_SLICE_HEIGHT_ERROR;
}
// Error! can't find valid slice_height
return NVT_STATUS_PPS_SLICE_HEIGHT_ERROR;
}
RANGE_CHECK("slice_height", out->slice_height, 8, out->pic_height);
@@ -1677,7 +1730,7 @@ DSC_PpsCalc
if (ret != NVT_STATUS_SUCCESS) return ret;
ret = DSC_PpsCalcRcInitValue(out);
if (ret != NVT_STATUS_SUCCESS) return ret;
ret = Dsc_PpsCalcHeight(out);
ret = Dsc_PpsCalcHeight(in, out);
if (ret != NVT_STATUS_SUCCESS) return ret;
ret = DSC_PpsCalcRcParam(out);
return ret;
@@ -1842,9 +1895,14 @@ _validateInput
(pDscInfo->forcedDscParams.sliceCount != 1U) &&
(pDscInfo->forcedDscParams.sliceCount != 2U) &&
(pDscInfo->forcedDscParams.sliceCount != 4U) &&
(pDscInfo->forcedDscParams.sliceCount != 8U))
(pDscInfo->forcedDscParams.sliceCount != 8U) &&
(pDscInfo->forcedDscParams.sliceCount != 10U) &&
(pDscInfo->forcedDscParams.sliceCount != 12U) &&
(pDscInfo->forcedDscParams.sliceCount != 16U) &&
(pDscInfo->forcedDscParams.sliceCount != 20U) &&
(pDscInfo->forcedDscParams.sliceCount != 24U))
{
// ERROR - Forced Slice Count has to be 1/2/4/8.
// ERROR - Forced Slice Count has to be 1/2/4/8/10/12/16/20/24.
return NVT_STATUS_DSC_SLICE_ERROR;
}
@@ -2013,7 +2071,7 @@ _validateInput
return NVT_STATUS_INVALID_PARAMETER;
}
if (!IS_VALID_LINKBW(pWARData->dpData.linkRateHz / DP_LINK_BW_FREQ_MULTI_MBPS))
if (!IS_VALID_DP2_X_LINKBW(pWARData->dpData.linkRateHz))
{
// ERROR - Incorrect DP Link rate info sent with WAR data
return NVT_STATUS_INVALID_PARAMETER;
@@ -2084,7 +2142,6 @@ DSC_GeneratePPSWithSliceCountMask
NvU32 sliceArrayCount;
NvU32 i;
DSC_INFO localDscInfo;
NvU32* ppsOut = NULL;
NVT_STATUS status;
DSC_GENERATE_PPS_OPAQUE_WORKAREA scratchBuffer;
@@ -2166,27 +2223,19 @@ DSC_GeneratePPSWithSliceCountMask
//
if (possibleSliceCountMask)
{
NvU32 minSliceCountOut = 0;
localDscInfo = *pDscInfo;
for(i = 0U ; i < sliceArrayCount; i++)
{
if (possibleSliceCountMask & DSC_SliceCountMaskforSliceNum(validSliceNum[i]))
{
ppsOut = NULL;
// Use the forced bits per pixel, if any
NvU32 bitsPerPixelX16Local = *pBitsPerPixelX16;
localDscInfo.forcedDscParams.sliceCount = validSliceNum[i];
if (localDscInfo.forcedDscParams.sliceCount == minSliceCount)
{
//
// We need to return PPS with minimum slice count if client
// has not forced any slice count even though we generate
// pps with all other possible slice counts to validate them.
//
ppsOut = pps;
}
status = DSC_GeneratePPS(&localDscInfo, pModesetInfo, pWARData,
availableBandwidthBitsPerSecond, &scratchBuffer,
ppsOut, pBitsPerPixelX16);
NULL, &bitsPerPixelX16Local);
if (status == NVT_STATUS_SUCCESS)
{
//
@@ -2200,9 +2249,30 @@ DSC_GeneratePPSWithSliceCountMask
// corresponding bit index.
//
validSliceCountMask |= NVBIT32((validSliceNum[i]) - 1U);
if ((minSliceCountOut == 0) || (minSliceCountOut > validSliceNum[i]))
{
minSliceCountOut = validSliceNum[i];
}
}
}
}
if (minSliceCountOut != 0)
{
//
// We need to return PPS with minimum slice count if client
// has not forced any slice count even though we generate
// pps with all other possible slice counts to validate them.
//
localDscInfo.forcedDscParams.sliceCount = minSliceCountOut;
status = DSC_GeneratePPS(&localDscInfo, pModesetInfo, pWARData,
availableBandwidthBitsPerSecond, &scratchBuffer,
pps, pBitsPerPixelX16);
if (status != NVT_STATUS_SUCCESS)
{
return status;
}
}
}
else
{
@@ -2390,7 +2460,14 @@ DSC_GeneratePPS
dscOverhead = minSliceCount * 2U;
dataRate = pWARData->dpData.linkRateHz;
if(pWARData->dpData.bIs128b132bChannelCoding)
{
dataRate = LINK_RATE_TO_DATA_RATE_128B_132B(pWARData->dpData.linkRateHz);
}
else
{
dataRate = LINK_RATE_TO_DATA_RATE_8B_10B(pWARData->dpData.linkRateHz);
}
if ((pWARData->dpData.hBlank * dataRate / pModesetInfo->pixelClockHz) <
(protocolOverhead + dscOverhead + 3U))
{
@@ -2408,6 +2485,7 @@ DSC_GeneratePPS
in->bits_per_pixel = i;
}
}
in->eDP = (pWARData->dpData.bIsEdp == NV_TRUE) ? 1 : 0;
}
//

View File

@@ -253,11 +253,13 @@ typedef struct
NvU32 laneCount;
DSC_DP_MODE dpMode;
NvU32 hBlank;
NvBool bIsEdp;
NvBool bIs128b132bChannelCoding;
}dpData;
} WAR_DATA;
typedef struct {
NvU8 data[496U]; // total size of DSC_IN/OUTPUT_PARAMS
NvU8 data[500U]; // total size of DSC_IN/OUTPUT_PARAMS
} DSC_GENERATE_PPS_OPAQUE_WORKAREA;
/*

View File

@@ -38,7 +38,7 @@ PUSH_SEGMENTS
// Macro to declare a TIMING initializer for given parameters without border
#define EST_TIMING(hv,hfp,hsw,ht,hsp,vv,vfp,vsw,vt,vsp,rr,pclk,format) \
{hv,0,hfp,hsw,ht,(hsp)=='-',vv,0,vfp,vsw,vt,(vsp)=='-',NVT_PROGRESSIVE,pclk,{0,rr,set_rrx1k(pclk,ht,vt),0,1,{0},{0},{0},{0},format,"VESA Established"}}
{hv,0,hfp,hsw,ht,(hsp)=='-',vv,0,vfp,vsw,vt,(vsp)=='-',NVT_PROGRESSIVE,pclk,((pclk<<3)+(pclk<<1)),{0,rr,set_rrx1k(pclk,ht,vt),0,1,{0},{0},{0},{0},format,"VESA Established"}}
DATA_SEGMENT(PAGE_DATA)
#if !defined(NV_WSA)
@@ -53,12 +53,12 @@ static const NVT_TIMING EDID_EST[] =
{
EST_TIMING( 720, 0, 0, 720,'-', 400, 0,0, 400,'-',70, 0,NVT_STATUS_EDID_EST), // 720x400x70Hz (IBM, VGA)
EST_TIMING( 720, 0, 0, 720,'-', 400, 0,0, 400,'-',88, 0,NVT_STATUS_EDID_EST), // 720x400x88Hz (IBM, XGA2)
{640,0,16,96,800,NVT_H_SYNC_NEGATIVE,480,0,10,2,525,NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE,2518,{0,60,60000,0,1,{0},{0},{0},{0},NVT_STATUS_EDID_EST,"EDID_Established"}},
{640,0,16,96,800,NVT_H_SYNC_NEGATIVE,480,0,10,2,525,NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE,2518,25180,{0,60,60000,0,1,{0},{0},{0},{0},NVT_STATUS_EDID_EST,"EDID_Established"}},
EST_TIMING( 640, 0, 0, 640,'-', 480, 0,0, 480,'-',67, 0,NVT_STATUS_EDID_EST), // 640x480x67Hz (Apple, Mac II)
// 640x480x72Hz (VESA) - this entry have borders
{640,8,16,40,832,NVT_H_SYNC_NEGATIVE,480,8,1,3,520,NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE,3150,{0,72,72000,0,1,{0},{0},{0},{0},NVT_STATUS_EDID_EST,"EDID_Established"}},
{640,8,16,40,832,NVT_H_SYNC_NEGATIVE,480,8,1,3,520,NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE,3150,31500,{0,72,72000,0,1,{0},{0},{0},{0},NVT_STATUS_EDID_EST,"EDID_Established"}},
EST_TIMING( 640,16, 64, 840,'-', 480, 1,3, 500,'-',75, 3150,NVT_STATUS_EDID_EST), // 640x480x75Hz (VESA)
EST_TIMING( 800,24, 72,1024,'+', 600, 1,2, 625,'+',56, 3600,NVT_STATUS_EDID_EST), // 800x600x56Hz (VESA)
EST_TIMING( 800,40,128,1056,'+', 600, 1,4, 628,'+',60, 4000,NVT_STATUS_EDID_EST), // 800x600x60Hz (VESA)
@@ -564,7 +564,8 @@ NVT_STATUS parseEdidDetailedTimingDescriptor(NvU8 *p, NVT_TIMING *pT)
pT->VSyncWidth = (NvU16)((pDTD->bDTVerticalSync & 0x0F) + ((pDTD->bDTHorizVertSyncOverFlow & 0x03) << 4));
// pixel clock
pT->pclk = (NvU32)pDTD->wDTPixelClock;
pT->pclk = (NvU32)pDTD->wDTPixelClock;
pT->pclk1khz = (NvU32)((pT->pclk << 3) + (pT->pclk << 1));
// sync polarities
if ((pDTD->bDTFlags & 0x18) == 0x18)
@@ -2964,7 +2965,7 @@ NvU32 NvTiming_CalculateCommonEDIDCRC32(NvU8* pEDIDBuffer, NvU32 edidVersion)
CommonEDIDBuffer[0x7F] = 0;
CommonEDIDBuffer[0xFF] = 0;
// We also need to zero out any "EDID Other Monitor Descriptors" (http://en.wikipedia.org/wiki/Extended_display_identification_data)
// We also need to zero out any "EDID Other Monitor Descriptors" (https://en.wikipedia.org/wiki/Extended_display_identification_data)
for (edidBufferIndex = 54; edidBufferIndex <= 108; edidBufferIndex += 18)
{
if (CommonEDIDBuffer[edidBufferIndex] == 0 && CommonEDIDBuffer[edidBufferIndex+1] == 0)

View File

@@ -38,15 +38,15 @@ PUSH_SEGMENTS
#define EIA_TIMING(hv,hfp,hsw,ht,hsp,vv,vfp,vsw,vt,vsp,rrx1k,ip,aspect,rep,format) \
{hv,0,hfp,hsw,ht,(hsp)=='-',vv,0,vfp,vsw,vt,(vsp)=='-',(ip)=='i' ? NVT_INTERLACED:NVT_PROGRESSIVE,\
0,{0,((rrx1k)+500)/1000,rrx1k,((1?aspect)<<16)|(0?aspect),rep,{0},{0},{0},{0},NVT_STATUS_EDID_861STn(format),"CEA-861B:#"#format""}}
0,0,{0,((rrx1k)+500)/1000,rrx1k,((1?aspect)<<16)|(0?aspect),rep,{0},{0},{0},{0},NVT_STATUS_EDID_861STn(format),"CEA-861B:#"#format""}}
#define NVT_TIMING(hv,hfp,hsw,ht,hsp,vv,vfp,vsw,vt,vsp,rrx1k,ip,aspect,rep,format,name) \
{hv,0,hfp,hsw,ht,(hsp)=='-',vv,0,vfp,vsw,vt,(vsp)=='-',(ip)=='i' ? NVT_INTERLACED:NVT_PROGRESSIVE,\
0,{0,((rrx1k)+500)/1000,rrx1k,((1?aspect)<<16)|(0?aspect),rep,{0},{0},{0},{0},NVT_TYPE_NV_PREDEFINEDn(format),name}}
0,0,{0,((rrx1k)+500)/1000,rrx1k,((1?aspect)<<16)|(0?aspect),rep,{0},{0},{0},{0},NVT_TYPE_NV_PREDEFINEDn(format),name}}
#define HDMI_EXT_TIMING(hv,hfp,hsw,ht,hsp,vv,vfp,vsw,vt,vsp,rrx1k,ip,aspect,rep,format,name) \
{hv,0,hfp,hsw,ht,(hsp)=='-',vv,0,vfp,vsw,vt,(vsp)=='-',(ip)=='i' ? NVT_INTERLACED:NVT_PROGRESSIVE,\
0,{0,((rrx1k)+500)/1000,rrx1k,((1?aspect)<<16)|(0?aspect),rep,{0},{0},{0},{0},NVT_STATUS_HDMI_EXTn(format),name}}
0,0,{0,((rrx1k)+500)/1000,rrx1k,((1?aspect)<<16)|(0?aspect),rep,{0},{0},{0},{0},NVT_STATUS_HDMI_EXTn(format),name}}
#define RID_MODE(hv, hsp, vv, vsp, ip, aspect, rid) \
{hv, (hsp)=='-', vv, (vsp)=='-',(ip)=='i'? NVT_INTERLACED:NVT_PROGRESSIVE,((1?aspect)<<16)|(0?aspect), rid}
@@ -261,7 +261,7 @@ static const NVT_TIMING EIA861B[]=
EIA_TIMING( 7680,2352,176,10800,'+',4320,16,20,4400,'+', 50000,'p', 16:9,0x1,198),// 7680 x 4320p @50 (Format 198)
EIA_TIMING( 7680, 552,176, 9000,'+',4320,16,20,4400,'+', 59940,'p', 16:9,0x1,199),// 7680 x 4320p @59.94/60 (Format 199)
EIA_TIMING( 7680,2112,176,10560,'+',4320,16,20,4500,'+',100000,'p', 16:9,0x1,200),// 7680 x 4320p @100 (Format 200)
EIA_TIMING( 7680, 352,176, 8000,'+',4320,16,20,4500,'+',119880,'p', 16:9,0x1,201),// 7680 x 4320p @119.88/120 (Format 201)
EIA_TIMING( 7680, 352,176, 8800,'+',4320,16,20,4500,'+',119880,'p', 16:9,0x1,201),// 7680 x 4320p @119.88/120 (Format 201)
EIA_TIMING( 7680,2552,176,11000,'+',4320,16,20,4500,'+', 23976,'p', 64:27,0x1,202),// 7680 x 4320p @23.98/24 (Format 202)
EIA_TIMING( 7680,2352,176,10800,'+',4320,16,20,4400,'+', 25000,'p', 64:27,0x1,203),// 7680 x 4320p @25 (Format 203)
EIA_TIMING( 7680, 552,176, 9000,'+',4320,16,20,4400,'+', 29970,'p', 64:27,0x1,204),// 7680 x 4320p @29.97/30 (Format 204)
@@ -269,12 +269,12 @@ static const NVT_TIMING EIA861B[]=
EIA_TIMING( 7680,2352,176,10800,'+',4320,16,20,4400,'+', 50000,'p', 64:27,0x1,206),// 7680 x 4320p @50 (Format 206)
EIA_TIMING( 7680, 552,176, 9000,'+',4320,16,20,4400,'+', 59940,'p', 64:27,0x1,207),// 7680 x 4320p @59.94/60 (Format 207)
EIA_TIMING( 7680,2112,176,10560,'+',4320,16,20,4500,'+',100000,'p', 64:27,0x1,208),// 7680 x 4320p @100 (Format 208)
EIA_TIMING( 7680, 352,176, 8800,'+',4500,16,20,4950,'+',119880,'p', 64:27,0x1,209),// 7680 x 4320p @119.88/120 (Format 209)
EIA_TIMING( 7680, 352,176, 8800,'+',4320,16,20,4500,'+',119880,'p', 64:27,0x1,209),// 7680 x 4320p @119.88/120 (Format 209)
EIA_TIMING(10240,1492,176,12500,'+',4320,16,20,4950,'+', 23976,'p', 64:27,0x1,210),//10240 x 4320p @23.98/24 (Format 210)
EIA_TIMING(10240,2492,176,13500,'+',4320,16,20,4400,'+', 25000,'p', 64:27,0x1,211),//10240 x 4320p @25 (Format 211)
EIA_TIMING(10240, 288,176,11000,'+',4320,16,20,4500,'+', 29970,'p', 64:27,0x1,212),//10240 x 4320p @29.97/30 (Format 212)
EIA_TIMING(10240,1492,176,12500,'+',4320,16,20,4950,'+', 47950,'p', 64:27,0x1,213),//10240 x 4320p @47.95/48 (Format 213)
EIA_TIMING(10240,2492,176,13500,'+',4320,16,20,4400,'+', 44000,'p', 64:27,0x1,214),//10240 x 4320p @50 (Format 214)
EIA_TIMING(10240,2492,176,13500,'+',4320,16,20,4400,'+', 50000,'p', 64:27,0x1,214),//10240 x 4320p @50 (Format 214)
EIA_TIMING(10240, 288,176,11000,'+',4320,16,20,4500,'+', 59940,'p', 64:27,0x1,215),//10240 x 4320p @59.94/60 (Format 215)
EIA_TIMING(10240,2192,176,13200,'+',4320,16,20,4500,'+',100000,'p', 64:27,0x1,216),//10240 x 4320p @100 (Format 216)
EIA_TIMING(10240, 288,176,11000,'+',4320,16,20,4500,'+',119880,'p', 64:27,0x1,217),//10240 x 4320p @119.88/120 (Format 217)
@@ -649,7 +649,8 @@ void parse861bShortTiming(NVT_EDID_CEA861_INFO *pExt861,
}
// calculate the pixel clock
newTiming.pclk = RRx1kToPclk(&newTiming);
newTiming.pclk = RRx1kToPclk(&newTiming);
newTiming.pclk1khz = (newTiming.pclk << 3) + (newTiming.pclk << 1); // *10
if ((vic <= 64) && (pVic[i] & NVT_CTA861_VIDEO_NATIVE_MASK))
{
@@ -790,7 +791,8 @@ void parseCta861VideoFormatDataBlock(NVT_EDID_CEA861_INFO *pExt861, void *pRawIn
pInfo->hdmiForumInfo.dc_48bit_420);
}
newTiming.etc.flag |= NVT_FLAG_CTA_OVT_TIMING;
newTiming.etc.aspect = RID[pVFDOneByte->rid].aspect;
newTiming.etc.flag |= NVT_FLAG_CTA_OVT_TIMING;
if (pExt861->vfdb[vfdb_idx].info.ntsc)
{
newTiming.etc.flag |= NVT_FLAG_CTA_OVT_FRR_TIMING;
@@ -924,7 +926,8 @@ void parse861bShortYuv420Timing(NVT_EDID_CEA861_INFO *pExt861,
}
// calculate the pixel clock
newTiming.pclk = RRx1kToPclk(&newTiming);
newTiming.pclk = RRx1kToPclk(&newTiming);
newTiming.pclk1khz = (newTiming.pclk << 3) + (newTiming.pclk << 1); // *10
// From CTA-861-F: By default, Y420VDB SVDs, when present in the EDID, shall be less preferred than all regular Video Data Block SVDs.
// So it should use normal VIC code without native flag.
@@ -2161,7 +2164,8 @@ NVT_STATUS NvTiming_EnumCEA861bTiming(NvU32 ceaFormat, NVT_TIMING *pT)
*pT = EIA861B[ceaFormat - 1];
// calculate the pixel clock
pT->pclk = RRx1kToPclk (pT);
pT->pclk = RRx1kToPclk (pT);
pT->pclk1khz = (pT->pclk << 3) + (pT->pclk << 1); // *10
NVT_SET_CEA_FORMAT(pT->etc.status, ceaFormat);
NVT_SNPRINTF((char *)pT->etc.name, sizeof(pT->etc.name), "CTA-861G:#%3d:%dx%dx%3d.%03dHz/%s", (int)ceaFormat, (int)pT->HVisible, (int)((pT->interlaced ? 2 : 1)*pT->VVisible), (int)pT->etc.rrx1k/1000, (int)pT->etc.rrx1k%1000, (pT->interlaced ? "I":"P"));
@@ -2270,7 +2274,8 @@ NVT_STATUS NvTiming_CalcCEA861bTiming(NvU32 width, NvU32 height, NvU32 rr, NvU32
*pT = EIA861B[i];
// calculate the pixel clock
pT->pclk = RRx1kToPclk (pT);
pT->pclk = RRx1kToPclk (pT);
pT->pclk1khz = (pT->pclk << 3) + (pT->pclk << 1); // *10
NVT_SET_CEA_FORMAT(pT->etc.status, NVT_GET_TIMING_STATUS_SEQ(pT->etc.status));
@@ -2336,8 +2341,8 @@ NVT_STATUS NvTiming_ConstructVideoInfoframeCtrl(const NVT_TIMING *pTiming, NVT_V
ridIdx = 10 * (pTiming->etc.name[10] - '0') + (pTiming->etc.name[11] - '0');
}
if (ridIdx > NVT_CTA861_RID_1280x720p_16x9 &&
ridIdx < NVT_CTA861_RID_20480x8640p_64x27)
if (ridIdx >= NVT_CTA861_RID_1280x720p_16x9 &&
ridIdx < NVT_CTA861_RID_EXCEED_RESOLUTION)
{
pCtrl->rid = ridIdx;
}
@@ -2472,7 +2477,7 @@ NVT_STATUS NvTiming_ConstructVideoInfoframeCtrl(const NVT_TIMING *pTiming, NVT_V
}
else
{
// default to no data, to cover other non-cea modes
// default to no data if there is no match, to cover other non-cta modes
pCtrl->pic_aspect_ratio = NVT_VIDEO_INFOFRAME_BYTE2_M1M0_NO_DATA;
}
}
@@ -2839,13 +2844,13 @@ NVT_STATUS NvTiming_ConstructVendorSpecificInfoframe(NVT_EDID_INFO *pEdidInfo, N
nvt_nvu8_set_bits(pInfoFrame->Header.version, NVT_HDMI_VS_HB1_VALUE, NVT_HDMI_VS_HB1_MASK, NVT_HDMI_VS_HB1_SHIFT);
nvt_nvu8_set_bits(pInfoFrame->Header.length, NVT_HDMI_VS_HB2_VALUE, NVT_HDMI_VS_HB2_MASK, NVT_HDMI_VS_HB2_SHIFT);
if (pCtrl->HDMIRevision == 14)
if (pCtrl->VSIFVersion == NVT_VSIF_VERSION_H14B_VSIF)
{
nvt_nvu8_set_bits(pInfoFrame->Data.byte1, NVT_HDMI_VS_BYTE1_OUI_VER_1_4, NVT_HDMI_VS_BYTE1_OUI_MASK, NVT_HDMI_VS_BYTE1_OUI_SHIFT);
nvt_nvu8_set_bits(pInfoFrame->Data.byte2, NVT_HDMI_VS_BYTE2_OUI_VER_1_4, NVT_HDMI_VS_BYTE2_OUI_MASK, NVT_HDMI_VS_BYTE2_OUI_SHIFT);
nvt_nvu8_set_bits(pInfoFrame->Data.byte3, NVT_HDMI_VS_BYTE3_OUI_VER_1_4, NVT_HDMI_VS_BYTE3_OUI_MASK, NVT_HDMI_VS_BYTE3_OUI_SHIFT);
}
else if (pCtrl->HDMIRevision >= 20)
else if (pCtrl->VSIFVersion == NVT_VSIF_VERSION_HF_VSIF)
{
nvt_nvu8_set_bits(pInfoFrame->Data.byte1, NVT_HDMI_VS_BYTE1_OUI_VER_2_0, NVT_HDMI_VS_BYTE1_OUI_MASK, NVT_HDMI_VS_BYTE1_OUI_SHIFT);
nvt_nvu8_set_bits(pInfoFrame->Data.byte2, NVT_HDMI_VS_BYTE2_OUI_VER_2_0, NVT_HDMI_VS_BYTE2_OUI_MASK, NVT_HDMI_VS_BYTE2_OUI_SHIFT);
@@ -3106,7 +3111,7 @@ void NvTiming_ConstructAdaptiveSyncSDP(
NVT_DP_ADAPTIVE_SYNC_SDP_DB3_TARGET_RR_LSB_MASK,
NVT_DP_ADAPTIVE_SYNC_SDP_DB3_TARGET_RR_LSB_SHIFT);
nvt_nvu8_set_bits(pSdp->payload.db4, pCtrl->targetRefreshRate & 0x1,
nvt_nvu8_set_bits(pSdp->payload.db4, (pCtrl->targetRefreshRate & 0x300) >> 8,
NVT_DP_ADAPTIVE_SYNC_SDP_DB4_TARGET_RR_MSB_MASK,
NVT_DP_ADAPTIVE_SYNC_SDP_DB4_TARGET_RR_MSB_SHIFT);
}
@@ -3158,7 +3163,8 @@ NVT_STATUS NvTiming_EnumNvPsfTiming(NvU32 nvPsfFormat, NVT_TIMING *pT)
*pT = PSF_TIMING[nvPsfFormat - 1];
// calculate the pixel clock
pT->pclk = RRx1kToPclk (pT);
pT->pclk = RRx1kToPclk (pT);
pT->pclk1khz = (pT->pclk << 3) + (pT->pclk << 1); // *10
return NVT_STATUS_SUCCESS;
}
@@ -3267,7 +3273,9 @@ void NvTiming_GetHDMIStereoTimingFrom2DTiming(const NVT_TIMING *pTiming, NvU8 St
}
}
// calculate the pixel clock
pExtTiming->timing.pclk = RRx1kToPclk (&(pExtTiming->timing));
pExtTiming->timing.pclk = RRx1kToPclk (&(pExtTiming->timing));
pExtTiming->timing.pclk1khz = (pExtTiming->timing.pclk << 3) + (pExtTiming->timing.pclk << 1); // *10;
return;
}
@@ -3491,7 +3499,8 @@ void parseEdidHDMILLCTiming(NVT_EDID_INFO *pInfo, VSDB_DATA *pVsdb, NvU32 *pMapS
sizeof(newTiming));
// Fill in the pixel clock
newTiming.pclk = RRx1kToPclk(&newTiming);
newTiming.pclk = RRx1kToPclk(&newTiming);
newTiming.pclk1khz = (newTiming.pclk << 3) + (newTiming.pclk << 1); // *10
if (!assignNextAvailableTiming(pInfo, &newTiming))
{
@@ -3638,7 +3647,8 @@ NVT_STATUS NvTiming_EnumHdmiVsdbExtendedTiming(NvU32 hdmi_vic, NVT_TIMING *pT)
return NVT_STATUS_ERR;
}
*pT = HDMI_EXT_4Kx2K_TIMING[hdmi_vic - 1];
pT->pclk = RRx1kToPclk(pT);
pT->pclk = RRx1kToPclk(pT);
pT->pclk1khz = (pT->pclk << 3) + (pT->pclk << 1); // *10
return NVT_STATUS_SUCCESS;
}

View File

@@ -264,6 +264,7 @@ NVT_STATUS NvTiming_CalcOVT(NvU32 width, NvU32 height, NvU32 refreshRate, NVT_TI
pT->VSyncWidth = (NvU16)NVT_OVT_V_SYNC_WIDTH;
pT->VFrontPorch = (NvU16)(vBlank - vSyncPosition);
pT->pclk = (NvU32)(pixelClockRate /*Hz*/ / 1000 + 5) / 10; //convert to 10Khz
pT->pclk1khz = (NvU32)(pixelClockRate /*Hz*/ / 1000); //convert to 1Khz
pT->HSyncPol = NVT_H_SYNC_POSITIVE;
pT->VSyncPol = NVT_V_SYNC_POSITIVE;
pT->HBorder = pT->VBorder = 0; // not supported

View File

@@ -37,24 +37,24 @@ CONS_SEGMENT(PAGE_CONS)
static const NVT_TIMING TV_TIMING[] =
{
{720, 0,21,66,894, NVT_H_SYNC_POSITIVE,240, 0,10,6,262, NVT_V_SYNC_POSITIVE,NVT_INTERLACED, 1407, {0,60,59940,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_SDTV_NTSC_M, "SDTV:NTSC_M"}},
{720, 0,21,66,894, NVT_H_SYNC_POSITIVE,240, 0,10,6,262, NVT_V_SYNC_POSITIVE,NVT_INTERLACED, 1407, {0,60,59940,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_SDTV_NTSC_J, "SDTV:NTSC_J"}},
{720, 0,21,66,894, NVT_H_SYNC_POSITIVE,288, 0,10,8,312, NVT_V_SYNC_POSITIVE,NVT_INTERLACED, 1397, {0,50,50000,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_SDTV_PAL_M, "SDTV:PAL_M"}},
{720, 0,21,66,894, NVT_H_SYNC_POSITIVE,288, 0,10,8,312, NVT_V_SYNC_POSITIVE,NVT_INTERLACED, 1397, {0,50,50000,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_SDTV_PAL_A, "SDTV:PAL_A"}},
{720, 0,21,66,894, NVT_H_SYNC_POSITIVE,288, 0,10,8,312, NVT_V_SYNC_POSITIVE,NVT_INTERLACED, 1397, {0,50,50000,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_SDTV_PAL_N, "SDTV:PAL_N"}},
{720, 0,21,66,894, NVT_H_SYNC_POSITIVE,288, 0,10,8,312, NVT_V_SYNC_POSITIVE,NVT_INTERLACED, 1397, {0,50,50000,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_SDTV_PAL_NC, "SDTV:PAL_NC"}},
{720, 0,21,66,894, NVT_H_SYNC_POSITIVE,240, 0,10,6,262, NVT_V_SYNC_POSITIVE,NVT_INTERLACED, 1407, {0,60,59940,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_480I, "HDTV(analog):480i"}},
{720, 0,15,8, 858, NVT_H_SYNC_NEGATIVE,480, 0,10,4,525, NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE,2700, {0,60,59940,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_480P, "HDTV(analog):480p"}},
{720, 0,21,66,894, NVT_H_SYNC_POSITIVE,288, 0,10,8,312, NVT_V_SYNC_POSITIVE,NVT_INTERLACED, 1397, {0,50,50000,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_576I, "HDTV(analog):576i"}},
{720, 0,10,8, 864, NVT_H_SYNC_NEGATIVE,576, 0,5, 4,625, NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE,2700, {0,50,50000,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_576P, "HDTV(analog):576p"}},
{1280,0,70,80, 1650,NVT_H_SYNC_NEGATIVE,720,0,5, 5,750, NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE,7418, {0,60,59940,0x1009,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_720P, "HDTV(analog):720p"}},
{1920,0,44,88,2200,NVT_H_SYNC_NEGATIVE,540, 0,2, 5,562, NVT_V_SYNC_NEGATIVE,NVT_INTERLACED, 7418, {0,60,59940,0x1009,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_1080I, "HDTV(analog):1080i"}},
{1920,0,44,88,2200,NVT_H_SYNC_NEGATIVE,1080,0,4, 5,1125,NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE,14835,{0,60,59940,0x1009,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_1080P, "HDTV(analog):1080p"}},
{1280,0,400,80,1980,NVT_H_SYNC_NEGATIVE,720,0,5, 5,750, NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE,7425, {0,50,50000,0x1009,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_720P50, "HDTV(analog):720p50"}},
{1920,0,594,88,2750,NVT_H_SYNC_NEGATIVE,1080,0,4, 5,1125,NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE,7425,{0,24,24000,0x1009,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_1080P24,"HDTV(analog):1080p24"}},
{1920,0,484,88,2640,NVT_H_SYNC_NEGATIVE,540, 0,4, 5,562, NVT_V_SYNC_NEGATIVE,NVT_INTERLACED, 7425,{0,50,50000,0x1009,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_1080I50,"HDTV(analog):1080i50"}},
{1920,0,484,88,2640,NVT_H_SYNC_NEGATIVE,1080,0,4, 5,1125,NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE,14850,{0,50,50000,0x1009,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_1080P50,"HDTV(analog):1080p50"}},
{0,0,0,0,0,NVT_H_SYNC_NEGATIVE,0,0,0,0,0,NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE,0,{0,0,0,0,0,{0},{0},{0},{0},0,""}}
{720, 0,21,66,894, NVT_H_SYNC_POSITIVE,240, 0,10, 6,262, NVT_V_SYNC_POSITIVE,NVT_INTERLACED, 1407 , 14070, {0,60,59940,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_SDTV_NTSC_M, "SDTV:NTSC_M"}},
{720, 0,21,66,894, NVT_H_SYNC_POSITIVE,240, 0,10, 6,262, NVT_V_SYNC_POSITIVE,NVT_INTERLACED, 1407 , 14070, {0,60,59940,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_SDTV_NTSC_J, "SDTV:NTSC_J"}},
{720, 0,21,66,894, NVT_H_SYNC_POSITIVE,288, 0,10, 8,312, NVT_V_SYNC_POSITIVE,NVT_INTERLACED, 1397 , 13970, {0,50,50000,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_SDTV_PAL_M, "SDTV:PAL_M"}},
{720, 0,21,66,894, NVT_H_SYNC_POSITIVE,288, 0,10, 8,312, NVT_V_SYNC_POSITIVE,NVT_INTERLACED, 1397 , 13970, {0,50,50000,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_SDTV_PAL_A, "SDTV:PAL_A"}},
{720, 0,21,66,894, NVT_H_SYNC_POSITIVE,288, 0,10, 8,312, NVT_V_SYNC_POSITIVE,NVT_INTERLACED, 1397 , 13970, {0,50,50000,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_SDTV_PAL_N, "SDTV:PAL_N"}},
{720, 0,21,66,894, NVT_H_SYNC_POSITIVE,288, 0,10, 8,312, NVT_V_SYNC_POSITIVE,NVT_INTERLACED, 1397 , 13970, {0,50,50000,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_SDTV_PAL_NC, "SDTV:PAL_NC"}},
{720, 0,21,66,894, NVT_H_SYNC_POSITIVE,240, 0,10, 6,262, NVT_V_SYNC_POSITIVE,NVT_INTERLACED, 1407 , 14070, {0,60,59940,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_480I, "HDTV(analog):480i"}},
{720, 0,15,8, 858, NVT_H_SYNC_NEGATIVE,480, 0,10, 4,525, NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE, 2700 , 27000, {0,60,59940,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_480P, "HDTV(analog):480p"}},
{720, 0,21,66,894, NVT_H_SYNC_POSITIVE,288, 0,10, 8,312, NVT_V_SYNC_POSITIVE,NVT_INTERLACED, 1397 , 13970, {0,50,50000,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_576I, "HDTV(analog):576i"}},
{720, 0,10,8, 864, NVT_H_SYNC_NEGATIVE,576, 0, 5, 4,625, NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE, 2700 , 27000, {0,50,50000,0x0403,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_576P, "HDTV(analog):576p"}},
{1280,0,70,80, 1650,NVT_H_SYNC_NEGATIVE,720, 0, 5, 5,750, NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE, 7418 , 74180, {0,60,59940,0x1009,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_720P, "HDTV(analog):720p"}},
{1920,0,44,88,2200, NVT_H_SYNC_NEGATIVE,540, 0, 2, 5,562, NVT_V_SYNC_NEGATIVE,NVT_INTERLACED, 7418 , 74180, {0,60,59940,0x1009,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_1080I, "HDTV(analog):1080i"}},
{1920,0,44,88,2200, NVT_H_SYNC_NEGATIVE,1080,0, 4, 5,1125,NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE, 14835,148350, {0,60,59940,0x1009,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_1080P, "HDTV(analog):1080p"}},
{1280,0,400,80,1980,NVT_H_SYNC_NEGATIVE,720, 0, 5, 5,750, NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE, 7425 , 74250, {0,50,50000,0x1009,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_720P50, "HDTV(analog):720p50"}},
{1920,0,594,88,2750,NVT_H_SYNC_NEGATIVE,1080,0, 4, 5,1125,NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE, 7425 , 74250, {0,24,24000,0x1009,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_1080P24,"HDTV(analog):1080p24"}},
{1920,0,484,88,2640,NVT_H_SYNC_NEGATIVE,540, 0, 4, 5,562, NVT_V_SYNC_NEGATIVE,NVT_INTERLACED, 7425 , 74250, {0,50,50000,0x1009,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_1080I50,"HDTV(analog):1080i50"}},
{1920,0,484,88,2640,NVT_H_SYNC_NEGATIVE,1080,0, 4, 5,1125,NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE,14850 ,148500, {0,50,50000,0x1009,0x1,{0},{0},{0},{0},NVT_STATUS_HDTV_1080P50,"HDTV(analog):1080p50"}},
{0,0,0,0,0,NVT_H_SYNC_NEGATIVE,0,0,0,0,0,NVT_V_SYNC_NEGATIVE,NVT_PROGRESSIVE,0,0,{0,0,0,0,0,{0},{0},{0},{0},0,""}}
};
//***********************************************

View File

@@ -343,9 +343,9 @@ NvU32 NvTiming_IsTimingRelaxedEqual(const NVT_TIMING *pT1, const NVT_TIMING *pT2
CODE_SEGMENT(NONPAGE_DD_CODE)
NvU32 RRx1kToPclk (NVT_TIMING *pT)
{
return axb_div_c(pT->HTotal * (pT->VTotal + ((pT->interlaced != 0) ? (pT->VTotal + 1) : 0)),
pT->etc.rrx1k,
1000 * ((pT->interlaced != 0) ? 20000 : 10000));
return (NvU32)axb_div_c_64(pT->HTotal * (pT->VTotal + ((pT->interlaced != 0) ? (pT->VTotal + 1) : 0)),
pT->etc.rrx1k,
1000 * ((pT->interlaced != 0) ? 20000 : 10000));
}
CODE_SEGMENT(PAGE_DD_CODE)

View File

@@ -189,6 +189,7 @@ typedef struct tagNVT_TIMING
NvU16 interlaced; //1-interlaced, 0-progressive
NvU32 pclk; //pixel clock in 10KHz
NvU32 pclk1khz; //pixel clock in 1kHz for Type7, CVT RB2, CVT RB3
//other timing related extras
NVT_TIMINGEXT etc;
@@ -774,6 +775,7 @@ typedef enum NVT_TV_FORMAT
#define NVT_CTA861_RID_15360x8640p_16x9 26
#define NVT_CTA861_RID_15360x8640p_64x27 27
#define NVT_CTA861_RID_20480x8640p_64x27 28
#define NVT_CTA861_RID_EXCEED_RESOLUTION NVT_CTA861_RID_NONE
// Table 12 - AVI InfoFrame Video Format Frame Rate
#define NVT_CTA861_FR_NO_DATA NVT_INFOFRAME_CTRL_DONTCARE
@@ -3060,7 +3062,7 @@ typedef struct tagNVT_AUDIO_INFOFRAME_CTRL
typedef struct tagNVT_VENDOR_SPECIFIC_INFOFRAME_CTRL
{
NvU8 Enable;
NvU8 HDMIRevision;
NvU8 VSIFVersion;
NvU8 HDMIFormat;
NvU8 HDMI_VIC;
NvBool ALLMEnable;
@@ -3073,6 +3075,10 @@ typedef struct tagNVT_VENDOR_SPECIFIC_INFOFRAME_CTRL
} NVT_VENDOR_SPECIFIC_INFOFRAME_CTRL;
#define NVT_3D_METADTATA_TYPE_PARALAX 0x00
#define NVT_3D_METADTATA_PARALAX_LEN 0x08
#define NVT_VSIF_VERSION_NONE 0
#define NVT_VSIF_VERSION_H14B_VSIF 14
#define NVT_VSIF_VERSION_HF_VSIF 20
#define NVT_EXTENDED_METADATA_PACKET_INFOFRAME_VER_HDMI21 0x0
#define NVT_EXTENDED_METADATA_PACKET_INFOFRAME_VER_HDMI21A 0x1
@@ -3210,6 +3216,7 @@ typedef struct tagNVT_VIDEO_INFOFRAME
#define NVT_VIDEO_INFOFRAME_BYTE1_Y2Y1Y0_YCbCr444 2
#define NVT_VIDEO_INFOFRAME_BYTE1_Y2Y1Y0_YCbCr420 3
#define NVT_VIDEO_INFOFRAME_BYTE1_Y2Y1Y0_FUTURE 3 // nvlEscape still uses this line 4266
// CTA-861I new requirement
#define NVT_VIDEO_INFOFRAME_BYTE1_Y2Y1Y0_IDODEFINED 7
// CEA-861-F - Unix still used this one
#define NVT_VIDEO_INFOFRAME_BYTE1_Y1Y0_MASK 0x60
@@ -4005,7 +4012,7 @@ typedef struct tagNVT_EXTENDED_METADATA_PACKET_INFOFRAME
#define NVT_DP_ADAPTIVE_SYNC_SDP_DB3_TARGET_RR_LSB_MASK 0xff
#define NVT_DP_ADAPTIVE_SYNC_SDP_DB3_TARGET_RR_LSB_SHIFT 0
#define NVT_DP_ADAPTIVE_SYNC_SDP_DB4_TARGET_RR_MSB_MASK 0x01
#define NVT_DP_ADAPTIVE_SYNC_SDP_DB4_TARGET_RR_MSB_MASK 0x03
#define NVT_DP_ADAPTIVE_SYNC_SDP_DB4_TARGET_RR_MSB_SHIFT 0
#define NVT_DP_ADAPTIVE_SYNC_SDP_DB4_RSVD_MASK 0x1c

View File

@@ -164,7 +164,7 @@ NvU32 axb_div_c_old(NvU32 a, NvU32 b, NvU32 c);
// Sentinel values for NVT_TIMING
#define NVT_TIMINGEXT_SENTINEL {0,0,0,0,0,{0},{0},{0},{0},0,""}
#define NVT_TIMING_SENTINEL {0,0,0,0,0,0,0,0,0,0,0,0,0,0,NVT_TIMINGEXT_SENTINEL}
#define NVT_TIMING_SENTINEL {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,NVT_TIMINGEXT_SENTINEL}
#endif //__NVTIMING_PVT_H_