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

@@ -25,6 +25,7 @@
* Purpose: Provide initialization functions for HDMI library
*/
#include <stddef.h>
#include "nvlimits.h"
#include "nvhdmipkt_common.h"
#include "nvhdmipkt_class.h"
@@ -46,6 +47,7 @@
#include "class/clc57d.h"
#include "class/clc670.h"
#include "class/clc67d.h"
#include "class/clc770.h"
// Class hierarchy structure
typedef struct tagNVHDMIPKT_CLASS_HIERARCHY
@@ -167,6 +169,16 @@ static const NVHDMIPKT_CLASS_HIERARCHY hierarchy[] =
NVC670_DISPLAY, // displayClass
NVC67D_CORE_CHANNEL_DMA // coreDmaClass
},
{// Index 8==NVHDMIPKT_C771_CLASS
NVHDMIPKT_C771_CLASS, // classId
NVHDMIPKT_C671_CLASS, // parentClassId
NV_FALSE, // isRootClass
initializeHdmiPktInterfaceC771, // initInterface
hdmiConstructorC771, // constructor
hdmiDestructorC771, // destructor
NVC770_DISPLAY, // displayClass
NVC67D_CORE_CHANNEL_DMA // coreDmaClass
},
};
#if defined(DSC_CALLBACK_MODIFIED)
@@ -234,6 +246,11 @@ NvHdmiPkt_PacketWrite(NvHdmiPkt_Handle libHandle,
return NVHDMIPKT_LIBRARY_INIT_FAIL;
}
if ((pPacket == NULL) || (packetLen == 0))
{
return NVHDMIPKT_INVALID_ARG;
}
return pClass->hdmiPacketWrite(pClass,
subDevice,
displayId,

View File

@@ -70,6 +70,12 @@ typedef enum _NVHDMIPKT_TYPE
NVHDMIPKT_TYPE_VENDOR_SPECIFIC_INFOFRAME = 4, // VSI
NVHDMIPKT_TYPE_AUDIO_INFOFRAME = 5, // Audio InfoFrame
NVHDMIPKT_TYPE_EXTENDED_METADATA_PACKET = 6, // Extended Metadata Packet (HDMI 2.1)
NVHDMIPKT_TYPE_SHARED_GENERIC1 = 7, // ADA+ Specifc shared generic infoframe 1~6
NVHDMIPKT_TYPE_SHARED_GENERIC2 = 8,
NVHDMIPKT_TYPE_SHARED_GENERIC3 = 9,
NVHDMIPKT_TYPE_SHARED_GENERIC4 = 10,
NVHDMIPKT_TYPE_SHARED_GENERIC5 = 11,
NVHDMIPKT_TYPE_SHARED_GENERIC6 = 12,
NVHDMIPKT_INVALID_PKT_TYPE = 13
} NVHDMIPKT_TYPE;
@@ -99,6 +105,11 @@ typedef enum _NVHDMIPKT_TYPE
#define NV_HDMI_PKT_TRANSMIT_CTRL_VIDEO_FMT_SW_CTRL 0x00000000
#define NV_HDMI_PKT_TRANSMIT_CTRL_VIDEO_FMT_HW_CTRL 0x00000001
#define NV_HDMI_PKT_TRANSMIT_CTRL_LOC 7:6
#define NV_HDMI_PKT_TRANSMIT_CTRL_LOC_VBLANK 0x00000000
#define NV_HDMI_PKT_TRANSMIT_CTRL_LOC_VSYNC 0x00000001
#define NV_HDMI_PKT_TRANSMIT_CTRL_LOC_LOADV 0x00000002
// NVHDMIPKT_TC: HDMI Packet Transmit Control
// NOTE: Client should use these defines below for transmit control, and avoid using the ones
// above. Use only if client knows and wants fine control. And in that case the value
@@ -132,6 +143,29 @@ typedef enum _NVHDMIPKT_TC
NVHDMIPKT_TRANSMIT_CONTROL_VIDEO_FMT_HW_CTRL =
(DRF_DEF(_HDMI_PKT, _TRANSMIT_CTRL, _VIDEO_FMT, _HW_CTRL)),
NVHDMIPKT_TRANSMIT_CONTROL_ENABLE_EVERY_FRAME_LOC_LOADV=
(NVHDMIPKT_TRANSMIT_CONTROL_ENABLE_EVERY_FRAME |
DRF_DEF(_HDMI_PKT, _TRANSMIT_CTRL, _LOC, _LOADV)),
NVHDMIPKT_TRANSMIT_CONTROL_ENABLE_SINGLE_FRAME_LOC_LOADV=
(NVHDMIPKT_TRANSMIT_CONTROL_ENABLE_SINGLE_FRAME |
DRF_DEF(_HDMI_PKT, _TRANSMIT_CTRL, _LOC, _LOADV)),
NVHDMIPKT_TRANSMIT_CONTROL_ENABLE_EVERY_FRAME_LOC_VSYNC=
(NVHDMIPKT_TRANSMIT_CONTROL_ENABLE_EVERY_FRAME |
DRF_DEF(_HDMI_PKT, _TRANSMIT_CTRL, _LOC, _VSYNC)),
NVHDMIPKT_TRANSMIT_CONTROL_ENABLE_SINGLE_FRAME_LOC_VSYNC=
(NVHDMIPKT_TRANSMIT_CONTROL_ENABLE_SINGLE_FRAME |
DRF_DEF(_HDMI_PKT, _TRANSMIT_CTRL, _LOC, _VSYNC)),
NVHDMIPKT_TRANSMIT_CONTROL_ENABLE_EVERY_FRAME_LOC_VBLANK=
(NVHDMIPKT_TRANSMIT_CONTROL_ENABLE_EVERY_FRAME |
DRF_DEF(_HDMI_PKT, _TRANSMIT_CTRL, _LOC, _VBLANK)),
NVHDMIPKT_TRANSMIT_CONTROL_ENABLE_SINGLE_FRAME_LOC_VBLANK=
(NVHDMIPKT_TRANSMIT_CONTROL_ENABLE_SINGLE_FRAME |
DRF_DEF(_HDMI_PKT, _TRANSMIT_CTRL, _LOC, _VBLANK)),
} NVHDMIPKT_TC;
// RM client handles. Used when client chooses that hdmi library make RM calls.

View File

@@ -109,6 +109,12 @@ hdmiPacketWrite0073(NVHDMIPKT_CLASS* pThis,
NvU8 const *const pPacket)
{
NVHDMIPKT_RESULT result = NVHDMIPKT_SUCCESS;
if (packetLen > NV0073_CTRL_SET_OD_MAX_PACKET_SIZE)
{
return NVHDMIPKT_INVALID_ARG;
}
NV0073_CTRL_SPECIFIC_SET_OD_PACKET_PARAMS params = {0};
NVMISC_MEMSET(&params, 0, sizeof(params));

View File

@@ -282,12 +282,9 @@ hdmiWriteVendorPacket9171(NVHDMIPKT_CLASS* pThis,
NvU32* pBaseReg,
NvU32 head,
NvU32 packetLen,
NvU8 const *const pPacketIn)
NvU8 const *const pPacket)
{
NvU32 data = 0;
NvU8 pPacket[31] = {0};
NVMISC_MEMCPY(pPacket, pPacketIn, packetLen);
data = REG_RD32(pBaseReg, NV9171_SF_HDMI_VSI_HEADER(head));
data = FLD_SET_DRF_NUM(9171, _SF_HDMI_VSI_HEADER, _HB0, pPacket[0], data);
@@ -515,6 +512,41 @@ checkPacketStatus_exit:
return result;
}
static NVHDMIPKT_RESULT
validateInputPacketLength(NvU32 pktType9171,
NvU32 packetLen,
NvU8 const *const pPacketIn)
{
NVHDMIPKT_RESULT result = NVHDMIPKT_SUCCESS;
HDMI_PACKET_TYPE infoframeType = pPacketIn[0];
// Lower bound check. Since actual infoframe size varies depending on the infoframe packet being sent,
// check all supported infoframe types and their expected sizes. This is not a strict == check becuase they may/may not need
// additional checksum byte (library clients take care of adding checksum byte if needed)
if (((infoframeType == hdmi_pktType_GeneralControl) && (packetLen < 6)) ||
((infoframeType == hdmi_pktType_GamutMetadata) && (packetLen < sizeof(NVT_GAMUT_METADATA))) ||
((infoframeType == hdmi_pktType_ExtendedMetadata) && (packetLen < sizeof(NVT_EXTENDED_METADATA_PACKET_INFOFRAME)))||
((infoframeType == hdmi_pktType_VendorSpecInfoFrame) && (packetLen < 8)) ||
((infoframeType == hdmi_pktType_AviInfoFrame) && (packetLen < sizeof(NVT_VIDEO_INFOFRAME))) ||
((infoframeType == hdmi_pktType_SrcProdDescInfoFrame) && (packetLen < sizeof(NVT_SPD_INFOFRAME))) ||
((infoframeType == hdmi_pktType_DynamicRangeMasteringInfoFrame) && (packetLen < sizeof(NVT_HDR_INFOFRAME))))
// Unused: hdmi_pktType_AudioClkRegeneration
// Unused: hdmi_pktType_MpegSrcInfoFrame
{
result = NVHDMIPKT_INVALID_ARG;
}
// Upper bound check. Check against number of bytes possible on the hw infoframe unit
if (((pktType9171 == NV9171_SF_HDMI_INFO_IDX_AVI_INFOFRAME) && (packetLen > 17)) || // 3 bytes header + 14 bytes data
((pktType9171 == NV9171_SF_HDMI_INFO_IDX_GENERIC_INFOFRAME) && (packetLen > 31)) || // 3 bytes header + 28 bytes data
((pktType9171 == NV9171_SF_HDMI_INFO_IDX_VSI) && (packetLen > 31))) // 3 bytes header + 28 bytes data
{
result = NVHDMIPKT_INVALID_ARG;
}
return result;
}
/*
* hdmiPacketWrite9171
*/
@@ -526,7 +558,7 @@ hdmiPacketWrite9171(NVHDMIPKT_CLASS* pThis,
NVHDMIPKT_TYPE packetType,
NVHDMIPKT_TC transmitControl,
NvU32 packetLen,
NvU8 const *const pPacket)
NvU8 const *const pPacketIn)
{
NVHDMIPKT_RESULT result = NVHDMIPKT_SUCCESS;
NvU32* pBaseReg = (NvU32*)pThis->memMap[subDevice].pMemBase;
@@ -534,13 +566,26 @@ hdmiPacketWrite9171(NVHDMIPKT_CLASS* pThis,
NvU32 tc = pThis->translateTransmitControl(pThis, transmitControl);
NV0073_CTRL_SPECIFIC_CTRL_HDMI_PARAMS params = {0};
if (pBaseReg == 0 || head >= NV9171_SF_HDMI_AVI_INFOFRAME_CTRL__SIZE_1 ||
packetLen == 0 || pPacket == 0 || pktType9171 == NVHDMIPKT_9171_INVALID_PKT_TYPE)
// packetIn can be of varying size. Use a fixed max size buffer for programing hw units to prevent out of bounds access
NvU8 pPacket[31] = {0};
if (pBaseReg == 0 || head >= NV9171_SF_HDMI_AVI_INFOFRAME_CTRL__SIZE_1 ||
packetLen == 0 || pPacketIn == 0 || pktType9171 == NVHDMIPKT_9171_INVALID_PKT_TYPE)
{
result = NVHDMIPKT_INVALID_ARG;
goto hdmiPacketWrite9171_exit;
}
if ((result = validateInputPacketLength(pktType9171, packetLen, pPacketIn)) != NVHDMIPKT_SUCCESS)
{
NvHdmiPkt_Print(pThis, "ERROR - input packet length incorrect");
NvHdmiPkt_Assert(0);
goto hdmiPacketWrite9171_exit;
}
// input packet looks ok to use, copy over the bytes
NVMISC_MEMCPY(pPacket, pPacketIn, packetLen);
// acquire mutex
pThis->callback.acquireMutex(pThis->cbHandle);

View File

@@ -0,0 +1,306 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2022 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_C771.c
*
* Purpose: Provides packet write functions for HDMI library for ADA+ chips
*/
#include "nvhdmipkt_common.h"
#include "nvhdmipkt_class.h"
#include "nvhdmipkt_internal.h"
#include "class/clc771.h"
extern NVHDMIPKT_RESULT hdmiPacketWrite9171(NVHDMIPKT_CLASS* pThis,
NvU32 subDevice,
NvU32 displayId,
NvU32 head,
NVHDMIPKT_TYPE packetType,
NVHDMIPKT_TC transmitControl,
NvU32 packetLen,
NvU8 const *const pPacket);
extern NVHDMIPKT_RESULT hdmiPacketCtrl9171(NVHDMIPKT_CLASS* pThis,
NvU32 subDevice,
NvU32 displayId,
NvU32 head,
NVHDMIPKT_TYPE packetType,
NVHDMIPKT_TC transmitControl);
static NvU32
translateTransmitControlC771(NVHDMIPKT_CLASS* pThis,
NVHDMIPKT_TC transmitControl)
{
NvU32 tc = 0;
if (FLD_TEST_DRF(_HDMI_PKT, _TRANSMIT_CTRL, _ENABLE, _EN, transmitControl))
{
tc = FLD_SET_DRF(C771, _SF_SHARED_GENERIC_CTRL, _ENABLE, _YES, tc);
}
if (FLD_TEST_DRF(_HDMI_PKT, _TRANSMIT_CTRL, _SINGLE, _EN, transmitControl))
{
tc = FLD_SET_DRF(C771, _SF_SHARED_GENERIC_CTRL, _SINGLE, _YES, tc);
}
if (FLD_TEST_DRF(_HDMI_PKT, _TRANSMIT_CTRL, _CHKSUM_HW, _EN, transmitControl))
{
tc = FLD_SET_DRF(C771, _SF_SHARED_GENERIC_CTRL, _CHECKSUM_HW, _YES, tc);
}
if (FLD_TEST_DRF(_HDMI_PKT, _TRANSMIT_CTRL, _LOC, _VBLANK, transmitControl))
{
tc = FLD_SET_DRF(C771, _SF_SHARED_GENERIC_CTRL, _LOC, _VBLANK, tc);
}
else if (FLD_TEST_DRF(_HDMI_PKT, _TRANSMIT_CTRL, _LOC, _VSYNC, transmitControl))
{
tc = FLD_SET_DRF(C771, _SF_SHARED_GENERIC_CTRL, _LOC, _VSYNC, tc);
}
else if (FLD_TEST_DRF(_HDMI_PKT, _TRANSMIT_CTRL, _LOC, _LOADV, transmitControl))
{
tc = FLD_SET_DRF(C771, _SF_SHARED_GENERIC_CTRL, _LOC, _LOADV, tc);
}
return tc;
}
static NVHDMIPKT_RESULT
hdmiWritePacketCtrlC771(NVHDMIPKT_CLASS* pThis,
NvU32* pBaseReg,
NvU32 head,
NvU32 pktTypeC771,
NvU32 transmitControl,
NvBool bDisable)
{
NvU32 regOffset = 0;
NvU32 hdmiCtrl = 0;
NvU32 sharedGenericIdx = pktTypeC771;
// This function only handles shared generic infoframe ctrl.
if (pBaseReg == 0 || head >= NVC771_SF_SHARED_GENERIC_INFOFRAME_HEADER__SIZE_1 ||
sharedGenericIdx >= NVC771_SF_SHARED_GENERIC_INFOFRAME_HEADER__SIZE_2)
{
return NVHDMIPKT_INVALID_ARG;
}
regOffset = NVC771_SF_SHARED_GENERIC_CTRL(head, sharedGenericIdx);
hdmiCtrl = REG_RD32(pBaseReg, regOffset);
hdmiCtrl = (bDisable == NV_TRUE) ?
(FLD_SET_DRF(C771, _SF_SHARED_GENERIC_CTRL, _ENABLE, _NO, hdmiCtrl)) :
(transmitControl);
REG_WR32(pBaseReg, regOffset, hdmiCtrl);
return NVHDMIPKT_SUCCESS;
}
static NVHDMIPKT_RESULT
hdmiPacketCtrlC771(NVHDMIPKT_CLASS* pThis,
NvU32 subDevice,
NvU32 displayId,
NvU32 head,
NVHDMIPKT_TYPE packetType,
NVHDMIPKT_TC transmitControl)
{
NVHDMIPKT_RESULT result = NVHDMIPKT_SUCCESS;
NvU32* pBaseReg = (NvU32*)pThis->memMap[subDevice].pMemBase;
if (pBaseReg == 0 || head >= NVC771_SF_SHARED_GENERIC_INFOFRAME_HEADER__SIZE_1
|| packetType >= NVHDMIPKT_INVALID_PKT_TYPE)
{
return NVHDMIPKT_INVALID_ARG;
}
NvU32 tc = 0;
switch (packetType)
{
case NVHDMIPKT_TYPE_SHARED_GENERIC1:
case NVHDMIPKT_TYPE_SHARED_GENERIC2:
case NVHDMIPKT_TYPE_SHARED_GENERIC3:
case NVHDMIPKT_TYPE_SHARED_GENERIC4:
case NVHDMIPKT_TYPE_SHARED_GENERIC5:
case NVHDMIPKT_TYPE_SHARED_GENERIC6:
tc = translateTransmitControlC771(pThis, transmitControl);
result = hdmiWritePacketCtrlC771(pThis, pBaseReg, head, packetType - NVHDMIPKT_TYPE_SHARED_GENERIC1, tc, NV_FALSE);
break;
default:
result = hdmiPacketCtrl9171(pThis, subDevice, displayId, head, packetType, transmitControl);
break;
}
return result;
}
static NVHDMIPKT_RESULT
hdmiWriteSharedGenericPacketC771(NVHDMIPKT_CLASS* pThis,
NvU32 subDevice,
NvU32 displayId,
NvU32 head,
NvU32 pktTypeC771,
NVHDMIPKT_TC transmitControl,
NvU32 packetLen,
NvU8 const *const pPacketIn)
{
NvU32 sharedGenericIdx = pktTypeC771;
NvU32 data = 0;
NvU32* pBaseReg = (NvU32*)pThis->memMap[subDevice].pMemBase;
NvU32 tc = translateTransmitControlC771(pThis, transmitControl);
NvU8 pPacket[36] = {0};
if (pBaseReg == 0 || head >= NVC771_SF_SHARED_GENERIC_INFOFRAME_HEADER__SIZE_1 ||
packetLen == 0 || (packetLen > 36) || pPacketIn == 0 || sharedGenericIdx >= NVC771_SF_SHARED_GENERIC_INFOFRAME_HEADER__SIZE_2)
{
return NVHDMIPKT_INVALID_ARG;
}
// In case client doesn't guarantee input pkt length to be 9 DWORDs, create a local buffer to avoid out of bound access of input
NVMISC_MEMCPY(pPacket, pPacketIn, packetLen);
// Disable this packet type.
hdmiWritePacketCtrlC771(pThis, pBaseReg, head, sharedGenericIdx, tc, NV_TRUE);
data = REG_RD32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_HEADER(head, sharedGenericIdx));
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_HEADER, _HB0, pPacket[0], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_HEADER, _HB1, pPacket[1], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_HEADER, _HB2, pPacket[2], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_HEADER, _HB3, pPacket[3], data);
REG_WR32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_HEADER(head, sharedGenericIdx), data);
data = REG_RD32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_SUBPACK0(head, sharedGenericIdx));
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK0, _DB0, pPacket[4], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK0, _DB1, pPacket[5], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK0, _DB2, pPacket[6], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK0, _DB3, pPacket[7], data);
REG_WR32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_SUBPACK0(head, sharedGenericIdx), data);
data = REG_RD32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_SUBPACK1(head, sharedGenericIdx));
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK1, _DB4, pPacket[8], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK1, _DB5, pPacket[9], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK1, _DB6, pPacket[10], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK1, _DB7, pPacket[11], data);
REG_WR32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_SUBPACK1(head, sharedGenericIdx), data);
data = REG_RD32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_SUBPACK2(head, sharedGenericIdx));
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK2, _DB8, pPacket[12], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK2, _DB9, pPacket[13], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK2, _DB10, pPacket[14], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK2, _DB11, pPacket[15], data);
REG_WR32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_SUBPACK2(head, sharedGenericIdx), data);
data = REG_RD32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_SUBPACK3(head, sharedGenericIdx));
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK3, _DB12, pPacket[16], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK3, _DB13, pPacket[17], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK3, _DB14, pPacket[18], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK3, _DB15, pPacket[19], data);
REG_WR32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_SUBPACK3(head, sharedGenericIdx), data);
data = REG_RD32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_SUBPACK4(head, sharedGenericIdx));
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK4, _DB16, pPacket[20], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK4, _DB17, pPacket[21], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK4, _DB18, pPacket[22], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK4, _DB19, pPacket[23], data);
REG_WR32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_SUBPACK4(head, sharedGenericIdx), data);
data = REG_RD32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_SUBPACK5(head, sharedGenericIdx));
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK5, _DB20, pPacket[24], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK5, _DB21, pPacket[25], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK5, _DB22, pPacket[26], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK5, _DB23, pPacket[27], data);
REG_WR32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_SUBPACK5(head, sharedGenericIdx), data);
data = REG_RD32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_SUBPACK6(head, sharedGenericIdx));
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK6, _DB24, pPacket[28], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK6, _DB25, pPacket[29], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK6, _DB26, pPacket[30], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK6, _DB27, pPacket[31], data);
REG_WR32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_SUBPACK6(head, sharedGenericIdx), data);
data = REG_RD32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_SUBPACK7(head, sharedGenericIdx));
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK7, _DB28, pPacket[32], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK7, _DB29, pPacket[33], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK7, _DB30, pPacket[34], data);
data = FLD_SET_DRF_NUM(C771, _SF_SHARED_GENERIC_INFOFRAME_SUBPACK7, _DB31, pPacket[35], data);
REG_WR32(pBaseReg, NVC771_SF_SHARED_GENERIC_INFOFRAME_SUBPACK7(head, sharedGenericIdx), data);
// Enable this infoframe.
hdmiWritePacketCtrlC771(pThis, pBaseReg, head, sharedGenericIdx, tc, NV_FALSE);
return NVHDMIPKT_SUCCESS;
}
static NVHDMIPKT_RESULT
hdmiPacketWriteC771(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;
if (head >= NVC771_SF_SHARED_GENERIC_INFOFRAME_HEADER__SIZE_1 ||
packetLen == 0 ||
pPacketIn == 0 ||
packetType >= NVHDMIPKT_INVALID_PKT_TYPE)
{
return NVHDMIPKT_INVALID_ARG;
}
if (packetType >= NVHDMIPKT_TYPE_SHARED_GENERIC1 && packetType <= NVHDMIPKT_TYPE_SHARED_GENERIC6)
{
result = hdmiWriteSharedGenericPacketC771(pThis, subDevice, displayId, head, packetType - NVHDMIPKT_TYPE_SHARED_GENERIC1, transmitControl, packetLen, pPacketIn);
}
else
{
result = hdmiPacketWrite9171(pThis, subDevice, displayId, head, packetType, transmitControl, packetLen, pPacketIn);
}
return result;
}
// non-HW - class utility/maintenance functions
NvBool
hdmiConstructorC771(NVHDMIPKT_CLASS* pThis)
{
NvBool result = NV_TRUE;
return result;
}
void
hdmiDestructorC771(NVHDMIPKT_CLASS* pThis)
{
return;
}
void
initializeHdmiPktInterfaceC771(NVHDMIPKT_CLASS* pClass)
{
// Update SF_USER data
pClass->dispSfUserClassId = NVC771_DISP_SF_USER;
pClass->dispSfUserSize = sizeof(NvC771DispSfUserMap);
pClass->hdmiPacketCtrl = hdmiPacketCtrlC771;
pClass->hdmiPacketWrite = hdmiPacketWriteC771;
}

View File

@@ -47,6 +47,7 @@ typedef enum
NVHDMIPKT_C371_CLASS = 5, // GV100
NVHDMIPKT_C571_CLASS = 6, // TU102
NVHDMIPKT_C671_CLASS = 7, // GA102, T234D
NVHDMIPKT_C771_CLASS = 8, // AD10X
NVHDMIPKT_INVALID_CLASS // Not to be used by client, and always the last entry here.
} NVHDMIPKT_CLASS_ID;

View File

@@ -41,6 +41,7 @@ extern void initializeHdmiPktInterface9471(NVHDMIPKT_CLASS*);
extern void initializeHdmiPktInterface9571(NVHDMIPKT_CLASS*);
extern void initializeHdmiPktInterfaceC371(NVHDMIPKT_CLASS*);
extern void initializeHdmiPktInterfaceC671(NVHDMIPKT_CLASS*);
extern void initializeHdmiPktInterfaceC771(NVHDMIPKT_CLASS*);
extern NvBool hdmiConstructor0073(NVHDMIPKT_CLASS*);
extern void hdmiDestructor0073 (NVHDMIPKT_CLASS*);
@@ -56,5 +57,7 @@ extern NvBool hdmiConstructorC371(NVHDMIPKT_CLASS*);
extern void hdmiDestructorC371 (NVHDMIPKT_CLASS*);
extern NvBool hdmiConstructorC671(NVHDMIPKT_CLASS*);
extern void hdmiDestructorC671 (NVHDMIPKT_CLASS*);
extern NvBool hdmiConstructorC771(NVHDMIPKT_CLASS*);
extern void hdmiDestructorC771 (NVHDMIPKT_CLASS*);
#endif //_NVHDMIPKT_INTERNAL_H_

View File

@@ -1,6 +1,6 @@
//*****************************************************************************
//
// SPDX-FileCopyrightText: Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: MIT
//
// Permission is hereby granted, free of charge, to any person obtaining a
@@ -38,19 +38,19 @@ CONS_SEGMENT(PAGE_CONS)
const NvU32 NVT_MAX_NVU32= (NvU32)(-1);
const NvU32 NVT_CVT_CELL_GRAN=8;
const NvU32 NVT_CVT_MIN_VSYNCBP=11; // in 550us (!!) [1000000:550 = 20000:11]
const NvU32 NVT_CVT_V_PORCH=3; // in pixels
const NvU32 NVT_CVT_C_PRIME=30; // value of (C' * 10)
const NvU32 NVT_CVT_M_PRIME_D_20=15; // value of (M' / 100)
const NvU32 NVT_CVT_CLOCK_STEP=25; // Pclk step, in 10kHz
const NvU32 NVT_CVT_H_SYNC_PER=8; // HSYNC percentage (8%)
const NvU32 NVT_CVT_CELL_GRAN = 8; // Character cell width.
const NvU32 NVT_CVT_MIN_VSYNCBP = 11; // in 550us (!!) [1000000:550 = 20000:11]
const NvU32 NVT_CVT_V_PORCH = 3; // in pixels
const NvU32 NVT_CVT_C_PRIME = 30; // value of (C' * 10)
const NvU32 NVT_CVT_M_PRIME_D_20 = 15; // value of (M' / 100)
const NvU32 NVT_CVT_CLOCK_STEP = 25; // Pclk step, in 10kHz
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_MIN_V_BPORCH=6;
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_MIN_V_BPORCH = 6; // Minimum vertical back porch.
// VESA CVT spec ver1.2:
@@ -60,13 +60,12 @@ const NvU32 NVT_CVT_MIN_V_BPORCH=6;
#define NVT_CVT_RB2_H_BLANK_PIXELS 80
#define NVT_CVT_RB2_H_SYNC_PIXELS 32
#define NVT_CVT_RB2_MIN_VBLANK_MICROSEC 460
#define NVT_CVT_RB2_V_FPORCH_MIN 1
#define NVT_CVT_RB2_V_BPORCH 6
#define NVT_CVT_RB2_MIN_V_FPORCH 1
#define NVT_CVT_RB2_MIN_V_BPORCH 6
// Page 16 : Table 3-2 : Vertical Sync Duration
#define NVT_CVT_RB2_V_SYNC_WIDTH 8
// Page 22: RB_MIN_VBI = RB_V_FPORCH + V_SYNC_RND + MIN_V_BPORCH
#define NVT_CVT_RB2_MIN_VBI NVT_CVT_RB2_V_SYNC_WIDTH + NVT_CVT_RB2_V_FPORCH_MIN + NVT_CVT_RB2_V_BPORCH
#define NVT_CVT_RB2_MIN_VBI NVT_CVT_RB2_V_SYNC_WIDTH + NVT_CVT_RB2_MIN_V_FPORCH + NVT_CVT_RB2_MIN_V_BPORCH
// Page 15 : The Horizontal Sync Pulse duration will in all cases be 32 pixel clocks in duration, with the position
// set so that the trailing edge of the Horizontal Sync Pulse is located in the center of the Horizontal
// Blanking period.This implies that for a fixed blank of 80 pixel clocks, the Horizontal Back Porch is
@@ -74,6 +73,21 @@ const NvU32 NVT_CVT_MIN_V_BPORCH=6;
#define NVT_CVT_RB2_H_FPORCH 8
#define NVT_CVT_RB2_H_BPORCH 40
// VESA CVT spec ver2.0:
//
// Page 15 : Table 3-2 Constants
#define NVT_CVT_RB3_CLOCK_STEP_KHZ 1000
#define NVT_CVT_RB3_H_BLANK_PIXELS NVT_CVT_RB2_H_BLANK_PIXELS
#define NVT_CVT_RB3_H_SYNC_PIXELS NVT_CVT_RB2_H_SYNC_PIXELS
#define NVT_CVT_RB3_H_FPORCH NVT_CVT_RB2_H_FPORCH
#define NVT_CVT_RB3_MIN_VBLANK_MICROSEC NVT_CVT_RB2_MIN_VBLANK_MICROSEC
#define NVT_CVT_RB3_V_FIELD_RATE_PPM_ADJ 350
#define NVT_CVT_RB3_V_SYNC_WIDTH NVT_CVT_RB2_V_SYNC_WIDTH
#define NVT_CVT_RB3_MIN_V_FPORCH NVT_CVT_RB2_MIN_V_FPORCH
#define NVT_CVT_RB3_MIN_V_BPROCH NVT_CVT_RB2_MIN_V_BPORCH
#define NVT_CVT_RB3_MIN_VBI NVT_CVT_RB2_MIN_VBI
CODE_SEGMENT(PAGE_DD_CODE)
static NvU16 getCVTVSync(NvU32 XRes, NvU32 YRes)
{
@@ -136,10 +150,12 @@ NVT_STATUS NvTiming_CalcCVT(NvU32 width, NvU32 height, NvU32 rr, NvU32 flag, NVT
NVMISC_MEMSET(pT, 0, sizeof(NVT_TIMING));
pT->etc.status = NVT_STATUS_CVT;
pT->etc.status = NVT_STATUS_CVT;
// H_PIXELS_RND = ROUNDDOWN(H_PIXELS / CELL_GRAN_RND,0) * CELL_GRAN_RND
if ((width % NVT_CVT_CELL_GRAN)!=0)
{
width = (width + NVT_CVT_CELL_GRAN / 2) / NVT_CVT_CELL_GRAN * NVT_CVT_CELL_GRAN;
width = (width / NVT_CVT_CELL_GRAN) * NVT_CVT_CELL_GRAN;
NVT_SET_TIMING_STATUS_MISMATCH(pT->etc.status, NVT_STATUS_TIMING_MISMATCH_ALIGNMENT);
}
@@ -245,11 +261,12 @@ NVT_STATUS NvTiming_CalcCVT_RB(NvU32 width, NvU32 height, NvU32 rr, NvU32 flag,
return NVT_STATUS_ERR;//NVT_STATUS_ERR_BACKOFF | NVT_STATUS_ERR_OUTOFRANGE;
NVMISC_MEMSET(pT, 0, sizeof(NVT_TIMING));
pT->etc.status = NVT_STATUS_CVT_RB;
// H_PIXELS_RND = ROUNDDOWN(H_PIXELS / CELL_GRAN_RND,0) * CELL_GRAN_RND
if ((width % NVT_CVT_CELL_GRAN)!=0)
{
width = (width + NVT_CVT_CELL_GRAN / 2) / NVT_CVT_CELL_GRAN * NVT_CVT_CELL_GRAN;
width = (width / NVT_CVT_CELL_GRAN) * NVT_CVT_CELL_GRAN;
NVT_SET_TIMING_STATUS_MISMATCH(pT->etc.status, NVT_STATUS_TIMING_MISMATCH_ALIGNMENT);
}
@@ -371,7 +388,7 @@ NVT_STATUS NvTiming_CalcCVT_RB2(NvU32 width, NvU32 height, NvU32 rr, NvBool is10
// 15. Find Actual Field Rate(Hz) :
// ACT_FIELD_RATE = 1000 * ACT_H_FREQ / TOTAL_V_LINES
// 16. Find actual Vertical Refresh Rate(Hz) :
// ACT_FRAME_RATE = IF(INT_RQD ? = "y", ACT_FIELD_RATE / 2, ACT_FI
// ACT_FRAME_RATE = IF(INT_RQD ? = "y", ACT_FIELD_RATE / 2, ACT_FIELD_RATE
// fill in the essential timing info for output
pT->HVisible = (NvU16)width;
@@ -381,7 +398,7 @@ NVT_STATUS NvTiming_CalcCVT_RB2(NvU32 width, NvU32 height, NvU32 rr, NvBool is10
pT->VVisible = (NvU16)height;
pT->VTotal = (NvU16)total_v_lines;
pT->VSyncWidth = NVT_CVT_RB2_V_SYNC_WIDTH;
pT->VFrontPorch = (NvU16)(act_vbi_lines - NVT_CVT_RB2_V_SYNC_WIDTH - NVT_CVT_RB2_V_BPORCH);
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->HSyncPol = NVT_H_SYNC_POSITIVE;
pT->VSyncPol = NVT_V_SYNC_NEGATIVE;
@@ -391,7 +408,7 @@ NVT_STATUS NvTiming_CalcCVT_RB2(NvU32 width, NvU32 height, NvU32 rr, NvBool is10
// fill in the extra timing info
pT->etc.flag = 0;
pT->etc.rr = (NvU16)rr;
pT->etc.rrx1k = axb_div_c((NvU32)pT->pclk, (NvU32)10000 * (NvU32)1000, (NvU32)pT->HTotal*(NvU32)pT->VTotal);
pT->etc.rrx1k = (NvU32)axb_div_c_64((NvU64)pT->pclk, (NvU64)10000 * (NvU64)1000, (NvU64)pT->HTotal*(NvU64)pT->VTotal);
pT->etc.aspect = 0;
pT->etc.rep = 0x1;
NVT_SNPRINTF((char *)pT->etc.name, 40, "CVT-RB2:%dx%dx%dHz", width, height, rr);
@@ -400,27 +417,206 @@ NVT_STATUS NvTiming_CalcCVT_RB2(NvU32 width, NvU32 height, NvU32 rr, NvBool is10
return NVT_STATUS_SUCCESS;
}
// CVT-RB3 timing calculation
// This is intended to work in conjunction with VESA Adaptive-Sync operation (or other similar VRR methodology)
CODE_SEGMENT(PAGE_DD_CODE)
NVT_STATUS NvTiming_CalcCVT_RB3(NvU32 width, NvU32 height, NvU32 rr, NvU32 deltaHBlank, NvU32 vBlankMicroSec, NvBool isEarlyVSync, NVT_TIMING *pT)
{
NvU32 vbi, act_v_blank_time, act_v_blank_lines, v_back_porch, total_v_lines, total_pixels, adj_rr_x1M, act_pixel_freq_khz;
NvU64 act_pixel_freq_hz = 0xFFFFFFFFFFFFFFFFULL;
// parameter check
if (pT == NULL)
return NVT_STATUS_ERR;
if (width == 0 || height == 0 || rr == 0)
return NVT_STATUS_ERR;
// Check for valid input parameter
if ( (height % 8 != 0) || (deltaHBlank % 8 != 0) || deltaHBlank > 120 || vBlankMicroSec > 245)
return NVT_STATUS_INVALID_PARAMETER;
NVMISC_MEMSET(pT, 0, sizeof(NVT_TIMING));
pT->etc.status = NVT_STATUS_CVT_RB_3;
// 1 Calculate the required field refresh rate (Hz):
// V_FIELD_RATE_RQD = I_IP_FREQ_RQD * (1 + C_V_FIELD_RATE_PPM_ADJ / 1000000)
// Parameters mapping:
// - V_FIELD_RATE_RQD == "adj_rr_x1M"
// - I_IP_FREQ_RQD == "rr"
// - C_V_FIELD_RATE_PPM_ADJ == "NVT_CVT_RB3_V_FIELD_RATE_PPM_ADJ"
adj_rr_x1M = rr * (1000000 + NVT_CVT_RB3_V_FIELD_RATE_PPM_ADJ);
// 2 Round the desired number of horizontal pixels down to the nearest character cell boundary:
// TOTAL_ACTIVE_PIXELS = ROUNDDOWN(I_H_PIXELS / C_CELL_GRAN_RND, 0) * C_CELL_GRAN_RND
// Parameters mapping:
// - TOTAL_ACTIVE_PIXELS and I_H_PIXELS == "width"
// - C_CELL_GRAN_RND == "NVT_CVT_CELL_GRAN"
if ((width % NVT_CVT_CELL_GRAN) != 0)
{
// ROUNDDOWN
width = (width / NVT_CVT_CELL_GRAN) * NVT_CVT_CELL_GRAN;
NVT_SET_TIMING_STATUS_MISMATCH(pT->etc.status, NVT_STATUS_TIMING_MISMATCH_ALIGNMENT);
}
// 3 Round the number of vertical lines down to the nearest integer:
// V_LINES_RND = ROUNDDOWN(I_V_LINES, 0)
// Parameters mapping:
// - V_LINES_RND == "height"
// 4 Calculate the estimated Horizontal Period (kHz):
// H_PERIOD_EST = ((1000000 / (V_FIELD_RATE_RQD)) - C_RB_MIN_V_BLANK) / V_LINES_RND
// Parameters mapping:
// - H_PERIOD_EST == "h_period_est"
// - C_RB_MIN_V_BLANK == "NVT_CVT_RB3_MIN_VBLANK_MICROSEC"
// h_period_est = ((1000000000000 / adj_rr_x1M) - NVT_CVT_RB3_MIN_VBLANK_MICROSEC) / height
// 5 Calculate the total VBlank time:
// ACT_V_BLANK_TIME = IF(I_VBLANK < C_RB_MIN_V_BLANK, C_RB_MIN_V_BLANK, I_VBLANK)
// Parameters mapping:
// - ACT_V_BLANK_TIME == "act_v_blank_time"
// - I_VBLANK == "vBlankMicroSec"
act_v_blank_time = MAX(vBlankMicroSec + 460, NVT_CVT_RB3_MIN_VBLANK_MICROSEC);
// 6 Calculate the number of idealized lines in the VBlank interval:
// VBI_LINES = ROUNDUP(ACT_V_BLANK_TIME / H_PERIOD_EST, 0)
// Parameters mapping:
// - VBI_LINES == vbi"
// below formula are combining step 4, 5, 6 togerther. i.e. both numerator and denominator multiple by height and addj_rr_x1M.
vbi = (NvU32)(((NvU64)height * (NvU64)act_v_blank_time * (NvU64)adj_rr_x1M) / ((NvU64)1000000000000 - (NvU64)act_v_blank_time * (NvU64)adj_rr_x1M));
// ROUNDUP
if (((NvU64)height * (NvU64)act_v_blank_time * (NvU64)adj_rr_x1M) % ((NvU64)1000000000000 - (NvU64)act_v_blank_time * (NvU64)adj_rr_x1M) !=0)
vbi += 1;
// 7 Determine whether idealized VBlank is sufficient and calculate the actual number of lines in the VBlank period:
// RB_MIN_VBI = C_RB_V_FPORCH + C_V_SYNC_RND + C_MIN_V_BPORCH
// V_BLANK = IF(VBI_LINES < RB_MIN_VBI, RB_MIN_VBI, VBI_LINES)
// Paameters mapping:
// - C_RB_V_FPORCH == 1
// - C_V_SYNC_RND == 8
// - C_MIN_V_BPORCH == 6
// - V_BLANK == "act_v_blank_lines"
// NVT_CVT_RB3_MIN_VBI == 1 + 8 + 6 = 15
act_v_blank_lines = MAX(vbi, NVT_CVT_RB3_MIN_VBI);
// 8 Calculate the total number of vertical lines:
// TOTAL_V_LINES = V_BLANK + V_LINES_RND
total_v_lines = act_v_blank_lines + height;
// 9 Calculate the vertical back porch:
// V_BACK_PORCH = IF(AND(I_RED_BLANK_VER=3, I_EARLY_VSYNC_RQD?="Y"), ROUNDDOWN(VBI_LINES / 2, 0), C_MIN_V_BPORCH)
// Paameters mapping:
// - V_BACK_PORCH == "v_back_porch"
// - I_RED_BLANK_VER == "3" this is for RB3 function so the value is 3
// - I_EARLY_VSYNC_RQD == "isEarlyVSync"
// - C_MIN_V_BPORCH == 6
if (isEarlyVSync)
v_back_porch = vbi / 2;
// v_back_porch = act_v_blank_lines /2 ;
else
v_back_porch = NVT_CVT_RB3_MIN_V_BPROCH;
// 10 Calculate the vertical front porch:
// V_FRONT_PORCH = V_BLANK V_BACK_PORCH C_V_SYNC_RND
// we directly use this to assign as pT->VFrontPorch value in NVT_TIMING
// 11 Calculate the total number of pixels per line:
// TOTAL_PIXELS = TOTAL_ACTIVE_PIXELS + C_RB_H_BLANK + IF(I_RED_BLANK_VER=3, I_ADDITIONAL_HBLANK, 0)
// Parameters mapping:
// - C_RB_H_BLANK == 80
// - I_ADDITIONAL_HBLANK == deltaHBlank scopes are defined in the TypeX in displayId2.1
// 80 <= HBlank <=200 is a valid scope
total_pixels = width + deltaHBlank + 80;
// 12 Calculate the horizontal back porch:
// H_BACK_PORCH = C_RB_H_BLANK + IF(I_RED_BLANK_VER=3, I_ADDITIONAL_HBLANK, 0) C_H_FRONT_PORCH C_RB_H_SYNC
// NVT_TIMING did not need to store H_BACK_PORCH
// sanity check just in case of bad edid where the timing value could exceed the limit of NVT_TIMING structure which unfortunately is defined in NvU16
if (total_pixels > (NvU16)-1 || total_v_lines > (NvU16)-1)
return NVT_STATUS_INVALID_PARAMETER;
// 13 Calculate the pixel clock frequency to the nearest C_CLOCK_STEP (MHz):
// ACT_PIXEL_FREQ = C_CLOCK_STEP * ROUNDUP((V_FIELD_RATE_RQD * TOTAL_V_LINES * TOTAL_PIXELS / 1000000 * 1) / C_CLOCK_STEP, 0))
// Parameters mapping:
// - ACT_PIXEL_FREQ == "act_pixel_freq_hz"
// - C_CLOCK_STEP == "NVT_CVT_RB3_CLOCK_STEP_KHZ" == 1000
act_pixel_freq_hz = ((NvU64)adj_rr_x1M * (NvU64)total_v_lines * (NvU64)total_pixels / (NvU64)1000000);
// Here we need to divide extra 1000 because adj_rr_x1M extends to Million, i.e 1Mhz / 1000 = 1kHz
act_pixel_freq_khz = (NvU32)(act_pixel_freq_hz / NVT_CVT_RB3_CLOCK_STEP_KHZ);
// kHz ROUNDUP
if ((act_pixel_freq_hz % 1000) != 0)
act_pixel_freq_khz += 1;
pT->HVisible = (NvU16)width;
pT->HTotal = (NvU16)total_pixels;
pT->HFrontPorch = NVT_CVT_RB3_H_FPORCH;
pT->HSyncWidth = NVT_CVT_RB3_H_SYNC_PIXELS;
pT->VVisible = (NvU16)height;
pT->VTotal = (NvU16)total_v_lines;
pT->VSyncWidth = NVT_CVT_RB3_V_SYNC_WIDTH;
pT->VFrontPorch = (NvU16)(act_v_blank_lines - NVT_CVT_RB2_V_SYNC_WIDTH - v_back_porch);
pT->pclk = ((NvU32)act_pixel_freq_khz + 5) / 10; //convert to 10Khz
pT->HSyncPol = NVT_H_SYNC_POSITIVE;
pT->VSyncPol = NVT_V_SYNC_NEGATIVE;
pT->HBorder = pT->VBorder = 0; // not supported
pT->interlaced = 0; // not supported yet
// fill in the extra timing info
pT->etc.flag = 0;
pT->etc.rr = (NvU16)rr;
pT->etc.rrx1k = (NvU32)axb_div_c_64((NvU64)pT->pclk, (NvU64)10000 * (NvU64)1000, (NvU64)pT->HTotal*(NvU64)pT->VTotal);
pT->etc.aspect = 0;
pT->etc.rep = 0x1;
NVT_SNPRINTF((char *)pT->etc.name, 40, "CVT-RB3:%dx%dx%dHz", width, height, rr);
pT->etc.name[39] = '\0';
return NVT_STATUS_SUCCESS;
}
CODE_SEGMENT(PAGE_DD_CODE)
NvBool NvTiming_IsTimingCVTRB(const NVT_TIMING *pTiming)
{
// Check from the Timing Type
NvU32 reducedType = 0;
NvU32 hblank = 0;
reducedType = NVT_GET_TIMING_STATUS_TYPE(pTiming->etc.status);
if (reducedType == NVT_TYPE_CVT_RB || reducedType == NVT_TYPE_CVT_RB_2)
if (reducedType == NVT_TYPE_CVT_RB || reducedType == NVT_TYPE_CVT_RB_2 || reducedType == NVT_TYPE_CVT_RB_3)
{
return NV_TRUE;
}
hblank = pTiming->HTotal - pTiming->HVisible;
// Manually Check for RB 1 and 2
// RB1 - HBlank = 160, and HSync = 32, HFrontPorch = 48, HBackPorch = 80
if (((pTiming->HTotal - pTiming->HVisible) == 160) && (pTiming->HSyncWidth == 32) && (pTiming->HFrontPorch == 48))
if ((hblank == 160) && (pTiming->HSyncWidth == 32) && (pTiming->HFrontPorch == 48))
{
return NV_TRUE;
}
// RB2 - HBlank = 80, HSync = 32, HFrontPorch = 8, HBackPorch = 40
if (((pTiming->HTotal - pTiming->HVisible) == 80) && (pTiming->HSyncWidth == 32) && (pTiming->HFrontPorch == 8))
if ((hblank == 80) && (pTiming->HSyncWidth == 32) && (pTiming->HFrontPorch == 8))
{
return NV_TRUE;
}
// RB3 - HBlank is any integer multiple of 8 [80-200], HSync = 32, HFrontPorch = 8
if (((hblank > 80) && (hblank <= 200) && (hblank % 8 == 0)) && (pTiming->HSyncWidth == 32) && (pTiming->HFrontPorch == 8))
{
return NV_TRUE;
}

View File

@@ -283,6 +283,114 @@ static const NvU8 maxqp444_12b[15][61]={
,{23,23,22,22,21,21,21,21,20,20,19,19,19,19,18,18,18,17,17,17,16,16,16,16,15,15,14,14,14,14,14,13,13,12,12,12,12,12,11,11,10,10,10,10,10, 9, 9, 8, 8, 8, 8, 8, 7, 7, 6, 6, 6, 6, 5, 5, 4}
};
static const NvU8 minqp422_8b[15][21] = {
{0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{1 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{3 ,3 ,3 ,3 ,3 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0}
,{3 ,3 ,3 ,3 ,3 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0}
,{3 ,3 ,3 ,3 ,3 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0}
,{3 ,3 ,3 ,3 ,3 ,3 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,0 ,0}
,{3 ,3 ,3 ,3 ,3 ,3 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1}
,{3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,2 ,2 ,2 ,1 ,1 ,1}
,{5 ,5 ,5 ,5 ,5 ,4 ,4 ,4 ,4 ,4 ,4 ,4 ,4 ,3 ,3 ,3 ,2 ,2 ,1 ,1 ,1}
,{5 ,5 ,5 ,5 ,5 ,5 ,5 ,4 ,4 ,4 ,4 ,4 ,4 ,4 ,3 ,3 ,3 ,2 ,2 ,1 ,1}
,{5 ,5 ,5 ,5 ,5 ,5 ,5 ,5 ,5 ,5 ,5 ,5 ,5 ,4 ,4 ,3 ,3 ,2 ,2 ,1 ,1}
,{8 ,8 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,6 ,6 ,5 ,5 ,4 ,4 ,3 ,3 ,2 ,2 ,2}
,{12,12,11,11,10,10,9 ,9 ,8 ,8 ,7 ,7 ,6 ,6 ,5 ,5 ,4 ,4 ,4 ,3 ,3}
};
static const NvU8 maxqp422_8b[15][21] = {
{4 ,4 ,3 ,3 ,2 ,2 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{4 ,4 ,4 ,4 ,4 ,3 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{5 ,5 ,5 ,5 ,5 ,4 ,3 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0}
,{6 ,6 ,6 ,6 ,6 ,5 ,4 ,3 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,0}
,{7 ,7 ,7 ,7 ,7 ,6 ,5 ,3 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1}
,{7 ,7 ,7 ,7 ,7 ,6 ,5 ,4 ,3 ,3 ,3 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1}
,{7 ,7 ,7 ,7 ,7 ,6 ,5 ,4 ,3 ,3 ,3 ,3 ,3 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1}
,{8 ,8 ,8 ,8 ,8 ,7 ,6 ,5 ,4 ,4 ,4 ,3 ,3 ,3 ,3 ,2 ,2 ,2 ,2 ,1 ,1}
,{9 ,9 ,9 ,8 ,8 ,7 ,6 ,6 ,5 ,5 ,5 ,4 ,4 ,3 ,3 ,3 ,3 ,2 ,2 ,2 ,2}
,{10,10,9 ,9 ,9 ,8 ,7 ,6 ,5 ,5 ,5 ,5 ,4 ,4 ,4 ,3 ,3 ,3 ,2 ,2 ,2}
,{10,10,10,9 ,9 ,8 ,7 ,7 ,6 ,6 ,6 ,5 ,5 ,4 ,4 ,4 ,3 ,3 ,2 ,2 ,2}
,{11,11,10,10,9 ,9 ,8 ,7 ,7 ,7 ,6 ,6 ,5 ,5 ,4 ,4 ,4 ,3 ,3 ,2 ,2}
,{11,11,11,10,9 ,9 ,8 ,8 ,7 ,7 ,7 ,6 ,6 ,5 ,5 ,4 ,4 ,3 ,3 ,2 ,2}
,{12,12,11,11,10,10,9 ,9 ,8 ,8 ,7 ,7 ,6 ,6 ,5 ,5 ,4 ,4 ,3 ,3 ,3}
,{13,13,12,12,11,11,10,10,9 ,9 ,8 ,8 ,7 ,7 ,6 ,6 ,5 ,5 ,5 ,4 ,4}
};
static const NvU8 minqp422_10b[15][29] = {
{0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{4 ,4 ,4 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{5 ,5 ,5 ,4 ,3 ,3 ,3 ,3 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{6 ,6 ,6 ,6 ,5 ,4 ,4 ,4 ,3 ,3 ,3 ,3 ,3 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{6 ,6 ,6 ,6 ,5 ,5 ,5 ,4 ,4 ,4 ,4 ,4 ,4 ,4 ,4 ,3 ,3 ,3 ,2 ,2 ,2 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0}
,{6 ,6 ,6 ,6 ,6 ,5 ,5 ,5 ,5 ,4 ,4 ,4 ,4 ,4 ,4 ,4 ,4 ,3 ,3 ,3 ,3 ,2 ,1 ,1 ,0 ,0 ,0 ,0 ,0}
,{6 ,6 ,6 ,6 ,6 ,5 ,5 ,5 ,5 ,5 ,5 ,5 ,5 ,4 ,4 ,4 ,4 ,4 ,3 ,3 ,3 ,2 ,2 ,1 ,1 ,1 ,0 ,0 ,0}
,{7 ,7 ,7 ,7 ,7 ,6 ,6 ,6 ,6 ,6 ,6 ,5 ,5 ,5 ,5 ,4 ,4 ,4 ,4 ,3 ,3 ,3 ,2 ,2 ,1 ,1 ,1 ,1 ,1}
,{7 ,7 ,7 ,7 ,7 ,6 ,6 ,6 ,6 ,6 ,6 ,6 ,6 ,5 ,5 ,5 ,4 ,4 ,4 ,4 ,4 ,3 ,2 ,2 ,1 ,1 ,1 ,1 ,1}
,{8 ,8 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,6 ,6 ,6 ,6 ,5 ,5 ,4 ,4 ,4 ,3 ,3 ,2 ,2 ,1 ,1 ,1 ,1}
,{9 ,9 ,9 ,8 ,8 ,8 ,8 ,8 ,8 ,8 ,8 ,7 ,7 ,6 ,6 ,6 ,5 ,5 ,5 ,5 ,5 ,3 ,3 ,2 ,2 ,2 ,1 ,1 ,1}
,{9 ,9 ,9 ,9 ,8 ,8 ,8 ,8 ,8 ,8 ,8 ,8 ,7 ,7 ,6 ,6 ,6 ,6 ,6 ,5 ,5 ,4 ,3 ,3 ,2 ,2 ,1 ,1 ,1}
,{9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,8 ,8 ,8 ,8 ,7 ,7 ,6 ,6 ,5 ,5 ,4 ,3 ,3 ,3 ,2 ,2 ,1 ,1}
,{12,12,11,11,11,11,11,11,11,11,10,10,9 ,9 ,8 ,8 ,7 ,7 ,6 ,6 ,5 ,5 ,4 ,4 ,3 ,3 ,2 ,2 ,1}
,{16,16,15,15,14,14,13,13,12,12,11,11,10,10,9 ,9 ,8 ,8 ,8 ,7 ,7 ,6 ,6 ,5 ,5 ,5 ,4 ,4 ,3}
};
static const NvU8 maxqp422_10b[15][29] = {
{8 ,8 ,7 ,5 ,4 ,4 ,3 ,3 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{8 ,8 ,8 ,6 ,6 ,5 ,4 ,4 ,3 ,3 ,3 ,3 ,3 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{9 ,9 ,9 ,8 ,7 ,6 ,5 ,4 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0}
,{10,10,10,10,9 ,8 ,7 ,6 ,5 ,5 ,5 ,5 ,5 ,4 ,4 ,3 ,3 ,3 ,3 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1}
,{11,11,11,11,10,9 ,8 ,6 ,5 ,5 ,5 ,5 ,5 ,5 ,5 ,4 ,4 ,4 ,3 ,3 ,3 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1}
,{11,11,11,11,11,10,9 ,8 ,7 ,6 ,6 ,5 ,5 ,5 ,5 ,5 ,5 ,4 ,4 ,4 ,4 ,3 ,2 ,2 ,1 ,1 ,1 ,1 ,1}
,{11,11,11,11,11,10,9 ,8 ,7 ,7 ,7 ,7 ,7 ,6 ,6 ,6 ,5 ,5 ,4 ,4 ,4 ,3 ,3 ,2 ,2 ,2 ,1 ,1 ,1}
,{12,12,12,12,12,11,10,9 ,8 ,8 ,8 ,7 ,7 ,7 ,7 ,6 ,5 ,5 ,5 ,4 ,4 ,4 ,3 ,3 ,2 ,2 ,2 ,2 ,2}
,{13,13,13,12,12,11,10,10,9 ,9 ,9 ,8 ,8 ,7 ,7 ,7 ,6 ,5 ,5 ,5 ,5 ,4 ,3 ,3 ,2 ,2 ,2 ,2 ,2}
,{14,14,13,13,13,12,11,10,9 ,9 ,9 ,9 ,8 ,8 ,8 ,7 ,6 ,6 ,5 ,5 ,5 ,4 ,4 ,3 ,3 ,2 ,2 ,2 ,2}
,{14,14,14,13,13,12,11,11,10,10,10,9 ,9 ,8 ,8 ,8 ,7 ,7 ,6 ,6 ,6 ,4 ,4 ,3 ,3 ,3 ,2 ,2 ,2}
,{15,15,14,14,13,13,12,11,11,11,10,10,9 ,9 ,8 ,8 ,8 ,7 ,7 ,6 ,6 ,5 ,4 ,4 ,3 ,3 ,2 ,2 ,2}
,{15,15,15,14,13,13,12,12,11,11,11,10,10,9 ,9 ,8 ,8 ,7 ,7 ,6 ,6 ,5 ,4 ,4 ,4 ,3 ,3 ,2 ,2}
,{16,16,15,15,14,14,13,13,12,12,11,11,10,10,9 ,9 ,8 ,8 ,7 ,7 ,6 ,6 ,5 ,5 ,4 ,4 ,3 ,3 ,2}
,{17,17,16,16,15,15,14,14,13,13,12,12,11,11,10,10,9 ,9 ,9 ,8 ,8 ,7 ,7 ,6 ,6 ,6 ,5 ,5 ,4}
};
static const NvU8 minqp422_12b[15][37] = {
{0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{4 ,4 ,4 ,4 ,4 ,3 ,3 ,3 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{9 ,9 ,9 ,8 ,7 ,6 ,5 ,5 ,4 ,4 ,4 ,4 ,4 ,4 ,3 ,3 ,2 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{10,10,10,10,8 ,8 ,8 ,7 ,6 ,6 ,6 ,6 ,6 ,5 ,4 ,3 ,3 ,3 ,3 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{11,11,11,11,10,9 ,9 ,8 ,7 ,7 ,7 ,7 ,6 ,6 ,5 ,4 ,4 ,4 ,3 ,3 ,3 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{11,11,11,11,11,10,10,9 ,9 ,8 ,8 ,7 ,6 ,6 ,5 ,5 ,5 ,4 ,4 ,4 ,4 ,3 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0}
,{11,11,11,11,11,10,10,10,9 ,9 ,9 ,9 ,8 ,7 ,7 ,7 ,6 ,6 ,5 ,5 ,5 ,4 ,4 ,3 ,3 ,3 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,0 ,0 ,0 ,0}
,{11,11,11,11,11,11,10,10,10,10,10,9 ,8 ,8 ,8 ,7 ,6 ,6 ,6 ,5 ,5 ,5 ,4 ,4 ,3 ,3 ,3 ,3 ,3 ,2 ,2 ,2 ,1 ,1 ,0 ,0 ,0}
,{11,11,11,11,11,11,11,11,11,11,11,10,9 ,8 ,8 ,8 ,7 ,6 ,6 ,6 ,6 ,5 ,4 ,4 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,2 ,2 ,1 ,0 ,0 ,0}
,{11,11,11,11,11,11,11,11,11,11,11,11,9 ,9 ,9 ,8 ,7 ,7 ,6 ,6 ,6 ,5 ,5 ,4 ,4 ,3 ,3 ,3 ,3 ,3 ,3 ,2 ,2 ,1 ,1 ,0 ,0}
,{13,13,13,13,13,12,12,12,12,12,12,11,11,10,10,10,9 ,9 ,8 ,8 ,8 ,6 ,6 ,5 ,5 ,5 ,4 ,4 ,4 ,4 ,3 ,3 ,2 ,2 ,1 ,1 ,1}
,{13,13,13,13,13,13,13,13,13,13,12,12,11,11,10,10,10,9 ,9 ,8 ,8 ,7 ,6 ,6 ,5 ,5 ,4 ,4 ,4 ,4 ,4 ,3 ,3 ,2 ,2 ,1 ,1}
,{13,13,13,13,13,13,13,13,13,13,13,12,12,11,11,10,10,9 ,9 ,8 ,8 ,7 ,6 ,6 ,6 ,5 ,5 ,4 ,4 ,4 ,4 ,3 ,3 ,2 ,2 ,1 ,1}
,{16,16,15,15,15,15,15,15,15,15,14,14,13,13,12,12,11,11,10,10,9 ,9 ,8 ,8 ,7 ,7 ,6 ,6 ,5 ,5 ,4 ,4 ,4 ,3 ,3 ,2 ,2}
,{20,20,19,19,18,18,17,17,16,16,15,15,14,14,13,13,12,12,12,11,11,10,10,9 ,9 ,9 ,8 ,8 ,7 ,7 ,6 ,6 ,6 ,5 ,5 ,4 ,4}
};
static const NvU8 maxqp422_12b[15][37] = {
{12,12,11,9 ,6 ,6 ,5 ,5 ,4 ,4 ,4 ,3 ,3 ,3 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{12,12,12,10,9 ,8 ,7 ,7 ,6 ,6 ,5 ,5 ,5 ,4 ,4 ,4 ,3 ,3 ,3 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{13,13,13,12,10,9 ,8 ,7 ,6 ,6 ,6 ,6 ,6 ,6 ,5 ,5 ,4 ,3 ,3 ,3 ,3 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}
,{14,14,14,14,12,11,10,9 ,8 ,8 ,8 ,8 ,8 ,7 ,6 ,5 ,5 ,5 ,5 ,4 ,4 ,4 ,3 ,3 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,0 ,0 ,0 ,0 ,0 ,0}
,{15,15,15,15,14,13,12,10,9 ,9 ,9 ,9 ,8 ,8 ,7 ,6 ,6 ,6 ,5 ,5 ,5 ,4 ,4 ,4 ,3 ,3 ,3 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,0 ,0 ,0}
,{15,15,15,15,15,14,13,12,11,10,10,9 ,8 ,8 ,7 ,7 ,7 ,6 ,6 ,6 ,6 ,5 ,4 ,4 ,3 ,3 ,3 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1}
,{15,15,15,15,15,14,13,12,11,11,11,11,10,9 ,9 ,9 ,8 ,8 ,7 ,7 ,7 ,6 ,6 ,5 ,5 ,5 ,4 ,4 ,4 ,3 ,3 ,2 ,2 ,1 ,1 ,1 ,1}
,{16,16,16,16,16,15,14,13,12,12,12,11,10,10,10,9 ,8 ,8 ,8 ,7 ,7 ,7 ,6 ,6 ,5 ,5 ,5 ,5 ,5 ,3 ,3 ,3 ,2 ,2 ,1 ,1 ,1}
,{17,17,17,16,16,15,14,14,13,13,13,12,11,10,10,10,9 ,8 ,8 ,8 ,8 ,7 ,6 ,6 ,5 ,5 ,5 ,5 ,5 ,4 ,4 ,3 ,3 ,2 ,1 ,1 ,1}
,{18,18,17,17,17,16,15,14,13,13,13,13,11,11,11,10,9 ,9 ,8 ,8 ,8 ,7 ,7 ,6 ,6 ,5 ,5 ,5 ,5 ,4 ,4 ,3 ,3 ,2 ,2 ,1 ,1}
,{18,18,18,17,17,16,15,15,14,14,14,13,13,12,12,12,11,11,10,10,10,8 ,8 ,7 ,7 ,7 ,6 ,6 ,6 ,5 ,4 ,4 ,3 ,3 ,2 ,2 ,2}
,{19,19,18,18,17,17,16,15,15,15,14,14,13,13,12,12,12,11,11,10,10,9 ,8 ,8 ,7 ,7 ,6 ,6 ,6 ,5 ,5 ,4 ,4 ,3 ,3 ,2 ,2}
,{19,19,19,18,17,17,16,16,15,15,15,14,14,13,13,12,12,11,11,10,10,9 ,8 ,8 ,8 ,7 ,7 ,6 ,6 ,5 ,5 ,4 ,4 ,3 ,3 ,2 ,2}
,{20,20,19,19,18,18,17,17,16,16,15,15,14,14,13,13,12,12,11,11,10,10,9 ,9 ,8 ,8 ,7 ,7 ,6 ,6 ,5 ,5 ,5 ,4 ,4 ,3 ,3}
,{21,21,20,20,19,19,18,18,17,17,16,16,15,15,14,14,13,13,13,12,12,11,11,10,10,10,9 ,9 ,8 ,8 ,7 ,7 ,7 ,6 ,6 ,5 ,5}
};
static const NvU32 rcBufThresh[] = { 896, 1792, 2688, 3584, 4480, 5376, 6272, 6720, 7168, 7616, 7744, 7872, 8000, 8064 };
/* ------------------------ Static Variables ------------------------------- */
@@ -369,7 +477,7 @@ DSC_PpsCalcExtraBits
DSC_OUTPUT_PARAMS *out
)
{
NvU32 numSsps = 3;
NvU32 numSsps = out->native_422 ? 4 : 3;
NvU32 sliceBits;
NvU32 extra_bits;
NvU32 bitsPerComponent = out->bits_per_component;
@@ -418,6 +526,7 @@ DSC_PpsCalcRcInitValue
)
{
NvU32 bitsPerPixel = out->bits_per_pixel;
NvU32 xmit_delay;
out->rc_model_size = 8192;
if (out->native_422)
@@ -427,7 +536,7 @@ DSC_PpsCalcRcInitValue
out->initial_offset = 2048;
else if (bitsPerPixel >= 14 * BPP_UNIT)
out->initial_offset = 5632 - ((bitsPerPixel - 14 * BPP_UNIT) * 1792 + BPP_UNIT / 2) / BPP_UNIT;
else if (bitsPerPixel >= 12 * BPP_UNIT)
else
out->initial_offset = 5632;
}
else
@@ -450,12 +559,52 @@ DSC_PpsCalcRcInitValue
}
RANGE_CHECK("initial_scale_value", out->initial_scale_value, 0, 63);
out->initial_xmit_delay = (4096*BPP_UNIT + bitsPerPixel / 2) / bitsPerPixel;
//RANGE_CHECK("initial_xmit_delay", out->initial_xmit_delay, 0, 1023);
xmit_delay = (4096*BPP_UNIT + bitsPerPixel/2) / bitsPerPixel;
if (out->native_420 || out->native_422)
{
NvU32 slicew = (out->native_420 || out->native_422) ? out->slice_width / 2 : out->slice_width;
NvU32 padding_pixels = ((slicew % 3) ? (3 - (slicew % 3)) : 0) * (xmit_delay / slicew);
if (3 * bitsPerPixel >= ((xmit_delay + 2) / 3) * (out->native_422 ? 4 : 3) * BPP_UNIT &&
(((xmit_delay + padding_pixels) % 3) == 1))
{
xmit_delay++;
}
}
out->initial_xmit_delay = xmit_delay;
RANGE_CHECK("initial_xmit_delay", out->initial_xmit_delay, 0, 1023);
return NVT_STATUS_SUCCESS;
}
static NvU32 DSC_PpsCalcComputeOffset(DSC_OUTPUT_PARAMS *out, NvU32 grpcnt)
{
NvU32 offset = 0;
NvU32 groupsPerLine = out->groups_per_line;
NvU32 grpcnt_id = (out->initial_xmit_delay + PIXELS_PER_GROUP - 1) / PIXELS_PER_GROUP;
if(grpcnt <= grpcnt_id)
offset = (grpcnt * PIXELS_PER_GROUP * out->bits_per_pixel + BPP_UNIT - 1) / BPP_UNIT;
else
offset = (grpcnt_id * PIXELS_PER_GROUP * out->bits_per_pixel + BPP_UNIT - 1) / BPP_UNIT - (((grpcnt-grpcnt_id) * out->slice_bpg_offset)>>OFFSET_FRACTIONAL_BITS);
if(grpcnt <= groupsPerLine)
offset += grpcnt * out->first_line_bpg_offset;
else
offset += groupsPerLine * out->first_line_bpg_offset - (((grpcnt - groupsPerLine) * out->nfl_bpg_offset)>>OFFSET_FRACTIONAL_BITS);
if(out->native_420)
{
if(grpcnt <= groupsPerLine)
offset -= (grpcnt * out->nsl_bpg_offset) >> OFFSET_FRACTIONAL_BITS;
else if(grpcnt <= 2*groupsPerLine)
offset += (grpcnt - groupsPerLine) * out->second_line_bpg_offset - ((groupsPerLine * out->nsl_bpg_offset)>>OFFSET_FRACTIONAL_BITS);
else
offset += (grpcnt - groupsPerLine) * out->second_line_bpg_offset - (((grpcnt - groupsPerLine) * out->nsl_bpg_offset)>>OFFSET_FRACTIONAL_BITS);
}
return(offset);
}
/*
* @brief Calculate bpg value except slice_bpg_offset
*
@@ -477,6 +626,7 @@ NvU32 DSC_PpsCalcBpg
NvU32 bitsPerPixel;
NvU32 rbsMin;
NvU32 hrdDelay;
NvU32 groups_total;
if (out->native_422)
uncompressedBpgRate = PIXELS_PER_GROUP * out->bits_per_component * 4;
@@ -515,9 +665,35 @@ NvU32 DSC_PpsCalcBpg
out->second_line_offset_adj = out->native_420 ? 512 : 0;
bitsPerPixel = out->bits_per_pixel;
rbsMin = out->rc_model_size - out->initial_offset
groups_total = out->groups_per_line * out->slice_height;
out->slice_bpg_offset = (((out->rc_model_size - out->initial_offset + out->num_extra_mux_bits) << OFFSET_FRACTIONAL_BITS)
+ groups_total - 1) / groups_total;
RANGE_CHECK("slice_bpg_offset", out->slice_bpg_offset, 0, 65535);
if((PIXELS_PER_GROUP * bitsPerPixel << OFFSET_FRACTIONAL_BITS) - (out->slice_bpg_offset + out->nfl_bpg_offset) * BPP_UNIT
< (1+5*PIXELS_PER_GROUP)*BPP_UNIT <<OFFSET_FRACTIONAL_BITS )
{
return NVT_STATUS_ERR;
}
if (((out->dsc_version_major > 1) || (out->dsc_version_major == 1 && out->dsc_version_minor >= 2)) &&
(out->native_420 || out->native_422))
{
// OPTIMIZED computation of rbsMin:
// Compute max by sampling offset at points of inflection
// *MODEL NOTE* MN_RBS_MIN
NvU32 maxOffset;
maxOffset = DSC_PpsCalcComputeOffset(out, (out->initial_xmit_delay+PIXELS_PER_GROUP-1)/PIXELS_PER_GROUP ); // After initial delay
maxOffset = MAX(maxOffset, DSC_PpsCalcComputeOffset(out, out->groups_per_line)); // After first line
maxOffset = MAX(maxOffset, DSC_PpsCalcComputeOffset(out, 2*out->groups_per_line));
rbsMin = out->rc_model_size - out->initial_offset + maxOffset;
}
else
{ // DSC 1.1 method
rbsMin = out->rc_model_size - out->initial_offset
+ (out->initial_xmit_delay * bitsPerPixel + BPP_UNIT - 1) / BPP_UNIT
+ out->groups_per_line * out->first_line_bpg_offset;
}
hrdDelay = (rbsMin * BPP_UNIT + bitsPerPixel - 1) / bitsPerPixel;
out->initial_dec_delay = hrdDelay - out->initial_xmit_delay;
RANGE_CHECK("initial_dec_delay", out->initial_dec_delay, 0, 65535);
@@ -526,7 +702,7 @@ NvU32 DSC_PpsCalcBpg
}
/*
* @brief Calculate slice_bpg_offset, final_offset and scale_increment_interval,
* @brief Calculate final_offset and scale_increment_interval,
* scale_decrement_interval
*
* @param[in/out] out DSC output parameter
@@ -541,22 +717,9 @@ DSC_PpsCalcScaleInterval
)
{
NvU32 final_scale;
NvU32 groups_total;
NvU32 bitsPerPixel = out->bits_per_pixel;
groups_total = out->groups_per_line * out->slice_height;
out->slice_bpg_offset = (((out->rc_model_size - out->initial_offset + out->num_extra_mux_bits) << OFFSET_FRACTIONAL_BITS)
+ groups_total - 1) / groups_total;
RANGE_CHECK("slice_bpg_offset", out->slice_bpg_offset, 0, 65535);
if ((PIXELS_PER_GROUP * bitsPerPixel << OFFSET_FRACTIONAL_BITS) - (out->slice_bpg_offset + out->nfl_bpg_offset) * BPP_UNIT
< (1 + 5 * PIXELS_PER_GROUP) * BPP_UNIT << OFFSET_FRACTIONAL_BITS)
{
DSC_Print("The bits/pixel allocation for non-first lines is too low (<5.33bpp).");
DSC_Print("Consider decreasing FIRST_LINE_BPG_OFFSET.");
}
out->final_offset = out->rc_model_size - (out->initial_xmit_delay * bitsPerPixel + 8)/BPP_UNIT + out->num_extra_mux_bits;
out->final_offset = (out->rc_model_size - (out->initial_xmit_delay * out->bits_per_pixel + 8) /
BPP_UNIT + out->num_extra_mux_bits);
RANGE_CHECK("final_offset", out->final_offset, 0, out->rc_model_size-1); //try increase initial_xmit_delay
final_scale = 8 * out->rc_model_size / (out->rc_model_size - out->final_offset);
@@ -571,7 +734,8 @@ DSC_PpsCalcScaleInterval
// for that configuration.
//
out->scale_increment_interval = (out->final_offset << OFFSET_FRACTIONAL_BITS) /
((final_scale - 9) * (out->nfl_bpg_offset + out->slice_bpg_offset + out->nsl_bpg_offset));
((final_scale - 9) * (out->nfl_bpg_offset +
out->slice_bpg_offset + out->nsl_bpg_offset));
RANGE_CHECK("scale_increment_interval", out->scale_increment_interval, 0, 65535);
}
else
@@ -607,6 +771,9 @@ DSC_PpsCalcRcParam
NvU32 bpcm8 = out->bits_per_component - 8;
NvU32 yuv_modifier = out->convert_rgb == 0 && out->dsc_version_minor == 1;
NvU32 qp_bpc_modifier = bpcm8 * 2 - yuv_modifier;
const int ofs_und6[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 };
const int ofs_und7[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 };
const int ofs_und10[] = { 10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12 };
out->flatness_min_qp = 3 + qp_bpc_modifier;
out->flatness_max_qp = 12 + qp_bpc_modifier;
@@ -620,102 +787,167 @@ DSC_PpsCalcRcParam
for (i = 0; i < NUM_BUF_RANGES - 1; i++)
out->rc_buf_thresh[i] = rcBufThresh[i] & (0xFF << 6);
//if (out->native_420)
// idx = bitsPerPixel/BPP_UNIT - 8;
//else if(out->native_422)
// idx = bitsPerPixel/BPP_UNIT - 12;
//else
idx = (2 * (bitsPerPixel - 6 * BPP_UNIT) ) / BPP_UNIT;
if (bpcm8 == 0)
if (out->native_422)
{
for (i = 0; i < NUM_BUF_RANGES; i++)
idx = bitsPerPixel/BPP_UNIT - 12;
if (bpcm8 == 0)
{
const NvU32 min = minqp444_8b[i][idx];
const NvU32 max = maxqp444_8b[i][idx];
out->range_min_qp[i] = MAX(0, min - yuv_modifier);
out->range_max_qp[i] = MAX(0, max - yuv_modifier);
for (i = 0; i < NUM_BUF_RANGES; ++i)
{
out->range_min_qp[i] = minqp422_8b[i][idx];
out->range_max_qp[i] = maxqp422_8b[i][idx];
}
}
}
else if (bpcm8 == 2)
{
for (i = 0; i < NUM_BUF_RANGES; i++)
else if (bpcm8 == 2)
{
const NvU32 min = minqp444_10b[i][idx];
const NvU32 max = maxqp444_10b[i][idx];
for (i=0; i < NUM_BUF_RANGES; i++)
{
out->range_min_qp[i] = minqp422_10b[i][idx];
out->range_max_qp[i] = maxqp422_10b[i][idx];
}
}
else
{
for (i=0; i<NUM_BUF_RANGES; i++)
{
out->range_min_qp[i] = minqp422_12b[i][idx];
out->range_max_qp[i] = maxqp422_12b[i][idx];
}
}
out->range_min_qp[i] = MAX(0, min - yuv_modifier);
out->range_max_qp[i] = MAX(0, max - yuv_modifier);
for (i = 0; i < NUM_BUF_RANGES; ++i)
{
if (bitsPerPixel <= 12*BPP_UNIT)
{
out->range_bpg_offset[i] = ofs_und6[i];
}
else if (bitsPerPixel <= 14*BPP_UNIT)
{
out->range_bpg_offset[i] = ofs_und6[i] + ((bitsPerPixel - 12*BPP_UNIT) *
(ofs_und7[i] - ofs_und6[i]) + BPP_UNIT) / (2*BPP_UNIT);
}
else if (bitsPerPixel <= 16*BPP_UNIT)
{
out->range_bpg_offset[i] = ofs_und7[i];
}
else if (bitsPerPixel <= 20*BPP_UNIT)
{
out->range_bpg_offset[i] = ofs_und7[i] + ((bitsPerPixel - 16*BPP_UNIT) *
(ofs_und10[i] - ofs_und7[i]) + 2*BPP_UNIT) / (4*BPP_UNIT);
}
else
{
out->range_bpg_offset[i] = ofs_und10[i];
}
}
}
else
{
for (i = 0; i < NUM_BUF_RANGES; i++)
{
const NvU32 min = minqp444_12b[i][idx];
const NvU32 max = maxqp444_12b[i][idx];
idx = (2 * (bitsPerPixel - 6 * BPP_UNIT) ) / BPP_UNIT;
out->range_min_qp[i] = MAX(0, min - yuv_modifier);
out->range_max_qp[i] = MAX(0, max - yuv_modifier);
if (bpcm8 == 0)
{
for (i = 0; i < NUM_BUF_RANGES; i++)
{
const NvU32 min = minqp444_8b[i][idx];
const NvU32 max = maxqp444_8b[i][idx];
out->range_min_qp[i] = MAX(0, min - yuv_modifier);
out->range_max_qp[i] = MAX(0, max - yuv_modifier);
}
}
}
for (i = 0; i < NUM_BUF_RANGES; ++i)
{
//if (out->native_420)
//{
// NvU32 ofs_und4[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 };
// NvU32 ofs_und5[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 };
// NvU32 ofs_und6[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 };
// NvU32 ofs_und8[] = { 10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12 };
// out->range_min_qp[i] = minqp_420[bpcm8 / 2][i][idx];
// out->range_max_qp[i] = maxqp_420[bpcm8 / 2][i][idx];
// if (bitsPerPixel <= 8*BPP_UNIT)
// out->range_bpg_offset[i] = ofs_und4[i];
// else if (bitsPerPixel <= 10*BPP_UNIT)
// out->range_bpg_offset[i] = ofs_und4[i] + (NvU32)(0.5 * (bitsPerPixel - 8.0) * (ofs_und5[i] - ofs_und4[i]) + 0.5);
// else if (bitsPerPixel <= 12*BPP_UNIT)
// out->range_bpg_offset[i] = ofs_und5[i] + (NvU32)(0.5 * (bitsPerPixel - 10.0) * (ofs_und6[i] - ofs_und5[i]) + 0.5);
// else if (bitsPerPixel <= 16*BPP_UNIT)
// out->range_bpg_offset[i] = ofs_und6[i] + (NvU32)(0.25 * (bitsPerPixel - 12.0) * (ofs_und8[i] - ofs_und6[i]) + 0.5);
// else
// out->range_bpg_offset[i] = ofs_und8[i];
//}
//else if (out->native_422)
//{
// NvU32 ofs_und6[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 };
// NvU32 ofs_und7[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 };
// NvU32 ofs_und10[] = { 10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12 };
// out->range_min_qp[i] = minqp_422[bpcm8 / 2][i][idx];
// out->range_max_qp[i] = maxqp_422[bpcm8 / 2][i][idx];
// if (bitsPerPixel <= 12*BPP_UNIT)
// out->range_bpg_offset[i] = ofs_und6[i];
// else if(bitsPerPixel <= 14*BPP_UNIT)
// out->range_bpg_offset[i] = ofs_und6[i] + (NvU32)((bitsPerPixel - 12.0) * (ofs_und7[i] - ofs_und6[i]) / 2.0 + 0.5);
// else if(bitsPerPixel <= 16*BPP_UNIT)
// out->range_bpg_offset[i] = ofs_und7[i];
// else if(bitsPerPixel <= 20*BPP_UNIT)
// out->range_bpg_offset[i] = ofs_und7[i] + (NvU32)((bitsPerPixel - 16.0) * (ofs_und10[i] - ofs_und7[i]) / 4.0 + 0.5);
// else
// out->range_bpg_offset[i] = ofs_und10[i];
//}
//else
else if (bpcm8 == 2)
{
const NvU32 ofs_und6[] = { 0, -2, -2, -4, -6, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 };
const NvU32 ofs_und8[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 };
const NvU32 ofs_und12[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 };
const NvU32 ofs_und15[] = { 10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12 };
if (bitsPerPixel <= 6 * BPP_UNIT)
out->range_bpg_offset[i] = ofs_und6[i];
else if (bitsPerPixel <= 8 * BPP_UNIT)
out->range_bpg_offset[i] = ofs_und6[i] + ((bitsPerPixel - 6 * BPP_UNIT) * (ofs_und8[i] - ofs_und6[i]) + BPP_UNIT) / (2 * BPP_UNIT);
else if (bitsPerPixel <= 12 * BPP_UNIT)
out->range_bpg_offset[i] = ofs_und8[i];
else if (bitsPerPixel <= 15 * BPP_UNIT)
out->range_bpg_offset[i] = ofs_und12[i] + ((bitsPerPixel - 12 * BPP_UNIT) * (ofs_und15[i] - ofs_und12[i]) + 3 * BPP_UNIT / 2) / (3 * BPP_UNIT);
else
out->range_bpg_offset[i] = ofs_und15[i];
for (i = 0; i < NUM_BUF_RANGES; i++)
{
const NvU32 min = minqp444_10b[i][idx];
const NvU32 max = maxqp444_10b[i][idx];
out->range_min_qp[i] = MAX(0, min - yuv_modifier);
out->range_max_qp[i] = MAX(0, max - yuv_modifier);
}
}
else
{
for (i = 0; i < NUM_BUF_RANGES; i++)
{
const NvU32 min = minqp444_12b[i][idx];
const NvU32 max = maxqp444_12b[i][idx];
out->range_min_qp[i] = MAX(0, min - yuv_modifier);
out->range_max_qp[i] = MAX(0, max - yuv_modifier);
}
}
for (i = 0; i < NUM_BUF_RANGES; ++i)
{
//if (out->native_420)
//{
// NvU32 ofs_und4[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 };
// NvU32 ofs_und5[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 };
// NvU32 ofs_und6[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 };
// NvU32 ofs_und8[] = { 10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12 };
// out->range_min_qp[i] = minqp_420[bpcm8 / 2][i][idx];
// out->range_max_qp[i] = maxqp_420[bpcm8 / 2][i][idx];
// if (bitsPerPixel <= 8*BPP_UNIT)
// out->range_bpg_offset[i] = ofs_und4[i];
// else if (bitsPerPixel <= 10*BPP_UNIT)
// out->range_bpg_offset[i] = ofs_und4[i] + (NvU32)(0.5 * (bitsPerPixel - 8.0) * (ofs_und5[i] - ofs_und4[i]) + 0.5);
// else if (bitsPerPixel <= 12*BPP_UNIT)
// out->range_bpg_offset[i] = ofs_und5[i] + (NvU32)(0.5 * (bitsPerPixel - 10.0) * (ofs_und6[i] - ofs_und5[i]) + 0.5);
// else if (bitsPerPixel <= 16*BPP_UNIT)
// out->range_bpg_offset[i] = ofs_und6[i] + (NvU32)(0.25 * (bitsPerPixel - 12.0) * (ofs_und8[i] - ofs_und6[i]) + 0.5);
// else
// out->range_bpg_offset[i] = ofs_und8[i];
//}
//else if (out->native_422)
//{
// NvU32 ofs_und6[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 };
// NvU32 ofs_und7[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 };
// NvU32 ofs_und10[] = { 10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12 };
// out->range_min_qp[i] = minqp_422[bpcm8 / 2][i][idx];
// out->range_max_qp[i] = maxqp_422[bpcm8 / 2][i][idx];
// if (bitsPerPixel <= 12*BPP_UNIT)
// out->range_bpg_offset[i] = ofs_und6[i];
// else if(bitsPerPixel <= 14*BPP_UNIT)
// out->range_bpg_offset[i] = ofs_und6[i] + (NvU32)((bitsPerPixel - 12.0) * (ofs_und7[i] - ofs_und6[i]) / 2.0 + 0.5);
// else if(bitsPerPixel <= 16*BPP_UNIT)
// out->range_bpg_offset[i] = ofs_und7[i];
// else if(bitsPerPixel <= 20*BPP_UNIT)
// out->range_bpg_offset[i] = ofs_und7[i] + (NvU32)((bitsPerPixel - 16.0) * (ofs_und10[i] - ofs_und7[i]) / 4.0 + 0.5);
// else
// out->range_bpg_offset[i] = ofs_und10[i];
//}
//else
{
const NvU32 ofs_und6[] = { 0, -2, -2, -4, -6, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 };
const NvU32 ofs_und8[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 };
const NvU32 ofs_und12[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 };
const NvU32 ofs_und15[] = { 10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12 };
if (bitsPerPixel <= 6 * BPP_UNIT)
{
out->range_bpg_offset[i] = ofs_und6[i];
}
else if (bitsPerPixel <= 8 * BPP_UNIT)
{
out->range_bpg_offset[i] = ofs_und6[i] + ((bitsPerPixel - 6 * BPP_UNIT) *
(ofs_und8[i] - ofs_und6[i]) + BPP_UNIT) / (2 * BPP_UNIT);
}
else if (bitsPerPixel <= 12 * BPP_UNIT)
{
out->range_bpg_offset[i] = ofs_und8[i];
}
else if (bitsPerPixel <= 15 * BPP_UNIT)
{
out->range_bpg_offset[i] = ofs_und12[i] + ((bitsPerPixel - 12 * BPP_UNIT) *
(ofs_und15[i] - ofs_und12[i]) + 3 * BPP_UNIT / 2) / (3 * BPP_UNIT);
}
else
{
out->range_bpg_offset[i] = ofs_und15[i];
}
}
}
}
return NVT_STATUS_SUCCESS;
@@ -1155,6 +1387,11 @@ DSC_PpsCalcSliceParams
out->slice_width = (out->pic_width + out->slice_num - 1) / out->slice_num;
if (out->native_420 || out->native_422)
{
out->slice_width = (out->slice_width+1)/2 * 2 ;
}
if (out->slice_width > max_slice_width)
{
DSC_Print("Slice width corresponding to the requested slice count is not supported\n");
@@ -1934,13 +2171,7 @@ DSC_GeneratePPS
if (*pBitsPerPixelX16 != 0)
{
*pBitsPerPixelX16 = DSC_AlignDownForBppPrecision(*pBitsPerPixelX16, pDscInfo->sinkCaps.bitsPerPixelPrecision);
// The calculation of in->bits_per_pixel here in PPSlib, which is the maximum bpp that is allowed by available bandwidth,
// which is applicable to DP alone and not to HDMI FRL.
// Before calling PPS lib to generate PPS data, HDMI library has done calculation according to HDMI2.1 spec
// to determine if FRL rate is sufficient for the requested bpp. So restricting the condition to DP alone.
if ((pWARData && (pWARData->connectorType == DSC_DP)) &&
(*pBitsPerPixelX16 > in->bits_per_pixel))
if (*pBitsPerPixelX16 > in->bits_per_pixel)
{
DSC_Print("ERROR - Invalid bits per pixel value specified.");
ret = NVT_STATUS_INVALID_PARAMETER;
@@ -2009,6 +2240,36 @@ DSC_GeneratePPS
in->slice_count_mask = pDscInfo->sinkCaps.sliceCountSupportedMask;
in->peak_throughput_mode0 = pDscInfo->sinkCaps.peakThroughputMode0;
in->peak_throughput_mode1 = pDscInfo->sinkCaps.peakThroughputMode1;
if (in->native_422)
{
if (in->dsc_version_minor == 1)
{
DSC_Print("Error! DSC1.1 can't support native422!\n");
ret = NVT_STATUS_INVALID_PARAMETER;
goto done;
}
//the bpp in native 422 mode is doubled.
if((((NvS32)(in->bits_per_pixel)) < (NvS32)(2*6*BPP_UNIT)) ||
(((NvS32)(in->bits_per_pixel)) > (NvS32)(2*32*BPP_UNIT-1)))
{
DSC_Print("bits_per_pixelx16 (=%u) needs to be between %u and %u",
in->bits_per_pixel, 2*6*BPP_UNIT, 2*32*BPP_UNIT-1);
ret = NVT_STATUS_INVALID_PARAMETER;
goto done;
}
}
else
{
if ((((NvS32)(in->bits_per_pixel)) < (NvS32)(8*BPP_UNIT)) ||
(((NvS32)(in->bits_per_pixel)) > (NvS32)(32*BPP_UNIT)))
{
DSC_Print("bits_per_pixelx16 (=%u) needs to be between %u and %u",
in->bits_per_pixel, 8*BPP_UNIT, 32*BPP_UNIT);
ret = NVT_STATUS_INVALID_PARAMETER;
goto done;
}
}
ret = DSC_PpsDataGen(in, pps);

View File

@@ -2871,6 +2871,7 @@ void parseEdidHdmiForumVSDB(VSDB_DATA *pVsdb, NVT_HDMI_FORUM_INFO *pHdmiInfo)
pHdmiInfo->cnmvrr = pHdmiForum->CNMVRR;
pHdmiInfo->cinemaVrr = pHdmiForum->CinemaVRR;
pHdmiInfo->m_delta = pHdmiForum->M_delta;
pHdmiInfo->fapa_end_extended = pHdmiForum->FAPA_End_Extended;
// sixth byte
if (!remainingSize--)

View File

@@ -304,6 +304,7 @@ typedef enum NVT_TIMING_TYPE
NVT_TYPE_DISPLAYID_8, // DisplayID 2.0 enumerated timing - Type VIII
NVT_TYPE_DISPLAYID_9, // DisplayID 2.0 formula-based timing - Type IX
NVT_TYPE_DISPLAYID_10, // DisplayID 2.0 formula-based timing - Type X
NVT_TYPE_CVT_RB_3, // CVT timing with reduced blanking V3
}NVT_TIMING_TYPE;
//
// 5. the timing sequence number like the TV format and EIA861B predefined timing format
@@ -357,6 +358,7 @@ typedef enum NVT_TV_FORMAT
#define NVT_STATUS_CVT NVT_DEF_TIMING_STATUS(NVT_TYPE_CVT, 0) // CVT timing with regular blanking
#define NVT_STATUS_CVT_RB NVT_DEF_TIMING_STATUS(NVT_TYPE_CVT_RB, 0) // CVT_RB timing
#define NVT_STATUS_CVT_RB_2 NVT_DEF_TIMING_STATUS(NVT_TYPE_CVT_RB_2, 0) // CVT_RB timing V2
#define NVT_STATUS_CVT_RB_3 NVT_DEF_TIMING_STATUS(NVT_TYPE_CVT_RB_3, 0) // CVT_RB timing V3
#define NVT_STATUS_CUST NVT_DEF_TIMING_STATUS(NVT_TYPE_CUST, 0) // Customized timing
#define NVT_STATUS_EDID_DTD NVT_DEF_TIMING_STATUS(NVT_TYPE_EDID_DTD, 0)
#define NVT_STATUS_EDID_STD NVT_DEF_TIMING_STATUS(NVT_TYPE_EDID_STD, 0)
@@ -2081,6 +2083,7 @@ typedef struct tagNVT_HDMI_LLC_INFO
typedef struct tagNVT_HDMI_FORUM_INFO
{
NvU8 max_TMDS_char_rate;
NvU8 threeD_Osd_Disparity : 1;
NvU8 dual_view : 1;
NvU8 independent_View : 1;
@@ -2089,29 +2092,40 @@ typedef struct tagNVT_HDMI_FORUM_INFO
NvU8 cable_status : 1;
NvU8 rr_capable : 1;
NvU8 scdc_present : 1;
NvU8 dc_30bit_420 : 1;
NvU8 dc_36bit_420 : 1;
NvU8 dc_48bit_420 : 1;
NvU8 uhd_vic : 1;
NvU8 max_FRL_Rate : 4;
NvU8 fapa_start_location : 1;
NvU8 allm : 1;
NvU8 fva : 1;
NvU8 cnmvrr : 1;
NvU8 cinemaVrr : 1;
NvU8 m_delta : 1;
NvU8 vrr_min : 6;
NvU8 fapa_end_extended : 1;
NvU8 rsvd : 1;
NvU16 vrr_min : 6;
NvU16 vrr_max : 10;
NvU16 dsc_MaxSlices : 6;
NvU16 dsc_MaxPclkPerSliceMHz : 10;
NvU8 dsc_10bpc : 1;
NvU8 dsc_12bpc : 1;
NvU8 dsc_16bpc : 1;
NvU8 dsc_All_bpp : 1;
NvU8 dsc_Max_FRL_Rate : 4;
NvU8 dsc_Native_420 : 1;
NvU8 dsc_1p2 : 1;
NvU8 dsc_MaxSlices : 6;
NvU16 dsc_MaxPclkPerSliceMHz : 10;
NvU8 dsc_Max_FRL_Rate : 4;
NvU8 rsvd_2 : 6;
NvU8 dsc_totalChunkKBytes : 7; // = 1 + EDID reported DSC_TotalChunkKBytes
NvU8 rsvd_3 : 1;
} NVT_HDMI_FORUM_INFO;
@@ -2785,10 +2799,6 @@ typedef struct tagNVT_SPD_INFOFRAME_PAYLOAD
NvU8 productBytes[16];
NvU8 sourceInformation;
// Since HDMI Library doesn't clear the rest of the bytes and checksum is calculated for all the 32 bytes : Temporary WAR
NvU8 paddingBytes[3];
} NVT_SPD_INFOFRAME_PAYLOAD;
@@ -3720,7 +3730,9 @@ typedef struct tagNVT_HDMI_FORUM_VSDB_PAYLOAD
NvU8 CNMVRR : 1;
NvU8 CinemaVRR : 1;
NvU8 M_delta : 1;
NvU8 Rsvd_2 : 2;
NvU8 Rsvd_2 : 1;
NvU8 FAPA_End_Extended : 1;
// sixth byte
NvU8 VRR_min : 6;
NvU8 VRR_max_high : 2;
@@ -5253,6 +5265,7 @@ NVT_STATUS NvTiming_CalcDMT_RB(NvU32 width, NvU32 height, NvU32 rr, NvU32 flag,
NVT_STATUS NvTiming_CalcCVT(NvU32 width, NvU32 height, NvU32 rr, NvU32 flag, NVT_TIMING *pT);
NVT_STATUS NvTiming_CalcCVT_RB(NvU32 width, NvU32 height, NvU32 rr, NvU32 flag, NVT_TIMING *pT);
NVT_STATUS NvTiming_CalcCVT_RB2(NvU32 width, NvU32 height, NvU32 rr, NvBool is1000div1001, NVT_TIMING *pT);
NVT_STATUS NvTiming_CalcCVT_RB3(NvU32 width, NvU32 height, NvU32 rr, NvU32 deltaHBlank, NvU32 vBlankMicroSec, NvBool isEarlyVSync, NVT_TIMING *pT);
NvBool NvTiming_IsTimingCVTRB(const NVT_TIMING *pTiming);
// CEA/EIA/Psf timing