This commit is contained in:
Andy Ritger
2022-11-10 08:39:33 -08:00
parent 7c345b838b
commit 758b4ee818
1323 changed files with 262135 additions and 60754 deletions

View File

@@ -254,6 +254,7 @@ typedef struct _tagNVHDMIPKT_CALLBACK
NvBool expression);
} NVHDMIPKT_CALLBACK;
/*********************** HDMI Library interface to write hdmi ctrl/packet ***********************/
typedef void* NvHdmiPkt_Handle;
#define NVHDMIPKT_INVALID_HANDLE ((NvHdmiPkt_Handle)0)
@@ -300,6 +301,7 @@ NvHdmiPkt_PacketWrite(NvHdmiPkt_Handle libHandle,
NvU32 packetLen,
NvU8 const *const pPacket);
/***************************** Interface to initialize HDMI Library *****************************/
/************************************************************************************************

View File

@@ -388,4 +388,5 @@ initializeHdmiPktInterface0073(NVHDMIPKT_CLASS* pClass)
pClass->hdmiQueryFRLConfig = hdmiQueryFRLConfigDummy;
pClass->hdmiSetFRLConfig = hdmiSetFRLConfigDummy;
pClass->hdmiClearFRLConfig = hdmiClearFRLConfigDummy;
}

View File

@@ -846,4 +846,5 @@ initializeHdmiPktInterface9171(NVHDMIPKT_CLASS* pClass)
pClass->hdmiQueryFRLConfig = hdmiQueryFRLConfigDummy;
pClass->hdmiSetFRLConfig = hdmiSetFRLConfigDummy;
pClass->hdmiClearFRLConfig = hdmiClearFRLConfigDummy;
}

View File

@@ -110,5 +110,4 @@ extern NVHDMIPKT_RESULT hdmiClearFRLConfigDummy(NVHDMIPKT_CLASS *pThis,
NvU32 subDevice,
NvU32 displayId);
#endif //_NVHDMIPKT_COMMON_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
@@ -100,14 +100,20 @@ typedef struct _tagDISPLAYID_2_0_DATA_BLOCK_HEADER
#define DISPLAYID_2_0_BLOCK_TYPE_TIMING_7 0x22
#define DISPLAYID_2_0_BLOCK_TYPE_TIMING_8 0x23
#define DISPLAYID_2_0_BLOCK_TYPE_TIMING_9 0x24
#define DISPLAYID_2_0_BLOCK_TYPE_TIMING_10 0x2A
#define DISPLAYID_2_0_BLOCK_TYPE_RANGE_LIMITS 0x25
#define DISPLAYID_2_0_BLOCK_TYPE_INTERFACE_FEATURES 0x26
#define DISPLAYID_2_0_BLOCK_TYPE_STEREO 0x27
#define DISPLAYID_2_0_BLOCK_TYPE_TILED_DISPLAY 0x28
#define DISPLAYID_2_0_BLOCK_TYPE_CONTAINER_ID 0x29
#define DISPLAYID_2_0_BLOCK_TYPE_TIMING_10 0x2A
#define DISPLAYID_2_0_BLOCK_TYPE_ADAPTIVE_SYNC 0x2B
#define DISPLAYID_2_0_BLOCK_TYPE_ARVR_HMD 0x2C
#define DISPLAYID_2_0_BLOCK_TYPE_ARVR_LAYER 0x2D
// 0x7D - 0x2E RESERVED for Additional VESA-defined Data Blocks
#define DISPLAYID_2_0_BLOCK_TYPE_VENDOR_SPEC 0x7E
// 0x80 - 0x7F RESERVED
#define DISPLAYID_2_0_BLOCK_TYPE_CTA_DATA 0x81
// 0xFF - 0x82 RESERVED for additional data blocks related to external standards organization(s).
#define DISPLAYID_2_0_PRODUCT_NAME_STRING_MAX_LEN ((0xFB - 0xF) + 1)
@@ -236,7 +242,7 @@ typedef struct _tag_DISPLAYID_2_0_TIMING_7_DESCRIPTOR
NvU8 interface_frame_scanning_type : 1;
NvU8 stereo_support : 2;
NvU8 is_preferred_or_ycc420 : 1;
}options;
} options;
struct
{
@@ -246,7 +252,7 @@ typedef struct _tag_DISPLAYID_2_0_TIMING_7_DESCRIPTOR
NvU8 front_porch_pixels_high : 7;
NvU8 sync_polarity : 1;
NvU8 sync_width_pixels[2];
}horizontal;
} horizontal;
struct
{
@@ -256,8 +262,7 @@ typedef struct _tag_DISPLAYID_2_0_TIMING_7_DESCRIPTOR
NvU8 front_porch_lines_high : 7;
NvU8 sync_polarity : 1;
NvU8 sync_width_lines[2];
}vertical;
} vertical;
} DISPLAYID_2_0_TIMING_7_DESCRIPTOR;
#define DISPLAYID_2_0_TIMING_7_MAX_DESCRIPTORS 12
@@ -336,11 +341,11 @@ typedef struct _tagDISPLAYID_2_0_TIMING_8_BLOCK
typedef struct _TAG_DISPLAYID_2_0_TIMING_9_DESCRIPTOR
{
struct {
NvU8 timing_formula:3;
NvU8 reserved0:1;
NvU8 fractional_refresh_rate_support:1;
NvU8 stereo_support:2;
NvU8 reserved1:1;
NvU8 timing_formula :3;
NvU8 reserved0 :1;
NvU8 rr_1000div1001_support :1;
NvU8 stereo_support :2;
NvU8 reserved1 :1;
} options;
NvU8 horizontal_active_pixels[2];
@@ -350,10 +355,10 @@ typedef struct _TAG_DISPLAYID_2_0_TIMING_9_DESCRIPTOR
#define DISPLAYID_2_0_TIMING_FORMULA_CVT_1_2_STANDARD 0
#define DISPLAYID_2_0_TIMING_FORMULA_CVT_1_2_REDUCED_BLANKING_1 1
#define DISPLAYID_2_0_TIMING_FORMULA_CVT_1_2_REDUCED_BLANKING_2 2
#define DISPLAYID_2_0_TIMING_FORMULA_CVT_1_2_REDUCED_BLANKING_3 3
#define DISPLAYID_2_0_TIMING_FORMULA_CVT_2_0_REDUCED_BLANKING_2 2
#define DISPLAYID_2_0_TIMING_FORMULA_CVT_2_0_REDUCED_BLANKING_3 3
#define DISPLAYID_2_0_TIMING_9_MAX_DESCRIPTORS 41
#define DISPLAYID_2_0_TIMING_9_MAX_DESCRIPTORS 18
typedef struct _tagDISPLAYID_2_0_TIMING_9_BLOCK
{
@@ -379,8 +384,8 @@ typedef struct _DISPLAYID_2_0_TIMING_10_6BYTES_DESCRIPTOR
{
struct {
NvU8 timing_formula :3;
NvU8 reserved0 :1;
NvU8 vrr_or_hblank :1;
NvU8 early_vsync :1;
NvU8 rr1000div1001_or_hblank :1;
NvU8 stereo_support :2;
NvU8 ycc420_support :1;
} options;
@@ -398,8 +403,8 @@ typedef struct _DISPLAYID_2_0_TIMING_10_7BYTES_DESCRIPTOR
NvU8 additional_vblank_timing :3;
} DISPLAYID_2_0_TIMING_10_7BYTES_DESCRIPTOR;
#define DISPLAYID_2_0_TIMING_10_MAX_6BYTES_DESCRIPTORS 41
#define DISPLAYID_2_0_TIMING_10_MAX_7BYTES_DESCRIPTORS 35
#define DISPLAYID_2_0_TIMING_10_MAX_6BYTES_DESCRIPTORS 18
#define DISPLAYID_2_0_TIMING_10_MAX_7BYTES_DESCRIPTORS 16
typedef struct _DISPLAYID_2_0_TIMING_10_BLOCK
{
@@ -416,10 +421,11 @@ typedef struct _tagDISPLAYID_2_0_RANGE_LIMITS_BLOCK
NvU8 pixel_clock_max[3];
NvU8 vertical_frequency_min;
NvU8 vertical_frequency_max_7_0;
struct {
NvU8 vertical_frequency_max_9_8:2;
NvU8 reserved:5;
NvU8 seamless_dynamic_video_timing_change:1;
NvU8 vertical_frequency_max_9_8 :2;
NvU8 reserved :5;
NvU8 seamless_dynamic_video_timing_change :1;
} dynamic_video_timing_range_support;
} DISPLAYID_2_0_RANGE_LIMITS_BLOCK;
@@ -677,6 +683,51 @@ typedef struct _tagDISPLAYID_2_0_CONTAINERID_BLOCK
NvU8 container_id[DISPLAYID_2_0_CONTAINERID_BLOCK_PAYLOAD_LENGTH];
} DISPLAYID_2_0_CONTAINERID_BLOCK;
#define DISPLAYID_2_0_ADAPTIVE_SYNC_DETAILED_TIMING_COUNT 4
typedef struct _tagDISPLAYID_2_0_ADAPTIVE_SYNC_BLOCK_HEADER
{
NvU8 type; // Adaptive-Sync (0x2B)
NvU8 revision :3;
NvU8 reserved0 :1;
NvU8 payload_bytes_adaptive_sync_len :3;
NvU8 reserved1 :1;
NvU8 payload_bytes;
} DISPLAYID_2_0_ADAPTIVE_SYNC_BLOCK_HEADER;
typedef struct _tagDISPLAYID_2_0_ADAPTIVE_SYNC_DESCRIPTOR
{
struct
{
NvU8 range : 1;
NvU8 successive_frame_inc_tolerance : 1;
NvU8 modes : 2;
NvU8 seamless_transition_not_support: 1;
NvU8 successive_frame_dec_tolerance : 1;
NvU8 reserved : 2;
} operation_range_info;
// 6.2 format (six integer bits and two fractional bits)
// six integer bits == 0 - 63ms
// two fractional bits == 0.00(00), 0.25(01b),0.50(10), 0.75(11b)
NvU8 max_single_frame_inc;
NvU8 min_refresh_rate;
struct
{
NvU8 max_rr_7_0;
NvU8 max_rr_9_8 : 2;
NvU8 reserved : 6;
} max_refresh_rate;
// same as max_single_frame_inc expression
NvU8 max_single_frame_dec;
} DISPLAYID_2_0_ADAPTIVE_SYNC_DESCRIPTOR;
typedef struct _tagDISPLAYID_2_0_ADAPTIVE_SYNC_BLOCK
{
DISPLAYID_2_0_ADAPTIVE_SYNC_BLOCK_HEADER header;
DISPLAYID_2_0_ADAPTIVE_SYNC_DESCRIPTOR descriptors[DISPLAYID_2_0_ADAPTIVE_SYNC_DETAILED_TIMING_COUNT];
} DISPLAYID_2_0_ADAPTIVE_SYNC_BLOCK;
typedef struct _tagDISPLAYID_2_0_VENDOR_SPECIFIC_BLOCK
{
DISPLAYID_2_0_DATA_BLOCK_HEADER header;

View File

@@ -49,8 +49,8 @@ typedef enum tagSDP_VSC_REVNUM
{
SDP_VSC_REVNUM_STEREO = 1,
SDP_VSC_REVNUM_STEREO_PSR,
SDP_VSC_REVNUM_STEREO_PSR2,
SDP_VSC_REVNUM_PSR2_EXTN,
SDP_VSC_REVNUM_STEREO_PSR2,
SDP_VSC_REVNUM_PSR2_EXTN,
SDP_VSC_REVNUM_STEREO_PSR2_COLOR,
SDP_VSC_REVNUM_STEREO_PR,
SDP_VSC_REVNUM_STEREO_PR_COLOR,
@@ -60,7 +60,7 @@ typedef enum tagSDP_VSC_VALID_DATA_BYTES
{
SDP_VSC_VALID_DATA_BYTES_STEREO = 1,
SDP_VSC_VALID_DATA_BYTES_STEREO_PSR = 8,
SDP_VSC_VALID_DATA_BYTES_PSR2 = 12,
SDP_VSC_VALID_DATA_BYTES_PSR2 = 12,
SDP_VSC_VALID_DATA_BYTES_PSR2_COLOR = 19,
SDP_VSC_VALID_DATA_BYTES_PR = 16,
SDP_VSC_VALID_DATA_BYTES_PR_COLOR = 19,
@@ -161,7 +161,7 @@ typedef enum tagSDP_VSC_COLOR_FMT_Y_COLORIMETRY
typedef struct tagDPSDP_DP_VSC_SDP_DESCRIPTOR
{
NvU8 dataSize; // the db data size
// header
struct
{
@@ -174,11 +174,11 @@ typedef struct tagDPSDP_DP_VSC_SDP_DESCRIPTOR
} hb;
// data content
struct
struct
{
// Stereo field. Note: Needs to be expanded when needed. Refer to DP1.3 spec.
// Stereo field. Note: Needs to be expanded when needed. Refer to DP1.3 spec.
NvU8 stereoInterface; // DB0
// PSR Field. Note: Needs to be expanded when needed. Refer to DP1.3 spec.
// PSR Field. Note: Needs to be expanded when needed. Refer to DP1.3 spec.
NvU8 psrState : 1; //DB1
NvU8 psrUpdateRfb : 1;
NvU8 psrCrcValid : 1;
@@ -203,7 +203,7 @@ typedef struct tagDPSDP_DP_VSC_SDP_DESCRIPTOR
NvU8 db14;
NvU8 db15;
// Colorimetry Infoframe Secondary Data Package following DP1.3 spec
// Colorimetry Infoframe Secondary Data Package following DP1.3 spec
NvU8 colorimetryFormat : 4; // DB16 infoframe per DP1.3 spec
NvU8 pixEncoding : 4; // DB16 infoframe per DP1.3 spec
@@ -229,7 +229,7 @@ typedef struct tagDPSDP_DP_VSC_SDP_DESCRIPTOR
typedef struct tagDPSDP_DP_PR_VSC_SDP_DESCRIPTOR
{
NvU8 dataSize; // the db data size
// header
struct
{
@@ -242,11 +242,11 @@ typedef struct tagDPSDP_DP_PR_VSC_SDP_DESCRIPTOR
} hb;
// data content
struct
struct
{
// Stereo field. Note: Needs to be expanded when needed. Refer to DP1.3 spec.
// Stereo field. Note: Needs to be expanded when needed. Refer to DP1.3 spec.
NvU8 stereoInterface; // DB0
// PSR Field. Note: Needs to be expanded when needed. Refer to DP1.3 spec.
// PSR Field. Note: Needs to be expanded when needed. Refer to DP1.3 spec.
NvU8 prState : 1; // DB1
NvU8 prReserved : 1; // Always ZERO
NvU8 prCrcValid : 1;
@@ -268,7 +268,7 @@ typedef struct tagDPSDP_DP_PR_VSC_SDP_DESCRIPTOR
NvU8 db14;
NvU8 db15;
// Colorimetry Infoframe Secondary Data Package following DP1.3 spec
// Colorimetry Infoframe Secondary Data Package following DP1.3 spec
NvU8 colorimetryFormat : 4; // DB16 infoframe per DP1.3 spec
NvU8 pixEncoding : 4; // DB16 infoframe per DP1.3 spec
@@ -294,12 +294,12 @@ typedef struct tagDPSDP_DP_PR_VSC_SDP_DESCRIPTOR
typedef struct tagDPSDP_DESCRIPTOR
{
NvU8 dataSize;
// header byte
struct
struct
{
NvU8 hb0;
NvU8 hb1;
NvU8 hb1;
NvU8 hb2;
NvU8 hb3;
} hb;
@@ -308,7 +308,7 @@ typedef struct tagDPSDP_DESCRIPTOR
struct
{
NvU8 db0;
NvU8 db1;
NvU8 db1;
NvU8 db2;
NvU8 db3;
NvU8 db4;

View File

@@ -30,12 +30,12 @@
#ifndef __EDID_H_
#define __EDID_H_
#include "nvtiming.h"
#include "nvtiming_pvt.h"
#include "displayid.h"
#include "displayid20.h"
// EDID 1.x detailed timing template
#define NVT_PVT_EDID_LDD_PAYLOAD_SIZE 13
typedef struct _tagEDID_LONG_DISPLAY_DESCRIPTOR
@@ -286,7 +286,6 @@ typedef struct _tagEIA861EXTENSION
NvU8 checksum; // 0x7F
}EIA861EXTENSION;
typedef struct _tagVTBEXTENSION
{
NvU8 tag; // 0x00
@@ -298,6 +297,18 @@ typedef struct _tagVTBEXTENSION
NvU8 checksum;
}VTBEXTENSION;
// EDID DisplayID extension block template
typedef struct _tagDIDEXTENSION
{
NvU8 tag; // 0x00
NvU8 struct_version; // 0x01
NvU8 length; // 0x02
NvU8 use_case; // 0x03
NvU8 ext_count; // 0x04
NvU8 data[NVT_DID_MAX_EXT_PAYLOAD]; // 0x05 - 0x7E
NvU8 checksum; // 0x7F
}DIDEXTENSION;
// video signal interface mask
#define NVT_PVT_EDID_INPUT_ISDIGITAL_MASK 0x80 // 0==analog
#define NVT_PVT_EDID_INPUT_ISDIGITAL_SHIFT 7

File diff suppressed because it is too large Load Diff

View File

@@ -2171,7 +2171,13 @@ DSC_GeneratePPS
if (*pBitsPerPixelX16 != 0)
{
*pBitsPerPixelX16 = DSC_AlignDownForBppPrecision(*pBitsPerPixelX16, pDscInfo->sinkCaps.bitsPerPixelPrecision);
if (*pBitsPerPixelX16 > in->bits_per_pixel)
// 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))
{
DSC_Print("ERROR - Invalid bits per pixel value specified.");
ret = NVT_STATUS_INVALID_PARAMETER;

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
@@ -217,7 +217,7 @@ NvU32 getEdidVersion(NvU8 *pEdid, NvU32 *pVer)
*pVer = (((NvU32) p->bVersionNumber) << 8) + ((NvU32) p->bRevisionNumber);
}
else if ((pEdid[0] & 0xF0) == 0x20 && (pEdid[0] & 0x0F) >=0)
else if ((pEdid[0] & 0xF0) == 0x20)
*pVer = (((NvU32) (pEdid[0] & 0XF0) << 4) + (NvU32) (pEdid[0] & 0X0F)) ; // DisplayID version 2.x
else
return NVT_STATUS_ERR; // un-recongnized EDID version
@@ -432,10 +432,9 @@ void parseEdidStandardTimingDescriptor(NvU16 timing, NVT_EDID_INFO *pInfo, NvU32
NVT_SNPRINTF((char *)pT->etc.name, 40, "EDID-STD(DMT):%dx%dx%dHz", (int)width, (int)height, (int)rr);
pT->etc.name[39] = '\0';
}
else if (pInfo->version >= NVT_EDID_VER_1_4)
// EDID1.4 and above defaults to CVT, instead of GTF. GTF is deprecated as of 1.4.
else if ((pInfo->version >= NVT_EDID_VER_1_4) && (NvTiming_CalcCVT(width, height, rr, NVT_PROGRESSIVE, pT) == NVT_STATUS_SUCCESS))
{
// EDID1.4 and above defaults to CVT, instead of GTF. GTF is deprecated as of 1.4.
NvTiming_CalcCVT(width, height, rr, NVT_PROGRESSIVE, pT);
pT->etc.status = NVT_STATUS_EDID_STDn(count);
NVT_SNPRINTF((char *)pT->etc.name, 40, "EDID-STD(CVT):%dx%dx%dHz", (int)width, (int)height, (int)rr);
pT->etc.name[39] = '\0';
@@ -443,10 +442,12 @@ void parseEdidStandardTimingDescriptor(NvU16 timing, NVT_EDID_INFO *pInfo, NvU32
else
{
// if the mode is not found in DMT, use GTF timing
NvTiming_CalcGTF(width, height, rr, NVT_PROGRESSIVE, pT);
if (NvTiming_CalcGTF(width, height, rr, NVT_PROGRESSIVE, pT) == NVT_STATUS_SUCCESS)
{
NVT_SNPRINTF((char *)pT->etc.name, 40, "EDID-STD(GTF):%dx%dx%dHz", (int)width, (int)height, (int)rr);
pT->etc.name[39] = '\0';
}
pT->etc.status = NVT_STATUS_EDID_STDn(count);
NVT_SNPRINTF((char *)pT->etc.name, 40, "EDID-STD(GTF):%dx%dx%dHz", (int)width, (int)height, (int)rr);
pT->etc.name[39] = '\0';
}
}
@@ -1055,7 +1056,10 @@ NVT_STATUS NV_STDCALL NvTiming_ParseEDIDInfo(NvU8 *pEdid, NvU32 length, NVT_EDID
parseCea861HdrStaticMetadataDataBlock(p861Info, pInfo, FROM_CTA861_EXTENSION);
// parse Dolby Vision related information from the DV vendor specific video data block
parseCea861DvStaticMetadataDataBlock(p861Info, &pInfo->dv_static_metadata_info);
parseCea861DvStaticMetadataDataBlock(p861Info, pInfo, FROM_CTA861_EXTENSION);
// parse HDR10+ related information from the HDR10+ LLC Vendor Specific Video Data Block
parseCea861Hdr10PlusDataBlock(p861Info, pInfo, FROM_CTA861_EXTENSION);
// Timings are listed (or shall) be listed in priority order
// So read SVD, yuv420 SVDs first before reading detailed timings
@@ -1955,7 +1959,15 @@ NVT_STATUS NvTiming_GetEDIDBasedASPRTiming( NvU16 width, NvU16 height, NvU16 rr,
return NVT_STATUS_ERR;
}
// check whether EDID is valid
/**
*
* @brief check EDID raw data is valid or not, and it will return the err flags if it existed
* @param pEdid : this is a pointer to EDID data
* @param length : read length of EDID
* @param bIsTrongValidation : true - added more check
* false- only header and checksum and size check
*
*/
CODE_SEGMENT(PAGE_DD_CODE)
NvU32 NvTiming_EDIDValidationMask(NvU8 *pEdid, NvU32 length, NvBool bIsStrongValidation)
{
@@ -2120,8 +2132,369 @@ NvU32 NvTiming_EDIDValidationMask(NvU8 *pEdid, NvU32 length, NvBool bIsStrongVal
break;
}
}
}
return ret;
}
/**
*
* @brief sanity check EDID binary frequently used data block is valid or not,
* and it will return error checkpoint flag if it existed
* @param pEdid : this is a pointer to EDID raw data
* @param length : read length of EDID
*
*/
CODE_SEGMENT(PAGE_DD_CODE)
NvU32 NvTiming_EDIDStrongValidationMask(NvU8 *pEdid, NvU32 length)
{
NvU32 i, j, version, extnCount;
EDIDV1STRUC *p = (EDIDV1STRUC *)pEdid;
EDID_LONG_DISPLAY_DESCRIPTOR *pLdd;
NvU8 *pExt;
DETAILEDTIMINGDESCRIPTOR *pDTD;
// For CTA861
NvU8 ctaDTD_Offset;
NvU8 *pData_collection;
NvU32 ctaBlockTag, ctaPayload, vic;
// For DisplayID
DIDEXTENSION *pDisplayid;
NvU8 did_section_length = 0x79;
NvU8 did2ExtCount = 0;
DISPLAYID_2_0_DATA_BLOCK_HEADER *pDID2Header;
DISPLAYID_DATA_BLOCK_HEADER *pHeader;
NvU8 block_length = 0;
NvBool bAllZero = NV_TRUE;
NvU32 ret = 0;
// check the EDID base size to avoid accessing beyond the EDID buffer, do not proceed with
// further validation.
if (length < sizeof(EDIDV1STRUC))
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_SIZE);
// check the EDID version and signature
if (getEdidVersion(pEdid, &version) != NVT_STATUS_SUCCESS)
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_HEADER);
// check block 0 checksum value
if (!isChecksumValid(pEdid))
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_CHECKSUM);
if (p->bVersionNumber != 0x01 || p->bRevisionNumber > 0x04)
{
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_VERSION);
}
// 18bytes in DTD or Display Descriptor check
for (i = 0; i < NVT_EDID_MAX_LONG_DISPLAY_DESCRIPTOR; i++)
{
if (*((NvU16 *)&p->DetailedTimingDesc[i]) != 0)
{
// This block is not a Display Descriptor.
// It must be a valid timing definition
// validate the block by passing NULL as the NVTIMING parameter to parseEdidDetailedTimingDescriptor
if (parseEdidDetailedTimingDescriptor((NvU8 *)&p->DetailedTimingDesc[i], NULL) != NVT_STATUS_SUCCESS)
{
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_DTD);
}
else
{
// check the max image size in monitor and its DTD defines value
if (p->bMaxHorizImageSize != 0 && p->bMaxVertImageSize != 0)
{
DETAILEDTIMINGDESCRIPTOR *pDTD = (DETAILEDTIMINGDESCRIPTOR *)&p->DetailedTimingDesc[i];
NvU16 hDTDImageSize = (pDTD->bDTHorizVertImage & 0xF0) << 4 | pDTD->bDTHorizontalImage;
NvU16 vDTDImageSize = (pDTD->bDTHorizVertImage & 0x0F) << 8 | pDTD->bDTVerticalImage;
if ((hDTDImageSize/10) > p->bMaxHorizImageSize || (vDTDImageSize/10) > p->bMaxVertImageSize)
{
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_DTD);
}
}
}
}
else
{
pLdd = (EDID_LONG_DISPLAY_DESCRIPTOR *)&p->DetailedTimingDesc[i];
// This block is a display descriptor, validate
if (((EDID_LONG_DISPLAY_DESCRIPTOR *)&p->DetailedTimingDesc[i])->rsvd != 0 || // (00 00 00)h indicates Display Descriptor
(pLdd->tag >= 0x11 && pLdd->tag <= 0xF6)) // Reserved : Do Not Use
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_DESCRIPTOR);
if (pLdd->tag == NVT_EDID_DISPLAY_DESCRIPTOR_DRL && (version == 0x103 || (version == 0x104 && (p->bFeatureSupport & 1))))
{
EDID_MONITOR_RANGE_LIMIT *pRangeLimit = (EDID_MONITOR_RANGE_LIMIT *)pLdd->data;
NvU8 max_v_rate_offset, min_v_rate_offset, max_h_rate_offset, min_h_rate_offset;
// add 255Hz offsets as needed before doing the check, use descriptor->rsvd2
nvt_assert(!(pLdd->rsvd2 & 0xF0));
max_v_rate_offset = pLdd->rsvd2 & NVT_PVT_EDID_RANGE_OFFSET_VER_MAX ? NVT_PVT_EDID_RANGE_OFFSET_AMOUNT : 0;
min_v_rate_offset = pLdd->rsvd2 & NVT_PVT_EDID_RANGE_OFFSET_VER_MIN ? NVT_PVT_EDID_RANGE_OFFSET_AMOUNT : 0;
max_h_rate_offset = pLdd->rsvd2 & NVT_PVT_EDID_RANGE_OFFSET_HOR_MAX ? NVT_PVT_EDID_RANGE_OFFSET_AMOUNT : 0;
min_h_rate_offset = pLdd->rsvd2 & NVT_PVT_EDID_RANGE_OFFSET_HOR_MIN ? NVT_PVT_EDID_RANGE_OFFSET_AMOUNT : 0;
if ((pRangeLimit->minVRate + min_v_rate_offset) > (pRangeLimit->maxVRate + max_v_rate_offset) ||
(pRangeLimit->minHRate + min_h_rate_offset) > (pRangeLimit->maxHRate + max_h_rate_offset) ||
pRangeLimit->maxVRate == 0 ||
pRangeLimit->maxHRate == 0)
{
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_RANGE_LIMIT);
}
}
}
}
// extension and size check
if ((NvU32)(p->bExtensionFlag + 1) * sizeof(EDIDV1STRUC) > length)
{
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXTENSION_COUNT);
}
// validate extension blocks
for (j = 1; j <= p->bExtensionFlag; j++)
{
pExt = pEdid + sizeof(EDIDV1STRUC) * j;
// check for 861 extension
switch (*pExt)
{
case NVT_EDID_EXTENSION_CTA:
ctaDTD_Offset = ((EIA861EXTENSION *)pExt)->offset;
// first sanity check on the extension block
if (get861ExtInfo(pExt, sizeof(EIA861EXTENSION), NULL) != NVT_STATUS_SUCCESS ||
((EIA861EXTENSION *)pExt)->revision < NVT_CEA861_REV_B)
{
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_CTA_BASIC);
}
// 0 indicated there is no DTD and data collection in this block
if (ctaDTD_Offset == 0)
{
if(!isChecksumValid(pExt))
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_CTA_CHECKSUM);
continue;
}
// validate SVD block
ctaBlockTag = NVT_CEA861_GET_SHORT_DESCRIPTOR_TAG(((EIA861EXTENSION *)pExt)->data[0]);
pData_collection = ((EIA861EXTENSION *)pExt)->data;
while ((ctaDTD_Offset - 4) > 0 && pData_collection != &pExt[ctaDTD_Offset] &&
ctaBlockTag > NVT_CEA861_TAG_RSVD && ctaBlockTag <= NVT_CEA861_TAG_EXTENDED_FLAG)
{
ctaBlockTag = NVT_CEA861_GET_SHORT_DESCRIPTOR_TAG(*pData_collection);
ctaPayload = NVT_CEA861_GET_SHORT_DESCRIPTOR_SIZE(*pData_collection);
if (parseCta861DataBlockInfo(pData_collection, (NvU32)ctaDTD_Offset - 4, NULL) == NVT_STATUS_SUCCESS)
{
pData_collection++;
if (ctaBlockTag == NVT_CEA861_TAG_VIDEO)
{
for (i=0; i < ctaPayload; i++)
{
vic = NVT_GET_CTA_8BIT_VIC(*pData_collection);
if (vic == 0 || vic > 255 || (vic >= 128 && vic <=192))
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_CTA_SVD);
pData_collection++;
}
}
else if (ctaBlockTag == NVT_CEA861_TAG_EXTENDED_FLAG)
{
if (*pData_collection == NVT_CEA861_EXT_TAG_HF_EEODB)
{
if ((p->bVersionNumber != 0x01) || (p->bRevisionNumber != 0x03))
{
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_CTA_INVALID_DATA_BLOCK);
pData_collection += ctaPayload;
}
else
{
ret &= ~NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXTENSION_COUNT);
extnCount = *(++pData_collection);
// check the EDID extension count value again because EDID extension block count
// value in EEODB override it and source shall ignore extension flag > 1 value
if ((extnCount + 1) != (length / (sizeof(EDIDV1STRUC))))
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXTENSION_COUNT);
pData_collection++;
}
}
else
pData_collection += ctaPayload;
}
else if (ctaBlockTag == NVT_CEA861_TAG_RSVD || ctaBlockTag == NVT_CEA861_TAG_RSVD1)
{
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_CTA_TAG);
pData_collection += ctaPayload;
}
else
pData_collection += ctaPayload;
}
else
{
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_CTA_INVALID_DATA_BLOCK);
pData_collection += ctaPayload;
}
}
// validate DTD blocks
pDTD = (DETAILEDTIMINGDESCRIPTOR *)&pExt[((EIA861EXTENSION *)pExt)->offset];
while (pDTD->wDTPixelClock != 0 && (NvU8 *)pDTD - pExt < (int)sizeof(EIA861EXTENSION))
{
if (parseEdidDetailedTimingDescriptor((NvU8 *)pDTD, NULL) != NVT_STATUS_SUCCESS)
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_DTD);
else
{
// check the max image size and
if (p->bMaxHorizImageSize != 0 && p->bMaxVertImageSize != 0)
{
NvU16 hDTDImageSize = (pDTD->bDTHorizVertImage & 0xF0) << 4 | pDTD->bDTHorizontalImage;
NvU16 vDTDImageSize = (pDTD->bDTHorizVertImage & 0x0F) << 8 | pDTD->bDTVerticalImage;
if ((hDTDImageSize/10) > (p->bMaxHorizImageSize) || (vDTDImageSize/10) > p->bMaxVertImageSize)
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_CTA_DTD);
}
}
pDTD++;
}
if(!isChecksumValid(pExt))
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_CTA_CHECKSUM);
break;
case NVT_EDID_EXTENSION_DISPLAYID:
pDisplayid = ((DIDEXTENSION *)pExt);
if (pDisplayid->ext_count != 0)
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_DID_EXTCOUNT);
if (pDisplayid->length != 0x79)
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_DID_SEC_SIZE);
if (!isChecksumValid(pExt))
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_DID_CHECKSUM);
// check the DID2 data blocks
if ((pDisplayid->struct_version & 0xF0) >> 4 == 2)
{
if ((pDisplayid->struct_version & 0xFF) == 0x21)
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_DID_VERSION);
did2ExtCount++;
if (pDisplayid->use_case == 0 && did2ExtCount == 1)
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_DID2_USE_CASE);
// check the DisplayId2 valid timing
pDID2Header = (DISPLAYID_2_0_DATA_BLOCK_HEADER*)pDisplayid->data;
pData_collection = pDisplayid->data;
// Sanity check every data blocks
while (((pDID2Header->type >= DISPLAYID_2_0_BLOCK_TYPE_PRODUCT_IDENTITY &&
pDID2Header->type <= DISPLAYID_2_0_BLOCK_TYPE_ARVR_LAYER) ||
pDID2Header->type == DISPLAYID_2_0_BLOCK_TYPE_VENDOR_SPEC ||
pDID2Header->type == DISPLAYID_2_0_BLOCK_TYPE_CTA_DATA) && pDID2Header->data_bytes != 0 &&
(pData_collection - pExt < (int)sizeof(DIDEXTENSION)))
{
if (parseDisplayId20EDIDExtDataBlocks(pData_collection, did_section_length, &block_length, NULL) == NVT_STATUS_ERR)
{
if (pDID2Header->type == DISPLAYID_2_0_BLOCK_TYPE_TIMING_7)
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_DID2_TYPE7);
if (pDID2Header->type == DISPLAYID_2_0_BLOCK_TYPE_RANGE_LIMITS)
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_RANGE_LIMIT);
if (pDID2Header->type == DISPLAYID_2_0_BLOCK_TYPE_ADAPTIVE_SYNC)
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_DID2_ADAPTIVE_SYNC);
// add more data blocks tag here to evaluate
}
pData_collection += block_length;
pDID2Header = (DISPLAYID_2_0_DATA_BLOCK_HEADER*)pData_collection;
}
// compare the remain 0 value are correct or not before meet checksum byte
for (i = 0; i <= (NvU32)(&pDisplayid->data[NVT_DID_MAX_EXT_PAYLOAD-1] - pData_collection); i++)
{
if (pData_collection[i] != 0)
{
bAllZero = NV_FALSE;
break;
}
}
// if the first tag failed, ignore all the tags afterward then
if (!bAllZero &&
(pDID2Header->type < DISPLAYID_2_0_BLOCK_TYPE_PRODUCT_IDENTITY ||
(pDID2Header->type > DISPLAYID_2_0_BLOCK_TYPE_ARVR_LAYER &&
pDID2Header->type != DISPLAYID_2_0_BLOCK_TYPE_VENDOR_SPEC &&
pDID2Header->type != DISPLAYID_2_0_BLOCK_TYPE_CTA_DATA)) &&
(pData_collection - pExt < (int)sizeof(DIDEXTENSION)))
{
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_DID2_TAG);
continue;
}
}
else if ((pDisplayid->struct_version & 0xFF) == 0x12 || (pDisplayid->struct_version & 0xFF) == 0x13)
{
if ((pDisplayid->struct_version & 0xFF) == 0x13)
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_DID_VERSION);
pHeader = (DISPLAYID_DATA_BLOCK_HEADER*)pDisplayid->data;
pData_collection = pDisplayid->data;
// Sanity check every data blocks
while ((pHeader->type <= NVT_DISPLAYID_BLOCK_TYPE_TILEDDISPLAY ||
pHeader->type == NVT_DISPLAYID_BLOCK_TYPE_CTA_DATA ||
pHeader->type == NVT_DISPLAYID_BLOCK_TYPE_VENDOR_SPEC) && pHeader->data_bytes != 0 &&
(pData_collection - pExt < (int)sizeof(DIDEXTENSION)))
{
if (parseDisplayIdBlock(pData_collection, did_section_length, &block_length, NULL) == NVT_STATUS_ERR)
{
if (pHeader->type == NVT_DISPLAYID_BLOCK_TYPE_TIMING_1)
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_DID13_TYPE1);
if (pHeader->type == NVT_DISPLAYID_BLOCK_TYPE_RANGE_LIMITS)
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_RANGE_LIMIT);
// add more data blocks tag here to evaluate
}
pData_collection += block_length;
pHeader = (DISPLAYID_DATA_BLOCK_HEADER*)pData_collection;
}
// compare the remain 0 value are correct or not before meet checksum byte
for (i = 0; i <= (NvU32)(&pDisplayid->data[NVT_DID_MAX_EXT_PAYLOAD-1] - pData_collection); i++)
{
if (pData_collection[i] != 0)
{
bAllZero = NV_FALSE;
break;
}
}
// if the first tag failed, ignore all the tags afterward then
if (!bAllZero &&
pHeader->type > NVT_DISPLAYID_BLOCK_TYPE_TILEDDISPLAY &&
pHeader->type != NVT_DISPLAYID_BLOCK_TYPE_CTA_DATA &&
pHeader->type != NVT_DISPLAYID_BLOCK_TYPE_VENDOR_SPEC &&
(pData_collection - pExt < (int)sizeof(DIDEXTENSION)))
{
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_DID13_TAG);
continue;
}
}
else
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXT_DID_VERSION);
break;
default:
// the useful extension only CTA (0x02) and DisplayID (0x70)
if ( *pExt != NVT_EDID_EXTENSION_VTB && *pExt != NVT_EDID_EXTENSION_DI &&
*pExt != NVT_EDID_EXTENSION_LS && *pExt != NVT_EDID_EXTENSION_DPVL &&
*pExt != NVT_EDID_EXTENSION_BM && *pExt != NVT_EDID_EXTENSION_OEM )
{
ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_EXTENSION_TAG);
}
break;
}
}
return ret;
@@ -2335,6 +2708,8 @@ CODE_SEGMENT(PAGE_DD_CODE)
NvBool assignNextAvailableTiming(NVT_EDID_INFO *pInfo,
const NVT_TIMING *pTiming)
{
if (pInfo == NULL) return NV_TRUE;
// Don't write past the end of
// pInfo->timing[NVT_EDID_MAX_TOTAL_TIMING]
if (pInfo->total_timings >= COUNT(pInfo->timing)) {
@@ -2386,7 +2761,7 @@ NvU32 NvTiming_CalculateEDIDCRC32(NvU8* pEDIDBuffer, NvU32 edidsize)
return calculateCRC32(pEDIDBuffer, edidsize);
}
//Calculates EDID's CRC after purging 'Week of Manufacture', 'Year of Manufacture',
//Calculates EDID/DisplayID2 CRC after purging 'Week of Manufacture', 'Year of Manufacture',
//'Product ID String' & 'Serial Number' from EDID
CODE_SEGMENT(PAGE_DD_CODE)
NvU32 NvTiming_CalculateCommonEDIDCRC32(NvU8* pEDIDBuffer, NvU32 edidVersion)
@@ -2403,30 +2778,64 @@ NvU32 NvTiming_CalculateCommonEDIDCRC32(NvU8* pEDIDBuffer, NvU32 edidVersion)
// Transfer over the original EDID buffer
NVMISC_MEMCPY(CommonEDIDBuffer, pEDIDBuffer, 256);
// Wipe out the Serial Number, Week of Manufacture, and Year of Manufacture or Model Year
NVMISC_MEMSET(CommonEDIDBuffer + 0x0C, 0, 6);
// Wipe out the checksums
CommonEDIDBuffer[0x7F] = 0;
CommonEDIDBuffer[0xFF] = 0;
// 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 ((pEDIDBuffer[0] & 0xF0) == 0x20)
{
if (CommonEDIDBuffer[edidBufferIndex] == 0 && CommonEDIDBuffer[edidBufferIndex+1] == 0)
/*
typedef struct DisplayId2Struct
{
// Wipe this block out. It contains OEM-specific details that contain things like serial numbers
NVMISC_MEMSET(CommonEDIDBuffer + edidBufferIndex, 0, 18);
}
}
NvU8 bVersion; // 0x00
NvU8 bSectionBytes; // 0x01 - section length, exclusive the five mandatory bytes.
NvU8 bwPrimaryUseCase; // 0x02
NvU8 bExtensionCount; // 0x03
// 0x20 DisplayId2 Standalone always exists Product Identification data block
NvU8 bProductIdtag; // 0x04
NvU8 bPIDRevision; // 0x05
NvU8 bPayloadByte; // 0x06
NvU8 bManuId[3]; // 0x07-0x09
NvU16 wProductId; // 0x0A-0x0B
NvU32 dwSerialNum; // 0x0C-0x0F
NvU16 wWeekandYear; // 0x10-0x11
NvU8 SizeOfProductNameString; // 0x12
} DISPLAY_ID2_FIXED_FORMAT;
*/
// Check what size we should do the compare against
if ( edidVersion > NVT_EDID_VER_1_4 )
{
// Wipe out the Serial Number, Week of Manufacture, and Year of Manufacture or Model Year
NVMISC_MEMSET(CommonEDIDBuffer + 0x0C, 0, 6);
// Wipe out the checksums
CommonEDIDBuffer[CommonEDIDBuffer[1]+5/*mandatory bytes*/-1] = 0;
CommonEDIDBuffer[0xFF] = 0;
// zero out any Produc Name in Prodcut Identification data block
if (CommonEDIDBuffer[0x12] != 0)
{
NVMISC_MEMSET(CommonEDIDBuffer + 0x13, 0, CommonEDIDBuffer[0x12]);
CommonEDIDBuffer[0x12] = 0;
}
// displayId2 standalone uses 256 length sections
commonEDIDBufferSize = 256;
}
else
else
{
// Wipe out the Serial Number, Week of Manufacture, and Year of Manufacture or Model Year
NVMISC_MEMSET(CommonEDIDBuffer + 0x0C, 0, 6);
// Wipe out the checksums
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)
for (edidBufferIndex = 54; edidBufferIndex <= 108; edidBufferIndex += 18)
{
if (CommonEDIDBuffer[edidBufferIndex] == 0 && CommonEDIDBuffer[edidBufferIndex+1] == 0)
{
// Wipe this block out. It contains OEM-specific details that contain things like serial numbers
NVMISC_MEMSET(CommonEDIDBuffer + edidBufferIndex, 0, 18);
}
}
// Check what size we should do the compare against
commonEDIDBufferSize = 128;
}

View File

@@ -880,7 +880,7 @@ void parseCea861HdrStaticMetadataDataBlock(NVT_EDID_CEA861_INFO *pExt861,
}
CODE_SEGMENT(PAGE_DD_CODE)
void parseCea861DvStaticMetadataDataBlock(NVT_EDID_CEA861_INFO *pExt861, NVT_DV_STATIC_METADATA *pDvInfo)
void parseCea861DvStaticMetadataDataBlock(NVT_EDID_CEA861_INFO *pExt861, void *pRawInfo, NVT_CTA861_ORIGIN flag)
{
NvU32 vsvdbVersion = 0;
NVT_DV_STATIC_METADATA_TYPE0 *pDvType0 = NULL;
@@ -888,7 +888,26 @@ void parseCea861DvStaticMetadataDataBlock(NVT_EDID_CEA861_INFO *pExt861, NVT_DV_
NVT_DV_STATIC_METADATA_TYPE1_1 *pvDvType1_1 = NULL;
NVT_DV_STATIC_METADATA_TYPE2 *pDvType2 = NULL;
if (pExt861 == NULL || pDvInfo == NULL)
NVT_EDID_INFO *pInfo = NULL;
NVT_DISPLAYID_2_0_INFO *pDisplayID20 = NULL;
NVT_DV_STATIC_METADATA *pDvInfo = NULL;
if (pExt861 == NULL || pRawInfo == NULL)
{
return;
}
if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
{
pInfo = (NVT_EDID_INFO *)pRawInfo;
pDvInfo = &pInfo->dv_static_metadata_info;
}
else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
{
pDisplayID20 = (NVT_DISPLAYID_2_0_INFO *)pRawInfo;
pDvInfo = &pDisplayID20->cta.dvInfo;
}
else
{
return;
}
@@ -898,6 +917,7 @@ void parseCea861DvStaticMetadataDataBlock(NVT_EDID_CEA861_INFO *pExt861, NVT_DV_
return;
}
//init
NVMISC_MEMSET(pDvInfo, 0, sizeof(NVT_DV_STATIC_METADATA));
@@ -1004,10 +1024,10 @@ void parseCea861DvStaticMetadataDataBlock(NVT_EDID_CEA861_INFO *pExt861, NVT_DV_
pDvInfo->supports_backlight_control = pDvType2->supports_backlight_control;
pDvInfo->supports_YUV422_12bit = pDvType2->supports_YUV422_12bit;
pDvInfo->dm_version = pDvType2->dm_version;
pDvInfo->backlt_min_luma = pDvType2->backlt_min_luma;
pDvInfo->supports_global_dimming = pDvType2->supports_global_dimming;
pDvInfo->target_min_luminance = pDvType2->target_min_luminance;
pDvInfo->interface_supported_by_sink = pDvType2->interface_supported_by_sink;
pDvInfo->parity = pDvType2->parity;
pDvInfo->target_max_luminance = pDvType2->target_max_luminance;
pDvInfo->cc_green_x = NVT_DOLBY_CHROMATICITY_MSB_GX | pDvType2->unique_Gx;
pDvInfo->cc_green_y = NVT_DOLBY_CHROMATICITY_MSB_GY | pDvType2->unique_Gy;
@@ -1213,8 +1233,13 @@ NVT_STATUS get861ExtInfo(NvU8 *p, NvU32 size, NVT_EDID_CEA861_INFO *p861info)
return NVT_STATUS_ERR;
}
// DTD offset sanity check
if (p[2] >= 1 && p[2] <= 3)
{
return NVT_STATUS_ERR;
}
// don't do anything further if p is NULL
// don't do anything further if p861info is NULL
if (p861info == NULL)
{
return NVT_STATUS_SUCCESS;
@@ -1251,7 +1276,8 @@ NVT_STATUS get861ExtInfo(NvU8 *p, NvU32 size, NVT_EDID_CEA861_INFO *p861info)
return parseCta861DataBlockInfo(&p[4], dtd_offset - 4, p861info);
}
// get the 861 extension tags info
// 1. get the 861 extension tags info
// 2. or validation purpose if p861info == NULL
CODE_SEGMENT(PAGE_DD_CODE)
NVT_STATUS parseCta861DataBlockInfo(NvU8 *p,
NvU32 size,
@@ -1265,6 +1291,7 @@ NVT_STATUS parseCta861DataBlockInfo(NvU8 *p,
NvU32 yuv420vdb_index = 0;
NvU32 yuv420cmdb_index = 0;
NvU8 svr_index = 0;
NvU32 ieee_id = 0;
NvU32 tag, ext_tag, payload;
i= 0;
@@ -1276,6 +1303,42 @@ NVT_STATUS parseCta861DataBlockInfo(NvU8 *p,
// move the pointer to the payload section
i++;
// NvTiming_EDIDValidationMask will use the different tag/payload value to make sure each of cta861 data block legal
if (p861info == NULL)
{
switch(tag)
{
case NVT_CEA861_TAG_AUDIO:
case NVT_CEA861_TAG_VIDEO:
case NVT_CEA861_TAG_SPEAKER_ALLOC:
case NVT_CEA861_TAG_VESA_DTC:
case NVT_CEA861_TAG_RSVD:
case NVT_CEA861_TAG_RSVD1:
break;
case NVT_CEA861_TAG_VENDOR:
if (payload < 3) return NVT_STATUS_ERR;
break;
case NVT_CEA861_TAG_EXTENDED_FLAG:
if (payload >= 1)
{
ext_tag = p[i];
if (ext_tag == NVT_CEA861_EXT_TAG_VIDEO_CAP && payload < 2) return NVT_STATUS_ERR;
else if (ext_tag == NVT_CEA861_EXT_TAG_COLORIMETRY && payload < 3) return NVT_STATUS_ERR;
else if (ext_tag == NVT_CEA861_EXT_TAG_VIDEO_FORMAT_PREFERENCE && payload < 2) return NVT_STATUS_ERR;
else if (ext_tag == NVT_CEA861_EXT_TAG_YCBCR420_VIDEO && payload < 2) return NVT_STATUS_ERR;
else if (ext_tag == NVT_CEA861_EXT_TAG_YCBCR420_CAP && payload < 1) return NVT_STATUS_ERR;
else if (ext_tag == NVT_CEA861_EXT_TAG_HDR_STATIC_METADATA && payload < 3) return NVT_STATUS_ERR;
else if (ext_tag == NVT_CEA861_EXT_TAG_VENDOR_SPECIFIC_VIDEO && payload < 4) return NVT_STATUS_ERR;
else if (ext_tag == NVT_CTA861_EXT_TAG_SCDB && payload < 7) return NVT_STATUS_ERR;
else if (ext_tag == NVT_CEA861_EXT_TAG_HF_EEODB && payload != 2) return NVT_STATUS_ERR;
}
break;
default:
break;
}
return NVT_STATUS_SUCCESS;
}
// loop through all descriptors
if (tag == NVT_CEA861_TAG_VIDEO)
@@ -1447,30 +1510,46 @@ NVT_STATUS parseCta861DataBlockInfo(NvU8 *p,
p861info->valid.hdr_static_metadata = 1;
}
else if(ext_tag == NVT_CEA861_EXT_TAG_VENDOR_SPECIFIC_VIDEO && ((payload >= 14) || (payload >= 11))) //version 2 of VSDB has 11 bytes of data and version 1 has 14
else if(ext_tag == NVT_CEA861_EXT_TAG_VENDOR_SPECIFIC_VIDEO)
{
ieee_id = p[i + 1]; //IEEE ID low byte
ieee_id |= (p[i + 2]) << 8; //IEEE ID middle byte
ieee_id |= (p[i + 3]) << 16; //IEEE ID high byte
// exclude the extended tag
i++; payload--;
p861info->vsvdb.ieee_id = p[i]; //IEEE ID low byte
p861info->vsvdb.ieee_id |= (p[i + 1]) << 8; //IEEE ID middle byte
p861info->vsvdb.ieee_id |= (p[i + 2]) << 16; //IEEE ID high byte
p861info->vsvdb.vendor_data_size = payload - 3;
// move the pointer to the payload
i += 3;
// get the other vendor specific video data
for (j = 0; j < payload - 3; j++, i++)
if ((ieee_id == NVT_CEA861_DV_IEEE_ID) || (ieee_id == NVT_CEA861_HDR10PLUS_IEEE_ID))
{
if (j < NVT_CEA861_VSDB_PAYLOAD_MAX_LENGTH)
// exclude the extended tag
i++; payload--;
p861info->vsvdb.ieee_id = ieee_id;
p861info->vsvdb.vendor_data_size = payload - 3;
// move the pointer to the payload
i += 3;
// get the other vendor specific video data
for (j = 0; j < payload - 3; j++, i++)
{
p861info->vsvdb.vendor_data[j] = p[i];
if (j < NVT_CEA861_VSVDB_PAYLOAD_MAX_LENGTH)
{
p861info->vsvdb.vendor_data[j] = p[i];
}
}
if (p861info->vsvdb.ieee_id == NVT_CEA861_DV_IEEE_ID)
{
p861info->valid.dv_static_metadata = 1;
}
else if (p861info->vsvdb.ieee_id == NVT_CEA861_HDR10PLUS_IEEE_ID)
{
p861info->valid.hdr10Plus = 1;
}
}
p861info->valid.dv_static_metadata = 1;
else
{
// skip the unsupported extended block
i += payload;
}
}
else if(ext_tag == NVT_CTA861_EXT_TAG_SCDB && payload >= 7) // sizeof(HDMI Forum Sink Capability Data Block) ranges between 7 to 31 bytes
{
@@ -1528,6 +1607,9 @@ NVT_STATUS NvTiming_EnumCEA861bTiming(NvU32 ceaFormat, NVT_TIMING *pT)
ceaFormat = NVT_GET_CTA_8BIT_VIC(ceaFormat);
if (ceaFormat ==0)
return NVT_STATUS_ERR;
*pT = EIA861B[ceaFormat - 1];
// calculate the pixel clock
@@ -2935,8 +3017,49 @@ void parseEdidHdmiForumVSDB(VSDB_DATA *pVsdb, NVT_HDMI_FORUM_INFO *pHdmiInfo)
default:
break;
}
}
CODE_SEGMENT(PAGE_DD_CODE)
void parseCea861Hdr10PlusDataBlock(NVT_EDID_CEA861_INFO *pExt861, void *pRawInfo, NVT_CTA861_ORIGIN flag)
{
NVT_EDID_INFO *pInfo = NULL;
NVT_DISPLAYID_2_0_INFO *pDisplayID20 = NULL;
NVT_HDR10PLUS_INFO *pHdr10PlusInfo = NULL;
if (pExt861 == NULL || pRawInfo == NULL)
{
return;
}
if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
{
pInfo = (NVT_EDID_INFO *)pRawInfo;
pHdr10PlusInfo = &pInfo->hdr10PlusInfo;
}
else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
{
pDisplayID20 = (NVT_DISPLAYID_2_0_INFO *)pRawInfo;
pHdr10PlusInfo = &pDisplayID20->cta.hdr10PlusInfo;
}
else
{
return;
}
if(pExt861->vsvdb.ieee_id != NVT_CEA861_HDR10PLUS_IEEE_ID)
{
return;
}
NVMISC_MEMSET(pHdr10PlusInfo, 0, sizeof(NVT_HDR10PLUS_INFO));
if (pExt861->vsvdb.vendor_data_size < sizeof(NVT_HDR10PLUS_INFO))
{
return;
}
NVMISC_MEMCPY(pHdr10PlusInfo, &pExt861->vsvdb.vendor_data, sizeof(NVT_HDR10PLUS_INFO));
}
POP_SEGMENTS

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
@@ -30,7 +30,6 @@
#include "nvBinSegment.h"
#include "nvmisc.h"
#include "displayid.h"
#include "edid.h"
PUSH_SEGMENTS
@@ -38,10 +37,6 @@ PUSH_SEGMENTS
static NVT_STATUS parseDisplayIdSection(DISPLAYID_SECTION * section,
NvU32 max_length,
NVT_EDID_INFO *pEdidInfo);
static NVT_STATUS parseDisplayIdBlock(NvU8 * block,
NvU8 max_length,
NvU8 * pLength,
NVT_EDID_INFO *pEdidInfo);
// Specific blocks that can be parsed based on DisplayID
static NVT_STATUS parseDisplayIdProdIdentityBlock(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
@@ -51,7 +46,7 @@ static NVT_STATUS parseDisplayIdTiming1(NvU8 * block, NVT_EDID_INFO *pEdidInfo);
static NVT_STATUS parseDisplayIdTiming2(NvU8 * block, NVT_EDID_INFO *pEdidInfo);
static NVT_STATUS parseDisplayIdTiming3(NvU8 * block, NVT_EDID_INFO *pEdidInfo);
static NVT_STATUS parseDisplayIdTiming4(NvU8 * block, NVT_EDID_INFO *pEdidInfo);
static NVT_STATUS parseDisplayIdTiming5(NvU8 * block, NVT_EDID_INFO *pEdidInfo, NVT_DISPLAYID_INFO *pInfo);
static NVT_STATUS parseDisplayIdTiming5(NvU8 * block, NVT_EDID_INFO *pEdidInfo);
static NVT_STATUS parseDisplayIdTimingVesa(NvU8 * block, NVT_EDID_INFO *pEdidInfo);
static NVT_STATUS parseDisplayIdTimingEIA(NvU8 * block, NVT_EDID_INFO *pEdidInfo);
static NVT_STATUS parseDisplayIdRangeLimits(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
@@ -63,7 +58,7 @@ static NVT_STATUS parseDisplayIdTransferChar(NvU8 * block, NVT_DISPLAYID_INFO *p
static NVT_STATUS parseDisplayIdDisplayInterface(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
static NVT_STATUS parseDisplayIdStereo(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
static NVT_STATUS parseDisplayIdTiledDisplay(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
static NVT_STATUS parseDisplayIdCtaData(NvU8 * block, NVT_EDID_INFO *pInfo, NVT_DISPLAYID_INFO *pDisplayIdInfo);
static NVT_STATUS parseDisplayIdCtaData(NvU8 * block, NVT_EDID_INFO *pInfo);
static NVT_STATUS parseDisplayIdDisplayInterfaceFeatures(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
static NVT_STATUS parseDisplayIdTiming1Descriptor(DISPLAYID_TIMING_1_DESCRIPTOR * desc, NVT_TIMING *pT);
@@ -232,7 +227,7 @@ static NVT_STATUS parseDisplayIdSection(DISPLAYID_SECTION * section,
while (block_location < section->section_bytes)
{
DISPLAYID_DATA_BLOCK_HEADER * hdr = (DISPLAYID_DATA_BLOCK_HEADER *) (section->data + block_location);
NvU8 is_prod_id = remaining_length > 3 && block_location == 0 && hdr->type == 0 && hdr->data_bytes > 0;
NvBool is_prod_id = remaining_length > 3 && block_location == 0 && hdr->type == 0 && hdr->data_bytes > 0;
NvU8 i;
// Check the padding.
@@ -265,90 +260,106 @@ static NVT_STATUS parseDisplayIdSection(DISPLAYID_SECTION * section,
return NVT_STATUS_SUCCESS;
}
/**
* @brief Parses a displayID data block
* @param block The DisplayID data block to parse
* @param max_length The indicated total length of the each data block for checking
* @param pLength return the indicated length of the each data block
* @param pEdidInfo EDID struct containing DisplayID information and
* the timings or validation purpose if it is NULL
*/
CODE_SEGMENT(PAGE_DD_CODE)
static NVT_STATUS parseDisplayIdBlock(NvU8 * block,
NvU8 max_length,
NvU8 * pLength,
NVT_EDID_INFO *pEdidInfo)
NVT_STATUS parseDisplayIdBlock(NvU8* pBlock,
NvU8 max_length,
NvU8* pLength,
NVT_EDID_INFO *pEdidInfo)
{
DISPLAYID_DATA_BLOCK_HEADER * hdr = (DISPLAYID_DATA_BLOCK_HEADER *) block;
NVT_DISPLAYID_INFO *pInfo = &pEdidInfo->ext_displayid;
DISPLAYID_DATA_BLOCK_HEADER * hdr = (DISPLAYID_DATA_BLOCK_HEADER *) pBlock;
NVT_STATUS ret = NVT_STATUS_SUCCESS;
NVT_DISPLAYID_INFO *pInfo;
if (block == NULL || max_length <= NVT_DISPLAYID_DATABLOCK_HEADER_LEN)
if (pBlock == NULL || max_length <= NVT_DISPLAYID_DATABLOCK_HEADER_LEN)
return NVT_STATUS_ERR;
if (hdr->data_bytes > max_length - NVT_DISPLAYID_DATABLOCK_HEADER_LEN)
return NVT_STATUS_ERR;
pInfo = pEdidInfo == NULL ? NULL : &pEdidInfo->ext_displayid;
*pLength = hdr->data_bytes + NVT_DISPLAYID_DATABLOCK_HEADER_LEN;
switch (hdr->type)
{
case NVT_DISPLAYID_BLOCK_TYPE_PRODUCT_IDENTITY:
parseDisplayIdProdIdentityBlock(block, pInfo);
ret = parseDisplayIdProdIdentityBlock(pBlock, pInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_DISPLAY_PARAM:
parseDisplayIdParam(block, pInfo);
ret = parseDisplayIdParam(pBlock, pInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_COLOR_CHAR:
parseDisplayIdColorChar(block, pInfo);
ret = parseDisplayIdColorChar(pBlock, pInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_TIMING_1:
parseDisplayIdTiming1(block, pEdidInfo);
ret = parseDisplayIdTiming1(pBlock, pEdidInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_TIMING_2:
parseDisplayIdTiming2(block, pEdidInfo);
ret = parseDisplayIdTiming2(pBlock, pEdidInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_TIMING_3:
parseDisplayIdTiming3(block, pEdidInfo);
ret = parseDisplayIdTiming3(pBlock, pEdidInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_TIMING_4:
parseDisplayIdTiming4(block, pEdidInfo);
ret = parseDisplayIdTiming4(pBlock, pEdidInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_TIMING_5:
parseDisplayIdTiming5(block, pEdidInfo, pInfo);
ret = parseDisplayIdTiming5(pBlock, pEdidInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_TIMING_VESA:
parseDisplayIdTimingVesa(block, pEdidInfo);
ret = parseDisplayIdTimingVesa(pBlock, pEdidInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_TIMING_CEA:
parseDisplayIdTimingEIA(block, pEdidInfo);
ret = parseDisplayIdTimingEIA(pBlock, pEdidInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_RANGE_LIMITS:
parseDisplayIdRangeLimits(block, pInfo);
ret = parseDisplayIdRangeLimits(pBlock, pInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_SERIAL_NUMBER:
parseDisplayIdSerialNumber(block, pInfo);
ret = parseDisplayIdSerialNumber(pBlock, pInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_ASCII_STRING:
parseDisplayIdAsciiString(block, pInfo);
ret = parseDisplayIdAsciiString(pBlock, pInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_DEVICE_DATA:
parseDisplayIdDeviceData(block, pInfo);
ret = parseDisplayIdDeviceData(pBlock, pInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_INTERFACE_POWER:
parseDisplayIdInterfacePower(block, pInfo);
ret = parseDisplayIdInterfacePower(pBlock, pInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_TRANSFER_CHAR:
parseDisplayIdTransferChar(block, pInfo);
ret = parseDisplayIdTransferChar(pBlock, pInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_DISPLAY_INTERFACE:
parseDisplayIdDisplayInterface(block, pInfo);
ret = parseDisplayIdDisplayInterface(pBlock, pInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_STEREO:
parseDisplayIdStereo(block, pInfo);
ret = parseDisplayIdStereo(pBlock, pInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_TILEDDISPLAY:
parseDisplayIdTiledDisplay(block, pInfo);
ret = parseDisplayIdTiledDisplay(pBlock, pInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_CTA_DATA:
parseDisplayIdCtaData(block, pEdidInfo, pInfo);
ret = parseDisplayIdCtaData(pBlock, pEdidInfo);
break;
case NVT_DISPLAYID_BLOCK_TYPE_DISPLAY_INTERFACE_FEATURES:
parseDisplayIdDisplayInterfaceFeatures(block, pInfo);
ret = parseDisplayIdDisplayInterfaceFeatures(pBlock, pInfo);
break;
default:
ret = NVT_STATUS_ERR;
break;
}
if (pEdidInfo == NULL) return ret;
return NVT_STATUS_SUCCESS;
}
CODE_SEGMENT(PAGE_DD_CODE)
@@ -371,6 +382,8 @@ static NVT_STATUS parseDisplayIdColorChar(NvU8 * block, NVT_DISPLAYID_INFO *pInf
return NVT_STATUS_ERR;
}
if (pInfo == NULL) return NVT_STATUS_SUCCESS;
for (i = 0; i < prim_num; i++)
{
x_p = (blk->points)[i].color_x_bits_low +
@@ -408,6 +421,8 @@ static NVT_STATUS parseDisplayIdProdIdentityBlock(NvU8 * block, NVT_DISPLAYID_IN
return NVT_STATUS_ERR;
}
if (pInfo == NULL) return NVT_STATUS_SUCCESS;
pInfo->vendor_id = (blk->vendor)[2] | ((blk->vendor)[1] << 8) | ((blk->vendor)[0] << 16);
pInfo->product_id = blk->product_code;
pInfo->serial_number = blk->serial_number;
@@ -432,6 +447,8 @@ static NVT_STATUS parseDisplayIdParam(NvU8 * block, NVT_DISPLAYID_INFO *pInfo)
return NVT_STATUS_ERR;
}
if (pInfo == NULL) return NVT_STATUS_SUCCESS;
pInfo->horiz_size = blk->horizontal_image_size;
pInfo->vert_size = blk->vertical_image_size;
pInfo->horiz_pixels = blk->horizontal_pixel_count;
@@ -474,11 +491,17 @@ static NVT_STATUS parseDisplayIdTiming1(NvU8 * block, NVT_EDID_INFO *pEdidInfo)
if (parseDisplayIdTiming1Descriptor(blk->descriptors + i,
&newTiming) == NVT_STATUS_SUCCESS)
{
if (pEdidInfo == NULL) continue;
if (!assignNextAvailableTiming(pEdidInfo, &newTiming))
{
break;
}
}
else
{
if (pEdidInfo == NULL) return NVT_STATUS_ERR;
}
}
return NVT_STATUS_SUCCESS;
}
@@ -610,11 +633,17 @@ static NVT_STATUS parseDisplayIdTiming2(NvU8 * block, NVT_EDID_INFO *pEdidInfo)
if (parseDisplayIdTiming2Descriptor(blk->descriptors + i,
&newTiming) == NVT_STATUS_SUCCESS)
{
if (pEdidInfo == NULL) continue;
if (!assignNextAvailableTiming(pEdidInfo, &newTiming))
{
break;
}
}
else
{
if (pEdidInfo == NULL) return NVT_STATUS_ERR;
}
}
return NVT_STATUS_SUCCESS;
}
@@ -777,11 +806,17 @@ static NVT_STATUS parseDisplayIdTiming3(NvU8 * block, NVT_EDID_INFO *pEdidInfo)
if (parseDisplayIdTiming3Descriptor(blk->descriptors + i,
&newTiming) == NVT_STATUS_SUCCESS)
{
if (pEdidInfo == NULL) continue;
if (!assignNextAvailableTiming(pEdidInfo, &newTiming))
{
break;
}
}
else
{
if (pEdidInfo == NULL) return NVT_STATUS_ERR;
}
}
return NVT_STATUS_SUCCESS;
}
@@ -806,11 +841,17 @@ static NVT_STATUS parseDisplayIdTiming4(NvU8 * block, NVT_EDID_INFO *pEdidInfo)
if (NvTiming_EnumDMT((NvU32)(blk->timing_codes[i]),
&newTiming) == NVT_STATUS_SUCCESS)
{
if (pEdidInfo == NULL) continue;
if (!assignNextAvailableTiming(pEdidInfo, &newTiming))
{
break;
}
}
else
{
if (pEdidInfo == NULL) return NVT_STATUS_ERR;
}
}
return NVT_STATUS_SUCCESS;
}
@@ -837,7 +878,7 @@ static NVT_STATUS parseDisplayIdTiming5Descriptor(DISPLAYID_TIMING_5_DESCRIPTOR
}
CODE_SEGMENT(PAGE_DD_CODE)
static NVT_STATUS parseDisplayIdTiming5(NvU8 * block, NVT_EDID_INFO *pEdidInfo, NVT_DISPLAYID_INFO *pInfo)
static NVT_STATUS parseDisplayIdTiming5(NvU8 * block, NVT_EDID_INFO *pEdidInfo)
{
NvU16 i;
NVT_TIMING newTiming;
@@ -854,11 +895,17 @@ static NVT_STATUS parseDisplayIdTiming5(NvU8 * block, NVT_EDID_INFO *pEdidInfo,
if (parseDisplayIdTiming5Descriptor(blk->descriptors + i, &newTiming) == NVT_STATUS_SUCCESS)
{
if (pEdidInfo == NULL) continue;
if (!assignNextAvailableTiming(pEdidInfo, &newTiming))
{
break;
}
}
else
{
if (pEdidInfo == NULL) return NVT_STATUS_ERR;
}
}
return NVT_STATUS_SUCCESS;
}
@@ -887,11 +934,17 @@ static NVT_STATUS parseDisplayIdTimingVesa(NvU8 * block, NVT_EDID_INFO *pEdidInf
if (NvTiming_EnumDMT((NvU32)(i * 8 + j + 1),
&newTiming) == NVT_STATUS_SUCCESS)
{
if (pEdidInfo == NULL) continue;
if (!assignNextAvailableTiming(pEdidInfo, &newTiming))
{
break;
}
}
else
{
if (pEdidInfo == NULL) return NVT_STATUS_ERR;
}
}
}
}
@@ -922,11 +975,17 @@ static NVT_STATUS parseDisplayIdTimingEIA(NvU8 * block, NVT_EDID_INFO *pEdidInfo
if (NvTiming_EnumCEA861bTiming((NvU32)(i * 8 + j + 1),
&newTiming) == NVT_STATUS_SUCCESS)
{
if (pEdidInfo == NULL) continue;
if (!assignNextAvailableTiming(pEdidInfo, &newTiming))
{
break;
}
}
else
{
if (pEdidInfo == NULL) return NVT_STATUS_ERR;
}
}
}
}
@@ -938,8 +997,31 @@ static NVT_STATUS parseDisplayIdRangeLimits(NvU8 * block, NVT_DISPLAYID_INFO *pI
{
NVT_DISPLAYID_RANGE_LIMITS * rl;
DISPLAYID_RANGE_LIMITS_BLOCK * blk = (DISPLAYID_RANGE_LIMITS_BLOCK *)block;
if ((blk->header.data_bytes != DISPLAYID_RANGE_LIMITS_BLOCK_LEN) ||
(pInfo->rl_num >= NVT_DISPLAYID_RANGE_LIMITS_MAX_COUNT))
NVT_STATUS status = NVT_STATUS_SUCCESS;
NvU32 minPclk = 0;
NvU32 maxPclk = 0;
if (blk->header.data_bytes != DISPLAYID_RANGE_LIMITS_BLOCK_LEN)
{
// Assert since this error is ignored
nvt_assert(0);
return NVT_STATUS_ERR;
}
minPclk = blk->pixel_clock_min[0] | (blk->pixel_clock_min[1] << 8) | (blk->pixel_clock_min[2] << 16);
maxPclk = blk->pixel_clock_max[0] | (blk->pixel_clock_max[1] << 8) | (blk->pixel_clock_max[2] << 16);
if (blk->vertical_refresh_rate_min == 0 || blk->vertical_refresh_rate_max == 0 ||
blk->vertical_refresh_rate_min > blk->vertical_refresh_rate_max ||
minPclk > maxPclk)
{
nvt_assert(0 && "wrong range limit");
status = NVT_STATUS_ERR;
}
if (pInfo == NULL) return status;
if (pInfo->rl_num >= NVT_DISPLAYID_RANGE_LIMITS_MAX_COUNT)
{
// Assert since this error is ignored
nvt_assert(0);
@@ -949,8 +1031,8 @@ static NVT_STATUS parseDisplayIdRangeLimits(NvU8 * block, NVT_DISPLAYID_INFO *pI
rl = pInfo->range_limits + pInfo->rl_num;
(pInfo->rl_num)++;
rl->pclk_min = blk->pixel_clock_min[0] | (blk->pixel_clock_min[1] << 8) | (blk->pixel_clock_min[2] << 16);
rl->pclk_max = blk->pixel_clock_max[0] | (blk->pixel_clock_max[1] << 8) | (blk->pixel_clock_max[2] << 16);
rl->pclk_min = minPclk;
rl->pclk_max = maxPclk;
rl->interlaced = DRF_VAL(T_DISPLAYID, _RANGE_LIMITS, _INTERLACE, blk->optns);
rl->cvt = DRF_VAL(T_DISPLAYID, _RANGE_LIMITS, _CVT_STANDARD, blk->optns);
@@ -978,6 +1060,8 @@ static NVT_STATUS parseDisplayIdSerialNumber(NvU8 * block, NVT_DISPLAYID_INFO *p
return NVT_STATUS_ERR;
}
if (pInfo == NULL) return NVT_STATUS_SUCCESS;
// Nothing is currently done to store any ASCII Serial Number, if it is
// required. Code here may need to be modified sometime in the future, along
// with NVT_DISPLAYID_INFO struct
@@ -995,6 +1079,8 @@ static NVT_STATUS parseDisplayIdAsciiString(NvU8 * block, NVT_DISPLAYID_INFO *pI
return NVT_STATUS_ERR;
}
if (pInfo == NULL) return NVT_STATUS_SUCCESS;
// Nothing is currently done to store any ASCII String Data, if it is
// required. Code here may need to be modified sometime in the future, along
// with NVT_DISPLAYID_INFO struct
@@ -1012,6 +1098,8 @@ static NVT_STATUS parseDisplayIdDeviceData(NvU8 * block, NVT_DISPLAYID_INFO *pIn
return NVT_STATUS_ERR;
}
if (pInfo == NULL) return NVT_STATUS_SUCCESS;
pInfo->tech_type = blk->technology;
pInfo->device_op_mode = DRF_VAL(T_DISPLAYID, _DEVICE, _OPERATING_MODE, blk->operating_mode);
@@ -1048,6 +1136,8 @@ static NVT_STATUS parseDisplayIdInterfacePower(NvU8 * block, NVT_DISPLAYID_INFO
return NVT_STATUS_ERR;
}
if (pInfo == NULL) return NVT_STATUS_SUCCESS;
// Note specifically that the data inside T1/T2 variables are the exact
// interface power data. the millisecond increments are dependent on the
// DisplayID specification.
@@ -1065,6 +1155,8 @@ static NVT_STATUS parseDisplayIdInterfacePower(NvU8 * block, NVT_DISPLAYID_INFO
CODE_SEGMENT(PAGE_DD_CODE)
static NVT_STATUS parseDisplayIdTransferChar(NvU8 * block, NVT_DISPLAYID_INFO *pInfo)
{
if (pInfo == NULL) return NVT_STATUS_SUCCESS;
// Transfer Characteristics are currently not supported, but parsing of the
// block should be added in the future when more specifications on monitors
// that require this information is located here.
@@ -1081,6 +1173,9 @@ static NVT_STATUS parseDisplayIdDisplayInterface(NvU8 * block, NVT_DISPLAYID_INF
nvt_assert(0);
return NVT_STATUS_ERR;
}
if (pInfo == NULL) return NVT_STATUS_SUCCESS;
pInfo->supported_displayId2_0 = 0;
// Type/Link Info
@@ -1152,6 +1247,8 @@ static NVT_STATUS parseDisplayIdStereo(NvU8 * block, NVT_DISPLAYID_INFO *pInfo)
return NVT_STATUS_ERR;
}
if (pInfo == NULL) return NVT_STATUS_SUCCESS;
sub = blk->timing_sub_block;
pInfo->stereo_code = blk->stereo_code;
@@ -1196,6 +1293,8 @@ static NVT_STATUS parseDisplayIdTiledDisplay(NvU8 * block, NVT_DISPLAYID_INFO *p
return NVT_STATUS_ERR;
}
if (pInfo == NULL) return NVT_STATUS_SUCCESS;
// For revision 0, we only allow one tiled display data block.
if (!blk->header.revision && pInfo->tile_topology_id.vendor_id)
return NVT_STATUS_SUCCESS;
@@ -1237,17 +1336,22 @@ static NVT_STATUS parseDisplayIdTiledDisplay(NvU8 * block, NVT_DISPLAYID_INFO *p
}
CODE_SEGMENT(PAGE_DD_CODE)
static NVT_STATUS parseDisplayIdCtaData(NvU8 * block, NVT_EDID_INFO *pInfo, NVT_DISPLAYID_INFO *pDisplayIdInfo)
static NVT_STATUS parseDisplayIdCtaData(NvU8 * block, NVT_EDID_INFO *pInfo)
{
DISPLAYID_DATA_BLOCK_HEADER * blk = (DISPLAYID_DATA_BLOCK_HEADER*)block;
NVT_EDID_CEA861_INFO *p861info = &pInfo->ext861;
NVT_EDID_CEA861_INFO *p861info;
if (blk->data_bytes > NVT_DISPLAYID_DATABLOCK_MAX_PAYLOAD_LEN)
{
// Assert since this error is ignored
nvt_assert(0);
return NVT_STATUS_ERR;
}
pDisplayIdInfo->cea_data_block_present = 1;
if (pInfo == NULL) return NVT_STATUS_SUCCESS;
p861info = &pInfo->ext861;
pInfo->ext_displayid.cea_data_block_present = 1;
p861info->revision = blk->revision;
//parse CEA tags which starts at 3rd byte from block
@@ -1287,6 +1391,9 @@ static NVT_STATUS parseDisplayIdDisplayInterfaceFeatures(NvU8 * block, NVT_DISPL
nvt_assert(0);
return NVT_STATUS_ERR;
}
if (pInfo == NULL) return NVT_STATUS_SUCCESS;
pInfo->supported_displayId2_0 = 1;
// Color Depths
@@ -1342,5 +1449,4 @@ static NVT_STATUS parseDisplayIdDisplayInterfaceFeatures(NvU8 * block, NVT_DISPL
return NVT_STATUS_SUCCESS;
}
POP_SEGMENTS

View File

@@ -30,14 +30,12 @@
#include "nvBinSegment.h"
#include "nvmisc.h"
#include "displayid20.h"
#include "edid.h"
PUSH_SEGMENTS
// DisplayId2 as EDID extension entry point functions
static NVT_STATUS parseDisplayId20EDIDExtSection(DISPLAYID_2_0_SECTION *section, NVT_EDID_INFO *pEdidInfo);
static NVT_STATUS parseDisplayId20EDIDExtDataBlocks(DISPLAYID_2_0_DATA_BLOCK_HEADER *pDataBlock, NvU8 remainSectionLength, NvU8 *pCurrentDBLength, NVT_EDID_INFO *pEdidInfo);
/**
*
@@ -70,8 +68,7 @@ getDisplayId20EDIDExtInfo(
// The function name
if (computeDisplayId20SectionCheckSum(p, sizeof(EDIDV1STRUC)) != 0)
{
return NVT_STATUS_ERR;
// ret |= NVT_EDID_VALIDATION_ERR_MASK(NVT_EDID_VALIDATION_ERR_CHECK_SUM);
nvt_assert(0 && "displayid2ext invalid checksum");
}
extSection = (DISPLAYID_2_0_SECTION *)(p + 1);
@@ -105,16 +102,20 @@ parseDisplayId20EDIDExtSection(
if (extSection->header.version == DISPLAYID_2_0_VERSION)
{
if (((pEdidInfo->total_did2_extensions == 1) && (extSection->header.product_type == 0 ||
if (((pEdidInfo->total_did2_extensions == 1) && (extSection->header.product_type == DISPLAYID_2_0_PROD_EXTENSION ||
extSection->header.product_type > DISPLAYID_2_0_PROD_HMD_AR ||
extSection->header.extension_count != 0)) ||
(pEdidInfo->total_did2_extensions > 1 && extSection->header.product_type != 0))
extSection->header.extension_count != DISPLAYID_2_0_PROD_EXTENSION)) ||
(pEdidInfo->total_did2_extensions > 1 && extSection->header.product_type != DISPLAYID_2_0_PROD_EXTENSION))
{
nvt_assert(0); // product_type value set incorrect in Display Product Primary Use Case field
}
pEdidInfo->ext_displayid20.version = extSection->header.version;
pEdidInfo->ext_displayid20.revision = extSection->header.revision;
if (pEdidInfo->total_did2_extensions == 1)
{
pEdidInfo->ext_displayid20.primary_use_case = extSection->header.product_type;
}
pEdidInfo->ext_displayid20.as_edid_extension = NV_TRUE;
}
else
@@ -152,11 +153,10 @@ parseDisplayId20EDIDExtSection(
}
else
{
if (parseDisplayId20EDIDExtDataBlocks(
dbHeader,
extSection->header.section_bytes - datablock_location,
&datablock_length,
pEdidInfo) != NVT_STATUS_SUCCESS)
if (parseDisplayId20EDIDExtDataBlocks((NvU8 *)(extSection->data + datablock_location),
extSection->header.section_bytes - datablock_location,
&datablock_length,
pEdidInfo) != NVT_STATUS_SUCCESS)
return NVT_STATUS_ERR;
}
@@ -169,39 +169,49 @@ parseDisplayId20EDIDExtSection(
/*
* @brief DisplayId20 as EDID extension block's "Data Block" entry point functions
* For validation, passed the NULL pEdidInfo, and client will check the return value
*/
CODE_SEGMENT(PAGE_DD_CODE)
static NVT_STATUS
NVT_STATUS
parseDisplayId20EDIDExtDataBlocks(
DISPLAYID_2_0_DATA_BLOCK_HEADER *pDataBlock,
NvU8 *pDataBlock,
NvU8 RemainSectionLength,
NvU8 *pCurrentDBLength,
NVT_EDID_INFO *pEdidInfo)
{
DISPLAYID_2_0_DATA_BLOCK_HEADER * block_header = (DISPLAYID_2_0_DATA_BLOCK_HEADER *) pDataBlock;
NVT_STATUS status = NVT_STATUS_SUCCESS;
NVT_DISPLAYID_2_0_INFO *pDisplayId20Info = NULL;
// size sanity checking
if ((pDataBlock == NULL || RemainSectionLength <= NVT_DISPLAYID_DATABLOCK_HEADER_LEN) ||
(pDataBlock->data_bytes > RemainSectionLength - NVT_DISPLAYID_DATABLOCK_HEADER_LEN))
(block_header->data_bytes > RemainSectionLength - NVT_DISPLAYID_DATABLOCK_HEADER_LEN))
return NVT_STATUS_ERR;
if (pDataBlock->type < DISPLAYID_2_0_BLOCK_TYPE_PRODUCT_IDENTITY)
if (block_header->type < DISPLAYID_2_0_BLOCK_TYPE_PRODUCT_IDENTITY)
{
return NVT_STATUS_INVALID_PARAMETER;
}
pDisplayId20Info = &pEdidInfo->ext_displayid20;
*pCurrentDBLength = pDataBlock->data_bytes + NVT_DISPLAYID_DATABLOCK_HEADER_LEN;
if (pEdidInfo != NULL)
{
pDisplayId20Info = &(pEdidInfo->ext_displayid20);
}
status = parseDisplayId20DataBlock(pDataBlock, pDisplayId20Info);
*pCurrentDBLength = block_header->data_bytes + NVT_DISPLAYID_DATABLOCK_HEADER_LEN;
status = parseDisplayId20DataBlock(block_header, pDisplayId20Info);
if (pDisplayId20Info == NULL) return status;
// TODO : All the data blocks shall sync the data from the datablock in DisplayID2_0 to pEdidInfo
if (status == NVT_STATUS_SUCCESS && pDisplayId20Info->as_edid_extension == NV_TRUE)
{
switch (pDataBlock->type)
switch (block_header->type)
{
case DISPLAYID_2_0_BLOCK_TYPE_PRODUCT_IDENTITY:
pDisplayId20Info->valid_data_blocks.product_id_present = NV_TRUE;
break;
case DISPLAYID_2_0_BLOCK_TYPE_INTERFACE_FEATURES:
pDisplayId20Info->valid_data_blocks.interface_feature_present = NV_TRUE;
@@ -234,15 +244,16 @@ parseDisplayId20EDIDExtDataBlocks(
pDisplayId20Info->valid_data_blocks.cta_data_present = NV_TRUE;
// copy all the vendor specific data block from DisplayId20 to pEdidInfo
// TODO: mixed CTA extension block and DID2.0 extension block is not handled
// NOTE: mixed CTA extension block and DID2.0 extension block are not handled
NVMISC_MEMCPY(&pEdidInfo->hdmiLlcInfo, &pDisplayId20Info->vendor_specific.hdmiLlc, sizeof(NVT_HDMI_LLC_INFO));
NVMISC_MEMCPY(&pEdidInfo->hdmiForumInfo, &pDisplayId20Info->vendor_specific.hfvs, sizeof(NVT_HDMI_FORUM_INFO));
NVMISC_MEMCPY(&pEdidInfo->nvdaVsdbInfo, &pDisplayId20Info->vendor_specific.nvVsdb, sizeof(NVDA_VSDB_PARSED_INFO));
NVMISC_MEMCPY(&pEdidInfo->msftVsdbInfo, &pDisplayId20Info->vendor_specific.msftVsdb, sizeof(MSFT_VSDB_PARSED_INFO));
NVMISC_MEMCPY(&pEdidInfo->hdr_static_metadata_info, &pDisplayId20Info->cta.hdrInfo, sizeof(NVT_HDR_STATIC_METADATA));
NVMISC_MEMCPY(&pEdidInfo->dv_static_metadata_info, &pDisplayId20Info->cta.dvInfo, sizeof(NVT_DV_STATIC_METADATA));
NVMISC_MEMCPY(&pEdidInfo->hdr10PlusInfo, &pDisplayId20Info->cta.hdr10PlusInfo, sizeof(NVT_HDR10PLUS_INFO));
// If the CTA861 extension existed already, we need to transfer the revision/basic_caps to cta embedded in DID20.
// If the CTA861 extension existed already, we need to synced the revision/basic_caps to CTA which is embedded in DID20
if (pEdidInfo->ext861.revision >= NVT_CEA861_REV_B)
{
pDisplayId20Info->cta.cta861_info.revision = pEdidInfo->ext861.revision;
@@ -268,7 +279,36 @@ parseDisplayId20EDIDExtDataBlocks(
}
break;
case DISPLAYID_2_0_BLOCK_TYPE_STEREO:
pDisplayId20Info->valid_data_blocks.stereo_interface_present = NV_TRUE;
break;
case DISPLAYID_2_0_BLOCK_TYPE_TILED_DISPLAY:
pDisplayId20Info->valid_data_blocks.tiled_display_present = NV_TRUE;
break;
case DISPLAYID_2_0_BLOCK_TYPE_CONTAINER_ID:
pDisplayId20Info->valid_data_blocks.container_id_present = NV_TRUE;
break;
case DISPLAYID_2_0_BLOCK_TYPE_TIMING_7:
pDisplayId20Info->valid_data_blocks.type7Timing_present = NV_TRUE;
break;
case DISPLAYID_2_0_BLOCK_TYPE_TIMING_8:
pDisplayId20Info->valid_data_blocks.type8Timing_present = NV_TRUE;
break;
case DISPLAYID_2_0_BLOCK_TYPE_TIMING_9:
pDisplayId20Info->valid_data_blocks.type9Timing_present = NV_TRUE;
break;
case DISPLAYID_2_0_BLOCK_TYPE_TIMING_10:
pDisplayId20Info->valid_data_blocks.type10Timing_present = NV_TRUE;
break;
case DISPLAYID_2_0_BLOCK_TYPE_RANGE_LIMITS:
pDisplayId20Info->valid_data_blocks.dynamic_range_limit_present = NV_TRUE;
break;
case DISPLAYID_2_0_BLOCK_TYPE_ADAPTIVE_SYNC:
pDisplayId20Info->valid_data_blocks.adaptive_sync_present = NV_TRUE;
break;
case DISPLAYID_2_0_BLOCK_TYPE_VENDOR_SPEC:
pDisplayId20Info->valid_data_blocks.vendor_specific_present = NV_TRUE;
break;
default:
break;
}

View File

@@ -356,7 +356,7 @@ typedef enum NVT_TV_FORMAT
#define NVT_STATUS_NTSC_TV NVT_DEF_TIMING_STATUS(NVT_TYPE_NTSC_TV, 0) // TVN
#define NVT_STATUS_PAL_TV NVT_DEF_TIMING_STATUS(NVT_TYPE_PAL_TV, 0) // TVP
#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 NVT_DEF_TIMING_STATUS(NVT_TYPE_CVT_RB, 0) // CVT_RB timing V1
#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
@@ -814,6 +814,7 @@ typedef struct VSDB_DATA
// vendor specific video data
//*******************************
#define NVT_CEA861_DV_IEEE_ID 0x00D046
#define NVT_CEA861_HDR10PLUS_IEEE_ID 0x90848B
#define NVT_CEA861_VSVDB_PAYLOAD_MAX_LENGTH 25 // max allowed vendor specific video data block payload (in byte)
#define NVT_CEA861_VSVDB_VERSION_MASK 0xE0 // vsdb version mask
#define NVT_CEA861_VSVDB_VERSION_MASK_SHIFT 5 // vsdb version shift mask
@@ -941,13 +942,13 @@ typedef struct tagNVT_DV_STATIC_METADATA_TYPE2
NvU8 VSVDB_version : 3;
// second byte
NvU8 backlt_min_luma : 2;
NvU8 reserved : 2;
NvU8 supports_global_dimming : 1;
NvU8 target_min_luminance : 5;
// third byte
NvU8 interface_supported_by_sink : 2;
NvU8 reserved : 1;
NvU8 parity : 1;
NvU8 target_max_luminance : 5;
//fourth byte
@@ -967,6 +968,14 @@ typedef struct tagNVT_DV_STATIC_METADATA_TYPE2
NvU8 unique_Ry : 5;
} NVT_DV_STATIC_METADATA_TYPE2;
typedef struct tagNVT_HDR10PLUS_INFO
{
// first byte
NvU8 application_version : 2;
NvU8 full_frame_peak_luminance_index : 2;
NvU8 peak_luminance_index : 4;
} NVT_HDR10PLUS_INFO;
#pragma pack()
//***************************
@@ -1111,6 +1120,7 @@ typedef struct tagNVT_VALID_EXTENDED_BLOCKS
NvU32 y420cmdb : 1;
NvU32 hdr_static_metadata : 1;
NvU32 dv_static_metadata : 1;
NvU32 hdr10Plus : 1;
NvU32 SCDB : 1;
NvU32 HF_EEODB : 1;
} NVT_VALID_EXTENDED_BLOCKS;
@@ -1799,7 +1809,7 @@ typedef struct tagNVT_EDID_DD_DUMMY_DESCRIPTOR
//
//
//
//*** (Tag = 0x0F) ***/
//*** (Tag = 0x00 to 0x0F) ***/
// Manufacturer Special Data
typedef struct tagNVT_EDID_DD_MANUF_DATA
{
@@ -2169,6 +2179,7 @@ typedef struct tagNVT_DV_STATIC_METADATA
NvU32 backlt_min_luma : 2;
NvU32 interface_supported_by_sink : 2;
NvU32 supports_10b_12b_444 : 2;
NvU32 parity : 1;
}NVT_DV_STATIC_METADATA;
//***********************************
@@ -2182,7 +2193,6 @@ typedef struct tagNVT_DV_STATIC_METADATA
#define NVT_DISPLAY_2_0_CAP_YCbCr_422 0x10 // DTV monitor supports YCbCr4:2:2
// vendor specific
#define NVT_VESA_VENDOR_SPECIFIC_IEEE_ID 0x3A0292
#define NVT_VESA_VENDOR_SPECIFIC_LENGTH 7
@@ -2195,6 +2205,9 @@ typedef struct tagNVT_DV_STATIC_METADATA
#define NVT_VESA_ORG_VSDB_PASS_THROUGH_INTEGER_MASK 0x3F
#define NVT_VESA_ORG_VSDB_PASS_THROUGH_FRACTIOINAL_MASK 0x0F
// adaptive-sync
#define NVT_ADAPTIVE_SYNC_DESCRIPTOR_MAX_COUNT 0x04
typedef enum _tagNVT_DISPLAYID_PRODUCT_PRIMARY_USE_CASE
{
PRODUCT_PRIMARY_USE_TEST_EQUIPMENT = 1,
@@ -2383,6 +2396,28 @@ typedef struct _tagNVT_DISPLAYID_DISPLAY_PARAMETERS
NvBool audio_speakers_integrated;
} NVT_DISPLAYID_DISPLAY_PARAMETERS;
typedef struct _tagNVT_DISPLAYID_ADAPTIVE_SYNC
{
union
{
NvU8 operation_range_info;
struct
{
NvU8 adaptive_sync_range : 1;
NvU8 duration_inc_flicker_perf : 1;
NvU8 modes : 2;
NvU8 seamless_not_support : 1;
NvU8 duration_dec_flicker_perf : 1;
NvU8 reserved : 2;
} information;
} u;
NvU8 max_duration_inc;
NvU8 min_rr;
NvU16 max_rr;
NvU8 max_duration_dec;
} NVT_DISPLAYID_ADAPTIVE_SYNC;
typedef struct _tagVESA_VSDB_PARSED_INFO
{
struct
@@ -2411,7 +2446,6 @@ typedef struct _tagVESA_VSDB_PARSED_INFO
NvU8 pass_through_fraction_dsc : 4;
NvU8 reserved : 4;
} pass_through_fractional;
} VESA_VSDB_PARSED_INFO;
typedef struct _tagNVT_DISPLAYID_VENDOR_SPECIFIC
@@ -2427,7 +2461,8 @@ typedef struct _tagNVT_DISPLAYID_CTA
{
NVT_EDID_CEA861_INFO cta861_info;
NVT_HDR_STATIC_METADATA hdrInfo;
NVT_DV_STATIC_METADATA dvInfo;
NVT_DV_STATIC_METADATA dvInfo;
NVT_HDR10PLUS_INFO hdr10PlusInfo;
} NVT_DISPLAYID_CTA;
typedef struct _tagNVT_VALID_DATA_BLOCKS
@@ -2442,6 +2477,10 @@ typedef struct _tagNVT_VALID_DATA_BLOCKS
NvBool stereo_interface_present;
NvBool tiled_display_present;
NvBool container_id_present;
NvBool type10Timing_present;
NvBool adaptive_sync_present;
NvBool arvr_hmd_present;
NvBool arvr_layer_present;
NvBool vendor_specific_present;
NvBool cta_data_present;
} NVT_VALID_DATA_BLOCKS;
@@ -2494,6 +2533,10 @@ typedef struct _tagNVT_DISPLAYID_2_0_INFO
// ContainerID Data Block (Mandatory for Multi-function Device)
NVT_DISPLAYID_CONTAINERID container_id;
// Adaptive-Sync Data Block (Mandatory for display device supports Adaptive-Sync)
NvU32 total_adaptive_sync_descriptor;
NVT_DISPLAYID_ADAPTIVE_SYNC adaptive_sync_descriptor[NVT_ADAPTIVE_SYNC_DESCRIPTOR_MAX_COUNT];
// Vendor-specific Data Block (Not Mandatory)
NVT_DISPLAYID_VENDOR_SPECIFIC vendor_specific;
@@ -2632,6 +2675,9 @@ typedef struct tagNVT_EDID_INFO
// DV capability information from the DV Metadata Data Block
NVT_DV_STATIC_METADATA dv_static_metadata_info;
// HDR10+ capability information from the HDR10+ LLC VSVDB
NVT_HDR10PLUS_INFO hdr10PlusInfo;
// HDMI LLC info
NVT_HDMI_LLC_INFO hdmiLlcInfo;
@@ -5182,28 +5228,60 @@ typedef enum
typedef enum
{
// errors returned as a bitmask by NvTiming_EDIDValidationMask()
// errors returned as a bitmask by NvTiming_EDIDValidationMask()
NVT_EDID_VALIDATION_ERR_EXT = 0,
NVT_EDID_VALIDATION_ERR_VERSION,
NVT_EDID_VALIDATION_ERR_SIZE,
NVT_EDID_VALIDATION_ERR_CHECKSUM,
NVT_EDID_VALIDATION_ERR_RANGE_LIMIT,
NVT_EDID_VALIDATION_ERR_DTD,
NVT_EDID_VALIDATION_ERR_HEADER,
NVT_EDID_VALIDATION_ERR_EXT_DTD,
NVT_EDID_VALIDATION_ERR_EXTENSION_TAG,
NVT_EDID_VALIDATION_ERR_EXTENSION_COUNT,
NVT_EDID_VALIDATION_ERR_DESCRIPTOR,
NVT_EDID_VALIDATION_ERR_EXT_CTA_BASIC,
NVT_EDID_VALIDATION_ERR_EXT_CTA_DTD,
NVT_EDID_VALIDATION_ERR_EXT_CTA_TAG,
NVT_EDID_VALIDATION_ERR_EXT_CTA_SVD,
NVT_EDID_VALIDATION_ERR_EXT_CTA_INVALID_DATA_BLOCK,
NVT_EDID_VALIDATION_ERR_EXT_CTA_CHECKSUM,
NVT_EDID_VALIDATION_ERR_EXT_DID_VERSION,
NVT_EDID_VALIDATION_ERR_EXT_DID_EXTCOUNT,
NVT_EDID_VALIDATION_ERR_EXT_DID_CHECKSUM,
NVT_EDID_VALIDATION_ERR_EXT_DID_SEC_SIZE,
NVT_EDID_VALIDATION_ERR_EXT_DID13_TAG,
NVT_EDID_VALIDATION_ERR_EXT_DID13_TYPE1,
NVT_EDID_VALIDATION_ERR_EXT_DID2_TAG,
NVT_EDID_VALIDATION_ERR_EXT_DID2_USE_CASE,
NVT_EDID_VALIDATION_ERR_EXT_DID2_MANDATORY_BLOCKS,
NVT_EDID_VALIDATION_ERR_EXT_DID2_TYPE7,
NVT_EDID_VALIDATION_ERR_EXT_DID2_TYPE10,
NVT_EDID_VALIDATION_ERR_EXT_RANGE_LIMIT,
NVT_EDID_VALIDATION_ERR_EXT_DID2_ADAPTIVE_SYNC,
} NVT_EDID_VALIDATION_ERR_STATUS;
#define NVT_EDID_VALIDATION_ERR_MASK(x) NVBIT32(x)
//*************************************
// The DisplayID2 validation Mask
//*************************************
typedef enum
{
// errors returned as a bitmask by NvTiming_DisplayID2ValidationMask()
NVT_DID2_VALIDATION_ERR_EXT = 0,
NVT_DID2_VALIDATION_ERR_VERSION,
NVT_DID2_VALIDATION_ERR_VERSION = 0,
NVT_DID2_VALIDATION_ERR_SIZE,
NVT_DID2_VALIDATION_ERR_CHECKSUM,
NVT_DID2_VALIDATION_ERR_PRODUCT_ID,
NVT_DID2_VALIDATION_ERR_CHECKSUM,
NVT_DID2_VALIDATION_ERR_NO_DATA_BLOCK,
NVT_EDID_VALIDATION_ERR_TAG,
NVT_DID2_VALIDATION_ERR_RANGE_LIMIT,
NVT_DID2_VALIDATION_ERR_NATIVE_DTD,
NVT_DID2_VALIDATION_ERR_MANDATORY_BLOCKS,
NVT_DID2_VALIDATION_ERR_PRODUCT_IDENTIFY,
NVT_DID2_VALIDATION_ERR_PARAMETER,
NVT_DID2_VALIDATION_ERR_INTERFACE,
NVT_DID2_VALIDATION_ERR_TYPE7,
NVT_DID2_VALIDATION_ERR_TYPE10,
NVT_DID2_VALIDATION_ERR_ADAPTIVE_SYNC,
} NVT_DID2_VALIDATION_ERR_STATUS;
#define NVT_DID2_VALIDATION_ERR_MASK(x) NVBIT32(x)
@@ -5229,9 +5307,9 @@ typedef enum
#define NVT_FLAG_DTD1_PREFERRED_TIMING 0x00080000
#define NVT_FLAG_DISPLAYID_DTD_PREFERRED_TIMING 0x00100000
#define NVT_FLAG_CEA_PREFERRED_TIMING 0x00200000
#define NVT_FLAG_DISPLAYID_7_DSC_PASSTHRU 0x00400000
#define NVT_FLAG_DISPLAYID_T7_DSC_PASSTHRU 0x00400000
#define NVT_FLAG_DISPLAYID_2_0_TIMING 0x00800000 // this one for the CTA861 embedded in DID20
#define NVT_FLAG_DISPLAYID_2_0_EXPLICT_YUV420 0x01000000 // DID2 E7 spec. supported yuv420 indicated
#define NVT_FLAG_DISPLAYID_T7_T8_EXPLICT_YUV420 0x01000000 // DID2 E7 spec. supported yuv420 indicated
#define NVT_FLAG_INTERLACED_MASK (NVT_FLAG_INTERLACED_TIMING | NVT_FLAG_INTERLACED_TIMING2)
@@ -5299,6 +5377,7 @@ NvU32 NvTiming_GetVESADisplayDescriptorVersion(NvU8 *rawData, NvU32 *pVer);
// EDID entry parse
NVT_STATUS NV_STDCALL NvTiming_ParseEDIDInfo(NvU8 *pEdid, NvU32 length, NVT_EDID_INFO *pEdidInfo);
NvU32 NvTiming_EDIDValidationMask(NvU8 *pEdid, NvU32 length, NvBool bIsStrongValidation);
NvU32 NvTiming_EDIDStrongValidationMask(NvU8 *pEdid, NvU32 length);
NVT_STATUS NvTiming_EDIDValidation(NvU8 *pEdid, NvU32 length, NvBool bIsStrongValidation);
// DisplayID20 standalone entry parse

View File

@@ -78,8 +78,9 @@ void parseEdidHdmiForumVSDB(VSDB_DATA *pVsdb, NVT_HDMI_FORUM_INFO *pHdmiIn
void getEdidHDM1_4bVsdbTiming(NVT_EDID_INFO *pInfo);
void parseEdidHDMILLCTiming(NVT_EDID_INFO *pInfo, VSDB_DATA *pVsdb, NvU32 *pSupported, HDMI3DSUPPORTMAP * pM);
void parseEdidNvidiaVSDBBlock(VSDB_DATA *pVsdb, NVDA_VSDB_PARSED_INFO *vsdbInfo);
void parseCea861HdrStaticMetadataDataBlock(NVT_EDID_CEA861_INFO *pExt861, void *pRawInfo, NVT_CTA861_ORIGIN);
void parseCea861DvStaticMetadataDataBlock(NVT_EDID_CEA861_INFO *pExt861, NVT_DV_STATIC_METADATA *pDvInfo);
void parseCea861HdrStaticMetadataDataBlock(NVT_EDID_CEA861_INFO *pExt861, void *pRawInfo, NVT_CTA861_ORIGIN flag);
void parseCea861DvStaticMetadataDataBlock(NVT_EDID_CEA861_INFO *pExt861, void *pRawInfo, NVT_CTA861_ORIGIN flag);
void parseCea861Hdr10PlusDataBlock(NVT_EDID_CEA861_INFO *pExt861, void *pRawInfo, NVT_CTA861_ORIGIN flag);
NvBool isMatchedCTA861Timing(NVT_EDID_INFO *pInfo, NVT_TIMING *pT);
NvU32 isHdmi3DStereoType(NvU8 StereoStructureType);
NvU32 getCEA861TimingAspectRatio(NvU32 vic);
@@ -91,7 +92,9 @@ void getMonitorDescriptorString(NvU8 *pEdid, NvU8 tag, char *str, int once
// DispalyID base / extension related functions
NvU32 getDID2Version(NvU8 *pData, NvU32 *pVer);
NVT_STATUS getDisplayIdEDIDExtInfo(NvU8* pEdid, NvU32 edidSize, NVT_EDID_INFO* pEdidInfo);
NVT_STATUS parseDisplayIdBlock(NvU8* pBlock, NvU8 max_length, NvU8* pLength, NVT_EDID_INFO* pEdidInfo);
NVT_STATUS getDisplayId20EDIDExtInfo(NvU8* pDisplayid, NvU32 edidSize, NVT_EDID_INFO* pEdidInfo);
NVT_STATUS parseDisplayId20EDIDExtDataBlocks(NvU8* pDataBlock, NvU8 remainSectionLength, NvU8* pCurrentDBLength, NVT_EDID_INFO* pEdidInfo);
void updateColorFormatForDisplayIdExtnTimings(NVT_EDID_INFO* pInfo, NvU32 timingIdx);
void updateColorFormatForDisplayId20ExtnTimings(NVT_EDID_INFO* pInfo, NvU32 timingIdx);
NvBool assignNextAvailableDisplayId20Timing(NVT_DISPLAYID_2_0_INFO *pDisplayIdInfo, const NVT_TIMING *pTiming);