1 //*****************************************************************************
2 //
3 //  SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4 //  SPDX-License-Identifier: MIT
5 //
6 //  Permission is hereby granted, free of charge, to any person obtaining a
7 //  copy of this software and associated documentation files (the "Software"),
8 //  to deal in the Software without restriction, including without limitation
9 //  the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 //  and/or sell copies of the Software, and to permit persons to whom the
11 //  Software is furnished to do so, subject to the following conditions:
12 //
13 //  The above copyright notice and this permission notice shall be included in
14 //  all copies or substantial portions of the Software.
15 //
16 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 //  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 //  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 //  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 //  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 //  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 //  DEALINGS IN THE SOFTWARE.
23 //
24 //  File:       nvt_edidext_861.c
25 //
26 //  Purpose:    the provide edid 861 extension related services
27 //
28 //*****************************************************************************
29 
30 #include "nvBinSegment.h"
31 #include "nvmisc.h"
32 
33 #include "edid.h"
34 
35 
36 
37 PUSH_SEGMENTS
38 
39 #define EIA_TIMING(hv,hfp,hsw,ht,hsp,vv,vfp,vsw,vt,vsp,rrx1k,ip,aspect,rep,format) \
40     {hv,0,hfp,hsw,ht,(hsp)=='-',vv,0,vfp,vsw,vt,(vsp)=='-',(ip)=='i' ? NVT_INTERLACED:NVT_PROGRESSIVE,\
41     0,{0,((rrx1k)+500)/1000,rrx1k,((1?aspect)<<16)|(0?aspect),rep,{0},{0},{0},{0},NVT_STATUS_EDID_861STn(format),"CEA-861B:#"#format""}}
42 
43 
44 #define NVT_TIMING(hv,hfp,hsw,ht,hsp,vv,vfp,vsw,vt,vsp,rrx1k,ip,aspect,rep,format,name) \
45     {hv,0,hfp,hsw,ht,(hsp)=='-',vv,0,vfp,vsw,vt,(vsp)=='-',(ip)=='i' ? NVT_INTERLACED:NVT_PROGRESSIVE,\
46     0,{0,((rrx1k)+500)/1000,rrx1k,((1?aspect)<<16)|(0?aspect),rep,{0},{0},{0},{0},NVT_TYPE_NV_PREDEFINEDn(format),name}}
47 
48 #define HDMI_EXT_TIMING(hv,hfp,hsw,ht,hsp,vv,vfp,vsw,vt,vsp,rrx1k,ip,aspect,rep,format,name) \
49     {hv,0,hfp,hsw,ht,(hsp)=='-',vv,0,vfp,vsw,vt,(vsp)=='-',(ip)=='i' ? NVT_INTERLACED:NVT_PROGRESSIVE,\
50     0,{0,((rrx1k)+500)/1000,rrx1k,((1?aspect)<<16)|(0?aspect),rep,{0},{0},{0},{0},NVT_STATUS_HDMI_EXTn(format),name}}
51 
52 DATA_SEGMENT(PAGE_DATA)
53 CONS_SEGMENT(PAGE_CONS)
54 
55 static const NVT_TIMING EIA861B[]=
56 {
57     // all 64 EIA/CEA-861E timings
58     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3,   0x1, 1),//640       x  480p @59.94/60   (Format 1)
59     EIA_TIMING( 720,  16, 62, 858,'-', 480, 9,6, 525,'-', 59940,'p', 4:3,   0x1, 2),//720       x  480p @59.94/60   (Format 2)
60     EIA_TIMING( 720,  16, 62, 858,'-', 480, 9,6, 525,'-', 59940,'p',16:9,   0x1, 3),//720       x  480p @59.94/60   (Format 3)
61     EIA_TIMING(1280, 110, 40,1650,'+', 720, 5,5, 750,'+', 59940,'p',16:9,   0x1, 4),//1280      x  720p @59.94/60   (Format 4)
62     EIA_TIMING(1920,  88, 44,2200,'+', 540, 2,5, 562,'+', 59940,'i',16:9,   0x1, 5),//1920      x 1080i @59.94/60   (Format 5)
63     EIA_TIMING(1440,  38,124,1716,'-', 240, 4,3, 262,'-', 59940,'i', 4:3,   0x2, 6),//720(1440) x  480i @59.94/60   (Format 6)
64     EIA_TIMING(1440,  38,124,1716,'-', 240, 4,3, 262,'-', 59940,'i',16:9,   0x2, 7),//720(1440) x  480i @59.94/60   (Format 7)
65     EIA_TIMING(1440,  38,124,1716,'-', 240, 4,3, 263,'-', 59940,'p', 4:3,   0x2, 8),//720(1440) x  240p @59.94/60   (Format 8)
66     EIA_TIMING(1440,  38,124,1716,'-', 240, 4,3, 263,'-', 59940,'p',16:9,   0x2, 9),//720(1440) x  240p @59.94/60   (Format 9)
67     EIA_TIMING(2880,  76,248,3432,'-', 240, 4,3, 262,'-', 59940,'i', 4:3, 0x3ff,10),//(2880)    x  480i @59.94/60   (Format 10)
68     EIA_TIMING(2880,  76,248,3432,'-', 240, 4,3, 262,'-', 59940,'i',16:9, 0x3ff,11),//(2880)    x  480i @59.94/60   (Format 11)
69     EIA_TIMING(2880,  76,248,3432,'-', 240, 5,3, 263,'-', 59940,'p', 4:3, 0x3ff,12),//(2880)    x  480p @59.94/60   (Format 12)
70     EIA_TIMING(2880,  76,248,3432,'-', 240, 5,3, 263,'-', 59940,'p',16:9, 0x3ff,13),//(2880)    x  480p @59.94/60   (Format 13)
71     EIA_TIMING(1440,  32,124,1716,'-', 480, 9,6, 525,'-', 59940,'p', 4:3,   0x3,14),//1440      x  480p @59.94/60   (Format 14)
72     EIA_TIMING(1440,  32,124,1716,'-', 480, 9,6, 525,'-', 59940,'p',16:9,   0x3,15),//1440      x  480p @59.94/60   (Format 15)
73     EIA_TIMING(1920,  88, 44,2200,'+',1080, 4,5,1125,'+', 59940,'p',16:9,   0x1,16),//1920      x 1080p @59.94/60   (Format 16)
74     EIA_TIMING( 720,  12, 64, 864,'-', 576, 5,5, 625,'-', 50000,'p', 4:3,   0x1,17),//720       x  576p @50         (Format 17)
75     EIA_TIMING( 720,  12, 64, 864,'-', 576, 5,5, 625,'-', 50000,'p',16:9,   0x1,18),//720       x  576p @50         (Format 18)
76     EIA_TIMING(1280, 440, 40,1980,'+', 720, 5,5, 750,'+', 50000,'p',16:9,   0x1,19),//1280      x  720p @50         (Format 19)
77     EIA_TIMING(1920, 528, 44,2640,'+', 540, 2,5, 562,'+', 50000,'i',16:9,   0x1,20),//1920      x 1080i @50         (Format 20)
78     EIA_TIMING(1440,  24,126,1728,'-', 288, 2,3, 312,'-', 50000,'i', 4:3,   0x2,21),//720(1440) x  576i @50         (Format 21)
79     EIA_TIMING(1440,  24,126,1728,'-', 288, 2,3, 312,'-', 50000,'i',16:9,   0x2,22),//720(1440) x  576i @50         (Format 22)
80     EIA_TIMING(1440,  24,126,1728,'-', 288, 2,3, 312,'-', 50000,'p', 4:3,   0x2,23),//720(1440) x  288p @50         (Format 23)
81     EIA_TIMING(1440,  24,126,1728,'-', 288, 2,3, 312,'-', 50000,'p',16:9,   0x2,24),//720(1440) x  288p @50         (Format 24)
82     EIA_TIMING(2880,  48,252,3456,'-', 288, 2,3, 312,'-', 50000,'i', 4:3, 0x3ff,25),//(2880)    x  576i @50         (Format 25)
83     EIA_TIMING(2880,  48,252,3456,'-', 288, 2,3, 312,'-', 50000,'i',16:9, 0x3ff,26),//(2880)    x  576i @50         (Format 26)
84     EIA_TIMING(2880,  48,252,3456,'-', 288, 2,3, 312,'-', 50000,'p', 4:3, 0x3ff,27),//(2880)    x  288p @50         (Format 27)
85     EIA_TIMING(2880,  48,252,3456,'-', 288, 2,3, 312,'-', 50000,'p',16:9, 0x3ff,28),//(2880)    x  288p @50         (Format 28)
86     EIA_TIMING(1440,  24,128,1728,'-', 576, 5,5, 625,'_', 50000,'p', 4:3,   0x3,29),//1440      x  576p @50         (Format 29)
87     EIA_TIMING(1440,  24,128,1728,'-', 576, 5,5, 625,'_', 50000,'p',16:9,   0x3,30),//1440      x  576p @50         (Format 30)
88     EIA_TIMING(1920, 528, 44,2640,'+',1080, 4,5,1125,'+', 50000,'p',16:9,   0x1,31),//1920      x 1080p @50         (Format 31)
89     EIA_TIMING(1920, 638, 44,2750,'+',1080, 4,5,1125,'+', 23976,'p',16:9,   0x1,32),//1920      x 1080p @23.97/24   (Format 32)
90     EIA_TIMING(1920, 528, 44,2640,'+',1080, 4,5,1125,'+', 25000,'p',16:9,   0x1,33),//1920      x 1080p @25         (Format 33)
91     EIA_TIMING(1920,  88, 44,2200,'+',1080, 4,5,1125,'+', 29970,'p',16:9,   0x1,34),//1920      x 1080p @29.97/30   (Format 34)
92     EIA_TIMING(2880,  64,248,3432,'-', 480, 9,6, 525,'-', 59940,'p', 4:3,   0x7,35),//(2880)    x  480p @59.94/60   (Format 35)
93     EIA_TIMING(2880,  64,248,3432,'-', 480, 9,6, 525,'-', 59940,'p',16:9,   0x7,36),//(2880)    x  480p @59.94/60   (Format 36)
94     EIA_TIMING(2880,  48,256,3456,'-', 576, 5,5, 625,'-', 50000,'p', 4:3,   0x7,37),//(2880)    x  576p @50         (Format 37)
95     EIA_TIMING(2880,  48,256,3456,'-', 576, 5,5, 625,'-', 50000,'p',16:9,   0x7,38),//(2880)    x  576p @50         (Format 38)
96     EIA_TIMING(1920,  32,168,2304,'+', 540,23,5, 625,'-', 50000,'i',16:9,   0x1,39),//1920      x 1080i @50         (Format 39)
97     EIA_TIMING(1920, 528, 44,2640,'+', 540, 2,5, 562,'+',100000,'i',16:9,   0x1,40),//1920      x 1080i @100        (Format 40)
98     EIA_TIMING(1280, 440, 40,1980,'+', 720, 5,5, 750,'+',100000,'p',16:9,   0x1,41),//1280      x  720p @100        (Format 41)
99     EIA_TIMING( 720,  12, 64, 864,'-', 576, 5,5, 625,'-',100000,'p', 4:3,   0x1,42),//720       x  576p @100        (Format 42)
100     EIA_TIMING( 720,  12, 64, 864,'-', 576, 5,5, 625,'-',100000,'p',16:9,   0x1,43),//720       x  576p @100        (Format 43)
101     EIA_TIMING(1440,  24,126,1728,'-', 288, 2,3, 312,'-',100000,'i', 4:3,   0x2,44),//720(1440) x  576i @100        (Format 44)
102     EIA_TIMING(1440,  24,126,1728,'-', 288, 2,3, 312,'-',100000,'i',16:9,   0x2,45),//720(1440) x  576i @100        (Format 45)
103     EIA_TIMING(1920,  88, 44,2200,'+', 540, 2,5, 562,'+',119880,'i',16:9,   0x1,46),//1920      x 1080i @119.88/120 (Format 46)
104     EIA_TIMING(1280, 110, 40,1650,'+', 720, 5,5, 750,'+',119880,'p',16:9,   0x1,47),//1280      x  720p @119.88/120 (Format 47)
105     EIA_TIMING( 720,  16, 62, 858,'-', 480, 9,6, 525,'-',119880,'p', 4:3,   0x1,48),//720       x  480p @119.88/120 (Format 48)
106     EIA_TIMING( 720,  16, 62, 858,'-', 480, 9,6, 525,'-',119880,'p',16:9,   0x1,49),//720       x  480p @119.88/120 (Format 49)
107     EIA_TIMING(1440,  38,124,1716,'-', 240, 4,3, 262,'-',119880,'i', 4:3,   0x2,50),//720(1440) x  480i @119.88/120 (Format 50)
108     EIA_TIMING(1440,  38,124,1716,'-', 240, 4,3, 262,'-',119880,'i',16:9,   0x2,51),//720(1440) x  480i @119.88/120 (Format 51)
109     EIA_TIMING( 720,  12, 64, 864,'-', 576, 5,5, 625,'-',200000,'p', 4:3,   0x1,52),//720       x  576p @200        (Format 52)
110     EIA_TIMING( 720,  12, 64, 864,'-', 576, 5,5, 625,'-',200000,'p',16:9,   0x1,53),//720       x  576p @200        (Format 53)
111     EIA_TIMING(1440,  24,126,1728,'-', 288, 2,3, 312,'-',200000,'i', 4:3,   0x2,54),//720(1440) x  576i @200        (Format 54)
112     EIA_TIMING(1440,  24,126,1728,'-', 288, 2,3, 312,'-',200000,'i',16:9,   0x2,55),//720(1440) x  576i @200        (Format 55)
113     EIA_TIMING( 720,  16, 62, 858,'-', 480, 9,6, 525,'-',239760,'p', 4:3,   0x1,56),//720       x  480p @239.76/240 (Format 56)
114     EIA_TIMING( 720,  16, 62, 858,'-', 480, 9,6, 525,'-',239760,'p',16:9,   0x1,57),//720       x  480p @239.76/240 (Format 57)
115     EIA_TIMING(1440,  38,124,1716,'-', 240, 4,3, 262,'-',239760,'i', 4:3,   0x2,58),//720(1440) x  480i @239.76/240 (Format 58)
116     EIA_TIMING(1440,  38,124,1716,'-', 240, 4,3, 262,'-',239760,'i',16:9,   0x2,59),//720(1440) x  480i @239.76/240 (Format 59)
117     EIA_TIMING(1280,1760, 40,3300,'+', 720, 5,5, 750,'+',23976, 'p',16:9,   0x1,60),//1280      x  720p @23.97/24   (Format 60)
118     EIA_TIMING(1280,2420, 40,3960,'+', 720, 5,5, 750,'+',25000, 'p',16:9,   0x1,61),//1280      x  720p @25         (Format 61)
119     EIA_TIMING(1280,1760, 40,3300,'-', 720, 5,5, 750,'+',29970, 'p',16:9,   0x1,62),//1280      x  720p @29.97/30   (Format 62)
120     EIA_TIMING(1920,  88, 44,2200,'+',1080, 4,5,1125,'+',119880,'p',16:9,   0x1,63),//1920      x 1080p @119.88/120 (Format 63)
121     EIA_TIMING(1920, 528, 44,2640,'+',1080, 4,5,1125,'+',100000,'p',16:9,   0x1,64),//1920      x 1080p @100        (Format 64)
122     // Following modes are from CEA-861F
123     EIA_TIMING(1280,1760, 40,3300,'+', 720, 5, 5, 750,'+', 23976,'p',  64:27,   0x1, 65),//1280      x 720p @23.98/24   (Format 65)
124     EIA_TIMING(1280,2420, 40,3960,'+', 720, 5, 5, 750,'+', 25000,'p',  64:27,   0x1, 66),//1280      x 720p @25         (Format 66)
125     EIA_TIMING(1280,1760, 40,3300,'+', 720, 5, 5, 750,'+', 29970,'p',  64:27,   0x1, 67),//1280      x 720p @29.97/30   (Format 67)
126     EIA_TIMING(1280, 440, 40,1980,'+', 720, 5, 5, 750,'+', 50000,'p',  64:27,   0x1, 68),//1280      x 720p @50         (Format 68)
127     EIA_TIMING(1280, 110, 40,1650,'+', 720, 5, 5, 750,'+', 59940,'p',  64:27,   0x1, 69),//1280      x 720p @59.94/60   (Format 69)
128     EIA_TIMING(1280, 440, 40,1980,'+', 720, 5, 5, 750,'+',100000,'p',  64:27,   0x1, 70),//1280      x 720p @100        (Format 70)
129     EIA_TIMING(1280, 110, 40,1650,'+', 720, 5, 5, 750,'+',119880,'p',  64:27,   0x1, 71),//1280      x 720p @119.88/120 (Format 71)
130     EIA_TIMING(1920, 638, 44,2750,'+',1080, 4, 5,1125,'+', 23976,'p',  64:27,   0x1, 72),//1920      x1080p @23.98/24   (Format 72)
131     EIA_TIMING(1920, 528, 44,2640,'+',1080, 4, 5,1125,'+', 25000,'p',  64:27,   0x1, 73),//1920      x1080p @25         (Format 73)
132     EIA_TIMING(1920,  88, 44,2200,'+',1080, 4, 5,1125,'+', 29970,'p',  64:27,   0x1, 74),//1920      x1080p @29.97/30   (Format 74)
133     EIA_TIMING(1920, 528, 44,2640,'+',1080, 4, 5,1125,'+', 50000,'p',  64:27,   0x1, 75),//1920      x1080p @50         (Format 75)
134     EIA_TIMING(1920,  88, 44,2200,'+',1080, 4, 5,1125,'+', 59940,'p',  64:27,   0x1, 76),//1920      x1080p @59.94/60   (Format 76)
135     EIA_TIMING(1920, 528, 44,2640,'+',1080, 4, 5,1125,'+',100000,'p',  64:27,   0x1, 77),//1920      x1080p @100        (Format 77)
136     EIA_TIMING(1920,  88, 44,2200,'+',1080, 4, 5,1125,'+',119880,'p',  64:27,   0x1, 78),//1920      x1080p @119.88/120 (Format 78)
137     EIA_TIMING(1680,1360, 40,3300,'+', 720, 5, 5, 750,'+', 23976,'p',  64:27,   0x1, 79),//1680      x 720p @23.98/24   (Format 79)
138     EIA_TIMING(1680,1228, 40,3168,'+', 720, 5, 5, 750,'+', 25000,'p',  64:27,   0x1, 80),//1680      x 720p @25         (Format 80)
139     EIA_TIMING(1680, 700, 40,2640,'+', 720, 5, 5, 750,'+', 29970,'p',  64:27,   0x1, 81),//1680      x 720p @29.97/30   (Format 81)
140     EIA_TIMING(1680, 260, 40,2200,'+', 720, 5, 5, 750,'+', 50000,'p',  64:27,   0x1, 82),//1680      x 720p @50         (Format 82)
141     EIA_TIMING(1680, 260, 40,2200,'+', 720, 5, 5, 750,'+', 59940,'p',  64:27,   0x1, 83),//1680      x 720p @59.94/60   (Format 83)
142     EIA_TIMING(1680,  60, 40,2000,'+', 720, 5, 5, 825,'+',100000,'p',  64:27,   0x1, 84),//1680      x 720p @100        (Format 84)
143     EIA_TIMING(1680,  60, 40,2000,'+', 720, 5, 5, 825,'+',119880,'p',  64:27,   0x1, 85),//1680      x 720p @119.88/120 (Format 85)
144     EIA_TIMING(2560, 998, 44,3750,'+',1080, 4, 5,1100,'+', 23976,'p',  64:27,   0x1, 86),//2560      x1080p @23.98/24   (Format 86)
145     EIA_TIMING(2560, 448, 44,3200,'+',1080, 4, 5,1125,'+', 25000,'p',  64:27,   0x1, 87),//2560      x1080p @25         (Format 87)
146     EIA_TIMING(2560, 768, 44,3520,'+',1080, 4, 5,1125,'+', 29970,'p',  64:27,   0x1, 88),//2560      x1080p @29.97/30   (Format 88)
147     EIA_TIMING(2560, 548, 44,3300,'+',1080, 4, 5,1125,'+', 50000,'p',  64:27,   0x1, 89),//2560      x1080p @50         (Format 89)
148     EIA_TIMING(2560, 248, 44,3000,'+',1080, 4, 5,1100,'+', 59940,'p',  64:27,   0x1, 90),//2560      x1080p @59.94/60   (Format 90)
149     EIA_TIMING(2560, 218, 44,2970,'+',1080, 4, 5,1250,'+',100000,'p',  64:27,   0x1, 91),//2560      x1080p @100        (Format 91)
150     EIA_TIMING(2560, 548, 44,3300,'+',1080, 4, 5,1250,'+',119880,'p',  64:27,   0x1, 92),//2560      x1080p @119.88/120 (Format 92)
151     EIA_TIMING(3840,1276, 88,5500,'+',2160, 8,10,2250,'+', 23976,'p',   16:9,   0x1, 93),//3840      x2160p @23.98/24   (Format 93)
152     EIA_TIMING(3840,1056, 88,5280,'+',2160, 8,10,2250,'+', 25000,'p',   16:9,   0x1, 94),//3840      x2160p @25         (Format 94)
153     EIA_TIMING(3840, 176, 88,4400,'+',2160, 8,10,2250,'+', 29970,'p',   16:9,   0x1, 95),//3840      x2160p @29.97/30   (Format 95)
154     EIA_TIMING(3840,1056, 88,5280,'+',2160, 8,10,2250,'+', 50000,'p',   16:9,   0x1, 96),//3840      x2160p @50         (Format 96)
155     EIA_TIMING(3840, 176, 88,4400,'+',2160, 8,10,2250,'+', 59940,'p',   16:9,   0x1, 97),//3840      x2160p @59.94/60   (Format 97)
156     EIA_TIMING(4096,1020, 88,5500,'+',2160, 8,10,2250,'+', 23976,'p',256:135,   0x1, 98),//4096      x2160p @23.98/24   (Format 98)
157     EIA_TIMING(4096, 968, 88,5280,'+',2160, 8,10,2250,'+', 25000,'p',256:135,   0x1, 99),//4096      x2160p @25         (Format 99)
158     EIA_TIMING(4096,  88, 88,4400,'+',2160, 8,10,2250,'+', 29970,'p',256:135,   0x1,100),//4096      x2160p @29.97/30   (Format 100)
159     EIA_TIMING(4096, 968, 88,5280,'+',2160, 8,10,2250,'+', 50000,'p',256:135,   0x1,101),//4096      x2160p @50         (Format 101)
160     EIA_TIMING(4096,  88, 88,4400,'+',2160, 8,10,2250,'+', 59940,'p',256:135,   0x1,102),//4096      x2160p @59.94/60   (Format 102)
161     EIA_TIMING(3840,1276, 88,5500,'+',2160, 8,10,2250,'+', 23976,'p',  64:27,   0x1,103),//3840      x2160p @23.98/24   (Format 103)
162     EIA_TIMING(3840,1056, 88,5280,'+',2160, 8,10,2250,'+', 25000,'p',  64:27,   0x1,104),//3840      x2160p @25         (Format 104)
163     EIA_TIMING(3840, 176, 88,4400,'+',2160, 8,10,2250,'+', 29970,'p',  64:27,   0x1,105),//3840      x2160p @29.97/30   (Format 105)
164     EIA_TIMING(3840,1056, 88,5280,'+',2160, 8,10,2250,'+', 50000,'p',  64:27,   0x1,106),//3840      x2160p @50         (Format 106)
165     EIA_TIMING(3840, 176, 88,4400,'+',2160, 8,10,2250,'+', 59940,'p',  64:27,   0x1,107),//3840      x2160p @59.94/60   (Format 107)
166     // VIC 108-127 timings are from CTA-861-G_FINAL_revised_2018_Errata_2.pdf
167     EIA_TIMING(1280, 960, 40, 2500,'+', 720, 5, 5, 750,'+', 47950,'p',   16:9,  0x1,108),//1280 x  720p @47.95/48   (Format 108)
168     EIA_TIMING(1280, 960, 40, 2500,'+', 720, 5, 5, 750,'+', 47950,'p',  64:27,  0x1,109),//1280 x  720p @47.95/48   (Format 109)
169     EIA_TIMING(1680, 810, 40, 2750,'+', 720, 5, 5, 750,'+', 47950,'p',  64:27,  0x1,110),//1680 x  720p @47.95/48   (Format 110)
170     EIA_TIMING(1920, 638, 44, 2750,'+',1080, 4, 5,1125,'+', 47950,'p',   16:9,  0x1,111),//1920 x 1080p @47.95/48   (Format 111)
171     EIA_TIMING(1920, 638, 44, 2750,'+',1080, 4, 5,1125,'+', 47950,'p',  64:27,  0x1,112),//1920 x 1080p @47.95/48   (Format 112)
172     EIA_TIMING(2560, 998, 44, 3750,'+',1080, 4, 5,1100,'+', 47950,'p',  64:27,  0x1,113),//2560 x 1080p @47.95/48   (Format 113)
173     EIA_TIMING(3840,1276, 88, 5500,'+',2160, 8,10,2250,'+', 47950,'p',   16:9,  0x1,114),//3840 x 2160p @47.95/48   (Format 114)
174     EIA_TIMING(4096,1020, 88, 5500,'+',2160, 8,10,2250,'+', 47950,'p',256:135,  0x1,115),//4096 x 2160p @47.95/48   (Format 115)
175     EIA_TIMING(3840,1276, 88, 5500,'+',2160, 8,10,2250,'+', 47950,'p',  64:27,  0x1,116),//3840 x 2160p @47.95/48   (Format 116)
176     EIA_TIMING(3840,1056, 88, 5280,'+',2160, 8,10,2250,'+',100000,'p',   16:9,  0x1,117),//3840 x 2160p @100        (Format 117)
177     EIA_TIMING(3840, 176, 88, 4400,'+',2160, 8,10,2250,'+',119880,'p',   16:9,  0x1,118),//3840 x 2160p @119.88/120 (Format 118)
178     EIA_TIMING(3840,1056, 88, 5280,'+',2160, 8,10,2250,'+',100000,'p',  64:27,  0x1,119),//3840 x 2160p @100        (Format 119)
179     EIA_TIMING(3840, 176, 88, 4400,'+',2160, 8,10,2250,'+',119880,'p',  64:27,  0x1,120),//3840 x 2160p @119.88/120 (Format 120)
180     EIA_TIMING(5120,1996, 88, 7500,'+',2160, 8,10,2200,'+', 23976,'p',  64:27,  0x1,121),//5120 x 2160p @23.98/24   (Format 121)
181     EIA_TIMING(5120,1696, 88, 7200,'+',2160, 8,10,2200,'+', 25000,'p',  64:27,  0x1,122),//5120 x 2160p @25         (Format 122)
182     EIA_TIMING(5120, 664, 88, 6000,'+',2160, 8,10,2200,'+', 29970,'p',  64:27,  0x1,123),//5120 x 2160p @29.97/30   (Format 123)
183     EIA_TIMING(5120, 746, 88, 6250,'+',2160, 8,10,2475,'+', 47950,'p',  64:27,  0x1,124),//5120 x 2160p @47.95/48   (Format 124)
184     EIA_TIMING(5120,1096, 88, 6600,'+',2160, 8,10,2250,'+', 50000,'p',  64:27,  0x1,125),//5120 x 2160p @50         (Format 125)
185     EIA_TIMING(5120, 164, 88, 5500,'+',2160, 8,10,2250,'+', 59940,'p',  64:27,  0x1,126),//5120 x 2160p @59.94/60   (Format 126)
186     EIA_TIMING(5120,1096, 88, 6600,'+',2160, 8,10,2250,'+',100000,'p',  64:27,  0x1,127),//5120 x 2160p @100        (Format 127)
187     // VIC 128-192 are Forbidden and should be never used. But to simplify the SVD access, put a default timing here.
188     // We can remove these after adding a function to access CEA Timings.
189     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 128)
190     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 129)
191     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 130)
192     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 131)
193     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 132)
194     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 133)
195     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 134)
196     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 135)
197     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 136)
198     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 137)
199     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 138)
200     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 139)
201     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 140)
202     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 141)
203     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 142)
204     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 143)
205     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 144)
206     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 145)
207     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 146)
208     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 147)
209     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 148)
210     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 149)
211     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 150)
212     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 151)
213     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 152)
214     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 153)
215     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 154)
216     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 155)
217     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 156)
218     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 157)
219     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 158)
220     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 159)
221     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 160)
222     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 161)
223     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 162)
224     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 163)
225     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 164)
226     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 165)
227     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 166)
228     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 167)
229     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 168)
230     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 169)
231     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 170)
232     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 171)
233     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 172)
234     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 173)
235     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 174)
236     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 175)
237     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 176)
238     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 177)
239     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 178)
240     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 179)
241     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 180)
242     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 181)
243     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 182)
244     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 183)
245     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 184)
246     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 185)
247     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 186)
248     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 187)
249     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 188)
250     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 189)
251     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 190)
252     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 191)
253     EIA_TIMING( 640,  16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 0),//640 x 480p @59.94/60 //Forbidden (Format 192)
254     // VIC 193-219 timings are from CTA-861-G_FINAL_revised_2018_Errata_2.pdf
255     EIA_TIMING( 5120, 164, 88, 5500,'+',2160, 8,10,2250,'+',120000,'p',  64:27,0x1,193),// 5120 x 2160p @119.88/120 (Format 193)
256     EIA_TIMING( 7680,2552,176,11000,'+',4320,16,20,4500,'+', 23976,'p',   16:9,0x1,194),// 7680 x 4320p @23.98/24   (Format 194)
257     EIA_TIMING( 7680,2352,176,10800,'+',4320,16,20,4400,'+', 25000,'p',   16:9,0x1,195),// 7680 x 4320p @25         (Format 195)
258     EIA_TIMING( 7680, 552,176, 9000,'+',4320,16,20,4400,'+', 29970,'p',   16:9,0x1,196),// 7680 x 4320p @29.97/30   (Format 196)
259     EIA_TIMING( 7680,2552,176,11000,'+',4320,16,20,4500,'+', 47950,'p',   16:9,0x1,197),// 7680 x 4320p @47.95/48   (Format 197)
260     EIA_TIMING( 7680,2352,176,10800,'+',4320,16,20,4400,'+', 50000,'p',   16:9,0x1,198),// 7680 x 4320p @50         (Format 198)
261     EIA_TIMING( 7680, 552,176, 9000,'+',4320,16,20,4400,'+', 59940,'p',   16:9,0x1,199),// 7680 x 4320p @59.94/60   (Format 199)
262     EIA_TIMING( 7680,2112,176,10560,'+',4320,16,20,4500,'+',100000,'p',   16:9,0x1,200),// 7680 x 4320p @100        (Format 200)
263     EIA_TIMING( 7680, 352,176, 8000,'+',4320,16,20,4500,'+',119880,'p',   16:9,0x1,201),// 7680 x 4320p @119.88/120 (Format 201)
264     EIA_TIMING( 7680,2552,176,11000,'+',4320,16,20,4500,'+', 23976,'p',  64:27,0x1,202),// 7680 x 4320p @23.98/24   (Format 202)
265     EIA_TIMING( 7680,2352,176,10800,'+',4320,16,20,4400,'+', 25000,'p',  64:27,0x1,203),// 7680 x 4320p @25         (Format 203)
266     EIA_TIMING( 7680, 552,176, 9000,'+',4320,16,20,4400,'+', 29970,'p',  64:27,0x1,204),// 7680 x 4320p @29.97/30   (Format 204)
267     EIA_TIMING( 7680,2552,176,11000,'+',4320,16,20,4500,'+', 47950,'p',  64:27,0x1,205),// 7680 x 4320p @47.95/48   (Format 205)
268     EIA_TIMING( 7680,2352,176,10800,'+',4320,16,20,4400,'+', 50000,'p',  64:27,0x1,206),// 7680 x 4320p @50         (Format 206)
269     EIA_TIMING( 7680, 552,176, 9000,'+',4320,16,20,4400,'+', 59940,'p',  64:27,0x1,207),// 7680 x 4320p @59.94/60   (Format 207)
270     EIA_TIMING( 7680,2112,176,10560,'+',4320,16,20,4500,'+',100000,'p',  64:27,0x1,208),// 7680 x 4320p @100        (Format 208)
271     EIA_TIMING( 7680, 352,176, 8800,'+',4500,16,20,4950,'+',119880,'p',  64:27,0x1,209),// 7680 x 4320p @119.88/120 (Format 209)
272     EIA_TIMING(10240,1492,176,12500,'+',4320,16,20,4950,'+', 23976,'p',  64:27,0x1,210),//10240 x 4320p @23.98/24   (Format 210)
273     EIA_TIMING(10240,2492,176,13500,'+',4320,16,20,4400,'+', 25000,'p',  64:27,0x1,211),//10240 x 4320p @25         (Format 211)
274     EIA_TIMING(10240, 288,176,11000,'+',4320,16,20,4500,'+', 29970,'p',  64:27,0x1,212),//10240 x 4320p @29.97/30   (Format 212)
275     EIA_TIMING(10240,1492,176,12500,'+',4320,16,20,4950,'+', 47950,'p',  64:27,0x1,213),//10240 x 4320p @47.95/48   (Format 213)
276     EIA_TIMING(10240,2492,176,13500,'+',4320,16,20,4400,'+', 44000,'p',  64:27,0x1,214),//10240 x 4320p @50         (Format 214)
277     EIA_TIMING(10240, 288,176,11000,'+',4320,16,20,4500,'+', 59940,'p',  64:27,0x1,215),//10240 x 4320p @59.94/60   (Format 215)
278     EIA_TIMING(10240,2192,176,13200,'+',4320,16,20,4500,'+',100000,'p',  64:27,0x1,216),//10240 x 4320p @100        (Format 216)
279     EIA_TIMING(10240, 288,176,11000,'+',4320,16,20,4500,'+',119880,'p',  64:27,0x1,217),//10240 x 4320p @119.88/120 (Format 217)
280     EIA_TIMING( 4096, 800, 88, 5280,'+',2160, 8,10,2250,'+',100000,'p',256:135,0x1,218),// 4096 x 2160p @100        (Format 218)
281     EIA_TIMING( 4096,  88, 88, 4400,'+',2160, 8,10,2250,'+',119880,'p',256:135,0x1,219),// 4096 x 2160p @119.88/120 (Format 219)
282     // 220-255 Reserved for the Future
283     // the end
284     EIA_TIMING(0,0,0,0,'-',0,0,0,0,'-',0,'p',4:3,0,0)
285 };
286 static NvU32 MAX_CEA861B_FORMAT = sizeof(EIA861B)/sizeof(EIA861B[0]) - 1;
287 
288 static const NvU32 EIA861B_DUAL_ASPECT_VICS[][2] =
289 {
290     { 2, 3 },   // 720x480p         59.94Hz/60Hz
291     { 4, 69 },  // 1280x720p        59.94Hz/60Hz
292     { 6, 7 },   // 720(1440)x480i   59.94Hz/60Hz
293     { 8, 9 },   // 720(1440)x240p   59.94Hz/60Hz
294 
295     { 10, 11 }, // 2880x480i        59.94Hz/60Hz
296     { 12, 13 }, // 2880x240p        59.94Hz/60Hz
297     { 14, 15 }, // 1440x480p        59.94Hz/60Hz
298     { 16, 76 }, // 1920x1080p       59.94Hz/60Hz
299     { 17, 18 }, // 720x576p         50Hz
300     { 19, 68 }, // 1280x720p        50Hz
301 
302     { 21, 22 }, // 720(1440)x576i   50Hz
303     { 23, 24 }, // 720(1440)x288p   50Hz
304     { 25, 26 }, // 2880x576i        50Hz
305     { 27, 28 }, // 2880x288p        50Hz
306     { 29, 30 }, // 1440x576p        50Hz
307 
308     { 31, 75 }, // 1920x1080p       50Hz
309     { 32, 72 }, // 1920x1080p       23.98Hz/24Hz
310     { 33, 73 }, // 1920x1080p       25Hz
311     { 34, 74 }, // 1920x1080p       29.97Hz/30Hz
312     { 35, 36 }, // 2880x480p        59.94Hz/60Hz
313     { 37, 38 }, // 2880x576p        50Hz
314 
315     { 41, 70 }, // 1280x720p        100Hz
316     { 42, 43 }, // 720x576p         100Hz
317     { 44, 45 }, // 720(1440)x576i   100Hz
318     { 47, 71 }, // 1280x720p        119.88/120Hz
319     { 48, 49 }, // 720x480p         119.88/120Hz
320 
321     { 50, 51 }, // 720(1440)x480i   119.88/120Hz
322     { 52, 53 }, // 720x576p         200Hz
323     { 54, 55 }, // 720(1440)x576i   200Hz
324     { 56, 57 }, // 720x480p         239.76/240Hz
325     { 58, 59 }, // 720(1440)x480i   239.76/240Hz
326 
327     { 60, 65 }, // 1280x720p        23.98Hz/24Hz
328     { 61, 66 }, // 1280x720p        25Hz
329     { 62, 67 }, // 1280x720p        29.97Hz/30Hz
330     { 63, 78 }, // 1920x1080p       119.88/120Hz
331     { 64, 77 }, // 1920x1080p       100Hz
332 
333     { 93, 103 }, // 3840x2160p      23.98Hz/24Hz
334     { 94, 104 }, // 3840x2160p      25Hz
335     { 95, 105 }, // 3840x2160p      29.97Hz/30Hz
336     { 96, 106 }, // 3840x2160p      50Hz
337     { 97, 107 }, // 3840x2160p      59.94Hz/60Hz
338 };
339 static NvU32 MAX_EIA861B_DUAL_ASPECT_VICS = sizeof(EIA861B_DUAL_ASPECT_VICS) / sizeof(EIA861B_DUAL_ASPECT_VICS[0]);
340 
341 static const NVT_TIMING PSF_TIMING[]=
342 {
343     NVT_TIMING( 1920,600, 88,2750,'+', 540, 2,5,562,'+',47952,'i',16:9,       0x1, 1, "ITU-R BT.709-5:1080i/24Psf"),//1920x1080i @47.952Hz  | 24/PsF | ITU-R BT.709-5
344     NVT_TIMING( 1920,488, 88,2640,'+', 540, 2,5,562,'+',49950,'i',16:9,       0x1, 2, "ITU-R BT.709-5:1080i/25Psf"),//1920x1080i @49.950Hz  | 25/PsF | ITU-R BT.709-5
345 
346     // the end
347     EIA_TIMING(0,0,0,0,'-',0,0,0,0,'-',0,'p',4:3,0,0)
348 };
349 static NvU32 MAX_PSF_FORMAT = sizeof(PSF_TIMING)/sizeof(PSF_TIMING[0]) - 1;
350 
351 static const NVT_TIMING HDMI_EXT_4Kx2K_TIMING[]=
352 {
353     HDMI_EXT_TIMING( 3840, 176, 88,4400,'+', 2160, 8,10,2250,'+',29970,'p',16:9,       0x1, NVT_HDMI_VS_BYTE5_HDMI_VIC_4Kx2Kx30Hz,       "HDMI EXT: 3840x2160x29.97/30hz"),//3840x2160 @29.97/30Hz VIC: 0x01
354     HDMI_EXT_TIMING( 3840,1056, 88,5280,'+', 2160, 8,10,2250,'+',25000,'p',16:9,       0x1, NVT_HDMI_VS_BYTE5_HDMI_VIC_4Kx2Kx25Hz,       "HDMI EXT: 3840x2160x25hz"),      //3840x2160 @25Hz       VIC: 0x02
355     HDMI_EXT_TIMING( 3840,1276, 88,5500,'+', 2160, 8,10,2250,'+',23976,'p',16:9,       0x1, NVT_HDMI_VS_BYTE5_HDMI_VIC_4Kx2Kx24Hz,       "HDMI EXT: 3840x2160x23.98/24hz"),//3840x2160 @23.98/24Hz VIC: 0x03
356     HDMI_EXT_TIMING( 4096,1020, 88,5500,'+', 2160, 8,10,2250,'+',24000,'p',16:9,       0x1, NVT_HDMI_VS_BYTE5_HDMI_VIC_4Kx2Kx24Hz_SMPTE, "HDMI EXT: 4096x2160x24hzSmpte"), //4096x2160 @24Hz       VIC: 0x04
357 
358     // the end
359     EIA_TIMING(0,0,0,0,'-',0,0,0,0,'-',0,'p',4:3,0,0)
360 };
361 static NvU32 MAX_HDMI_EXT_4Kx2K_FORMAT = sizeof(HDMI_EXT_4Kx2K_TIMING)/sizeof(HDMI_EXT_4Kx2K_TIMING[0]) - 1;
362 
363 // HDMI 1.4a mandatory 3D video formats.
364 // From HDMI 1.4a specification page 147 of 201, table 8-15. And HDMI 1.4a Complaince test specification page 190.
365 static const HDMI3DDETAILS   HDMI_MANDATORY_3D_FORMATS[] =
366 {
367     {32, NVT_HDMI_3D_SUPPORTED_FRAMEPACK_MASK | NVT_HDMI_3D_SUPPORTED_TOPBOTTOM_MASK, 0},       // 1920 x 1080p @ 24 Hz
368     { 4, NVT_HDMI_3D_SUPPORTED_FRAMEPACK_MASK | NVT_HDMI_3D_SUPPORTED_TOPBOTTOM_MASK, 0},       // 1280 x  720p @ 60 Hz
369     {19, NVT_HDMI_3D_SUPPORTED_FRAMEPACK_MASK | NVT_HDMI_3D_SUPPORTED_TOPBOTTOM_MASK, 0},       // 1280 x  720p @ 50 Hz
370     { 5, NVT_HDMI_3D_SUPPORTED_SIDEBYSIDEHALF_MASK, NVT_HDMI_VS_BYTE_OPT1_HDMI_3DEX_SSH},       // 1920 x 1080i @ 60 Hz
371     {20, NVT_HDMI_3D_SUPPORTED_SIDEBYSIDEHALF_MASK, NVT_HDMI_VS_BYTE_OPT1_HDMI_3DEX_SSH}        // 1920 x 1080i @ 50 Hz
372 };
373 static NvU32 MAX_HDMI_MANDATORY_3D_FORMAT = sizeof(HDMI_MANDATORY_3D_FORMATS) / sizeof(HDMI_MANDATORY_3D_FORMATS[0]);
374 static const NVT_VIDEO_INFOFRAME DEFAULT_VIDEO_INFOFRAME = {/*header*/2,2,13, /*byte1*/0, /*byte2*/0x8, /*byte3*/0, /*byte4*/0, /*byte5*/0, /*byte6~13*/0,0,0,0,0,0,0,0};
375 static const NVT_AUDIO_INFOFRAME DEFAULT_AUDIO_INFOFRAME = {/*header*/4,1,10, /*byte1*/0, /*byte2*/0,   /*byte3*/0, /*byte*/0,  /*byte5*/0, /*byte6~10*/0,0,0,0,0};
376 
377 CODE_SEGMENT(PAGE_DD_CODE)
378 static NvU8
379 getExistedCTATimingSeqNumber(
380     NVT_EDID_INFO *pInfo,
381     enum NVT_TIMING_TYPE timingType)
382 {
383     NvU8 count = 0;
384     NvU8 i     = 0;
385 
386     switch (timingType)
387     {
388     case NVT_TYPE_CTA861_DID_T7:
389     case NVT_TYPE_CTA861_DID_T8:
390     case NVT_TYPE_CTA861_DID_T10:
391         break;
392     default:
393         return count;
394     }
395 
396     for (i = 0; i< pInfo->total_timings; i++)
397     {
398         if (NVT_GET_TIMING_STATUS_TYPE(pInfo->timing[i].etc.status) == timingType)
399             ++count;
400     }
401 
402     return count;
403 }
404 
405 // parse the 861 detailed timing info
406 CODE_SEGMENT(PAGE_DD_CODE)
407 void parse861ExtDetailedTiming(NvU8 *pEdidExt,
408                                NvU8 basicCaps,
409                                NVT_EDID_INFO *pInfo)
410 {
411     NvU32 count = 0;
412     EIA861EXTENSION *pEIA861 = (EIA861EXTENSION *) pEdidExt;
413     DETAILEDTIMINGDESCRIPTOR *pDTD;
414     NVT_TIMING newTiming;
415 
416     // sanity check for CEA ext block
417     if ((pEIA861->tag != 0x2) || (0 == pEIA861->offset) || (NVT_CEA861_REV_NONE == pEIA861->revision))
418     {
419         // no CEA ext block, return
420         return;
421     }
422 
423     // Get all detailed timings in CEA ext block
424     pDTD = (DETAILEDTIMINGDESCRIPTOR *)&pEdidExt[pEIA861->offset];
425 
426     while((NvU8 *)pDTD + sizeof(DETAILEDTIMINGDESCRIPTOR) < (pEdidExt + sizeof(EDIDV1STRUC)) &&
427           pDTD->wDTPixelClock != 0)
428     {
429         NVMISC_MEMSET(&newTiming, 0, sizeof(newTiming));
430 
431         if (parseEdidDetailedTimingDescriptor((NvU8 *)pDTD,
432                                               &newTiming) == NVT_STATUS_SUCCESS)
433         {
434             NVT_SNPRINTF((char *)newTiming.etc.name, sizeof(newTiming.etc.name),
435                          "CTA-861Long:%5dx%4dx%3d.%03dHz/%s",
436                          (int)newTiming.HVisible,
437                          (int)((newTiming.interlaced ? 2 : 1) * newTiming.VVisible),
438                          (int)newTiming.etc.rrx1k/1000,
439                          (int)newTiming.etc.rrx1k%1000,
440                          (newTiming.interlaced ? "I":"P"));
441             newTiming.etc.name[sizeof(newTiming.etc.name)-1] = '\0';
442             newTiming.etc.status = NVT_STATUS_EDID_EXT_DTDn(++count);
443 
444             if (!assignNextAvailableTiming(pInfo, &newTiming))
445             {
446                 break;
447             }
448         }
449         pDTD ++;
450     }
451 }
452 
453 // parse the 861B short timing descriptor
454 CODE_SEGMENT(PAGE_DD_CODE)
455 void parse861bShortTiming(NVT_EDID_CEA861_INFO *pExt861,
456                           void *pRawInfo,
457                           NVT_CTA861_ORIGIN flag)
458 {
459     NvU32 i;
460     NvU32 vic, bytePos, bitPos;
461     NVT_TIMING               newTiming;
462     NVT_HDMI_FORUM_INFO     *pHfvs          = NULL;
463     NVT_EDID_INFO           *pInfo          = NULL;
464     NVT_DISPLAYID_2_0_INFO  *pDisplayID20   = NULL;
465 
466     NvU8                    *pVic           = pExt861->video;
467     NvU32                    total_svd      = pExt861->total_svd;
468     NvU8                    *pYuv420Map     = pExt861->valid.y420cmdb ? pExt861->map_y420cmdb : NULL;
469     NvU8                     yuv420MapCount = pExt861->total_y420cmdb;
470 
471     if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
472     {
473         pInfo    = (NVT_EDID_INFO *)pRawInfo;
474         pHfvs    = &pInfo->hdmiForumInfo;
475     }
476     else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
477     {
478         pDisplayID20 = (NVT_DISPLAYID_2_0_INFO *)pRawInfo;
479         pHfvs    = &pDisplayID20->vendor_specific.hfvs;
480     }
481     else
482     {
483         return;
484     }
485 
486     for (i = 0; i < total_svd; i++)
487     {
488         vic = NVT_GET_CTA_8BIT_VIC(pVic[i]);
489 
490         if (vic == 0 || vic > MAX_CEA861B_FORMAT)
491             continue;
492 
493         // assign corresponding CEA format's timing from pre-defined CE timing table, EIA861B
494         newTiming = EIA861B[vic-1];
495         newTiming.etc.status = NVT_STATUS_EDID_861STn(vic);
496 
497         // set CEA format to location of _CEA_FORMAT. _CEA_FORMAT isn't set in pre-defined CE timing from
498         // EIA861B table
499         if (NVT_GET_TIMING_STATUS_SEQ(newTiming.etc.status) !=
500             NVT_CEA861_640X480P_59940HZ_4X3)
501         {
502             // Although IT 640x480 video timing has a CE id, it is not a CE timing. See 3.1
503             // "General Video Format Requirements" section in CEA-861-E spec
504             NVT_SET_CEA_FORMAT(newTiming.etc.status,
505                                NVT_GET_TIMING_STATUS_SEQ(newTiming.etc.status));
506         }
507 
508         // calculate the pixel clock
509         newTiming.pclk  = RRx1kToPclk(&newTiming);
510 
511         if ((vic <= 64) && (pVic[i] & NVT_CTA861_VIDEO_NATIVE_MASK))
512         {
513             NVT_SET_NATIVE_TIMING_FLAG(newTiming.etc.status);
514         }
515         NVT_SNPRINTF((char *)newTiming.etc.name, sizeof(newTiming.etc.name),
516                      "CTA-861G:#%3d:%5dx%4dx%3d.%03dHz/%s", (int)vic,
517                      (int)newTiming.HVisible,
518                      (int)((newTiming.interlaced ? 2 : 1)*newTiming.VVisible),
519                      (int)newTiming.etc.rrx1k/1000, (int)newTiming.etc.rrx1k%1000,
520                      (newTiming.interlaced ? "I":"P"));
521         newTiming.etc.name[sizeof(newTiming.etc.name)-1] = '\0';
522 
523         // if yuv420 is supported in the video SVDs, it is indicated by CMDB bitmap
524         bytePos = i / (8 * sizeof(NvU8));
525         if (bytePos < yuv420MapCount)
526         {
527             bitPos  = 1 << (i % (8 * sizeof(NvU8)));
528             if (pYuv420Map[bytePos] & bitPos)
529             {
530                 // pHfvs->dcXXX are only for YCbCr420; when bitPos is set, 8bpc yuv420 always supported
531                 UPDATE_BPC_FOR_COLORFORMAT(newTiming.etc.yuv420, 0, 1,
532                                            pHfvs->dc_30bit_420,
533                                            pHfvs->dc_36bit_420, 0,
534                                            pHfvs->dc_48bit_420);
535             }
536         }
537 
538         // Y420CMDB with L == 1, implies yuv420MapCount == 0 but all SVDs support 420
539         if (pYuv420Map && yuv420MapCount == 0)
540         {
541             UPDATE_BPC_FOR_COLORFORMAT(newTiming.etc.yuv420, 0, 1,
542                                        pHfvs->dc_30bit_420,
543                                        pHfvs->dc_36bit_420, 0,
544                                        pHfvs->dc_48bit_420);
545         }
546 
547         if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
548         {
549             if (!assignNextAvailableTiming(pInfo, &newTiming))
550             {
551                 break;
552             }
553         }
554         else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
555         {
556            newTiming.etc.flag |= NVT_FLAG_DISPLAYID_2_0_TIMING;
557 
558            if (!assignNextAvailableDisplayId20Timing(pDisplayID20, &newTiming))
559             {
560                 break;
561             }
562         }
563     }
564 }
565 
566 // parse the 861B short Yuv420 timing descriptor
567 CODE_SEGMENT(PAGE_DD_CODE)
568 void parse861bShortYuv420Timing(NVT_EDID_CEA861_INFO *pExt861,
569                                 void *pRawInfo,
570                                 NVT_CTA861_ORIGIN flag)
571 {
572     NvU32 i;
573     NvU8 vic;
574     NVT_TIMING              newTiming;
575     NVT_HDMI_FORUM_INFO    *pHfvs         = NULL;
576     NVT_EDID_INFO          *pInfo         = NULL;
577     NVT_DISPLAYID_2_0_INFO *pDisplayID20  = NULL;
578     NvU8                   *pYuv420Vic    = pExt861->svd_y420vdb;
579     NvU32                   total_y420vdb = pExt861->total_y420vdb;
580     NvU8                   *pVdb          = pExt861->video;
581     NvU32                   total_svd     = pExt861->total_svd;
582     NvU32                   total_timings = 0;
583 
584     if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
585     {
586         pInfo = (NVT_EDID_INFO *)pRawInfo;
587         pHfvs = &pInfo->hdmiForumInfo;
588         total_timings = pInfo->total_timings;
589     }
590     else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
591     {
592         pDisplayID20 = (NVT_DISPLAYID_2_0_INFO *)pRawInfo;
593         pHfvs = &pDisplayID20->vendor_specific.hfvs;
594         total_timings = pDisplayID20->total_timings;
595     }
596     else
597     {
598         return;
599     }
600 
601     if (total_timings == 0)
602     {
603         return;
604     }
605 
606 
607     for (i = 0; i < total_y420vdb; i++)
608     {
609         vic = NVT_GET_CTA_8BIT_VIC(pYuv420Vic[i]);
610 
611         if (vic == 0 || vic > MAX_CEA861B_FORMAT)
612             continue;
613 
614         // assign corresponding CEA format's timing from pre-defined CE timing table, EIA861B
615         newTiming = EIA861B[vic-1];
616 
617         // if yuv420 is supported in the video SVDs, it is indicated by yuv420vdb
618         if(total_svd > 0)
619         {
620             NvU8 idx, j;
621             NvBool bFound = NV_FALSE;
622             for (idx=0; idx < total_svd; idx++)
623             {
624                 if (pVdb[idx] == vic)
625                 {
626                     for (j=0; j < total_timings; j++)
627                     {
628                         NVT_TIMING *timing = NULL;
629 
630                         if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
631                         {
632                             timing = &pInfo->timing[j];
633                         }
634                         else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
635                         {
636                             timing = &pDisplayID20->timing[j];
637                         }
638 
639                         if (NvTiming_IsTimingExactEqual(timing, &newTiming))
640                         {
641                             bFound = NV_TRUE;
642                             // we found one in pExt861->video[]. pHfvs->dcXXX are only for YCbCr420, so we can support:
643                             // 1. 8bpc yuv420 always supported.
644                             // 2. only add yuv420 and its deep colour caps into Video Data Block
645                             UPDATE_BPC_FOR_COLORFORMAT(timing->etc.yuv420, 0, 1,
646                                                        pHfvs->dc_30bit_420,
647                                                        pHfvs->dc_36bit_420, 0,
648                                                        pHfvs->dc_48bit_420);
649                             break;
650                         }
651                     }
652                 }
653             }
654             if (bFound) continue;
655         }
656 
657         newTiming.etc.status = NVT_STATUS_EDID_861STn(vic);
658 
659         // set CEA format to location of _CEA_FORMAT. _CEA_FORMAT isn't set in pre-defined CE timing from
660         // EIA861B table
661         if (NVT_GET_TIMING_STATUS_SEQ(newTiming.etc.status) !=
662             NVT_CEA861_640X480P_59940HZ_4X3)
663         {
664             // Although IT 640x480 video timing has a CE id, it is not a CE timing. See 3.1
665             // "General Video Format Requirements" section in CEA-861-E spec
666             NVT_SET_CEA_FORMAT(newTiming.etc.status,
667                                NVT_GET_TIMING_STATUS_SEQ(newTiming.etc.status));
668         }
669 
670         // calculate the pixel clock
671         newTiming.pclk = RRx1kToPclk(&newTiming);
672 
673         // From CTA-861-F: By default, Y420VDB SVDs, when present in the EDID, shall be less preferred than all regular Video Data Block SVDs.
674         // So it should use normal VIC code without native flag.
675         //if ((vic <= 64) && (pVic[i] & NVT_CTA861_VIDEO_NATIVE_MASK))
676         //{
677         //     NVT_SET_NATIVE_TIMING_FLAG(newTiming.etc.status);
678         //}
679         NVT_SNPRINTF((char *)newTiming.etc.name, sizeof(newTiming.etc.name),
680                      "CTA-861G:#%3d:%5dx%4dx%3d.%03dHz/%s", (int)vic,
681                      (int)newTiming.HVisible,
682                      (int)((newTiming.interlaced ? 2 : 1)*newTiming.VVisible),
683                      (int)newTiming.etc.rrx1k/1000, (int)newTiming.etc.rrx1k%1000,
684                      (newTiming.interlaced ? "I":"P"));
685         newTiming.etc.name[sizeof(newTiming.etc.name)-1] = '\0';
686 
687         // update supported color space; any VICs enumerated in the Y420VDB are yuv420 only modes
688         // update 8bpc supported color space; other bpc updated once VSDB is parsed
689 
690         // pHfvs->dcXXX are only for YCbCr420; when Vic enumerated here, 8bpc yuv420 always supported
691         UPDATE_BPC_FOR_COLORFORMAT(newTiming.etc.yuv420, 0, 1,
692                                    pHfvs->dc_30bit_420,
693                                    pHfvs->dc_36bit_420, 0,
694                                    pHfvs->dc_48bit_420);
695 
696         if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
697         {
698             if (!assignNextAvailableTiming(pInfo, &newTiming))
699             {
700                 break;
701             }
702         }
703         else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
704         {
705             newTiming.etc.flag |= NVT_FLAG_DISPLAYID_2_0_TIMING;
706 
707             if (assignNextAvailableDisplayId20Timing(pDisplayID20, &newTiming))
708             {
709 
710                 break;
711             }
712         }
713     }
714 }
715 
716 // Currently, the SVR both used in the NVRDB and VFPDB.
717 // "One particular application is a Sink that prefers a Video Format that is not listed as an SVD in a VDB
718 // but instead listed in a YCBCR 4:2:0 Video Data Block"
719 CODE_SEGMENT(PAGE_DD_CODE)
720 void parseCta861NativeOrPreferredTiming(NVT_EDID_CEA861_INFO *pExt861,
721                                            void *pRawInfo,
722                                            NVT_CTA861_ORIGIN flag)
723 {
724     NvU32 isMatch,i,j = 0;
725 
726     NVT_TIMING               preferTiming;
727     NVT_EDID_INFO           *pInfo         = NULL;
728     NVT_DISPLAYID_2_0_INFO  *pDisplayID20  = NULL;
729     NvU8                     nativeSvr     = 0;
730     NvU8                    *pSvr          = pExt861->svr_vfpdb;
731     NvU8                     totalSvr      = pExt861->total_svr;
732     NvU8                     kth           = 0;
733     NvU8                     extKth        = 0;
734     NvU8                     DTDCount      = 0;
735     NvU8                     extDTDCount   = 0;
736     NvU8                     DIDT7Count    = 0;
737     NvU8                     DIDT10Count   = 0;
738 
739     if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
740     {
741         pInfo = (NVT_EDID_INFO *)pRawInfo;
742     }
743     else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
744     {
745         pDisplayID20 = (NVT_DISPLAYID_2_0_INFO *)pRawInfo;
746     }
747     else
748     {
749         return;
750     }
751 
752     // finding all the DTD in Base 0 or CTA861
753     if (flag == FROM_CTA861_EXTENSION)
754     {
755         // get the NVRDB, from the spec this native resolution has more high priority than others
756         if (pExt861->valid.NVRDB == 1)
757         {
758             nativeSvr = pExt861->native_video_resolution_db.native_svr;
759             totalSvr = 1;
760         }
761 
762         for (j = 0; j < pInfo->total_timings; j++)
763         {
764             if (NVT_IS_DTD(pInfo->timing[j].etc.status))                  DTDCount++;
765             else if (NVT_IS_EXT_DTD(pInfo->timing[j].etc.status))         extDTDCount++;
766             else if (NVT_IS_CTA861_DID_T7(pInfo->timing[j].etc.status))   DIDT7Count++;
767             else if (NVT_IS_CTA861_DID_T10(pInfo->timing[j].etc.status))  DIDT10Count++;
768         }
769     }
770 
771     // this only handle single SVR right now
772     for (i = 0; i < totalSvr; i++)
773     {
774         NvU8 svr = 0;
775         NvU8 vic = 0;
776 
777         if (pExt861->valid.NVRDB == 1)
778             svr = nativeSvr;
779         else
780             svr = pSvr[i];
781 
782         // Reserved
783         if (svr == 0 || svr == 128 || (svr >= 176 && svr <= 192) || svr == 255)
784             continue;
785 
786         // Interpret as the Kth 18-byte DTD, where K = SVR - 128 (for K = 1 to 16) in both base0 and CTA block
787         if (svr >= 129 && svr <= 144)
788         {
789             kth = svr - 128;
790             // only base EDID and CTA861 can support 18bytes
791             if (flag == FROM_CTA861_EXTENSION)
792             {
793                 for (j = 0; j < pInfo->total_timings; j++)
794                 {
795                     if (kth <= DTDCount)
796                     {
797                         if (NVT_IS_DTDn(pInfo->timing[j].etc.status, kth))
798                             break;
799                     }
800                     else
801                     {
802                         extKth = kth - DTDCount;
803                         if (NVT_IS_EXT_DTDn(pInfo->timing[j].etc.status, extKth))
804                             break;
805                     }
806                 }
807 
808                 if (pExt861->valid.NVRDB == 1)
809                     pInfo->timing[j].etc.flag |= NVT_FLAG_CTA_NATIVE_TIMING;
810                 else
811                     pInfo->timing[j].etc.flag |= NVT_FLAG_CTA_PREFERRED_TIMING;
812             }
813         }
814         else if (svr >= 145 && svr <= 160)
815         {
816             // Interpret as the Nth 20-byte DTD or 6- or 7-byte CVT-based descriptor
817             // where N = SVR – 144 (for N = 1 to 16)
818             kth = svr - 144;
819 
820             if (flag == FROM_CTA861_EXTENSION)
821             {
822                 for (j = 0; j < pInfo->total_timings; j++)
823                 {
824                     if (kth <= DIDT7Count) // pick the Nth 20-byte first
825                     {
826                         if (NVT_IS_CTA861_DID_T7n(pInfo->timing[j].etc.status, kth))
827                             break;
828                     }
829                     else
830                     {
831                         extKth = kth - DIDT7Count; // pick the T10 CVT-based timing then
832                         if (NVT_IS_CTA861_DID_T10n(pInfo->timing[j].etc.status, extKth))
833                             break;
834                     }
835                 }
836 
837                 if (pExt861->valid.NVRDB == 1)
838                     pInfo->timing[j].etc.flag |= NVT_FLAG_CTA_NATIVE_TIMING;
839                 else
840                     pInfo->timing[j].etc.flag |= NVT_FLAG_CTA_PREFERRED_TIMING;
841             }
842         }
843         else if (svr >= 161 && svr <= 175)
844         {
845             // Interpret as the video format indicated by the first VFD of the first VFDB with Frame Rates of Rate Index N
846             // where N = SVR - 160 (for N = 1 to 15)
847             break;
848         }
849         else if (svr == 254)
850         {
851             // Interpret as the timing format indicated by the first code of the first T8VTDB
852             if (flag == FROM_CTA861_EXTENSION)
853             {
854                 for (j = 0; j < pInfo->total_timings; j++)
855                 {
856                     if (NVT_IS_CTA861_DID_T8_1(pInfo->timing[j].etc.status))
857                     {
858                         if (pExt861->valid.NVRDB == 1)
859                             pInfo->timing[j].etc.flag |= NVT_FLAG_CTA_NATIVE_TIMING;
860                         else
861                             pInfo->timing[j].etc.flag |= NVT_FLAG_CTA_PREFERRED_TIMING;
862                         break;
863                     }
864                 }
865             }
866             break;
867         }
868         else // assign corresponding CEA format's timing from pre-defined CE timing table, EIA861B
869         {
870             // ( SVR >= 1 and SVR <= 127) and (SVR >= 193 and SVR <= 253)
871             vic = NVT_GET_CTA_8BIT_VIC(svr);
872             preferTiming = EIA861B[vic-1];
873 
874             if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
875             {
876                 for (j = 0; j < pInfo->total_timings; j++)
877                 {
878                     isMatch = NvTiming_IsTimingExactEqual(&pInfo->timing[j], &preferTiming);
879                     if (isMatch && (NVT_GET_TIMING_STATUS_TYPE(pInfo->timing[j].etc.status) == NVT_TYPE_EDID_861ST))
880                     {
881                         if (pExt861->valid.NVRDB == 1)
882                             pInfo->timing[j].etc.flag |= NVT_FLAG_CTA_NATIVE_TIMING;
883                         else
884                             pInfo->timing[j].etc.flag |= NVT_FLAG_CTA_PREFERRED_TIMING;
885                         break;
886                     }
887                 }
888             }
889             else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
890             {
891                 for (j = 0; j < pDisplayID20->total_timings; j++)
892                 {
893                     isMatch = NvTiming_IsTimingExactEqual(&pDisplayID20->timing[j], &preferTiming);
894                     if (isMatch && (NVT_GET_TIMING_STATUS_TYPE(pDisplayID20->timing[j].etc.status) == NVT_TYPE_EDID_861ST))
895                     {
896                         if (pExt861->valid.NVRDB == 1)
897                             pDisplayID20->timing[j].etc.flag |= NVT_FLAG_CTA_NATIVE_TIMING | NVT_FLAG_DISPLAYID_2_0_TIMING;
898                         else
899                             pDisplayID20->timing[j].etc.flag |= NVT_FLAG_CTA_PREFERRED_TIMING | NVT_FLAG_DISPLAYID_2_0_TIMING;
900                         break;
901                     }
902                 }
903             }
904         }
905     }
906 }
907 
908 CODE_SEGMENT(PAGE_DD_CODE)
909 void parseCea861HdrStaticMetadataDataBlock(NVT_EDID_CEA861_INFO *pExt861,
910                                            void *pRawInfo,
911                                            NVT_CTA861_ORIGIN flag)
912 {
913     NVT_EDID_INFO           *pInfo         = NULL;
914     NVT_DISPLAYID_2_0_INFO  *pDisplayID20  = NULL;
915     NVT_HDR_STATIC_METADATA *pHdrInfo      = NULL;
916 
917     if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
918     {
919         pInfo = (NVT_EDID_INFO *)pRawInfo;
920         pHdrInfo = &pInfo->hdr_static_metadata_info;
921     }
922     else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
923     {
924         pDisplayID20 = (NVT_DISPLAYID_2_0_INFO *)pRawInfo;
925         pHdrInfo = &pDisplayID20->cta.hdrInfo;
926     }
927     else
928     {
929         return;
930     }
931 
932     if (pExt861 == NULL || pHdrInfo == NULL)
933     {
934         return;
935     }
936 
937     // Parse the EOTF capability information. It's possible to have multiple EOTF
938     if (pExt861->hdr_static_metadata.byte1 & NVT_CEA861_EOTF_GAMMA_SDR)
939     {
940         pHdrInfo->supported_eotf.trad_gamma_sdr_eotf = 1;
941     }
942     if (pExt861->hdr_static_metadata.byte1 & NVT_CEA861_EOTF_GAMMA_HDR)
943     {
944         pHdrInfo->supported_eotf.trad_gamma_hdr_eotf = 1;
945     }
946     if (pExt861->hdr_static_metadata.byte1 & NVT_CEA861_EOTF_SMPTE_ST2084)
947     {
948         pHdrInfo->supported_eotf.smpte_st_2084_eotf = 1;
949     }
950     if (pExt861->hdr_static_metadata.byte1 & NVT_CEA861_EOTF_FUTURE)
951     {
952         pHdrInfo->supported_eotf.future_eotf = 1;
953     }
954 
955     // Parse the static metadata descriptor
956     if (pExt861->hdr_static_metadata.byte2)
957     {
958         pHdrInfo->static_metadata_type = 1;
959     }
960     else
961     {
962         pHdrInfo->static_metadata_type = 0;
963     }
964 
965     pHdrInfo->max_cll  = pExt861->hdr_static_metadata.byte3 & NVT_CEA861_MAX_CLL_MASK;
966     pHdrInfo->max_fall = pExt861->hdr_static_metadata.byte4 & NVT_CEA861_MAX_FALL_MASK;
967     pHdrInfo->min_cll  = pExt861->hdr_static_metadata.byte5 & NVT_CEA861_MIN_CLL_MASK;
968 }
969 
970 CODE_SEGMENT(PAGE_DD_CODE)
971 void parseCea861DvStaticMetadataDataBlock(NVT_EDID_CEA861_INFO *pExt861, void *pRawInfo, NVT_CTA861_ORIGIN flag)
972 {
973     NvU32 vsvdbVersion = 0;
974     NVT_DV_STATIC_METADATA_TYPE0   *pDvType0 = NULL;
975     NVT_DV_STATIC_METADATA_TYPE1   *pDvType1 = NULL;
976     NVT_DV_STATIC_METADATA_TYPE1_1 *pvDvType1_1 = NULL;
977     NVT_DV_STATIC_METADATA_TYPE2   *pDvType2 = NULL;
978 
979     NVT_EDID_INFO           *pInfo         = NULL;
980     NVT_DISPLAYID_2_0_INFO  *pDisplayID20  = NULL;
981     NVT_DV_STATIC_METADATA  *pDvInfo       = NULL;
982 
983     if (pExt861 == NULL || pRawInfo == NULL)
984     {
985         return;
986     }
987 
988     if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
989     {
990         pInfo = (NVT_EDID_INFO *)pRawInfo;
991         pDvInfo = &pInfo->dv_static_metadata_info;
992     }
993     else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
994     {
995         pDisplayID20 = (NVT_DISPLAYID_2_0_INFO *)pRawInfo;
996         pDvInfo = &pDisplayID20->cta.dvInfo;
997     }
998     else
999     {
1000         return;
1001     }
1002 
1003     if(pExt861->vsvdb.ieee_id != NVT_CEA861_DV_IEEE_ID)
1004     {
1005         return;
1006     }
1007 
1008 
1009     //init
1010     NVMISC_MEMSET(pDvInfo, 0, sizeof(NVT_DV_STATIC_METADATA));
1011 
1012     // copy ieee id
1013     pDvInfo->ieee_id = pExt861->vsvdb.ieee_id;
1014 
1015     vsvdbVersion = (pExt861->vsvdb.vendor_data[0] & NVT_CEA861_VSVDB_VERSION_MASK) >> NVT_CEA861_VSVDB_VERSION_MASK_SHIFT;
1016 
1017     switch (vsvdbVersion)
1018     {
1019         case 0:
1020             if (pExt861->vsvdb.vendor_data_size < sizeof(NVT_DV_STATIC_METADATA_TYPE0))
1021             {
1022                 return;
1023             }
1024             pDvType0 = (NVT_DV_STATIC_METADATA_TYPE0 *)(&pExt861->vsvdb.vendor_data);
1025             // copy the data
1026             pDvInfo->VSVDB_version               = pDvType0->VSVDB_version;
1027             pDvInfo->supports_2160p60hz          = pDvType0->supports_2160p60hz;
1028             pDvInfo->supports_YUV422_12bit       = pDvType0->supports_YUV422_12bit;
1029             pDvInfo->supports_global_dimming     = pDvType0->supports_global_dimming;
1030             pDvInfo->colorimetry                 = 0; // this field does not exist in type0
1031             pDvInfo->dm_version                  = (pDvType0->dm_version_major << 4)   | pDvType0->dm_version_minor;
1032             pDvInfo->target_min_luminance        = (pDvType0->target_min_pq_11_4 << 4) | pDvType0->target_min_pq_3_0;
1033             pDvInfo->target_max_luminance        = (pDvType0->target_max_pq_11_4 << 4) | pDvType0->target_max_pq_3_0;
1034             pDvInfo->cc_red_x                    = (pDvType0->cc_red_x_11_4 << 4)      | pDvType0->cc_red_x_3_0;
1035             pDvInfo->cc_red_y                    = (pDvType0->cc_red_y_11_4 << 4)      | pDvType0->cc_red_y_3_0;
1036             pDvInfo->cc_green_x                  = (pDvType0->cc_green_x_11_4 << 4)    | pDvType0->cc_green_x_3_0;
1037             pDvInfo->cc_green_y                  = (pDvType0->cc_green_y_11_4 << 4)    | pDvType0->cc_green_y_3_0;
1038             pDvInfo->cc_blue_x                   = (pDvType0->cc_blue_x_11_4 << 4)     | pDvType0->cc_blue_x_3_0;
1039             pDvInfo->cc_blue_y                   = (pDvType0->cc_blue_y_11_4 << 4)     | pDvType0->cc_blue_y_3_0;
1040             pDvInfo->cc_white_x                  = (pDvType0->cc_white_x_11_4 << 4)    | pDvType0->cc_white_x_3_0;
1041             pDvInfo->cc_white_y                  = (pDvType0->cc_white_y_11_4 << 4)    | pDvType0->cc_white_y_3_0;
1042             pDvInfo->supports_backlight_control  = 0;
1043             pDvInfo->backlt_min_luma             = 0;
1044             pDvInfo->interface_supported_by_sink = 0;
1045             pDvInfo->supports_10b_12b_444        = 0;
1046             break;
1047         case 1:
1048             if (pExt861->vsvdb.vendor_data_size == sizeof(NVT_DV_STATIC_METADATA_TYPE1))
1049             {
1050                 pDvType1 = (NVT_DV_STATIC_METADATA_TYPE1 *)(&pExt861->vsvdb.vendor_data);
1051                 // copy the data
1052                 pDvInfo->VSVDB_version                  = pDvType1->VSVDB_version;
1053                 pDvInfo->supports_2160p60hz             = pDvType1->supports_2160p60hz;
1054                 pDvInfo->supports_YUV422_12bit          = pDvType1->supports_YUV422_12bit;
1055                 pDvInfo->dm_version                     = pDvType1->dm_version;
1056                 pDvInfo->supports_global_dimming        = pDvType1->supports_global_dimming;
1057                 pDvInfo->colorimetry                    = pDvType1->colorimetry;
1058                 pDvInfo->target_min_luminance           = pDvType1->target_min_luminance;
1059                 pDvInfo->target_max_luminance           = pDvType1->target_max_luminance;
1060                 pDvInfo->cc_red_x                       = pDvType1->cc_red_x;
1061                 pDvInfo->cc_red_y                       = pDvType1->cc_red_y;
1062                 pDvInfo->cc_green_x                     = pDvType1->cc_green_x;
1063                 pDvInfo->cc_green_y                     = pDvType1->cc_green_y;
1064                 pDvInfo->cc_blue_x                      = pDvType1->cc_blue_x;
1065                 pDvInfo->cc_blue_y                      = pDvType1->cc_blue_y;
1066                 pDvInfo->supports_backlight_control     = 0;
1067                 pDvInfo->backlt_min_luma                = 0;
1068                 pDvInfo->interface_supported_by_sink    = 0;
1069                 pDvInfo->supports_10b_12b_444           = 0;
1070                 pDvInfo->cc_white_x                     = 0;
1071                 pDvInfo->cc_white_y                     = 0;
1072             }
1073             else if (pExt861->vsvdb.vendor_data_size == sizeof(NVT_DV_STATIC_METADATA_TYPE1_1))
1074             {
1075                 pvDvType1_1 = (NVT_DV_STATIC_METADATA_TYPE1_1 *)(&pExt861->vsvdb.vendor_data);
1076                 // copy the data
1077                 pDvInfo->VSVDB_version                  = pvDvType1_1->VSVDB_version;
1078                 pDvInfo->supports_2160p60hz             = pvDvType1_1->supports_2160p60hz;
1079                 pDvInfo->supports_YUV422_12bit          = pvDvType1_1->supports_YUV422_12bit;
1080                 pDvInfo->dm_version                     = pvDvType1_1->dm_version;
1081                 pDvInfo->supports_global_dimming        = pvDvType1_1->supports_global_dimming;
1082                 pDvInfo->colorimetry                    = pvDvType1_1->colorimetry;
1083                 pDvInfo->target_min_luminance           = pvDvType1_1->target_min_luminance;
1084                 pDvInfo->target_max_luminance           = pvDvType1_1->target_max_luminance;
1085                 pDvInfo->cc_green_x                     = NVT_DOLBY_CHROMATICITY_MSB_GX | pvDvType1_1->unique_Gx;
1086                 pDvInfo->cc_green_y                     = NVT_DOLBY_CHROMATICITY_MSB_GY | pvDvType1_1->unique_Gy;
1087                 pDvInfo->cc_blue_x                      = NVT_DOLBY_CHROMATICITY_MSB_BX | pvDvType1_1->unique_Bx;
1088                 pDvInfo->cc_blue_y                      = NVT_DOLBY_CHROMATICITY_MSB_BY | pvDvType1_1->unique_By;
1089                 pDvInfo->cc_red_x                       = NVT_DOLBY_CHROMATICITY_MSB_RX | pvDvType1_1->unique_Rx;
1090                 pDvInfo->cc_red_y                       = NVT_DOLBY_CHROMATICITY_MSB_RY | (pvDvType1_1->unique_Ry_bit_0 | (pvDvType1_1->unique_Ry_bit_1 <<1) | (pvDvType1_1->unique_Ry_bit_2_to_4 << 2));
1091                 pDvInfo->supports_backlight_control     = 0;
1092                 pDvInfo->backlt_min_luma                = 0;
1093                 pDvInfo->interface_supported_by_sink    = pvDvType1_1->interface_supported_by_sink;
1094                 pDvInfo->supports_10b_12b_444           = 0;
1095                 pDvInfo->cc_white_x                     = 0;
1096                 pDvInfo->cc_white_y                     = 0;
1097             }
1098             else
1099             {
1100                 return;
1101             }
1102 
1103             break;
1104         case 2:
1105             if (pExt861->vsvdb.vendor_data_size < sizeof(NVT_DV_STATIC_METADATA_TYPE2))
1106             {
1107                 return;
1108             }
1109             pDvType2 = (NVT_DV_STATIC_METADATA_TYPE2 *)(&pExt861->vsvdb.vendor_data);
1110             // copy the data
1111             pDvInfo->VSVDB_version               = pDvType2->VSVDB_version;
1112             pDvInfo->supports_backlight_control  = pDvType2->supports_backlight_control;
1113             pDvInfo->supports_YUV422_12bit       = pDvType2->supports_YUV422_12bit;
1114             pDvInfo->dm_version                  = pDvType2->dm_version;
1115             pDvInfo->supports_global_dimming     = pDvType2->supports_global_dimming;
1116             pDvInfo->target_min_luminance        = pDvType2->target_min_luminance;
1117             pDvInfo->interface_supported_by_sink = pDvType2->interface_supported_by_sink;
1118             pDvInfo->parity                      = pDvType2->parity;
1119             pDvInfo->target_max_luminance        = pDvType2->target_max_luminance;
1120             pDvInfo->cc_green_x                  = NVT_DOLBY_CHROMATICITY_MSB_GX | pDvType2->unique_Gx;
1121             pDvInfo->cc_green_y                  = NVT_DOLBY_CHROMATICITY_MSB_GY | pDvType2->unique_Gy;
1122             pDvInfo->cc_blue_x                   = NVT_DOLBY_CHROMATICITY_MSB_BX | pDvType2->unique_Bx;
1123             pDvInfo->cc_blue_y                   = NVT_DOLBY_CHROMATICITY_MSB_BY | pDvType2->unique_By;
1124             pDvInfo->cc_red_x                    = NVT_DOLBY_CHROMATICITY_MSB_RX | pDvType2->unique_Rx;
1125             pDvInfo->cc_red_y                    = NVT_DOLBY_CHROMATICITY_MSB_RY | pDvType2->unique_Ry;
1126             pDvInfo->supports_10b_12b_444        = pDvType2->supports_10b_12b_444_bit0 | (pDvType2->supports_10b_12b_444_bit1 << 1);
1127             pDvInfo->colorimetry                 = 0;
1128             pDvInfo->supports_2160p60hz          = 0;
1129             pDvInfo->cc_white_x                  = 0;
1130             pDvInfo->cc_white_y                  = 0;
1131             break;
1132         default:
1133             break;
1134     }
1135 }
1136 
1137 // find both hdmi llc and hdmi forum vendor specific data block and return basic hdmi information
1138 CODE_SEGMENT(PAGE_DD_CODE)
1139 void parseCta861VsdbBlocks(NVT_EDID_CEA861_INFO *pExt861,
1140                            void *pRawInfo,
1141                            NVT_CTA861_ORIGIN flag
1142     )
1143 {
1144     NvU32 i;
1145 
1146     NVT_EDID_INFO           *pInfo         = NULL;
1147     NVT_DISPLAYID_2_0_INFO  *pDisplayID20  = NULL;
1148     NVT_HDMI_LLC_INFO       *pHdmiLlc      = NULL;
1149     NVT_HDMI_FORUM_INFO     *pHfvs         = NULL;
1150     NVDA_VSDB_PARSED_INFO   *pNvVsdb       = NULL;
1151     MSFT_VSDB_PARSED_INFO   *pMsftVsdb     = NULL;
1152 
1153     if (pExt861 == NULL || pRawInfo == NULL)
1154     {
1155         return;
1156     }
1157 
1158     if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
1159     {
1160         pInfo     = (NVT_EDID_INFO *)pRawInfo;
1161         pHdmiLlc  = &pInfo->hdmiLlcInfo;
1162         pHfvs     = &pInfo->hdmiForumInfo;
1163         pNvVsdb   = &pInfo->nvdaVsdbInfo;
1164         pMsftVsdb = &pInfo->msftVsdbInfo;
1165     }
1166     else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
1167     {
1168         pDisplayID20 = (NVT_DISPLAYID_2_0_INFO *)pRawInfo;
1169         pHdmiLlc  = &pDisplayID20->vendor_specific.hdmiLlc;
1170         pHfvs     = &pDisplayID20->vendor_specific.hfvs;
1171         pNvVsdb   = &pDisplayID20->vendor_specific.nvVsdb;
1172         pMsftVsdb = &pDisplayID20->vendor_specific.msftVsdb;
1173     }
1174     else
1175     {
1176         return;
1177     }
1178 
1179     if (pHdmiLlc == NULL || pHfvs == NULL || pNvVsdb == NULL || pMsftVsdb == NULL || (pExt861->total_vsdb == 0))
1180     {
1181         return;
1182     }
1183 
1184     for (i = 0; i < pExt861->total_vsdb; i++)
1185     {
1186         // Assumes each vsdb is unique for this CEA block, e.g., no two HDMI_IEEE_ID
1187         switch (pExt861->vsdb[i].ieee_id)
1188         {
1189             case NVT_CEA861_HDMI_IEEE_ID:
1190                 // set any 3D timings and HDMI extended timing specified in the VSDB
1191                 parseEdidHdmiLlcBasicInfo((VSDB_DATA *)(&pExt861->vsdb[i]), pHdmiLlc);
1192                 pExt861->valid.H14B_VSDB = 1;
1193                 break;
1194 
1195             case NVT_CEA861_HDMI_FORUM_IEEE_ID:
1196                 parseEdidHdmiForumVSDB((VSDB_DATA *)(&pExt861->vsdb[i]), pHfvs);
1197                 pExt861->valid.H20_HF_VSDB = 1;
1198                 break;
1199 
1200             case NVT_CEA861_NVDA_IEEE_ID:
1201                 parseEdidNvidiaVSDBBlock((VSDB_DATA *)(&pExt861->vsdb[i]), pNvVsdb);
1202                 pExt861->valid.nvda_vsdb = 1;
1203                 break;
1204 
1205             case NVT_CEA861_MSFT_IEEE_ID:
1206                 parseEdidMsftVsdbBlock((VSDB_DATA *)(&pExt861->vsdb[i]), pMsftVsdb);
1207                 pExt861->valid.msft_vsdb = 1;
1208                 break;
1209 
1210         }
1211     }
1212 
1213     // H20_HF_VSDB shall be listed only if H14B_VSDB is also listed
1214     // H20_HF_VSDB should not specify > 600MHz
1215     nvt_assert(!pExt861->valid.H20_HF_VSDB || (pExt861->valid.H14B_VSDB && (pHfvs->max_TMDS_char_rate <= 0x78)));
1216 
1217     // Done with reading CEA VSDB blocks, sanitize them now
1218     if (pExt861->valid.SCDB)
1219     {
1220         pHdmiLlc->effective_tmds_clock = pExt861->hfscdb[1];
1221     }
1222     else if (pExt861->valid.H14B_VSDB)
1223     {
1224         // HDMI 2.0 Spec -  section 10.3.2
1225         // The maximum Rate = Max_TMDS_Character_Rate * 5 MHz.
1226         // If the Sink does not support TMDS Character Rates > 340 Mcsc, then the Sink shall set this field to 0.
1227         // If the Sink supports TMDS Character Rates > 340 Mcsc, the Sink shall set Max_TMDS_Character_Rate appropriately and non - zero.
1228 
1229         // Pick updated TMDS clock rate
1230         pHdmiLlc->effective_tmds_clock = (pExt861->valid.H20_HF_VSDB) ?
1231                                             MAX(pHdmiLlc->max_tmds_clock, pHfvs->max_TMDS_char_rate) :
1232                                             MIN(pHdmiLlc->max_tmds_clock, 0x44);
1233     }
1234 
1235 }
1236 
1237 CODE_SEGMENT(PAGE_DD_CODE)
1238 void parseCta861HfEeodb(NVT_EDID_CEA861_INFO *pExt861,
1239                         NvU32 *pTotalEdidExtensions)
1240 {
1241     // *pTotalEdidExtensions set by the edid extension flag should be >= 1 for HFEEODB to be valid.
1242     if (pTotalEdidExtensions == NULL || pExt861 == NULL || !pExt861->valid.HF_EEODB || *pTotalEdidExtensions == 0)
1243     {
1244         return;
1245     }
1246 
1247     // HDMI 2.1 AmendmentA1 specifies that if EEODB is present sources shall ignore the Extension flag.
1248     // This effectively overrides the extension count from extension flag.
1249     *pTotalEdidExtensions = pExt861->hfeeodb;
1250 }
1251 
1252 
1253 CODE_SEGMENT(PAGE_DD_CODE)
1254 void parseCta861HfScdb(NVT_EDID_CEA861_INFO *pExt861,
1255                        void *pRawInfo,
1256                        NVT_CTA861_ORIGIN flag)
1257 {
1258     NVT_EDID_INFO   *pInfo = (NVT_EDID_INFO *)pRawInfo;
1259     VSDB_DATA       vsdbData;
1260 
1261     if (pExt861 == NULL || pRawInfo == NULL)
1262     {
1263         return;
1264     }
1265 
1266     if (!pExt861->valid.SCDB || pExt861->valid.H20_HF_VSDB)
1267     {
1268         return;
1269     }
1270     NVMISC_MEMSET(&vsdbData, 0, sizeof(vsdbData));
1271     NVMISC_MEMCPY(&vsdbData.vendor_data, pExt861->hfscdb, sizeof(vsdbData.vendor_data));
1272 
1273     vsdbData.vendor_data_size = pExt861->hfscdbSize;
1274 
1275     parseEdidHdmiForumVSDB(&vsdbData, &pInfo->hdmiForumInfo);
1276 }
1277 
1278 
1279 CODE_SEGMENT(PAGE_DD_CODE)
1280 void getEdidHDM1_4bVsdbTiming(NVT_EDID_INFO *pInfo)
1281 {
1282     NvU32 i = 0, j = 0;
1283 
1284     for (i = 0; i < 2; ++i)
1285     {
1286         NVT_EDID_CEA861_INFO *pExt861 = (0 == i) ? &pInfo->ext861 : &pInfo->ext861_2;
1287 
1288         for (j = 0; j < pExt861->total_vsdb; ++j)
1289         {
1290             switch (pExt861->vsdb[j].ieee_id)
1291             {
1292                 case NVT_CEA861_HDMI_IEEE_ID:
1293                 {
1294                     NvU32 count = 0;
1295                     // set any 3D timings and HDMI extended timing specified in the VSDB
1296                     parseEdidHDMILLCTiming(pInfo, (VSDB_DATA *)(&pExt861->vsdb[j]), &count, &(pInfo->Hdmi3Dsupport));
1297                     pInfo->HDMI3DSupported = 0 < count;
1298                     break;
1299                 }
1300 
1301                 default:
1302                     break;
1303             }
1304         }
1305     }
1306 }
1307 
1308 // get the full EDID 861 extension info
1309 CODE_SEGMENT(PAGE_DD_CODE)
1310 NVT_STATUS get861ExtInfo(NvU8 *p, NvU32 size, NVT_EDID_CEA861_INFO *p861info)
1311 {
1312 
1313     NvU32 dtd_offset;
1314     // sanity check
1315     if (p == NULL || size < sizeof(EDIDV1STRUC))
1316     {
1317         return NVT_STATUS_ERR;
1318     }
1319 
1320     // make sure we have 861 extension
1321     if (p[0] != 0x2 || p[1] < NVT_CEA861_REV_ORIGINAL)
1322     {
1323         return NVT_STATUS_ERR;
1324     }
1325 
1326     // DTD offset sanity check
1327     if (p[2] >= 1 && p[2] <= 3)
1328     {
1329         return NVT_STATUS_ERR;
1330     }
1331 
1332     // don't do anything further if p861info is NULL
1333     if (p861info == NULL)
1334     {
1335         return NVT_STATUS_SUCCESS;
1336     }
1337 
1338     // init
1339     NVMISC_MEMSET(p861info, 0, sizeof(NVT_EDID_CEA861_INFO));
1340 
1341     // get the revision number
1342     p861info->revision = p[1];
1343 
1344     // no extra info for 861-original, returning from here
1345     if (p861info->revision == NVT_CEA861_REV_ORIGINAL)
1346     {
1347         return NVT_STATUS_SUCCESS;
1348     }
1349 
1350     p861info->basic_caps = p[3];
1351 
1352     // no extra info for 861-A, returning from here
1353     if (p861info->revision == NVT_CEA861_REV_A)
1354     {
1355         return NVT_STATUS_SUCCESS;
1356     }
1357 
1358     dtd_offset = (NvU32)p[2];
1359     if (dtd_offset == 0 || dtd_offset == 4)
1360     {
1361         return NVT_STATUS_SUCCESS;
1362     }
1363 
1364     // resolve all short descriptors in the reserved block
1365     // reserved block starts from offset 04 to dtd_offset-1
1366     return parseCta861DataBlockInfo(&p[4], dtd_offset - 4, p861info);
1367 }
1368 
1369 // 1. get the  861 extension tags info
1370 // 2. or validation purpose if p861info == NULL
1371 CODE_SEGMENT(PAGE_DD_CODE)
1372 NVT_STATUS parseCta861DataBlockInfo(NvU8 *p,
1373                                     NvU32 size,
1374                                     NVT_EDID_CEA861_INFO *p861info)
1375 {
1376     NvU32 i, j;
1377     NvU32 video_index      = 0;
1378     NvU32 audio_index      = 0;
1379     NvU32 speaker_index    = 0;
1380     NvU32 vendor_index     = 0;
1381     NvU32 yuv420vdb_index  = 0;
1382     NvU32 yuv420cmdb_index = 0;
1383     NvU8  didT7_index      = 0;
1384     NvU8  didT8_index      = 0;
1385     NvU8  didT10_index     = 0;
1386     NvU8  svr_index        = 0;
1387     NvU32 ieee_id          = 0;
1388     NvU32 tag, ext_tag, payload;
1389     i= 0;
1390 
1391     while (i < size)
1392     {
1393         // get the descriptor's tag and payload size
1394         tag = NVT_CEA861_GET_SHORT_DESCRIPTOR_TAG(p[i]);
1395         payload = NVT_CEA861_GET_SHORT_DESCRIPTOR_SIZE(p[i]);
1396 
1397         /*don't allow data colleciton totally size larger than [127 - 5 (tag, revision, offset, describing native video format, checksum)]*/
1398         if ((i + payload > size) || (i + payload > 122))
1399         {
1400             break;
1401         }
1402         // move the pointer to the payload section or extended Tag Code
1403         i++;
1404 
1405         // NvTiming_EDIDValidationMask will use the different tag/payload value to make sure each of cta861 data block legal
1406         if (p861info == NULL)
1407         {
1408             switch(tag)
1409             {
1410                 case NVT_CEA861_TAG_AUDIO:
1411                 case NVT_CEA861_TAG_VIDEO:
1412                 case NVT_CEA861_TAG_SPEAKER_ALLOC:
1413                 case NVT_CEA861_TAG_VESA_DTC:
1414                 case NVT_CEA861_TAG_RSVD:
1415                 break;
1416                 case NVT_CEA861_TAG_VENDOR:
1417                     if (payload < 3) return NVT_STATUS_ERR;
1418                 break;
1419                 case NVT_CEA861_TAG_EXTENDED_FLAG:
1420                     if (payload >= 1)
1421                     {
1422                         ext_tag = p[i];
1423                         if      (ext_tag == NVT_CEA861_EXT_TAG_VIDEO_CAP && payload < 2)               return NVT_STATUS_ERR;
1424                         else if (ext_tag == NVT_CEA861_EXT_TAG_COLORIMETRY && payload < 3)             return NVT_STATUS_ERR;
1425                         else if (ext_tag == NVT_CEA861_EXT_TAG_VIDEO_FORMAT_PREFERENCE && payload < 2) return NVT_STATUS_ERR;
1426                         else if (ext_tag == NVT_CEA861_EXT_TAG_YCBCR420_VIDEO && payload < 2)          return NVT_STATUS_ERR;
1427                         else if (ext_tag == NVT_CEA861_EXT_TAG_YCBCR420_CAP && payload < 1)            return NVT_STATUS_ERR;
1428                         else if (ext_tag == NVT_CEA861_EXT_TAG_HDR_STATIC_METADATA && payload < 3)     return NVT_STATUS_ERR;
1429                         else if (ext_tag == NVT_CEA861_EXT_TAG_VENDOR_SPECIFIC_VIDEO && payload < 4)   return NVT_STATUS_ERR;
1430                         else if (ext_tag == NVT_CTA861_EXT_TAG_SCDB && payload < 7)                    return NVT_STATUS_ERR;
1431                         else if (ext_tag == NVT_CTA861_EXT_TAG_HF_EEODB && payload != 2)               return NVT_STATUS_ERR;
1432                         else if (ext_tag == NVT_CTA861_EXT_TAG_DID_TYPE_VII && payload <= 2)           return NVT_STATUS_ERR;
1433                         else if (ext_tag == NVT_CTA861_EXT_TAG_DID_TYPE_VIII && payload <= 2)          return NVT_STATUS_ERR;
1434                         else if (ext_tag == NVT_CTA861_EXT_TAG_DID_TYPE_X && payload <= 2)             return NVT_STATUS_ERR;
1435                         else if (ext_tag == NVT_CTA861_EXT_TAG_NATIVE_VIDEO_RESOLUTION)
1436                         {
1437                             if (payload != 2 && payload != 3 && payload != 7)                          return NVT_STATUS_ERR;
1438                         }
1439 
1440                         if (payload > 2)
1441                         {
1442                             if (ext_tag == NVT_CTA861_EXT_TAG_DID_TYPE_VII)
1443                             {
1444                                 if ((payload-2) != 20)                                                 return NVT_STATUS_ERR;    // only support 20-bytes
1445                                 if ((p[i+1] & 0x7) != 2)                                               return NVT_STATUS_ERR;    // Block Revision shall be 2
1446                                 if ((p[i+1] & 0x70) >> 4 != 0)                                         return NVT_STATUS_ERR;    // Not allow extra byte
1447                             }
1448                             else if (ext_tag == NVT_CTA861_EXT_TAG_DID_TYPE_VIII)
1449                             {
1450                                  if ((payload-2) < 1)                                                  return NVT_STATUS_ERR;    // minimum one code supported
1451                                  if ((p[i+1] & 0x7) != 1)                                              return NVT_STATUS_ERR;    // Block Revision shall be 1
1452                                  if ((p[i+1] & 0xC0) >> 6 != 0)                                        return NVT_STATUS_ERR;    // Not allow others than DMT Timing
1453                             }
1454                             else if (ext_tag == NVT_CTA861_EXT_TAG_DID_TYPE_X)
1455                             {
1456                                 if ((p[i+1] & 0x7) != 0)                                               return NVT_STATUS_ERR;    // Block Revision shall be 0
1457                                 if (((p[i+1] & 0x70) >> 4 == 0) && (payload-2) % 6)                    return NVT_STATUS_ERR;    // supported 6-bytes descriptors
1458                                 if (((p[i+1] & 0x70) >> 4 == 1) && (payload-2) % 7)                    return NVT_STATUS_ERR;    // supported 7-bytes descriptors
1459                             }
1460                         }
1461                     }
1462                 break;
1463                 default:
1464                 break;
1465             }
1466             return NVT_STATUS_SUCCESS;
1467         }
1468 
1469         // loop through all descriptors
1470         if (tag == NVT_CEA861_TAG_VIDEO)
1471         {
1472             // short video descriptor
1473             for (j = 0; j < payload; j ++, i ++, video_index ++)
1474             {
1475                 if (video_index < NVT_CEA861_VIDEO_MAX_DESCRIPTOR)
1476                 {
1477                     p861info->video[video_index] = p[i];
1478                 }
1479                 else
1480                 {
1481                     break;
1482                 }
1483             }
1484             p861info->total_svd = (NvU8)video_index;
1485         }
1486         else if (tag == NVT_CEA861_TAG_AUDIO)
1487         {
1488             // short audio descriptor
1489             for (j = 0; j < payload / 3; j ++, i += 3, audio_index ++)
1490             {
1491                 if (audio_index < NVT_CEA861_AUDIO_MAX_DESCRIPTOR)
1492                 {
1493                     p861info->audio[audio_index].byte1 = p[i];
1494                     p861info->audio[audio_index].byte2 = p[i+1];
1495                     p861info->audio[audio_index].byte3 = p[i+2];
1496                 }
1497                 else
1498                 {
1499                     break;
1500                 }
1501             }
1502             p861info->total_sad = (NvU8)audio_index;
1503         }
1504         else if (tag == NVT_CEA861_TAG_SPEAKER_ALLOC)
1505         {
1506             // speaker allocation descriptor
1507             for (j = 0; j < payload / 3; j ++, i += 3, speaker_index ++)
1508             {
1509                 if (speaker_index < NVT_CEA861_SPEAKER_MAX_DESCRIPTOR)
1510                 {
1511                     p861info->speaker[speaker_index].byte1 = p[i];
1512                     p861info->speaker[speaker_index].byte2 = p[i+1];
1513                     p861info->speaker[speaker_index].byte3 = p[i+2];
1514                 }
1515                 else
1516                 {
1517                     break;
1518                 }
1519             }
1520             p861info->total_ssd = (NvU8)speaker_index;
1521         }
1522         else if (tag == NVT_CEA861_TAG_VENDOR)
1523         {
1524             if (vendor_index < NVT_CEA861_VSDB_MAX_BLOCKS)
1525             {
1526                 if (payload < 3)
1527                 {
1528                     // This malformed payload will cause a hang below.
1529                     return NVT_STATUS_ERR;
1530                 }
1531 
1532                 p861info->vsdb[vendor_index].ieee_id = p[i];                 //IEEE ID low byte
1533                 p861info->vsdb[vendor_index].ieee_id |= (p[i+1]) << 8;       //IEEE ID middle byte
1534                 p861info->vsdb[vendor_index].ieee_id |= (p[i+2]) << 16;      //IEEE ID high byte
1535 
1536                 p861info->vsdb[vendor_index].vendor_data_size = payload - 3;
1537 
1538                 // move the pointer to the payload
1539                 i += 3;
1540 
1541                 // get the other vendor specific data
1542                 for (j = 0; j < payload - 3; j ++, i ++)
1543                 {
1544                     if (j < NVT_CEA861_VSDB_PAYLOAD_MAX_LENGTH)
1545                     {
1546                         p861info->vsdb[vendor_index].vendor_data[j] = p[i];
1547                     }
1548                 }
1549                 vendor_index++;
1550             }
1551         }
1552         else if (tag == NVT_CEA861_TAG_EXTENDED_FLAG)
1553         {
1554             if (payload >= 1)
1555             {
1556                 ext_tag = p[i];
1557                 if (ext_tag == NVT_CEA861_EXT_TAG_VIDEO_CAP && payload >= 2)
1558                 {
1559                     p861info->video_capability = p[i + 1] & NVT_CEA861_VIDEO_CAPABILITY_MASK;
1560                     p861info->valid.VCDB = 1;
1561                     i += 2;
1562                 }
1563                 else if (ext_tag == NVT_CEA861_EXT_TAG_COLORIMETRY && payload >= 3)
1564                 {
1565                     p861info->colorimetry.byte1 = p[i + 1] & NVT_CEA861_COLORIMETRY_MASK;
1566                     p861info->colorimetry.byte2 = p[i + 2] & NVT_CEA861_GAMUT_METADATA_MASK;
1567                     p861info->valid.colorimetry = 1;
1568                     i += 3;
1569                 }
1570                 else if (ext_tag == NVT_CEA861_EXT_TAG_VIDEO_FORMAT_PREFERENCE && payload >= 2)
1571                 {
1572                     // when present, indicates the order of preference for selected Video Formats listed as DTDs and/or SVDs throughout Block 0 and the CTA Extensions of the
1573                     // order of SVD preferred modes shall take precedence over preferred modes defined elsewhere in the EDID/CEA861 blocks
1574 
1575                     // exclude the extended tag
1576                     i++; payload--;
1577 
1578                     for (j = 0; (j < payload) && (svr_index < NVT_CEA861_VFPDB_MAX_DESCRIPTOR); j++, i++, svr_index++)
1579                     {
1580                         p861info->svr_vfpdb[svr_index] = p[i];
1581                     }
1582                     p861info->total_svr = svr_index;
1583                 }
1584                 else if (ext_tag == NVT_CEA861_EXT_TAG_YCBCR420_VIDEO && payload >= 2)
1585                 {
1586                     // when present, list SVDs that are only supported in YCbCr 4:2:0
1587 
1588                     // exclude the extended tag
1589                     i++; payload--;
1590 
1591                     for (j = 0; (j < payload) && (yuv420vdb_index < NVT_CEA861_Y420VDB_MAX_DESCRIPTOR); j++, i++, yuv420vdb_index++)
1592                     {
1593                         p861info->svd_y420vdb[yuv420vdb_index] = p[i];
1594                     }
1595                     p861info->total_y420vdb = (NvU8)yuv420vdb_index;
1596                 }
1597                 else if (ext_tag == NVT_CEA861_EXT_TAG_YCBCR420_CAP && payload >= 1)
1598                 {
1599                     // when present, provides bitmap to video SVDs that also support YCbCr 4:2:0 in addition to RGB, YCbCr 4:4:4, and/or YCbCr 4: 2:0
1600 
1601                     // exclude the extended tag
1602                     i++; payload--;
1603 
1604                     for (j = 0; (j < payload) && (yuv420cmdb_index < NVT_CEA861_Y420CMDB_MAX_DESCRIPTOR); j++, i++, yuv420cmdb_index++)
1605                     {
1606                         p861info->map_y420cmdb[yuv420cmdb_index] = p[i];
1607                     }
1608                     p861info->total_y420cmdb = (NvU8)yuv420cmdb_index;
1609 
1610                     p861info->valid.y420cmdb = 1; // total_y420cmdb is not enough as this could be 0.  See CEA861-F 7.5.11
1611                 }
1612                 else if(ext_tag == NVT_CEA861_EXT_TAG_HDR_STATIC_METADATA && payload >= 3)
1613                 {
1614                     p861info->hdr_static_metadata.byte1 = p[i + 1] & NVT_CEA861_EOTF_MASK;                            // This byte has bits which identify which EOTF supported by the sink.
1615                     p861info->hdr_static_metadata.byte2 = p[i + 2] & NVT_CEA861_STATIC_METADATA_DESCRIPTOR_MASK;      // This byte has bits which identify which Static Metadata descriptors are supported by the sink.
1616 
1617                     i += 3;
1618 
1619                     if (payload > 3)
1620                     {
1621                         p861info->hdr_static_metadata.byte3 = p[i];
1622                         i++;
1623                     }
1624 
1625                     if (payload > 4)
1626                     {
1627                         p861info->hdr_static_metadata.byte4 = p[i];
1628                         i++;
1629                     }
1630 
1631                     if (payload > 5)
1632                     {
1633                         p861info->hdr_static_metadata.byte5 = p[i];
1634                         i++;
1635                     }
1636 
1637                     p861info->valid.hdr_static_metadata = 1;
1638                 }
1639                 else if(ext_tag == NVT_CEA861_EXT_TAG_VENDOR_SPECIFIC_VIDEO)
1640                 {
1641                     ieee_id  =  p[i + 1];           //IEEE ID low byte
1642                     ieee_id |= (p[i + 2]) << 8;     //IEEE ID middle byte
1643                     ieee_id |= (p[i + 3]) << 16;    //IEEE ID high byte
1644 
1645                     if ((ieee_id == NVT_CEA861_DV_IEEE_ID) || (ieee_id == NVT_CEA861_HDR10PLUS_IEEE_ID))
1646                     {
1647                         // exclude the extended tag
1648                         i++; payload--;
1649 
1650                         p861info->vsvdb.ieee_id = ieee_id;
1651                         p861info->vsvdb.vendor_data_size = payload - 3;
1652 
1653                         // move the pointer to the payload
1654                         i += 3;
1655 
1656                         // get the other vendor specific video data
1657                         for (j = 0; j < payload - 3; j++, i++)
1658                         {
1659                             if (j < NVT_CEA861_VSVDB_PAYLOAD_MAX_LENGTH)
1660                             {
1661                                 p861info->vsvdb.vendor_data[j] = p[i];
1662                             }
1663                         }
1664 
1665                         if (p861info->vsvdb.ieee_id == NVT_CEA861_DV_IEEE_ID)
1666                         {
1667                             p861info->valid.dv_static_metadata = 1;
1668                         }
1669                         else if (p861info->vsvdb.ieee_id == NVT_CEA861_HDR10PLUS_IEEE_ID)
1670                         {
1671                             p861info->valid.hdr10Plus = 1;
1672                         }
1673                     }
1674                     else
1675                     {
1676                         // skip the unsupported extended block
1677                         i += payload;
1678                     }
1679                 }
1680                 else if (ext_tag == NVT_CTA861_EXT_TAG_NATIVE_VIDEO_RESOLUTION)
1681                 {
1682                     if (payload != 2 && payload != 3 && payload != 7) break;
1683 
1684                     i++; payload--;
1685                     p861info->native_video_resolution_db.native_svr = p[i];
1686                     p861info->valid.NVRDB = 1;
1687 
1688                     i++; payload--;
1689                     if (payload != 0)
1690                     {
1691                         p861info->native_video_resolution_db.option.img_size =  p[i] & 0x01;
1692                         p861info->native_video_resolution_db.option.sz_prec  = (p[i] & 0x80) >> 7;
1693 
1694                         i++; payload--;
1695                         if (p861info->native_video_resolution_db.option.img_size == 1)
1696                         {
1697                             for (j = 0; j< payload; j++, i++)
1698                             {
1699                                 p861info->native_video_resolution_db.image_size[j] = p[i];
1700                             }
1701                         }
1702                     }
1703                 }
1704                 else if (ext_tag == NVT_CTA861_EXT_TAG_DID_TYPE_VII)
1705                 {
1706                     if( payload != 22) break;
1707 
1708                     i++; payload--;
1709                     p861info->did_type7_data_block[didT7_index].version.revision =  p[i] & 0x07;
1710                     p861info->did_type7_data_block[didT7_index].version.dsc_pt   = (p[i] & 0x08) >> 3;
1711                     p861info->did_type7_data_block[didT7_index].version.t7_m     = (p[i] & 0x70) >> 4;
1712 
1713                     //do not consider Byte 3
1714                     i++; payload--;
1715 
1716                     p861info->did_type7_data_block[didT7_index].total_descriptors =
1717                         (NvU8)(payload / (NVT_CTA861_DID_TYPE7_DESCRIPTORS_LENGTH + p861info->did_type7_data_block[didT7_index].version.t7_m));
1718 
1719                     for (j = 0; j < payload; j++, i++)
1720                     {
1721                         p861info->did_type7_data_block[didT7_index].payload[j] = p[i];
1722                     }
1723                     // next type7 data block if it exists
1724                     p861info->total_did_type7db = ++didT7_index;
1725                 }
1726                 else if (ext_tag == NVT_CTA861_EXT_TAG_DID_TYPE_VIII)
1727                 {
1728                     if (payload <= 2) break;
1729 
1730                     i++; payload--;
1731                     p861info->did_type8_data_block[didT8_index].version.revision  =  p[i] & 0x07;
1732                     p861info->did_type8_data_block[didT8_index].version.tcs       = (p[i] & 0x08) >> 3;
1733                     p861info->did_type8_data_block[didT8_index].version.t8y420    = (p[i] & 0x20) >> 5;
1734                     p861info->did_type8_data_block[didT8_index].version.code_type = (p[i] & 0xC0) >> 6;
1735 
1736                     //do not consider Byte 3
1737                     i++; payload--;
1738 
1739                     if (p861info->did_type8_data_block[didT8_index].version.tcs == 0)
1740                         p861info->did_type8_data_block[didT8_index].total_descriptors = (NvU8)payload;
1741                     else if (p861info->did_type8_data_block[didT8_index].version.tcs == 1)
1742                         p861info->did_type8_data_block[didT8_index].total_descriptors = (NvU8)(payload / 2);
1743 
1744                     for (j = 0; j < payload; j++, i++)
1745                     {
1746                         p861info->did_type8_data_block[didT8_index].payload[j] = p[i];
1747                     }
1748                     // next type7 data block if it exists
1749                     p861info->total_did_type8db = ++didT8_index;
1750                 }
1751                 else if (ext_tag == NVT_CTA861_EXT_TAG_DID_TYPE_X)
1752                 {
1753                     if (payload < 8 || ((payload-2) % 6 != 0 && (payload-2) % 7 != 0)) break;
1754 
1755                     i++; payload--;
1756                     p861info->did_type10_data_block[didT10_index].version.revision =  p[i] & 0x07;
1757                     p861info->did_type10_data_block[didT10_index].version.t10_m    = (p[i] & 0x70) >> 4;
1758 
1759                     // do not consider Byte 3
1760                     i++; payload--;
1761 
1762                     if (p861info->did_type10_data_block[didT10_index].version.t10_m == 0)
1763                         p861info->did_type10_data_block[didT10_index].total_descriptors = (NvU8)(payload / 6);
1764                     else if (p861info->did_type10_data_block[didT10_index].version.t10_m == 1)
1765                         p861info->did_type10_data_block[didT10_index].total_descriptors = (NvU8)(payload / 7);
1766 
1767                     for (j = 0; j < payload; j++, i++)
1768                     {
1769                         p861info->did_type10_data_block[didT10_index].payload[j] = p[i];
1770                     }
1771                     // next type10 data block if it exists
1772                     p861info->total_did_type10db = ++didT10_index;
1773                 }
1774                 else if(ext_tag == NVT_CTA861_EXT_TAG_SCDB && payload >= 7) // sizeof(HDMI Forum Sink Capability Data Block) ranges between 7 to 31 bytes
1775                 {
1776                     // As per HDMI2.1 A1 amendment Sink Capability Data Structure(SCDS) can alternatively be included in HDMI Forum Sink Capability Data Block(HF-SCDB),
1777                     //  instead of HF-VSDB, to indicate HDMI2.1 capability.
1778                     // Sinks will expose HF-SCDB if they do not expose HF-VSDB.
1779 
1780                     // move pointer to SCDS
1781                     i += 3;
1782 
1783                     // Copy SCDS over to p861info->vsdb[vendor_index]. Parsing will later be handled in parseEdidHdmiForumVSDB().
1784                     for (j = 0; (j < payload - 3) && (j < NVT_CTA861_EXT_SCDB_PAYLOAD_MAX_LENGTH); j ++, i ++)
1785                     {
1786                         p861info->hfscdb[j] = p[i];
1787                     }
1788                     p861info->hfscdbSize = MIN(payload - 3, NVT_CTA861_EXT_SCDB_PAYLOAD_MAX_LENGTH);
1789                     p861info->valid.SCDB = 1;
1790                 }
1791                 else if (ext_tag == NVT_CTA861_EXT_TAG_HF_EEODB && payload == 2)
1792                 {
1793                     // Skip over extended tag
1794                     i++; payload--;
1795 
1796                     p861info->hfeeodb = p[i];
1797                     p861info->valid.HF_EEODB = 1;
1798                     i += payload;
1799                 }
1800                 else
1801                 {
1802                     // skip the unrecognized extended block
1803                     i += payload;
1804                 }
1805             }
1806         }
1807         else
1808         {
1809             // reserved block, just skip here
1810             i += payload;
1811         }
1812     }
1813 
1814     if (p861info)
1815     {
1816         p861info->total_vsdb = (NvU8)vendor_index;
1817     }
1818 
1819     return NVT_STATUS_SUCCESS;
1820 }
1821 
1822 // enum the EIA/CEA 861B predefined timing
1823 CODE_SEGMENT(PAGE_DD_CODE)
1824 NVT_STATUS NvTiming_EnumCEA861bTiming(NvU32 ceaFormat, NVT_TIMING *pT)
1825 {
1826     if (pT == NULL || ceaFormat == 0 || ceaFormat > MAX_CEA861B_FORMAT)
1827     {
1828         return NVT_STATUS_ERR;
1829     }
1830 
1831     ceaFormat = NVT_GET_CTA_8BIT_VIC(ceaFormat);
1832 
1833     if (ceaFormat ==0)
1834         return NVT_STATUS_ERR;
1835 
1836     *pT = EIA861B[ceaFormat - 1];
1837 
1838     // calculate the pixel clock
1839     pT->pclk  = RRx1kToPclk (pT);
1840     NVT_SET_CEA_FORMAT(pT->etc.status, ceaFormat);
1841 
1842     NVT_SNPRINTF((char *)pT->etc.name, sizeof(pT->etc.name), "CTA-861G:#%3d:%dx%dx%3d.%03dHz/%s", (int)ceaFormat, (int)pT->HVisible, (int)((pT->interlaced ? 2 : 1)*pT->VVisible), (int)pT->etc.rrx1k/1000, (int)pT->etc.rrx1k%1000, (pT->interlaced ? "I":"P"));
1843     pT->etc.name[sizeof(pT->etc.name) - 1] = '\0';
1844 
1845     return NVT_STATUS_SUCCESS;
1846 }
1847 
1848 
1849 // Check whether the given timing is a CEA 861 timing.
1850 CODE_SEGMENT(PAGE_DD_CODE)
1851 NvU32 NvTiming_GetCEA861TimingIndex (NVT_TIMING *pT)
1852 {
1853     NvU32 i = 0, j = 0;
1854     NvU32 ceaIndex = 0;
1855     NvU32 aspect_x;
1856     NvU32 aspect_y;
1857 
1858     if (pT == NULL)
1859     {
1860         return ceaIndex;
1861     }
1862 
1863     if (NVT_GET_CEA_FORMAT(pT->etc.status) != 0)
1864     {
1865         // CEA format has been set, done
1866         return NVT_GET_CEA_FORMAT(pT->etc.status);
1867     }
1868 
1869     aspect_x = nvt_aspect_x(pT->etc.aspect);
1870     aspect_y = nvt_aspect_y(pT->etc.aspect);
1871 
1872     // loop through the pre-defined CEA 861 table
1873     // Skip VIC1 - Although IT 640x480 video timing has a CE id, it is not a CE timing. See 3.1
1874     // "General Video Format Requirements" section in CEA-861-E spec
1875     for (i = 1; i < MAX_CEA861B_FORMAT; i++)
1876     {
1877         if (NvTiming_IsTimingRelaxedEqual(pT, &EIA861B[i]))
1878         {
1879             // The timing matches with a CEA 861 timing. Set CEA format to NVT_TIMING.etc.status.
1880             ceaIndex = NVT_GET_TIMING_STATUS_SEQ(EIA861B[i].etc.status);
1881 
1882             if (!aspect_x || !aspect_y)
1883             {
1884                 return ceaIndex;
1885             }
1886 
1887             // for the dual-aspect ratio timings we should further check the aspect ratio matching(16:9 or 4:3) based on the integer rounding error
1888             for (j = 0; j < MAX_EIA861B_DUAL_ASPECT_VICS; j++)
1889             {
1890                 if (ceaIndex == EIA861B_DUAL_ASPECT_VICS[j][0])
1891                 {
1892                     NvU32 ceaIndex1 = EIA861B_DUAL_ASPECT_VICS[j][1];
1893 
1894                     NvU32 format1 = axb_div_c(aspect_x, nvt_aspect_y(EIA861B[ceaIndex - 1].etc.aspect), aspect_y);
1895                     NvU32 format2 = axb_div_c(aspect_x, nvt_aspect_y(EIA861B[ceaIndex1 - 1].etc.aspect), aspect_y);
1896 
1897                     NvU32 format_1_diff = abs_delta(format1, nvt_aspect_x(EIA861B[ceaIndex - 1].etc.aspect));
1898                     NvU32 format_2_diff = abs_delta(format2, nvt_aspect_x(EIA861B[ceaIndex1 - 1].etc.aspect));
1899 
1900                     if (format_2_diff < format_1_diff)
1901                     {
1902                         ceaIndex = ceaIndex1;
1903                     }
1904                     break;
1905                 }
1906                 else if (ceaIndex < EIA861B_DUAL_ASPECT_VICS[j][0]) // not a dual-dspect ratio timing
1907                 {
1908                     break;
1909                 }
1910             }
1911             break;
1912         }
1913     }
1914     return ceaIndex;
1915 }
1916 
1917 // calculate 861B based timing
1918 CODE_SEGMENT(PAGE_DD_CODE)
1919 NVT_STATUS NvTiming_CalcCEA861bTiming(NvU32 width, NvU32 height, NvU32 rr, NvU32 flag, NvU32 pixelRepeatCount, NVT_TIMING *pT)
1920 
1921 {
1922     NvU32 i = 0;
1923     NvU16 pixelRepeatMask = 1 << (pixelRepeatCount - 1);
1924 
1925     nvt_assert(pixelRepeatCount > 0 && pixelRepeatCount <= 10);
1926 
1927     if (pT == NULL)
1928     {
1929         return NVT_STATUS_ERR;
1930     }
1931 
1932     // loop through the table
1933     for (i = 0; i < MAX_CEA861B_FORMAT; i ++)
1934     {
1935         if ((EIA861B[i].etc.rep & pixelRepeatMask) == 0)
1936         {
1937             continue;
1938         }
1939 
1940         if (width == (NvU32)NvTiming_MaxFrameWidth(EIA861B[i].HVisible, pixelRepeatMask) &&
1941             height == frame_height(EIA861B[i])&&
1942             rr == EIA861B[i].etc.rr &&
1943             (!!(flag & NVT_PVT_INTERLACED_MASK)) == (!!EIA861B[i].interlaced))
1944         {
1945             *pT = EIA861B[i];
1946 
1947             // calculate the pixel clock
1948             pT->pclk  = RRx1kToPclk (pT);
1949 
1950             NVT_SET_CEA_FORMAT(pT->etc.status, NVT_GET_TIMING_STATUS_SEQ(pT->etc.status));
1951 
1952             NVT_SNPRINTF((char *)pT->etc.name, sizeof(pT->etc.name), "CTA-861G:#%3d:%dx%dx%3d.%03dHz/%s", (int)NVT_GET_TIMING_STATUS_SEQ(pT->etc.status), (int)pT->HVisible, (int)((pT->interlaced ? 2 : 1)*pT->VVisible), (int)pT->etc.rrx1k/1000, (int)pT->etc.rrx1k%1000, (pT->interlaced ? "I":"P"));
1953             pT->etc.name[sizeof(pT->etc.name) - 1] = '\0';
1954 
1955             return NVT_STATUS_SUCCESS;
1956         }
1957     }
1958 
1959     return NVT_STATUS_ERR;
1960 
1961 }
1962 
1963 // Assign fields in NVT_VIDEO_INFOFRAME_CTRL, using NVT_TIMING
1964 CODE_SEGMENT(PAGE_DD_CODE)
1965 NVT_STATUS NvTiming_ConstructVideoInfoframeCtrl(const NVT_TIMING *pTiming, NVT_VIDEO_INFOFRAME_CTRL *pCtrl)
1966 {
1967     // setup VIC code it is not specified
1968     if (pCtrl->video_format_id == NVT_INFOFRAME_CTRL_DONTCARE ||
1969         pCtrl->video_format_id == 0                           ||
1970         pCtrl->video_format_id >  NVT_CEA861_1920X1080P_29970HZ_16X9)
1971     {
1972         // setup video format ID
1973         pCtrl->video_format_id = (NvU8)NVT_GET_CEA_FORMAT(pTiming->etc.status);
1974         if (pCtrl->video_format_id < NVT_CEA861_640X480P_59940HZ_4X3 ||
1975             pCtrl->video_format_id > NVT_CTA861_4096x2160p_119880HZ_256X135)
1976         {
1977             // Prior RFE 543088
1978             if (pCtrl->video_format_id == 0 &&
1979                 NVT_GET_TIMING_STATUS_TYPE(pTiming->etc.status) == NVT_TYPE_EDID_861ST)
1980             {
1981                 pCtrl->video_format_id = (NvU8)NVT_GET_TIMING_STATUS_SEQ(pTiming->etc.status);
1982             }
1983             if (pCtrl->video_format_id == 0 &&
1984                 pTiming->HVisible == 640 &&
1985                 pTiming->VVisible == 480 &&
1986                 pTiming->interlaced == 0 &&
1987                 pTiming->etc.rr == 60)
1988             {
1989                 pCtrl->video_format_id = NVT_CEA861_640X480P_59940HZ_4X3;
1990             }
1991         }
1992     }
1993 
1994     // for HDMI_EXT timing, AVI VIC should be 0.
1995     if (NVT_GET_TIMING_STATUS_TYPE(pTiming->etc.status) == NVT_TYPE_HDMI_EXT)
1996     {
1997         pCtrl->video_format_id = 0;
1998     }
1999 
2000     // setup aspect ratio it is not specified
2001     if (pCtrl->pic_aspect_ratio == NVT_INFOFRAME_CTRL_DONTCARE            ||
2002         pCtrl->pic_aspect_ratio == NVT_VIDEO_INFOFRAME_BYTE2_M1M0_NO_DATA ||
2003         pCtrl->pic_aspect_ratio >  NVT_VIDEO_INFOFRAME_BYTE2_M1M0_FUTURE)
2004     {
2005         // extract the screen measurements from the DTD aspect ratio.
2006         // (we pack the height & width in a DWORD to form the aspect ratio)
2007 
2008         NvU32 x,y;
2009         x = (pTiming->etc.aspect         & 0x0fff);
2010         y = ((pTiming->etc.aspect >> 16) & 0x0fff);
2011 
2012         if (axb_div_c(y,3,x) == 4)
2013         {
2014             pCtrl->pic_aspect_ratio = NVT_VIDEO_INFOFRAME_BYTE2_M1M0_4X3;
2015         }
2016         else if (axb_div_c(y,9,x) == 16)
2017         {
2018             pCtrl->pic_aspect_ratio = NVT_VIDEO_INFOFRAME_BYTE2_M1M0_16X9;
2019         }
2020         else if (pCtrl->video_format_id == NVT_CEA861_640X480P_59940HZ_4X3)
2021         {
2022             pCtrl->pic_aspect_ratio = NVT_VIDEO_INFOFRAME_BYTE2_M1M0_4X3;
2023         }
2024         else
2025         {
2026             // default to no data, to cover other non-cea modes
2027             pCtrl->pic_aspect_ratio = NVT_VIDEO_INFOFRAME_BYTE2_M1M0_NO_DATA;
2028         }
2029     }
2030 
2031     if (pCtrl->it_content == NVT_INFOFRAME_CTRL_DONTCARE)
2032     {
2033         // Initialize ITC flag to NVT_VIDEO_INFOFRAME_BYTE3_ITC_IT_CONTENT
2034         pCtrl->it_content = NVT_VIDEO_INFOFRAME_BYTE3_ITC_IT_CONTENT;
2035         pCtrl->it_content_type = NVT_VIDEO_INFOFRAME_BYTE5_CN1CN0_GRAPHICS;
2036     }
2037 
2038     if (pCtrl->pixel_repeat == NVT_INFOFRAME_CTRL_DONTCARE)
2039     {
2040         // Initialize pixel repetitions
2041         NvU32 pixelRepeat = pTiming->etc.rep;
2042         LOWESTBITIDX_32(pixelRepeat);
2043         pCtrl->pixel_repeat = (NvU8)pixelRepeat;
2044     }
2045 
2046     return NVT_STATUS_SUCCESS;
2047 }
2048 
2049 
2050 // construct AVI video infoframe based on the user control and the current context state
2051 CODE_SEGMENT(PAGE_DD_CODE)
2052 NVT_STATUS NvTiming_ConstructVideoInfoframe(NVT_EDID_INFO *pEdidInfo, NVT_VIDEO_INFOFRAME_CTRL *pCtrl, NVT_VIDEO_INFOFRAME *pContext, NVT_VIDEO_INFOFRAME *pInfoFrame)
2053 {
2054     // parameter check
2055     if (pEdidInfo == NULL || pInfoFrame == NULL)
2056     {
2057         return NVT_STATUS_ERR;
2058     }
2059 
2060     // infoframe is only supported on 861A and later
2061     if (pEdidInfo->ext861.revision < NVT_CEA861_REV_A)
2062     {
2063         return NVT_STATUS_ERR;
2064     }
2065 
2066     // if context state is provided, use it to initialize the infoframe buffer
2067     if (pContext != NULL)
2068     {
2069         *pInfoFrame = *pContext;
2070     }
2071     else
2072     {
2073         *pInfoFrame = DEFAULT_VIDEO_INFOFRAME;
2074     }
2075 
2076     // init the header
2077     pInfoFrame->type = NVT_INFOFRAME_TYPE_VIDEO;
2078 
2079     // TODO : This is just to check the version, we still need to change lots of structure
2080     //        "NVT_VIDEO_INFOFRAME" / "VIDEO_INFOFRAME" / "DEFAULT_VIDEO_INFOFRAME" / "NVM_DISP_STATE" etc..
2081     //        to accept the new ACE0-3 bits supported in the future. Right now no any sink to support this.
2082     //
2083     // Based on the latest CTA-861-H.pdf file, we need to do following logic to get the correct CTA861 version
2084     // When Y=7, the IDO defines the C, EC and ACE fields, it shall use AVI InfoFrame Version 4.
2085     // When Y < 7, the following algorithm shall be used for AVI InfoFrame version selection:
2086     // if (C=3 and EC=7)
2087     //     Sources shall use AVI InfoFrame Version 4.
2088     // Else if (VIC>=128)
2089     //     Sources shall use AVI InfoFrame Version 3.
2090     // Else
2091     //     Sources shall use AVI InfoFrame Version 2.
2092     // End if
2093     //
2094     if (pCtrl)
2095     {
2096         if (nvt_get_bits(pInfoFrame->byte1, NVT_VIDEO_INFOFRAME_BYTE1_Y2Y1Y0_MASK, NVT_VIDEO_INFOFRAME_BYTE1_Y2Y1Y0_SHIFT) == NVT_VIDEO_INFOFRAME_BYTE1_Y2Y1Y0_IDODEFINED)
2097         {
2098             pInfoFrame->version = NVT_VIDEO_INFOFRAME_VERSION_4;
2099         }
2100         else if (nvt_get_bits(pInfoFrame->byte1, NVT_VIDEO_INFOFRAME_BYTE1_Y2Y1Y0_MASK, NVT_VIDEO_INFOFRAME_BYTE1_Y2Y1Y0_SHIFT) < NVT_VIDEO_INFOFRAME_BYTE1_Y2Y1Y0_IDODEFINED)
2101         {
2102             if ((nvt_get_bits(pInfoFrame->byte2, NVT_VIDEO_INFOFRAME_BYTE2_C1C0_MASK, NVT_VIDEO_INFOFRAME_BYTE2_C1C0_SHIFT) == NVT_VIDEO_INFOFRAME_BYTE2_C1C0_EXT_COLORIMETRY) &&
2103                 //EC2-0 is based on the 7.5.5 at CTA861-G which DCI-P3 bit defined or notat byte4
2104                 (nvt_get_bits(pInfoFrame->byte3, NVT_VIDEO_INFOFRAME_BYTE3_EC_MASK, NVT_VIDEO_INFOFRAME_BYTE3_EC_SHIFT)     == NVT_VIDEO_INFOFRAME_BYTE3_EC_AdditionalColorExt))
2105             {
2106                  pInfoFrame->version = NVT_VIDEO_INFOFRAME_VERSION_4; // just put the logic to get the correct version 4, but it shall not be used at currently stage.
2107             }
2108             else
2109             {
2110                 pInfoFrame->version = (((pCtrl->video_format_id & NVT_VIDEO_INFOFRAME_BYTE4_VIC7) == NVT_VIDEO_INFOFRAME_BYTE4_VIC7) ? NVT_VIDEO_INFOFRAME_VERSION_3 :
2111                                        ((pEdidInfo->ext861.revision >= NVT_CEA861_REV_B) ? NVT_VIDEO_INFOFRAME_VERSION_2 : NVT_VIDEO_INFOFRAME_VERSION_1));
2112             }
2113         }
2114     }
2115     else
2116     {
2117         pInfoFrame->version = (pEdidInfo->ext861.revision >= NVT_CEA861_REV_B) ? NVT_VIDEO_INFOFRAME_VERSION_2 : NVT_VIDEO_INFOFRAME_VERSION_1;
2118     }
2119     pInfoFrame->length = sizeof(NVT_VIDEO_INFOFRAME) - sizeof(NVT_INFOFRAME_HEADER);
2120 
2121     if (pInfoFrame->version < NVT_VIDEO_INFOFRAME_VERSION_3)
2122     {
2123         nvt_nvu8_set_bits(pInfoFrame->byte1, 0, NVT_VIDEO_INFOFRAME_BYTE1_RESERVED_MASK, NVT_VIDEO_INFOFRAME_BYTE1_RESERVED_SHIFT);
2124     }
2125 
2126     if (pInfoFrame->version == NVT_VIDEO_INFOFRAME_VERSION_2)
2127     {
2128         nvt_nvu8_set_bits(pInfoFrame->byte4, 0, NVT_VIDEO_INFOFRAME_BYTE4_RESERVED_V2_MASK, NVT_VIDEO_INFOFRAME_BYTE4_RESERVED_V2_SHIFT);
2129     }
2130     else if (pInfoFrame->version == NVT_VIDEO_INFOFRAME_VERSION_1)
2131     {
2132         nvt_nvu8_set_bits(pInfoFrame->byte3, 0, NVT_VIDEO_INFOFRAME_BYTE3_RESERVED_V1_MASK, NVT_VIDEO_INFOFRAME_BYTE3_RESERVED_V1_SHIFT);
2133         nvt_nvu8_set_bits(pInfoFrame->byte4, 0, NVT_VIDEO_INFOFRAME_BYTE4_RESERVED_V1_MASK, NVT_VIDEO_INFOFRAME_BYTE4_RESERVED_V1_SHIFT);
2134         nvt_nvu8_set_bits(pInfoFrame->byte5, 0, NVT_VIDEO_INFOFRAME_BYTE5_RESERVED_V1_MASK, NVT_VIDEO_INFOFRAME_BYTE5_RESERVED_V1_SHIFT);
2135     }
2136 
2137     // construct the desired infoframe contents based on the control
2138     if (pCtrl)
2139     {
2140         // byte 1
2141         if (pCtrl->color_space != NVT_INFOFRAME_CTRL_DONTCARE)
2142         {
2143             nvt_nvu8_set_bits(pInfoFrame->byte1, pCtrl->color_space, NVT_VIDEO_INFOFRAME_BYTE1_Y2Y1Y0_MASK, NVT_VIDEO_INFOFRAME_BYTE1_Y2Y1Y0_SHIFT);
2144         }
2145 
2146         if (pCtrl->active_format_info_present != NVT_INFOFRAME_CTRL_DONTCARE)
2147         {
2148             nvt_nvu8_set_bits(pInfoFrame->byte1, pCtrl->active_format_info_present, NVT_VIDEO_INFOFRAME_BYTE1_A0_MASK, NVT_VIDEO_INFOFRAME_BYTE1_A0_SHIFT);
2149         }
2150 
2151         if (pCtrl->bar_info != NVT_INFOFRAME_CTRL_DONTCARE)
2152         {
2153             nvt_nvu8_set_bits(pInfoFrame->byte1, pCtrl->bar_info, NVT_VIDEO_INFOFRAME_BYTE1_B1B0_MASK, NVT_VIDEO_INFOFRAME_BYTE1_B1B0_SHIFT);
2154         }
2155 
2156         if (pCtrl->scan_info != NVT_INFOFRAME_CTRL_DONTCARE)
2157         {
2158             nvt_nvu8_set_bits(pInfoFrame->byte1, pCtrl->scan_info, NVT_VIDEO_INFOFRAME_BYTE1_S1S0_MASK, NVT_VIDEO_INFOFRAME_BYTE1_S1S0_SHIFT);
2159         }
2160 
2161         // byte 2
2162         if (pCtrl->colorimetry != NVT_INFOFRAME_CTRL_DONTCARE)
2163         {
2164             nvt_nvu8_set_bits(pInfoFrame->byte2, pCtrl->colorimetry, NVT_VIDEO_INFOFRAME_BYTE2_C1C0_MASK, NVT_VIDEO_INFOFRAME_BYTE2_C1C0_SHIFT);
2165         }
2166 
2167         if (pCtrl->pic_aspect_ratio != NVT_INFOFRAME_CTRL_DONTCARE)
2168         {
2169             nvt_nvu8_set_bits(pInfoFrame->byte2, pCtrl->pic_aspect_ratio, NVT_VIDEO_INFOFRAME_BYTE2_M1M0_MASK, NVT_VIDEO_INFOFRAME_BYTE2_M1M0_SHIFT);
2170         }
2171 
2172         if (pCtrl->active_format_aspect_ratio != NVT_INFOFRAME_CTRL_DONTCARE)
2173         {
2174             nvt_nvu8_set_bits(pInfoFrame->byte2, pCtrl->active_format_aspect_ratio, NVT_VIDEO_INFOFRAME_BYTE2_R3R2R1R0_MASK, NVT_VIDEO_INFOFRAME_BYTE2_R3R2R1R0_SHIFT);
2175         }
2176 
2177         // byte 3
2178         if (pCtrl->it_content != NVT_INFOFRAME_CTRL_DONTCARE)
2179         {
2180             nvt_nvu8_set_bits(pInfoFrame->byte3, pCtrl->it_content, NVT_VIDEO_INFOFRAME_BYTE3_ITC_MASK, NVT_VIDEO_INFOFRAME_BYTE3_ITC_SHIFT);
2181         }
2182 
2183         if (pCtrl->extended_colorimetry != NVT_INFOFRAME_CTRL_DONTCARE)
2184         {
2185             nvt_nvu8_set_bits(pInfoFrame->byte3, pCtrl->extended_colorimetry, NVT_VIDEO_INFOFRAME_BYTE3_EC_MASK, NVT_VIDEO_INFOFRAME_BYTE3_EC_SHIFT);
2186         }
2187 
2188         if (pCtrl->rgb_quantization_range != NVT_INFOFRAME_CTRL_DONTCARE)
2189         {
2190             nvt_nvu8_set_bits(pInfoFrame->byte3, pCtrl->rgb_quantization_range, NVT_VIDEO_INFOFRAME_BYTE3_Q1Q0_MASK, NVT_VIDEO_INFOFRAME_BYTE3_Q1Q0_SHIFT);
2191         }
2192 
2193         if (pCtrl->nonuniform_scaling != NVT_INFOFRAME_CTRL_DONTCARE)
2194         {
2195             nvt_nvu8_set_bits(pInfoFrame->byte3, pCtrl->nonuniform_scaling, NVT_VIDEO_INFOFRAME_BYTE3_SC_MASK, NVT_VIDEO_INFOFRAME_BYTE3_SC_SHIFT);
2196         }
2197 
2198         // byte 4 and byte 5 only supported on InfoFrame 2.0
2199         if (pInfoFrame->version >= NVT_VIDEO_INFOFRAME_VERSION_2)
2200         {
2201             // byte 4
2202             if (pCtrl->video_format_id != NVT_INFOFRAME_CTRL_DONTCARE)
2203             {
2204                 nvt_nvu8_set_bits(pInfoFrame->byte4, pCtrl->video_format_id, NVT_VIDEO_INFOFRAME_BYTE4_VIC_MASK, NVT_VIDEO_INFOFRAME_BYTE4_VIC_SHIFT);
2205             }
2206 
2207             // byte 5
2208             if (pCtrl->pixel_repeat != NVT_INFOFRAME_CTRL_DONTCARE)
2209             {
2210                 nvt_nvu8_set_bits(pInfoFrame->byte5, pCtrl->pixel_repeat, NVT_VIDEO_INFOFRAME_BYTE5_PR_MASK, NVT_VIDEO_INFOFRAME_BYTE5_PR_SHIFT);
2211             }
2212 
2213             // byte5
2214             if (pCtrl->it_content_type != NVT_INFOFRAME_CTRL_DONTCARE)
2215             {
2216                 nvt_nvu8_set_bits(pInfoFrame->byte5, pCtrl->it_content_type, NVT_VIDEO_INFOFRAME_BYTE5_CN1CN0_MASK, NVT_VIDEO_INFOFRAME_BYTE5_CN1CN0_SHIFT);
2217             }
2218         }
2219 
2220         // byte 6~13, bar info
2221         if (pCtrl->top_bar != 0xFFFF)
2222         {
2223             pInfoFrame->top_bar_low  = (NvU8)(pCtrl->top_bar % 0x100);
2224             pInfoFrame->top_bar_high = (NvU8)(pCtrl->top_bar / 0x100);
2225         }
2226         if (pCtrl->bottom_bar != 0xFFFF)
2227         {
2228             pInfoFrame->bottom_bar_low  = (NvU8)(pCtrl->bottom_bar % 0x100);
2229             pInfoFrame->bottom_bar_high = (NvU8)(pCtrl->bottom_bar / 0x100);
2230         }
2231         if (pCtrl->left_bar != 0xFFFF)
2232         {
2233             pInfoFrame->left_bar_low  = (NvU8)(pCtrl->left_bar % 0x100);
2234             pInfoFrame->left_bar_high = (NvU8)(pCtrl->left_bar / 0x100);
2235         }
2236         if (pCtrl->right_bar != 0xFFFF)
2237         {
2238             pInfoFrame->right_bar_low  = (NvU8)(pCtrl->right_bar % 0x100);
2239             pInfoFrame->right_bar_high = (NvU8)(pCtrl->right_bar / 0x100);
2240         }
2241     }
2242 
2243     return NVT_STATUS_SUCCESS;
2244 }
2245 
2246 // construct AVI audio infoframe based on the user control and the current context state
2247 CODE_SEGMENT(PAGE_DD_CODE)
2248 NVT_STATUS NvTiming_ConstructAudioInfoframe(NVT_AUDIO_INFOFRAME_CTRL *pUserCtrl, NVT_AUDIO_INFOFRAME *pContext, NVT_AUDIO_INFOFRAME *pInfoFrame)
2249 {
2250     NVT_AUDIO_INFOFRAME_CTRL ctrl;
2251 
2252     // parameter check
2253     if (pInfoFrame == NULL)
2254     {
2255         return NVT_STATUS_ERR;
2256     }
2257 
2258     // use the user provided control if possible
2259     if (pUserCtrl)
2260     {
2261         ctrl = *pUserCtrl;
2262     }
2263     else
2264     {
2265         // otherwise use the default control
2266         NVMISC_MEMSET(&ctrl, NVT_INFOFRAME_CTRL_DONTCARE, sizeof(ctrl));
2267     }
2268 
2269     // if context state is provided, use it to initialize the infoframe buffer
2270     if (pContext != NULL)
2271     {
2272         *pInfoFrame = *pContext;
2273     }
2274     else
2275     {
2276         *pInfoFrame = DEFAULT_AUDIO_INFOFRAME;
2277 
2278         // if the context state is not provide, we should user EDID info to build a default ctrl
2279         //buildDefaultAudioInfoframeCtrl(pEdidInfo, &ctrl);
2280     }
2281 
2282     // init the header
2283     pInfoFrame->type = NVT_INFOFRAME_TYPE_AUDIO;
2284     pInfoFrame->version = NVT_VIDEO_INFOFRAME_VERSION_1;
2285     pInfoFrame->length = sizeof(NVT_AUDIO_INFOFRAME) - sizeof(NVT_INFOFRAME_HEADER);
2286 
2287     // init the reserved fields
2288     nvt_nvu8_set_bits(pInfoFrame->byte1, 0, NVT_AUDIO_INFOFRAME_BYTE1_RESERVED_MASK, NVT_AUDIO_INFOFRAME_BYTE1_RESERVED_SHIFT);
2289     nvt_nvu8_set_bits(pInfoFrame->byte2, 0, NVT_AUDIO_INFOFRAME_BYTE2_RESERVED_MASK, NVT_AUDIO_INFOFRAME_BYTE2_RESERVED_SHIFT);
2290     nvt_nvu8_set_bits(pInfoFrame->byte5, 0, NVT_AUDIO_INFOFRAME_BYTE5_RESERVED_MASK, NVT_AUDIO_INFOFRAME_BYTE5_RESERVED_SHIFT);
2291     pInfoFrame->rsvd_byte6  = 0;
2292     pInfoFrame->rsvd_byte7  = 0;
2293     pInfoFrame->rsvd_byte8  = 0;
2294     pInfoFrame->rsvd_byte9  = 0;
2295     pInfoFrame->rsvd_byte10 = 0;
2296 
2297     // byte 1
2298     if (ctrl.channel_count != NVT_INFOFRAME_CTRL_DONTCARE)
2299     {
2300         nvt_nvu8_set_bits(pInfoFrame->byte1, ctrl.channel_count, NVT_AUDIO_INFOFRAME_BYTE1_CC_MASK, NVT_AUDIO_INFOFRAME_BYTE1_CC_SHIFT);
2301     }
2302 
2303     if (ctrl.coding_type != NVT_INFOFRAME_CTRL_DONTCARE)
2304     {
2305         nvt_nvu8_set_bits(pInfoFrame->byte1, ctrl.coding_type, NVT_AUDIO_INFOFRAME_BYTE1_CT_MASK, NVT_AUDIO_INFOFRAME_BYTE1_CT_SHIFT);
2306     }
2307 
2308     // byte 2
2309     if (ctrl.sample_depth != NVT_INFOFRAME_CTRL_DONTCARE)
2310     {
2311         nvt_nvu8_set_bits(pInfoFrame->byte2, ctrl.sample_depth, NVT_AUDIO_INFOFRAME_BYTE2_SS_MASK, NVT_AUDIO_INFOFRAME_BYTE2_SS_SHIFT);
2312     }
2313 
2314     if (ctrl.sample_rate != NVT_INFOFRAME_CTRL_DONTCARE)
2315     {
2316         nvt_nvu8_set_bits(pInfoFrame->byte2, ctrl.sample_rate, NVT_AUDIO_INFOFRAME_BYTE2_SF_MASK, NVT_AUDIO_INFOFRAME_BYTE2_SF_SHIFT);
2317     }
2318 
2319     // byte 3
2320     pInfoFrame->byte3 = 0;
2321 
2322     // byte 4
2323     if (ctrl.speaker_placement != NVT_INFOFRAME_CTRL_DONTCARE)
2324     {
2325         nvt_nvu8_set_bits(pInfoFrame->byte4, ctrl.speaker_placement, NVT_AUDIO_INFOFRAME_BYTE4_CA_MASK, NVT_AUDIO_INFOFRAME_BYTE4_CA_SHIFT);
2326     }
2327 
2328     // byte 5
2329     if (ctrl.level_shift != NVT_INFOFRAME_CTRL_DONTCARE)
2330     {
2331         nvt_nvu8_set_bits(pInfoFrame->byte5, ctrl.level_shift, NVT_AUDIO_INFOFRAME_BYTE5_LSV_MASK, NVT_AUDIO_INFOFRAME_BYTE5_LSV_SHIFT);
2332     }
2333 
2334     if (ctrl.down_mix_inhibit != NVT_INFOFRAME_CTRL_DONTCARE)
2335     {
2336         nvt_nvu8_set_bits(pInfoFrame->byte5, ctrl.down_mix_inhibit, NVT_AUDIO_INFOFRAME_BYTE5_DM_INH_MASK, NVT_AUDIO_INFOFRAME_BYTE5_DM_INH_SHIFT);
2337     }
2338 
2339 
2340     return NVT_STATUS_SUCCESS;
2341 
2342 }
2343 
2344 // Construct Vendor Specific Infoframe
2345 CODE_SEGMENT(PAGE_DD_CODE)
2346 NVT_STATUS NvTiming_ConstructVendorSpecificInfoframe(NVT_EDID_INFO *pEdidInfo, NVT_VENDOR_SPECIFIC_INFOFRAME_CTRL *pCtrl, NVT_VENDOR_SPECIFIC_INFOFRAME *pInfoFrame)
2347 {
2348     NVT_STATUS RetCode = NVT_STATUS_SUCCESS;
2349     NvU8  optIdx  = 0;
2350     NvU8  HDMIFormat;
2351 
2352     // parameter check
2353     if (pEdidInfo == NULL || pInfoFrame == NULL || pCtrl == NULL)
2354     {
2355         return NVT_STATUS_INVALID_PARAMETER;
2356     }
2357 
2358     // infoframe is only supported on 861A and later
2359     if (pEdidInfo->ext861.revision < NVT_CEA861_REV_A)
2360     {
2361         return NVT_STATUS_ERR;
2362     }
2363 
2364 
2365     // initialize the infoframe buffer
2366     nvt_nvu8_set_bits(pInfoFrame->Header.type, NVT_HDMI_VS_HB0_VALUE, NVT_HDMI_VS_HB0_MASK, NVT_HDMI_VS_HB0_SHIFT);
2367     nvt_nvu8_set_bits(pInfoFrame->Header.version, NVT_HDMI_VS_HB1_VALUE, NVT_HDMI_VS_HB1_MASK, NVT_HDMI_VS_HB1_SHIFT);
2368     nvt_nvu8_set_bits(pInfoFrame->Header.length, NVT_HDMI_VS_HB2_VALUE, NVT_HDMI_VS_HB2_MASK, NVT_HDMI_VS_HB2_SHIFT);
2369 
2370     if (pCtrl->HDMIRevision == 14)
2371     {
2372         nvt_nvu8_set_bits(pInfoFrame->Data.byte1, NVT_HDMI_VS_BYTE1_OUI_VER_1_4, NVT_HDMI_VS_BYTE1_OUI_MASK, NVT_HDMI_VS_BYTE1_OUI_SHIFT);
2373         nvt_nvu8_set_bits(pInfoFrame->Data.byte2, NVT_HDMI_VS_BYTE2_OUI_VER_1_4, NVT_HDMI_VS_BYTE2_OUI_MASK, NVT_HDMI_VS_BYTE2_OUI_SHIFT);
2374         nvt_nvu8_set_bits(pInfoFrame->Data.byte3, NVT_HDMI_VS_BYTE3_OUI_VER_1_4, NVT_HDMI_VS_BYTE3_OUI_MASK, NVT_HDMI_VS_BYTE3_OUI_SHIFT);
2375     }
2376     else if (pCtrl->HDMIRevision >= 20)
2377     {
2378         nvt_nvu8_set_bits(pInfoFrame->Data.byte1, NVT_HDMI_VS_BYTE1_OUI_VER_2_0, NVT_HDMI_VS_BYTE1_OUI_MASK, NVT_HDMI_VS_BYTE1_OUI_SHIFT);
2379         nvt_nvu8_set_bits(pInfoFrame->Data.byte2, NVT_HDMI_VS_BYTE2_OUI_VER_2_0, NVT_HDMI_VS_BYTE2_OUI_MASK, NVT_HDMI_VS_BYTE2_OUI_SHIFT);
2380         nvt_nvu8_set_bits(pInfoFrame->Data.byte3, NVT_HDMI_VS_BYTE3_OUI_VER_2_0, NVT_HDMI_VS_BYTE3_OUI_MASK, NVT_HDMI_VS_BYTE3_OUI_SHIFT);
2381     }
2382 
2383     // init the header (mostly done in default Infoframe)
2384     pInfoFrame->Header.length   = offsetof(NVT_VENDOR_SPECIFIC_INFOFRAME_PAYLOAD, optionalBytes);
2385 
2386     // construct the desired infoframe contents based on the control
2387 
2388     // clear all static reserved fields
2389     nvt_nvu8_set_bits(pInfoFrame->Data.byte4, 0, NVT_HDMI_VS_BYTE4_RSVD_MASK, NVT_HDMI_VS_BYTE4_RSVD_SHIFT);
2390 
2391     // setup the parameters
2392     nvt_nvu8_set_bits(pInfoFrame->Data.byte4, pCtrl->HDMIFormat, NVT_HDMI_VS_BYTE4_HDMI_VID_FMT_MASK, NVT_HDMI_VS_BYTE4_HDMI_VID_FMT_SHIFT);
2393 
2394     // determine what the format is -- if disabled, force the format to NONE.
2395     if (pCtrl->Enable)
2396     {
2397         HDMIFormat = pCtrl->HDMIFormat;
2398     }
2399     else
2400     {
2401         HDMIFormat = NVT_HDMI_VS_BYTE4_HDMI_VID_FMT_NONE;
2402     }
2403 
2404     switch(HDMIFormat)
2405     {
2406     case NVT_HDMI_VS_BYTE4_HDMI_VID_FMT_NONE:
2407         {
2408             nvt_nvu8_set_bits(pInfoFrame->Data.byte5, 0, NVT_HDMI_VS_BYTENv_RSVD_MASK, NVT_HDMI_VS_BYTENv_RSVD_SHIFT);
2409             break;
2410         }
2411     case NVT_HDMI_VS_BYTE4_HDMI_VID_FMT_EXT:
2412         {
2413             // Note: extended resolution frames are not yet fully supported
2414             nvt_nvu8_set_bits(pInfoFrame->Data.byte5, pCtrl->HDMI_VIC, NVT_HDMI_VS_BYTE5_HDMI_VIC_MASK, NVT_HDMI_VS_BYTE5_HDMI_VIC_SHIFT);
2415             break;
2416         }
2417     case NVT_HDMI_VS_BYTE4_HDMI_VID_FMT_3D:
2418         {
2419             nvt_nvu8_set_bits(pInfoFrame->Data.byte5, 0, NVT_HDMI_VS_BYTE5_HDMI_RSVD_MASK, NVT_HDMI_VS_BYTE5_HDMI_RSVD_SHIFT);
2420             nvt_nvu8_set_bits(pInfoFrame->Data.byte5, pCtrl->ThreeDStruc, NVT_HDMI_VS_BYTE5_HDMI_3DS_MASK, NVT_HDMI_VS_BYTE5_HDMI_3DS_SHIFT);
2421 
2422             // side by side half requires additional format data in the infoframe.
2423             if (NVT_HDMI_VS_BYTE5_HDMI_3DS_SIDEBYSIDEHALF == pCtrl->ThreeDStruc)
2424             {
2425                 nvt_nvu8_set_bits(pInfoFrame->Data.optionalBytes[optIdx], pCtrl->ThreeDDetail, NVT_HDMI_VS_BYTE_OPT1_HDMI_3DEX_MASK, NVT_HDMI_VS_BYTE_OPT1_HDMI_3DEX_SHIFT);
2426                 optIdx++;
2427             }
2428             if (pCtrl->MetadataPresent)
2429             {
2430                 nvt_nvu8_set_bits(pInfoFrame->Data.byte5, NVT_HDMI_VS_BYTE5_HDMI_META_PRESENT_PRES, NVT_HDMI_VS_BYTE5_3D_META_PRESENT_MASK, NVT_HDMI_VS_BYTE5_3D_META_PRESENT_SHIFT);
2431 
2432                 switch(pCtrl->MetadataType)
2433                 {
2434                 case NVT_HDMI_VS_BYTE_OPT2_HDMI_METADATA_TYPE_PARALLAX:
2435                     {
2436                         if (sizeof(pCtrl->Metadata) >= NVT_HDMI_VS_BYTE_OPT2_HDMI_METADATA_LEN_PARALLAX &&
2437                             sizeof(pInfoFrame->Data.optionalBytes) - (optIdx + 1) >= NVT_HDMI_VS_BYTE_OPT2_HDMI_METADATA_LEN_PARALLAX)
2438                         {
2439                             nvt_nvu8_set_bits(pInfoFrame->Data.optionalBytes[optIdx], NVT_HDMI_VS_BYTE_OPT2_HDMI_METADATA_LEN_PARALLAX, NVT_HDMI_VS_BYTE_OPT2_HDMI_METADATA_LEN_MASK, NVT_HDMI_VS_BYTE_OPT2_HDMI_METADATA_LEN_SHIFT);
2440                             nvt_nvu8_set_bits(pInfoFrame->Data.optionalBytes[optIdx], NVT_HDMI_VS_BYTE_OPT2_HDMI_METADATA_TYPE_PARALLAX, NVT_HDMI_VS_BYTE_OPT2_HDMI_METADATA_TYPE_MASK, NVT_HDMI_VS_BYTE_OPT2_HDMI_METADATA_TYPE_SHIFT);
2441                             ++optIdx;
2442 
2443                             NVMISC_MEMCPY(pCtrl->Metadata, &pInfoFrame->Data.optionalBytes[optIdx], NVT_HDMI_VS_BYTE_OPT2_HDMI_METADATA_LEN_PARALLAX);
2444                             optIdx += NVT_HDMI_VS_BYTE_OPT2_HDMI_METADATA_LEN_PARALLAX;
2445                         }
2446                         else
2447                         {
2448                             // not enough data in the control struct or not enough room in the infoframe -- BOTH compile time issues!!
2449                             // ignore metadata.
2450                             nvt_nvu8_set_bits(pInfoFrame->Data.byte5, NVT_HDMI_VS_BYTE5_HDMI_META_PRESENT_NOTPRES, NVT_HDMI_VS_BYTE5_3D_META_PRESENT_MASK, NVT_HDMI_VS_BYTE5_3D_META_PRESENT_SHIFT);
2451                         }
2452                         break;
2453                     }
2454                 default:
2455                     {
2456                         // unrecognised metadata, recover the best we can.
2457                         // note -- can not copy whatever is there because type implies length.
2458                         nvt_nvu8_set_bits(pInfoFrame->Data.byte5, NVT_HDMI_VS_BYTE5_HDMI_META_PRESENT_NOTPRES, NVT_HDMI_VS_BYTE5_3D_META_PRESENT_MASK, NVT_HDMI_VS_BYTE5_3D_META_PRESENT_SHIFT);
2459                         RetCode = NVT_STATUS_ERR;
2460                     }
2461                 }
2462 
2463             }
2464             else
2465             {
2466                 nvt_nvu8_set_bits(pInfoFrame->Data.byte5, NVT_HDMI_VS_BYTE5_HDMI_META_PRESENT_NOTPRES, NVT_HDMI_VS_BYTE5_3D_META_PRESENT_MASK, NVT_HDMI_VS_BYTE5_3D_META_PRESENT_SHIFT);
2467             }
2468             break;
2469         }
2470 
2471     }
2472 
2473     if (pCtrl->ALLMEnable == 1)
2474     {
2475         nvt_nvu8_set_bits(pInfoFrame->Data.byte5, NVT_HDMI_VS_BYTE5_ALLM_MODE_EN, NVT_HDMI_VS_BYTE5_ALLM_MODE_MASK, NVT_HDMI_VS_BYTE5_ALLM_MODE_SHIFT);
2476     }
2477     else if (pCtrl->ALLMEnable == 0)
2478     {
2479         nvt_nvu8_set_bits(pInfoFrame->Data.byte5, NVT_HDMI_VS_BYTE5_ALLM_MODE_DIS, NVT_HDMI_VS_BYTE5_ALLM_MODE_MASK, NVT_HDMI_VS_BYTE5_ALLM_MODE_SHIFT);
2480     }
2481 
2482     // clear last byte of infoframe (reserved per spec).
2483     pInfoFrame->Header.length += optIdx + 1;
2484     for (; optIdx < sizeof(pInfoFrame->Data.optionalBytes); ++optIdx)
2485     {
2486         nvt_nvu8_set_bits(pInfoFrame->Data.optionalBytes[optIdx], NVT_HDMI_VS_BYTENv_RSVD, NVT_HDMI_VS_BYTENv_RSVD_MASK, NVT_HDMI_VS_BYTENv_RSVD_SHIFT);
2487     }
2488 
2489     return RetCode;
2490 }
2491 
2492 // Construct Extended Metadata Packet Infoframe
2493 CODE_SEGMENT(PAGE_DD_CODE)
2494 NVT_STATUS NvTiming_ConstructExtendedMetadataPacketInfoframe(
2495     NVT_EXTENDED_METADATA_PACKET_INFOFRAME_CTRL *pCtrl,
2496     NVT_EXTENDED_METADATA_PACKET_INFOFRAME *pInfoFrame)
2497 {
2498     NVT_STATUS RetCode = NVT_STATUS_SUCCESS;
2499     if (!pCtrl || !pInfoFrame)
2500     {
2501         return NVT_STATUS_INVALID_PARAMETER;
2502     }
2503 
2504     // Initialize the infoframe
2505     NVMISC_MEMSET(pInfoFrame, 0, sizeof(*pInfoFrame));
2506 
2507     // Construct an infoframe to enable or disable HDMI 2.1 VRR
2508     pInfoFrame->Header.type = NVT_INFOFRAME_TYPE_EXTENDED_METADATA_PACKET;
2509     pInfoFrame->Header.firstLast = NVT_EMP_HEADER_FIRST_LAST;
2510     pInfoFrame->Header.sequenceIndex = 0x00;
2511 
2512     if (pCtrl->EnableQMS)
2513     {
2514         nvt_nvu8_set_bits(pInfoFrame->Data.byte1, NVT_HDMI_EMP_BYTE1_SYNC_ENABLE,
2515                                                   NVT_HDMI_EMP_BYTE1_SYNC_MASK,
2516                                                   NVT_HDMI_EMP_BYTE1_SYNC_SHIFT);
2517     }
2518 
2519     nvt_nvu8_set_bits(pInfoFrame->Data.byte1, NVT_HDMI_EMP_BYTE1_VFR_ENABLE,
2520                                               NVT_HDMI_EMP_BYTE1_VFR_MASK,
2521                                               NVT_HDMI_EMP_BYTE1_VFR_SHIFT);
2522 
2523     nvt_nvu8_set_bits(pInfoFrame->Data.byte1, NVT_HDMI_EMP_BYTE1_NEW_ENABLE,
2524                                               NVT_HDMI_EMP_BYTE1_NEW_MASK,
2525                                               NVT_HDMI_EMP_BYTE1_NEW_SHIFT);
2526 
2527     if (!pCtrl->EnableVRR && !pCtrl->EnableQMS)
2528     {
2529         nvt_nvu8_set_bits(pInfoFrame->Data.byte1, NVT_HDMI_EMP_BYTE1_END_ENABLE,
2530                                                   NVT_HDMI_EMP_BYTE1_END_MASK,
2531                                                   NVT_HDMI_EMP_BYTE1_END_SHIFT);
2532     }
2533 
2534     nvt_nvu8_set_bits(pInfoFrame->Data.byte3,
2535                       NVT_HDMI_EMP_BYTE3_ORGANIZATION_ID_SPEC_DEFINED,
2536                       NVT_HDMI_EMP_BYTE3_ORGANIZATION_ID_MASK,
2537                       NVT_HDMI_EMP_BYTE3_ORGANIZATION_ID_SHIFT);
2538 
2539     nvt_nvu8_set_bits(pInfoFrame->Data.byte5, 1,
2540                       NVT_HDMI_EMP_BYTE5_DATA_SET_TAG_LSB_MASK,
2541                       NVT_HDMI_EMP_BYTE5_DATA_SET_TAG_LSB_SHIFT);
2542 
2543     nvt_nvu8_set_bits(pInfoFrame->Data.byte7, ((pCtrl->EnableVRR || pCtrl->EnableQMS) ? 4 : 0),
2544                       NVT_HDMI_EMP_BYTE7_DATA_SET_LENGTH_LSB_MASK,
2545                       NVT_HDMI_EMP_BYTE7_DATA_SET_LENGTH_LSB_SHIFT);
2546 
2547     if (pCtrl->EnableVRR)
2548     {
2549         nvt_nvu8_set_bits(pInfoFrame->Data.metadataBytes[0],
2550                           NVT_HDMI_EMP_BYTE8_MD0_VRR_EN_ENABLE,
2551                           NVT_HDMI_EMP_BYTE8_MD0_VRR_EN_MASK,
2552                           NVT_HDMI_EMP_BYTE8_MD0_VRR_EN_SHIFT);
2553     }
2554     else if (pCtrl->EnableQMS)
2555     {
2556         nvt_nvu8_set_bits(pInfoFrame->Data.metadataBytes[0], 1,
2557                           NVT_HDMI_EMP_BYTE8_MD0_M_CONST_MASK,
2558                           NVT_HDMI_EMP_BYTE8_MD0_M_CONST_SHIFT);
2559         nvt_nvu8_set_bits(pInfoFrame->Data.metadataBytes[0],
2560                           NVT_HDMI_EMP_BYTE8_MD0_QMS_EN_ENABLE,
2561                           NVT_HDMI_EMP_BYTE8_MD0_QMS_EN_MASK,
2562                           NVT_HDMI_EMP_BYTE8_MD0_QMS_EN_SHIFT);
2563     }
2564 
2565     if (pCtrl->ITTiming)
2566     {
2567         nvt_nvu8_set_bits(pInfoFrame->Data.metadataBytes[1],
2568                           pCtrl->BaseVFP,
2569                           NVT_HDMI_EMP_BYTE8_MD1_BASE_VFRONT_MASK,
2570                           NVT_HDMI_EMP_BYTE8_MD1_BASE_VFRONT_SHIFT);
2571 
2572         // In HDMI2.1, MD2 bit 2 is set when RB timing is used.
2573         // In HDMI2.1A, MD2 bit 2 is RSVD as 0
2574         if (pCtrl->version == NVT_EXTENDED_METADATA_PACKET_INFOFRAME_VER_HDMI21)
2575         {
2576             nvt_nvu8_set_bits(pInfoFrame->Data.metadataBytes[2],
2577                               pCtrl->ReducedBlanking,
2578                               NVT_HDMI_EMP_BYTE8_MD2_RB_MASK,
2579                               NVT_HDMI_EMP_BYTE8_MD2_RB_SHIFT);
2580         }
2581 
2582         // MSB for Base Refresh Rate
2583         nvt_nvu8_set_bits(pInfoFrame->Data.metadataBytes[2],
2584                           pCtrl->BaseRefreshRate >> 8,
2585                           NVT_HDMI_EMP_BYTE8_MD2_BASE_RR_MSB_MASK,
2586                           NVT_HDMI_EMP_BYTE8_MD2_BASE_RR_MSB_SHIFT);
2587 
2588         // LSB for Base Refresh Rate
2589         nvt_nvu8_set_bits(pInfoFrame->Data.metadataBytes[3],
2590                           pCtrl->BaseRefreshRate,
2591                           NVT_HDMI_EMP_BYTE8_MD3_BASE_RR_LSB_MASK,
2592                           NVT_HDMI_EMP_BYTE8_MD3_BASE_RR_LSB_SHIFT);
2593     }
2594 
2595     return RetCode;
2596 }
2597 
2598 // Construct Adaptive Sync SDP
2599 CODE_SEGMENT(PAGE_DD_CODE)
2600 void NvTiming_ConstructAdaptiveSyncSDP(
2601     const NVT_ADAPTIVE_SYNC_SDP_CTRL    *pCtrl,
2602     NVT_ADAPTIVE_SYNC_SDP               *pSdp)
2603 {
2604     if (!pCtrl || !pSdp)
2605     {
2606         return;
2607     }
2608 
2609     // Initialize the infoframe
2610     NVMISC_MEMSET(pSdp, 0, sizeof(*pSdp));
2611 
2612     // Construct an infoframe to enable or disable Adaptive Sync SDP
2613     pSdp->header.type = NVT_DP_ADAPTIVE_SYNC_SDP_PACKET_TYPE;
2614     pSdp->header.version = NVT_DP_ADAPTIVE_SYNC_SDP_VERSION;
2615     pSdp->header.length = NVT_DP_ADAPTIVE_SYNC_SDP_LENGTH;
2616 
2617     // Payload
2618     if (pCtrl->bFixedVTotal)
2619     {
2620         nvt_nvu8_set_bits(pSdp->payload.db0, NVT_DP_ADAPTIVE_SYNC_SDP_DB0_VARIABLE_FRAME_RATE_FAVT_TARGET_REACHED,
2621                                     NVT_DP_ADAPTIVE_SYNC_SDP_DB0_VARIABLE_FRAME_RATE_MASK,
2622                                     NVT_DP_ADAPTIVE_SYNC_SDP_DB0_VARIABLE_FRAME_RATE_SHIFT);
2623         if (pCtrl->targetRefreshRate)
2624         {
2625             nvt_nvu8_set_bits(pSdp->payload.db3, pCtrl->targetRefreshRate & 0xff,
2626                                         NVT_DP_ADAPTIVE_SYNC_SDP_DB3_TARGET_RR_LSB_MASK,
2627                                         NVT_DP_ADAPTIVE_SYNC_SDP_DB3_TARGET_RR_LSB_SHIFT);
2628 
2629             nvt_nvu8_set_bits(pSdp->payload.db4, pCtrl->targetRefreshRate & 0x1,
2630                                         NVT_DP_ADAPTIVE_SYNC_SDP_DB4_TARGET_RR_MSB_MASK,
2631                                         NVT_DP_ADAPTIVE_SYNC_SDP_DB4_TARGET_RR_MSB_SHIFT);
2632         }
2633     }
2634     else
2635     {
2636         nvt_nvu8_set_bits(pSdp->payload.db0, NVT_DP_ADAPTIVE_SYNC_SDP_DB0_VARIABLE_FRAME_RATE_AVT_VARIABLE,
2637                                     NVT_DP_ADAPTIVE_SYNC_SDP_DB0_VARIABLE_FRAME_RATE_MASK,
2638                                     NVT_DP_ADAPTIVE_SYNC_SDP_DB0_VARIABLE_FRAME_RATE_SHIFT);
2639     }
2640 
2641     if (pCtrl->minVTotal)
2642     {
2643         nvt_nvu8_set_bits(pSdp->payload.db1, pCtrl->minVTotal & 0xff,
2644                                     NVT_DP_ADAPTIVE_SYNC_SDP_DB1_MIN_VTOTAL_LSB_MASK,
2645                                     NVT_DP_ADAPTIVE_SYNC_SDP_DB1_MIN_VTOTAL_LSB_SHIFT);
2646         nvt_nvu8_set_bits(pSdp->payload.db2, (pCtrl->minVTotal & 0xff00) >> 8,
2647                                     NVT_DP_ADAPTIVE_SYNC_SDP_DB2_MIN_VTOTAL_MSB_MASK,
2648                                     NVT_DP_ADAPTIVE_SYNC_SDP_DB2_MIN_VTOTAL_MSB_SHIFT);
2649     }
2650 
2651     if (pCtrl->bRefreshRateDivider)
2652     {
2653         nvt_nvu8_set_bits(pSdp->payload.db4, NVT_DP_ADAPTIVE_SYNC_SDP_DB4_TARGET_RR_DIVIDER_ENABLE,
2654                                     NVT_DP_ADAPTIVE_SYNC_SDP_DB4_TARGET_RR_DIVIDER_MASK,
2655                                     NVT_DP_ADAPTIVE_SYNC_SDP_DB4_TARGET_RR_DIVIDER_SHIFT);
2656     }
2657 }
2658 
2659 // Enumerate Psf Timing
2660 CODE_SEGMENT(PAGE_DD_CODE)
2661 NVT_STATUS NvTiming_EnumNvPsfTiming(NvU32 nvPsfFormat, NVT_TIMING *pT)
2662 {
2663     if (pT == NULL || nvPsfFormat == 0 || nvPsfFormat > MAX_PSF_FORMAT)
2664     {
2665         return NVT_STATUS_ERR;
2666     }
2667 
2668     *pT = PSF_TIMING[nvPsfFormat - 1];
2669 
2670     // calculate the pixel clock
2671     pT->pclk  = RRx1kToPclk (pT);
2672 
2673     return NVT_STATUS_SUCCESS;
2674 }
2675 
2676 // Set ActiveSpace for HDMI 3D stereo timing
2677 CODE_SEGMENT(PAGE_DD_CODE)
2678 void SetActiveSpaceForHDMI3DStereo(const NVT_TIMING *pTiming, NVT_EXT_TIMING *pExtTiming)
2679 {
2680     // Note -- this assumes that the Timng is the 2D instance.
2681     NvU16 VBlank;
2682 
2683     // assume no active space to start.
2684     pExtTiming->HDMI3D.VActiveSpace[0] = 0;
2685     pExtTiming->HDMI3D.VActiveSpace[1] = 0;
2686 
2687     if (NVT_HDMI_VS_BYTE5_HDMI_3DS_FRAMEPACK == pExtTiming->HDMI3D.StereoStructureType)
2688     {
2689         VBlank = pTiming->VTotal - pTiming->VVisible;
2690         if (pTiming->interlaced)
2691         {
2692             //++++ This need to be revisited, not sure when active space 1 & 2 should be different.
2693             // (fortunately, we are not supporting any interlaced packed frame modes yet).
2694             pExtTiming->HDMI3D.VActiveSpace[0] = VBlank + 1;
2695             pExtTiming->HDMI3D.VActiveSpace[1] = VBlank - 1;
2696         }
2697         else
2698         {
2699             pExtTiming->HDMI3D.VActiveSpace[0] = VBlank;
2700         }
2701     }
2702     return;
2703 }
2704 
2705 // Generate HDMI stereo timing from 2D timing
2706 CODE_SEGMENT(PAGE_DD_CODE)
2707 void NvTiming_GetHDMIStereoTimingFrom2DTiming(const NVT_TIMING *pTiming, NvU8 StereoStructureType, NvU8 SideBySideHalfDetail, NVT_EXT_TIMING *pExtTiming)
2708 {
2709     NvU16 VBlank;
2710     NvU16 HBlank;
2711 
2712     if ((NULL == pTiming) || (NULL == pExtTiming) || (!isHdmi3DStereoType(StereoStructureType)))
2713     {
2714         return;
2715     }
2716     // init the extended timing
2717     NVMISC_MEMSET(pExtTiming, 0, sizeof(NVT_EXT_TIMING));
2718 
2719     // copy the 2D timing to the 3D timing.
2720     pExtTiming->timing = *pTiming;
2721 
2722     // init the extension w/in the 3D timing
2723     pExtTiming->HDMI3D.StereoStructureType  = StereoStructureType;
2724     pExtTiming->HDMI3D.SideBySideHalfDetail = SideBySideHalfDetail;
2725 
2726 
2727     switch(StereoStructureType)
2728     {
2729     case NVT_HDMI_VS_BYTE5_HDMI_3DS_FRAMEPACK:
2730         {
2731             // calculate VBlank
2732             VBlank = pTiming->VTotal - pTiming->VVisible;
2733 
2734             // Use the 2D timing to calculate the Active Space
2735             SetActiveSpaceForHDMI3DStereo(pTiming, pExtTiming);
2736 
2737             // Calculate the 3D VVisible size based on the 2D VVisible and the active space.
2738             if (pTiming->interlaced)
2739             {
2740                 pExtTiming->timing.VVisible = ((pTiming->VVisible * 4) + (pExtTiming->HDMI3D.VActiveSpace[0]) * 2) + pExtTiming->HDMI3D.VActiveSpace[1];
2741             }
2742             else
2743             {
2744                 pExtTiming->timing.VVisible = (pTiming->VVisible * 2) + pExtTiming->HDMI3D.VActiveSpace[0];
2745             }
2746             // Calculate the 3D VTotal from the 3D VVisible & the VBlank.
2747             pExtTiming->timing.VTotal = pExtTiming->timing.VVisible + VBlank;
2748 
2749             pExtTiming->timing.etc.status = NVT_SET_TIMING_STATUS_TYPE(pExtTiming->timing.etc.status, NVT_TYPE_HDMI_STEREO);
2750 
2751             break;
2752         }
2753     case NVT_HDMI_VS_BYTE5_HDMI_3DS_SIDEBYSIDEFULL:
2754         {
2755             // calculate HBlank before calculating new HVisible
2756             HBlank = pTiming->HTotal - pTiming->HVisible;
2757 
2758             pExtTiming->timing.HVisible = pTiming->HVisible * 2;
2759 
2760             pExtTiming->timing.HTotal   = pExtTiming->timing.HVisible + HBlank;
2761 
2762             pExtTiming->timing.etc.status = NVT_SET_TIMING_STATUS_TYPE(pExtTiming->timing.etc.status, NVT_TYPE_HDMI_STEREO);
2763 
2764             break;
2765         }
2766     case NVT_HDMI_VS_BYTE5_HDMI_3DS_SIDEBYSIDEHALF:     // valid formats with no timing changes.
2767     case NVT_HDMI_VS_BYTE5_HDMI_3DS_TOPBOTTOM:
2768         {
2769             break;
2770         }
2771     case NVT_HDMI_VS_BYTE5_HDMI_3DS_FIELD_ALT:          // formats we are not supporting.
2772     case NVT_HDMI_VS_BYTE5_HDMI_3DS_LINE_ALT:
2773     case NVT_HDMI_VS_BYTE5_HDMI_3DS_LDEPTH:
2774     case NVT_HDMI_VS_BYTE5_HDMI_3DS_LDEPTHGFX:
2775         {
2776             break;
2777         }
2778     }
2779     // calculate the pixel clock
2780     pExtTiming->timing.pclk  = RRx1kToPclk (&(pExtTiming->timing));
2781     return;
2782 }
2783 
2784 // Add mode to 3D stereo support map
2785 CODE_SEGMENT(PAGE_DD_CODE)
2786 void AddModeToSupportMap(HDMI3DSUPPORTMAP * pMap, NvU8 Vic, NvU8 StereoStructureType, NvU8 SideBySideHalfDetail)
2787 {
2788     NvU32 i;
2789 
2790     if (0 < Vic)
2791     {
2792         // first check if the vic is already listed.
2793         for (i = 0; i < pMap->total; ++i)
2794         {
2795             if (pMap->map[i].Vic == Vic)
2796             {
2797                 break;
2798             }
2799         }
2800         if (i == pMap->total)
2801         {
2802             // vic is not in the map.
2803             // add it.
2804             // note that we can't add the VIC to one of the 1st 16 entries.
2805             // 1st 16 entries in the map are reserved for the vics from the EDID.
2806             // if we add this VIC to the 1st 16, & there are any optional modes listed,
2807             // the optional mode(s) will be improperly applied to this VIC as well
2808             i = MAX(MAX_EDID_ADDRESSABLE_3D_VICS, pMap->total);
2809             if (i < MAX_3D_VICS_SUPPORTED)
2810             {
2811                 pMap->map[i].Vic = Vic;
2812                 pMap->total = i + 1;
2813             }
2814         }
2815         nvt_assert(pMap->total <= MAX_3D_VICS_SUPPORTED);
2816         if (i < pMap->total)
2817         {
2818             pMap->map[i].StereoStructureMask = pMap->map[i].StereoStructureMask | NVT_HDMI_3D_SUPPORTED_STRUCT_MASK(StereoStructureType);
2819             if (NVT_HDMI_VS_BYTE5_HDMI_3DS_SIDEBYSIDEHALF == StereoStructureType)
2820             {
2821                 pMap->map[i].SideBySideHalfDetail = SideBySideHalfDetail;
2822             }
2823         }
2824     }
2825 }
2826 
2827 CODE_SEGMENT(PAGE_DD_CODE)
2828 void parseEdidHdmiLlcBasicInfo(VSDB_DATA *pVsdb, NVT_HDMI_LLC_INFO *pHdmiLlc)
2829 {
2830     NVT_HDMI_LLC_VSDB_PAYLOAD *p;
2831     if (pVsdb == NULL || pHdmiLlc == NULL)
2832     {
2833         return;
2834     }
2835 
2836     p = (NVT_HDMI_LLC_VSDB_PAYLOAD *)(&pVsdb->vendor_data);
2837 
2838     // Minimum vendor_data_size is 2
2839     pHdmiLlc->addrA = p->A;
2840     pHdmiLlc->addrB = p->B;
2841     pHdmiLlc->addrC = p->C;
2842     pHdmiLlc->addrD = p->D;
2843 
2844     // If more data is provided, we read it as well each field at a time up to video latency
2845     if (pVsdb->vendor_data_size >= 3)
2846     {
2847         pHdmiLlc->supports_AI  = p->Supports_AI;
2848         pHdmiLlc->dc_48_bit    = p->DC_48bit;
2849         pHdmiLlc->dc_36_bit    = p->DC_36bit;
2850         pHdmiLlc->dc_30_bit    = p->DC_30bit;
2851         pHdmiLlc->dc_y444      = p->DC_Y444;
2852         pHdmiLlc->dual_dvi     = p->DVI_Dual;
2853 
2854         if (pVsdb->vendor_data_size >= 4)
2855         {
2856             pHdmiLlc->max_tmds_clock        = p->Max_TMDS_Clock;
2857 
2858             if (pVsdb->vendor_data_size >= 5)
2859             {
2860                 pHdmiLlc->latency_field_present     = p->Latency_Fields_Present;
2861                 pHdmiLlc->i_latency_field_present   = p->I_Latency_Fields_Present;
2862                 pHdmiLlc->hdmi_video_present        = p->HDMI_Video_present;
2863                 pHdmiLlc->cnc3 = p->CNC3;
2864                 pHdmiLlc->cnc2 = p->CNC2;
2865                 pHdmiLlc->cnc1 = p->CNC1;
2866                 pHdmiLlc->cnc0 = p->CNC0;
2867             }
2868         }
2869     }
2870 
2871 }
2872 
2873 // get HDMI 1.4 specific timing (3D stereo timings and extended mode timings)
2874 CODE_SEGMENT(PAGE_DD_CODE)
2875 void parseEdidHDMILLCTiming(NVT_EDID_INFO *pInfo, VSDB_DATA *pVsdb, NvU32 *pMapSz, HDMI3DSUPPORTMAP * pM)
2876 {
2877     NVT_HDMI_LLC_VSDB_PAYLOAD   *pHdmiLLC;
2878     NVT_HDMI_VIDEO              *pHDMIVideo;
2879     NvU32                       DataCnt = 0;
2880     NvU32                       DataSz;
2881     NvU16                       i, j, k;
2882     NvU16                       Supports50Hz;
2883     NvU16                       Supports60Hz;
2884     NvU32                       vendorDataSize;
2885 
2886     if ((NULL == pInfo) || (NULL == pVsdb) || (NULL == pM))
2887     {
2888         return;
2889     }
2890 
2891     // init the support map
2892     NVMISC_MEMSET(pM, 0, sizeof(HDMI3DSUPPORTMAP));
2893     Supports50Hz = 0;
2894     Supports60Hz = 0;
2895 
2896     nvt_assert(pInfo->total_timings <= COUNT(pInfo->timing));
2897 
2898     for (i = 0; i < pInfo->total_timings; ++i)
2899     {
2900         if (NVT_GET_TIMING_STATUS_TYPE(pInfo->timing[i].etc.status) == NVT_TYPE_EDID_861ST)
2901         {
2902             if (MAX_EDID_ADDRESSABLE_3D_VICS > pM->total)
2903             {
2904                 // fill in the VICs from the EDID (up to the 1st 16). These are used for applying any 3D optional modes listed in the LLC
2905                 // -- the optional modes are addressed based on their relative location within the EDID.
2906                 pM->map[pM->total].Vic = (NvU8) NVT_GET_TIMING_STATUS_SEQ(pInfo->timing[i].etc.status);
2907                 ++pM->total;
2908             }
2909 
2910             // since we are spinning through the timing array anyway,
2911             // check to see which refresh rates are supported.
2912             if (50 == pInfo->timing[i].etc.rr)
2913             {
2914                 Supports50Hz = 1;
2915             }
2916             else if (60 == pInfo->timing[i].etc.rr)
2917             {
2918                 Supports60Hz = 1;
2919             }
2920         }
2921     }
2922 
2923     if (0 == pM->total)
2924     {
2925         if (NULL != pMapSz)
2926         {
2927             *pMapSz = 0;
2928         }
2929     }
2930 
2931     vendorDataSize = pVsdb->vendor_data_size;
2932     if ((NVT_CEA861_HDMI_IEEE_ID == pVsdb->ieee_id) &&
2933         (offsetof(NVT_HDMI_LLC_VSDB_PAYLOAD, Data) < vendorDataSize))
2934     {
2935         pHdmiLLC = (NVT_HDMI_LLC_VSDB_PAYLOAD *)(&pVsdb->vendor_data);
2936         DataSz = (NvU32) MIN(vendorDataSize - offsetof(NVT_HDMI_LLC_VSDB_PAYLOAD, Data), sizeof(pHdmiLLC->Data));
2937 
2938         if (5 <= vendorDataSize)
2939         {
2940             if (pHdmiLLC->Latency_Fields_Present)
2941             {
2942                 DataCnt += (NvU32) sizeof(NVT_CEA861_LATENCY);
2943 
2944                 if (pHdmiLLC->I_Latency_Fields_Present)
2945                 {
2946                     DataCnt += (NvU32) sizeof(NVT_CEA861_LATENCY);
2947                 }
2948             }
2949 
2950             if ((pHdmiLLC->HDMI_Video_present) &&
2951                 (DataSz > DataCnt) &&
2952                 (DataSz - DataCnt >= sizeof(NVT_HDMI_VIDEO)))
2953             {
2954                 pHDMIVideo = (NVT_HDMI_VIDEO *) &pHdmiLLC->Data[DataCnt];
2955                 DataCnt += (NvU32) sizeof(NVT_HDMI_VIDEO);
2956 
2957                 // If 3D is present, then add the basic 3D modes 1st.
2958                 if (pHDMIVideo->ThreeD_Present)
2959                 {
2960                     if ((0 != Supports50Hz) || (0 != Supports60Hz))
2961                     {
2962                         // 50 and / or 60 Hz is supported, add 1920 x 1080 @ 24Hz 3D modes.
2963                         AddModeToSupportMap(pM, 32, NVT_HDMI_VS_BYTE5_HDMI_3DS_FRAMEPACK, 0);       // 1920 x 1080p @ 24 Hz
2964                         AddModeToSupportMap(pM, 32, NVT_HDMI_VS_BYTE5_HDMI_3DS_TOPBOTTOM, 0);       // 1920 x 1080p @ 24 Hz
2965 
2966                         if (0 != Supports50Hz)
2967                         {
2968                             // add the mandatory modes for 50 Hz
2969                             AddModeToSupportMap(pM, 19, NVT_HDMI_VS_BYTE5_HDMI_3DS_FRAMEPACK, 0);       // 1280 x  720p @ 50 Hz
2970                             AddModeToSupportMap(pM, 19, NVT_HDMI_VS_BYTE5_HDMI_3DS_TOPBOTTOM, 0);       // 1280 x  720p @ 50 Hz
2971                                                                                                         // 1920 x 1080i @ 50 Hz
2972                             AddModeToSupportMap(pM, 20, NVT_HDMI_VS_BYTE5_HDMI_3DS_SIDEBYSIDEHALF, NVT_HDMI_VS_BYTE_OPT1_HDMI_3DEX_SSH);
2973                         }
2974 
2975                         if (0 != Supports60Hz)
2976                         {
2977                             // add the mandatory modes for 60 Hz
2978                             AddModeToSupportMap(pM,  4, NVT_HDMI_VS_BYTE5_HDMI_3DS_FRAMEPACK, 0);       // 1280 x  720p @ 60 Hz
2979                             AddModeToSupportMap(pM,  4, NVT_HDMI_VS_BYTE5_HDMI_3DS_TOPBOTTOM, 0);       // 1280 x  720p @ 60 Hz
2980                                                                                                         // 1920 x 1080i @ 60 Hz
2981                             AddModeToSupportMap(pM,  5, NVT_HDMI_VS_BYTE5_HDMI_3DS_SIDEBYSIDEHALF, NVT_HDMI_VS_BYTE_OPT1_HDMI_3DEX_SSH);
2982                         }
2983                     }
2984                 }
2985 
2986                 if ((DataSz > DataCnt) &&
2987                     (DataSz - DataCnt >= pHDMIVideo->HDMI_VIC_Len))
2988                 {
2989                     // handle HDMI VIC entries to add HDMI 1.4a 4kx2k extended modes
2990                     NVT_HDMI_VIC_LIST * pVicList = (NVT_HDMI_VIC_LIST *) &pHdmiLLC->Data[DataCnt];
2991 
2992                     for ( k = 0; k < pHDMIVideo->HDMI_VIC_Len; ++k)
2993                     {
2994                         NVT_TIMING newTiming;
2995 
2996                         // extended mode VIC code from 1 - 4.
2997                         if ((0 < pVicList->HDMI_VIC[k]) && (pVicList->HDMI_VIC[k] <= MAX_HDMI_EXT_4Kx2K_FORMAT))
2998                         {
2999                             NVMISC_MEMCPY(&newTiming,
3000                                           &HDMI_EXT_4Kx2K_TIMING[pVicList->HDMI_VIC[k] - 1],
3001                                           sizeof(newTiming));
3002 
3003                             // Fill in the pixel clock
3004                             newTiming.pclk = RRx1kToPclk(&newTiming);
3005 
3006                             if (!assignNextAvailableTiming(pInfo, &newTiming))
3007                             {
3008                                 break;
3009                             }
3010                         }
3011                     }
3012 
3013                     DataCnt += pHDMIVideo->HDMI_VIC_Len;
3014                 }
3015 
3016                 // the following code implements parsing the HDMI 3D additional modes (all modes bitmap & additional vic modes)
3017                 // Kepler and above support 3D secondary modes
3018                 if ((pHDMIVideo->ThreeD_Present) &&
3019                     ((1 == pHDMIVideo->ThreeD_Multi_Present) || (2 == pHDMIVideo->ThreeD_Multi_Present)) &&
3020                     (0 < pHDMIVideo->HDMI_3D_Len) &&
3021                     (DataSz > (DataCnt + 1)) &&   //make sure pHdmiLLC->Data[DataCnt + 1] is valid
3022                     (DataSz - DataCnt >= pHDMIVideo->HDMI_3D_Len))
3023                 {
3024                     NvU16   AllVicStructMask;
3025                     NvU16   AllVicIdxMask;
3026                     NvU8    AllVicDetail;
3027 
3028                     // determine which modes to apply to all VICs.
3029                     AllVicStructMask = (pHdmiLLC->Data[DataCnt] << 8) | pHdmiLLC->Data[DataCnt + 1];
3030                     AllVicStructMask = AllVicStructMask & NVT_ALL_HDMI_3D_STRUCT_SUPPORTED_MASK;
3031                     DataCnt += 2;
3032 
3033                     if ((2 == pHDMIVideo->ThreeD_Multi_Present) && (DataSz > (DataCnt+1)))   //make sure pHdmiLLC->Data[DataCnt + 1] is valid
3034                     {
3035                         AllVicIdxMask = pHdmiLLC->Data[DataCnt] << 8 | pHdmiLLC->Data[DataCnt + 1];
3036                         DataCnt += 2;
3037                     }
3038                     else
3039                     {
3040                         AllVicIdxMask = 0xffff;
3041                     }
3042 
3043                     // determine what the detail should be.
3044                     AllVicDetail = 0 != (AllVicStructMask & NVT_HDMI_3D_SUPPORTED_SIDEBYSIDEHALF_MASK) ? NVT_HDMI_VS_BYTE_OPT1_HDMI_3DEX_SSH : 0;
3045 
3046                     // add the modes to the Support map for all the listed VICs.
3047                     for (k = 0; k < MIN(MAX_EDID_ADDRESSABLE_3D_VICS, pM->total); ++k)
3048                     {
3049                         if ((0 != (AllVicIdxMask & (1 << k))) && (0 != pM->map[k].Vic))
3050                         {
3051                             pM->map[k].StereoStructureMask  = pM->map[k].StereoStructureMask | AllVicStructMask;
3052                             pM->map[k].SideBySideHalfDetail = AllVicDetail;
3053                         }
3054                     }
3055                 }
3056 
3057                 // handle any additional per vic modes listed in the EDID
3058                 while (DataSz > DataCnt)
3059                 {
3060                     // get a pointer to the entry.
3061                     NVT_3D_MULTI_LIST * pMultiListEntry = (NVT_3D_MULTI_LIST *) &pHdmiLLC->Data[DataCnt];
3062 
3063                     // apply the specified structure to the Support Map
3064                     pM->map[pMultiListEntry->TwoD_VIC_order].StereoStructureMask =
3065                         pM->map[pMultiListEntry->TwoD_VIC_order].StereoStructureMask | NVT_HDMI_3D_SUPPORTED_STRUCT_MASK(pMultiListEntry->ThreeD_Structure);
3066 
3067                     // increment the Data count by 2 if this is side by side half,
3068                     // or 1 if it is any other structure.
3069                     if (NVT_HDMI_VS_BYTE5_HDMI_3DS_SIDEBYSIDEHALF <= pMultiListEntry->ThreeD_Structure)
3070                     {
3071                         pM->map[pMultiListEntry->TwoD_VIC_order].SideBySideHalfDetail = pMultiListEntry->ThreeD_Detail;
3072                         DataCnt += 2;
3073                     }
3074                     else
3075                     {
3076                         pM->map[pMultiListEntry->TwoD_VIC_order].SideBySideHalfDetail = 0;
3077                         DataCnt += 1;
3078                     }
3079                 }
3080             }
3081         }
3082     }
3083 
3084 
3085     // compress out entries where there is no 3D support.
3086     for (i = 0, j = 0; i < pM->total; ++i)
3087     {
3088         if (0 != pM->map[i].StereoStructureMask)
3089         {
3090             pM->map[j] = pM->map[i];
3091             ++j;
3092         }
3093     }
3094 
3095     pM->total = j;
3096 
3097     if (NULL != pMapSz)
3098     {
3099         *pMapSz = pM->total;
3100     }
3101 }
3102 
3103 // get HDMI 1.4 3D mandatory stereo format datail base on the input vic.
3104 // If the vic is not in the mandatory format list, return error.
3105 CODE_SEGMENT(PAGE_DD_CODE)
3106 NVT_STATUS NvTiming_GetHDMIStereoMandatoryFormatDetail(const NvU8 vic, NvU16 *pStereoStructureMask, NvU8 *pSideBySideHalfDetail)
3107 {
3108     NvU32   i;
3109 
3110     if ((vic < 1) || (vic > MAX_CEA861B_FORMAT))
3111     {
3112         return NVT_STATUS_ERR;
3113     }
3114 
3115     for (i = 0; i < MAX_HDMI_MANDATORY_3D_FORMAT; i++)
3116     {
3117         if (vic == HDMI_MANDATORY_3D_FORMATS[i].Vic)
3118         {
3119             if (pStereoStructureMask != NULL)
3120             {
3121                 *pStereoStructureMask  = HDMI_MANDATORY_3D_FORMATS[i].StereoStructureMask;
3122             }
3123 
3124             if (pSideBySideHalfDetail != NULL)
3125             {
3126                 *pSideBySideHalfDetail = HDMI_MANDATORY_3D_FORMATS[i].SideBySideHalfDetail;
3127             }
3128 
3129             return NVT_STATUS_SUCCESS;
3130         }
3131     }
3132 
3133     return NVT_STATUS_ERR;
3134 }
3135 // return the aspect ratio of a given CEA/EIA 861 timing
3136 CODE_SEGMENT(PAGE_DD_CODE)
3137 NvU32 getCEA861TimingAspectRatio(NvU32 vic)
3138 {
3139     return (vic > 0 && vic < MAX_CEA861B_FORMAT + 1) ? EIA861B[vic-1].etc.aspect : 0;
3140 }
3141 
3142 // expose the HDMI extended video timing defined by the HDMI LLC VSDB
3143 CODE_SEGMENT(PAGE_DD_CODE)
3144 NVT_STATUS NvTiming_EnumHdmiVsdbExtendedTiming(NvU32 hdmi_vic, NVT_TIMING *pT)
3145 {
3146     if (hdmi_vic > MAX_HDMI_EXT_4Kx2K_FORMAT || hdmi_vic == 0 || pT == NULL)
3147     {
3148         return NVT_STATUS_ERR;
3149     }
3150     *pT = HDMI_EXT_4Kx2K_TIMING[hdmi_vic - 1];
3151     pT->pclk = RRx1kToPclk(pT);
3152     return NVT_STATUS_SUCCESS;
3153 }
3154 
3155 CODE_SEGMENT(PAGE_DD_CODE)
3156 void parseEdidNvidiaVSDBBlock(VSDB_DATA *pVsdb, NVDA_VSDB_PARSED_INFO *vsdbInfo)
3157 {
3158     NVT_NVDA_VSDB_PAYLOAD       *pNvda;
3159 
3160     if ((pVsdb == NULL) || (vsdbInfo == NULL))
3161     {
3162         return;
3163     }
3164 
3165     if ((NVT_CEA861_NVDA_IEEE_ID == pVsdb->ieee_id) &&
3166         (pVsdb->vendor_data_size >= sizeof(NVT_NVDA_VSDB_PAYLOAD)))
3167     {
3168         pNvda = (NVT_NVDA_VSDB_PAYLOAD *)(&pVsdb->vendor_data);
3169 
3170         // only version 0x1 is supported
3171         if (pNvda->opcode == 0x1)
3172         {
3173             vsdbInfo->vsdbVersion = pNvda->opcode;
3174         }
3175 
3176         switch (vsdbInfo->vsdbVersion)
3177         {
3178             case 1:
3179                 vsdbInfo->valid = NV_TRUE;
3180                 vsdbInfo->vrrData.v1.supportsVrr = NV_TRUE;
3181                 vsdbInfo->vrrData.v1.minRefreshRate = pNvda->vrrMinRefreshRate;
3182                 break;
3183 
3184             default:
3185                 break;
3186         }
3187     }
3188 }
3189 
3190 CODE_SEGMENT(PAGE_DD_CODE)
3191 void parseEdidMsftVsdbBlock(VSDB_DATA *pVsdb, MSFT_VSDB_PARSED_INFO *pVsdbInfo)
3192 {
3193     if ((pVsdb == NULL) || (pVsdbInfo == NULL))
3194     {
3195         return;
3196     }
3197 
3198     NVMISC_MEMSET(pVsdbInfo, 0, sizeof(MSFT_VSDB_PARSED_INFO));
3199 
3200     if ((NVT_CEA861_MSFT_IEEE_ID == pVsdb->ieee_id) &&
3201         (pVsdb->vendor_data_size >= sizeof(NVT_MSFT_VSDB_PAYLOAD)))
3202     {
3203         NvU32 i = 0;
3204         NVT_MSFT_VSDB_PAYLOAD *pMsftVsdbPayload = (NVT_MSFT_VSDB_PAYLOAD *)(&pVsdb->vendor_data);
3205 
3206         pVsdbInfo->version = pMsftVsdbPayload->version;
3207 
3208         if (pVsdbInfo->version >= 1)
3209         {
3210             for (i = 0; i < MSFT_VSDB_CONTAINER_ID_SIZE; i++)
3211             {
3212                 pVsdbInfo->containerId[i] = pMsftVsdbPayload->containerId[i];
3213             }
3214 
3215             pVsdbInfo->desktopUsage = pMsftVsdbPayload->desktopUsage;
3216             pVsdbInfo->thirdPartyUsage = pMsftVsdbPayload->thirdPartyUsage;
3217             pVsdbInfo->valid = NV_TRUE;
3218         }
3219         // Version 3 is the latest version of MSFT VSDB at the time of writing this code
3220         // Any update from newer version will be ignored and be parsed as Version 3, till
3221         // we have an explicit handling for newer version here.
3222         if (pVsdbInfo->version >= 3)
3223         {
3224             // Primary Use case is valid from Version 3 and is ignored on previous versions.
3225             pVsdbInfo->primaryUseCase = pMsftVsdbPayload->primaryUseCase;
3226         }
3227     }
3228 }
3229 
3230 CODE_SEGMENT(PAGE_DD_CODE)
3231 void parseEdidHdmiForumVSDB(VSDB_DATA *pVsdb, NVT_HDMI_FORUM_INFO *pHdmiInfo)
3232 {
3233     NVT_HDMI_FORUM_VSDB_PAYLOAD *pHdmiForum;
3234     NvU32 remainingSize;
3235 
3236     if ((pVsdb == NULL) || pHdmiInfo == NULL)
3237     {
3238         return;
3239     }
3240 
3241     pHdmiForum = (NVT_HDMI_FORUM_VSDB_PAYLOAD *)(&pVsdb->vendor_data);
3242     switch(pHdmiForum->Version)
3243     {
3244         case 1:
3245             // From HDMI spec the payload data size is from 7 to 31
3246             // In parseCta861DataBlockInfo(), the payload size recorded in pHdmiForum is
3247             //    subtracted by 3. Thus the expected range here is 4 - 28.
3248             // Assert if the the vendor_data_size < 4.
3249             nvt_assert(pVsdb->vendor_data_size >= 4);
3250 
3251             remainingSize  =  pVsdb->vendor_data_size;
3252 
3253             // second byte
3254             pHdmiInfo->max_TMDS_char_rate   = pHdmiForum->Max_TMDS_Character_Rate;
3255 
3256             // third byte
3257             pHdmiInfo->threeD_Osd_Disparity = pHdmiForum->ThreeD_Osd_Disparity;
3258             pHdmiInfo->dual_view            = pHdmiForum->Dual_View;
3259             pHdmiInfo->independent_View     = pHdmiForum->Independent_View;
3260             pHdmiInfo->lte_340Mcsc_scramble = pHdmiForum->Lte_340mcsc_Scramble;
3261             pHdmiInfo->ccbpci               = pHdmiForum->CCBPCI;
3262             pHdmiInfo->cable_status         = pHdmiForum->CABLE_STATUS;
3263             pHdmiInfo->rr_capable           = pHdmiForum->RR_Capable;
3264             pHdmiInfo->scdc_present         = pHdmiForum->SCDC_Present;
3265 
3266             // fourth byte
3267             pHdmiInfo->dc_30bit_420         = pHdmiForum->DC_30bit_420;
3268             pHdmiInfo->dc_36bit_420         = pHdmiForum->DC_36bit_420;
3269             pHdmiInfo->dc_48bit_420         = pHdmiForum->DC_48bit_420;
3270             pHdmiInfo->uhd_vic              = pHdmiForum->UHD_VIC;
3271             pHdmiInfo->max_FRL_Rate         = pHdmiForum->Max_FRL_Rate;
3272 
3273             remainingSize -= 4;
3274 
3275             // fifth byte
3276             if (!remainingSize--)
3277             {
3278                 break;
3279             }
3280             pHdmiInfo->fapa_start_location  = pHdmiForum->FAPA_start_location;
3281             pHdmiInfo->allm                 = pHdmiForum->ALLM;
3282             pHdmiInfo->fva                  = pHdmiForum->FVA;
3283             pHdmiInfo->cnmvrr               = pHdmiForum->CNMVRR;
3284             pHdmiInfo->cinemaVrr            = pHdmiForum->CinemaVRR;
3285             pHdmiInfo->m_delta              = pHdmiForum->M_delta;
3286             pHdmiInfo->qms                  = pHdmiForum->QMS;
3287             pHdmiInfo->fapa_end_extended    = pHdmiForum->FAPA_End_Extended;
3288 
3289             // sixth byte
3290             if (!remainingSize--)
3291             {
3292                 break;
3293             }
3294             pHdmiInfo->vrr_min              = pHdmiForum->VRR_min;
3295             pHdmiInfo->vrr_max              = ((NvU16)pHdmiForum->VRR_max_high) << 8;
3296 
3297             // seventh byte
3298             if (!remainingSize--)
3299             {
3300                 break;
3301             }
3302             pHdmiInfo->vrr_max             |= (pHdmiForum->VRR_max_low);
3303 
3304             // eighth byte
3305             if (!remainingSize--)
3306             {
3307                 break;
3308             }
3309             pHdmiInfo->dsc_10bpc            = pHdmiForum->DSC_10bpc;
3310             pHdmiInfo->dsc_12bpc            = pHdmiForum->DSC_12bpc;
3311             pHdmiInfo->dsc_16bpc            = pHdmiForum->DSC_16bpc;
3312             pHdmiInfo->dsc_All_bpp          = pHdmiForum->DSC_All_bpp;
3313             pHdmiInfo->dsc_Native_420       = pHdmiForum->DSC_Native_420;
3314             pHdmiInfo->dsc_1p2              = pHdmiForum->DSC_1p2;
3315             pHdmiInfo->qms_tfr_min          = pHdmiForum->QMS_TFR_min;
3316             pHdmiInfo->qms_tfr_max          = pHdmiForum->QMS_TFR_max;
3317 
3318             // ninth byte
3319             if (!remainingSize--)
3320             {
3321                 break;
3322             }
3323             pHdmiInfo->dsc_MaxSlices          = 0;
3324             pHdmiInfo->dsc_MaxPclkPerSliceMHz = 0;
3325             switch(pHdmiForum->DSC_MaxSlices)
3326             {
3327             case 7: pHdmiInfo->dsc_MaxSlices = 16; pHdmiInfo->dsc_MaxPclkPerSliceMHz = 400; break;
3328             case 6: pHdmiInfo->dsc_MaxSlices = 12; pHdmiInfo->dsc_MaxPclkPerSliceMHz = 400; break;
3329             case 5: pHdmiInfo->dsc_MaxSlices = 8;  pHdmiInfo->dsc_MaxPclkPerSliceMHz = 400; break;
3330             case 4: pHdmiInfo->dsc_MaxSlices = 8;  pHdmiInfo->dsc_MaxPclkPerSliceMHz = 340; break;
3331             case 3: pHdmiInfo->dsc_MaxSlices = 4;  pHdmiInfo->dsc_MaxPclkPerSliceMHz = 340; break;
3332             case 2: pHdmiInfo->dsc_MaxSlices = 2;  pHdmiInfo->dsc_MaxPclkPerSliceMHz = 340; break;
3333             case 1: pHdmiInfo->dsc_MaxSlices = 1;  pHdmiInfo->dsc_MaxPclkPerSliceMHz = 340; break;
3334             default: break;
3335             }
3336 
3337             pHdmiInfo->dsc_Max_FRL_Rate     = pHdmiForum->DSC_Max_FRL_Rate;
3338 
3339             // tenth byte
3340             if (!remainingSize--)
3341             {
3342                 break;
3343             }
3344 
3345             // Per spec, number of bytes has to be computed as 1024 x (1 + DSC_TotalChunkKBytes).
3346             // For driver parser purposes, add 1 here so that the field means max num of KBytes in a link of chunks
3347             pHdmiInfo->dsc_totalChunkKBytes = (pHdmiForum->DSC_totalChunkKBytes == 0) ? 0 : pHdmiForum->DSC_totalChunkKBytes + 1;
3348             break;
3349 
3350         default:
3351             break;
3352 
3353     }
3354 }
3355 
3356 CODE_SEGMENT(PAGE_DD_CODE)
3357 void parseCea861Hdr10PlusDataBlock(NVT_EDID_CEA861_INFO *pExt861, void *pRawInfo, NVT_CTA861_ORIGIN flag)
3358 {
3359     NVT_EDID_INFO           *pInfo          = NULL;
3360     NVT_DISPLAYID_2_0_INFO  *pDisplayID20   = NULL;
3361     NVT_HDR10PLUS_INFO      *pHdr10PlusInfo = NULL;
3362 
3363     if (pExt861 == NULL || pRawInfo == NULL)
3364         return;
3365 
3366     if(pExt861->vsvdb.ieee_id != NVT_CEA861_HDR10PLUS_IEEE_ID)
3367         return;
3368 
3369     if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
3370     {
3371         pInfo = (NVT_EDID_INFO *)pRawInfo;
3372         pHdr10PlusInfo = &pInfo->hdr10PlusInfo;
3373     }
3374     else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
3375     {
3376         pDisplayID20 = (NVT_DISPLAYID_2_0_INFO *)pRawInfo;
3377         pHdr10PlusInfo = &pDisplayID20->cta.hdr10PlusInfo;
3378     }
3379     else
3380     {
3381         return;
3382     }
3383 
3384     NVMISC_MEMSET(pHdr10PlusInfo, 0, sizeof(NVT_HDR10PLUS_INFO));
3385 
3386     if (pExt861->vsvdb.vendor_data_size < sizeof(NVT_HDR10PLUS_INFO))
3387         return;
3388 
3389     NVMISC_MEMCPY(pHdr10PlusInfo, &pExt861->vsvdb.vendor_data, sizeof(NVT_HDR10PLUS_INFO));
3390 }
3391 
3392 CODE_SEGMENT(PAGE_DD_CODE)
3393 void parseCta861DIDType7VideoTimingDataBlock(NVT_EDID_CEA861_INFO *pExt861, void *pRawInfo)
3394 {
3395     NvU8 i = 0;
3396     NvU8 t7db_idx = 0;
3397     NvU8 startSeqNum = 0;
3398 
3399     NVT_TIMING newTiming;
3400     NVT_EDID_INFO *pInfo = (NVT_EDID_INFO *)pRawInfo;
3401     const DISPLAYID_2_0_TIMING_7_DESCRIPTOR *pT7Descriptor = NULL;
3402     NvU8 eachOfDescSize = sizeof(DISPLAYID_2_0_TIMING_7_DESCRIPTOR);
3403 
3404     for (t7db_idx = 0; t7db_idx < pExt861->total_did_type7db; t7db_idx++)
3405     {
3406         // 20 bytes
3407         eachOfDescSize += pExt861->did_type7_data_block[t7db_idx].version.t7_m;
3408 
3409         if (pExt861->did_type7_data_block[t7db_idx].total_descriptors != NVT_CTA861_DID_TYPE7_DESCRIPTORS_MAX)
3410         {
3411             nvt_assert(0 && "payload descriptor invalid. expect T7VTDB only 1 descriptor");
3412             continue;
3413         }
3414 
3415         if (pExt861->did_type7_data_block[t7db_idx].version.revision != 2 )
3416         {
3417             nvt_assert(0 && "The revision supported by CTA-861 is not 2");
3418         }
3419 
3420         startSeqNum = getExistedCTATimingSeqNumber(pInfo, NVT_TYPE_CTA861_DID_T7);
3421 
3422         for (i = 0; i < pExt861->did_type7_data_block[i].total_descriptors; i++)
3423         {
3424             NVMISC_MEMSET(&newTiming, 0, sizeof(newTiming));
3425             if (NVT_STATUS_SUCCESS == parseDisplayId20Timing7Descriptor(&pExt861->did_type7_data_block[t7db_idx].payload[i*eachOfDescSize],
3426                                                                         &newTiming,
3427                                                                         startSeqNum+i))
3428             {
3429                 // T7VTDB shall not be used with video timing that can be expressed in an 18-byte DTD
3430                 if (newTiming.HVisible < 4096 && newTiming.VVisible < 4096 && newTiming.pclk < 65536)
3431                 {
3432                     nvt_assert(0 && "The timing can be expressed in an 18-byte DTD");
3433                     continue;
3434                 }
3435 
3436                 pT7Descriptor = (const DISPLAYID_2_0_TIMING_7_DESCRIPTOR *)
3437                                     &pExt861->did_type7_data_block[t7db_idx].payload[i*eachOfDescSize];
3438 
3439                 if (pT7Descriptor->options.is_preferred_or_ycc420 == 1 && newTiming.pclk > NVT_HDMI_YUV_420_PCLK_SUPPORTED_MIN)
3440                 {
3441                     newTiming.etc.yuv420.bpcs = 0;
3442                     UPDATE_BPC_FOR_COLORFORMAT(newTiming.etc.yuv420, 0, 1,
3443                                                pInfo->hdmiForumInfo.dc_30bit_420,
3444                                                pInfo->hdmiForumInfo.dc_36bit_420, 0,
3445                                                pInfo->hdmiForumInfo.dc_48bit_420);
3446                 }
3447 
3448                 NVT_SNPRINTF((char *)newTiming.etc.name, sizeof(newTiming.etc.name), "CTA861-T7:#%3d:%dx%dx%3d.%03dHz/%s",
3449                                                                                      (int)NVT_GET_TIMING_STATUS_SEQ(newTiming.etc.status),
3450                                                                                      (int)newTiming.HVisible,
3451                                                                                      (int)newTiming.VVisible,
3452                                                                                      (int)newTiming.etc.rrx1k/1000,
3453                                                                                      (int)newTiming.etc.rrx1k%1000,
3454                                                                                      (newTiming.interlaced ? "I":"P"));
3455                 newTiming.etc.status = NVT_STATUS_CTA861_DID_T7N(NVT_GET_TIMING_STATUS_SEQ(newTiming.etc.status));
3456                 newTiming.etc.name[sizeof(newTiming.etc.name) - 1] = '\0';
3457                 newTiming.etc.rep = 0x1;
3458 
3459                 if (!assignNextAvailableTiming(pInfo, &newTiming))
3460                 {
3461                     break;
3462                 }
3463             }
3464         }
3465     }
3466 }
3467 
3468 CODE_SEGMENT(PAGE_DD_CODE)
3469 void parseCta861DIDType8VideoTimingDataBlock(NVT_EDID_CEA861_INFO *pExt861, void *pRawInfo)
3470 {
3471     NvU8 i = 0;
3472     NvU8 t8db_idx = 0;
3473     NvU8 startSeqNum = 0;
3474     NvU8 codeSize = 0;
3475     NvU8 codeType = 0;
3476 
3477     NVT_TIMING newTiming;
3478     NVT_EDID_INFO *pInfo = (NVT_EDID_INFO *)pRawInfo;
3479 
3480     for (t8db_idx = 0; t8db_idx < pExt861->total_did_type8db; t8db_idx++)
3481     {
3482         codeType = pExt861->did_type8_data_block[t8db_idx].version.code_type;
3483         codeSize = pExt861->did_type8_data_block[t8db_idx].version.tcs;
3484 
3485         if (codeType != 0 /*DMT*/)
3486         {
3487             nvt_assert(0 && "Not DMT code type!");
3488             continue;
3489         }
3490 
3491         startSeqNum = getExistedCTATimingSeqNumber(pInfo, NVT_TYPE_CTA861_DID_T8);
3492 
3493         for (i=0; i < pExt861->did_type8_data_block[t8db_idx].total_descriptors; i++)
3494         {
3495             NVMISC_MEMSET(&newTiming, 0, sizeof(newTiming));
3496 
3497             if (parseDisplayId20Timing8Descriptor(pExt861->did_type8_data_block[t8db_idx].payload,
3498                                                   &newTiming, codeType, codeSize, i, startSeqNum + i) == NVT_STATUS_SUCCESS)
3499             {
3500                 if (pExt861->did_type8_data_block[t8db_idx].version.t8y420 == 1 && newTiming.pclk > NVT_HDMI_YUV_420_PCLK_SUPPORTED_MIN)
3501                 {
3502                     UPDATE_BPC_FOR_COLORFORMAT(newTiming.etc.yuv420, 0, 1,
3503                                                 pInfo->hdmiForumInfo.dc_30bit_420,
3504                                                 pInfo->hdmiForumInfo.dc_36bit_420, 0,
3505                                                 pInfo->hdmiForumInfo.dc_48bit_420);
3506                 }
3507                 NVT_SNPRINTF((char *)newTiming.etc.name, sizeof(newTiming.etc.name), "CTA861-T8:#%3d:%dx%dx%3d.%03dHz/%s",
3508                                                                                     (int)NVT_GET_TIMING_STATUS_SEQ(newTiming.etc.status),
3509                                                                                     (int)newTiming.HVisible, (int)newTiming.VVisible,
3510                                                                                     (int)newTiming.etc.rrx1k/1000, (int)newTiming.etc.rrx1k%1000,
3511                                                                                     (newTiming.interlaced ? "I":"P"));
3512                 newTiming.etc.status = NVT_STATUS_CTA861_DID_T8N(NVT_GET_TIMING_STATUS_SEQ(newTiming.etc.status));
3513                 newTiming.etc.name[sizeof(newTiming.etc.name) - 1] = '\0';
3514                 newTiming.etc.rep = 0x1;
3515 
3516                 if (!assignNextAvailableTiming(pInfo, &newTiming))
3517                 {
3518                     break;
3519                 }
3520             }
3521         }
3522     }
3523 }
3524 
3525 CODE_SEGMENT(PAGE_DD_CODE)
3526 void parseCta861DIDType10VideoTimingDataBlock(NVT_EDID_CEA861_INFO *pExt861, void *pRawInfo)
3527 {
3528     NvU8 i = 0;
3529     NvU8 t10db_idx = 0;
3530     NvU8 startSeqNum = 0;
3531 
3532     NVT_TIMING newTiming;
3533     NVT_EDID_INFO *pInfo = (NVT_EDID_INFO *)pRawInfo;
3534     const DISPLAYID_2_0_TIMING_10_6BYTES_DESCRIPTOR *p6bytesDescriptor = NULL;
3535     NvU8 eachOfDescriptorsSize = sizeof (DISPLAYID_2_0_TIMING_10_6BYTES_DESCRIPTOR);
3536 
3537     for (t10db_idx = 0; t10db_idx < pExt861->total_did_type10db; t10db_idx++)
3538     {
3539         startSeqNum = getExistedCTATimingSeqNumber(pInfo, NVT_TYPE_CTA861_DID_T10);
3540 
3541         // 6 or 7 bytes length
3542         eachOfDescriptorsSize += pExt861->did_type10_data_block[t10db_idx].version.t10_m;
3543 
3544         for (i = 0; i < pExt861->did_type10_data_block[t10db_idx].total_descriptors; i++)
3545         {
3546             if (pExt861->did_type10_data_block[t10db_idx].total_descriptors < NVT_CTA861_DID_TYPE10_DESCRIPTORS_MIN ||
3547                 pExt861->did_type10_data_block[t10db_idx].total_descriptors > NVT_CTA861_DID_TYPE10_DESCRIPTORS_MAX)
3548             {
3549                 nvt_assert(0 && "payload descriptor invalid. expect T10VTDB has minimum 1 descriptor, maximum 4 descriptors");
3550                 continue;
3551             }
3552 
3553             NVMISC_MEMSET(&newTiming, 0, sizeof(newTiming));
3554             if (NVT_STATUS_SUCCESS == parseDisplayId20Timing10Descriptor(&pExt861->did_type10_data_block[t10db_idx].payload[i*eachOfDescriptorsSize],
3555                                                                         &newTiming,
3556                                                                         pExt861->did_type10_data_block[t10db_idx].version.t10_m, startSeqNum+i))
3557             {
3558                 p6bytesDescriptor = (const DISPLAYID_2_0_TIMING_10_6BYTES_DESCRIPTOR *)
3559                                     &pExt861->did_type10_data_block[t10db_idx].payload[i*eachOfDescriptorsSize];
3560 
3561                 if (p6bytesDescriptor->options.ycc420_support && newTiming.pclk > NVT_HDMI_YUV_420_PCLK_SUPPORTED_MIN)
3562                 {
3563                     UPDATE_BPC_FOR_COLORFORMAT(newTiming.etc.yuv420, 0, 1,
3564                                                pInfo->hdmiForumInfo.dc_30bit_420,
3565                                                pInfo->hdmiForumInfo.dc_36bit_420, 0,
3566                                                pInfo->hdmiForumInfo.dc_48bit_420);
3567                 }
3568 
3569                 if (p6bytesDescriptor->options.timing_formula == DISPLAYID_2_0_TIMING_FORMULA_CVT_1_2_STANDARD)
3570                 {
3571                     NVT_SNPRINTF((char *)newTiming.etc.name, sizeof(newTiming.etc.name), "CTA861-T10:#%3d:%dx%dx%3d.%03dHz/%s",
3572                                                                                          (int)NVT_GET_TIMING_STATUS_SEQ(newTiming.etc.status),
3573                                                                                          (int)newTiming.HVisible,
3574                                                                                          (int)newTiming.VVisible,
3575                                                                                          (int)newTiming.etc.rrx1k/1000,
3576                                                                                          (int)newTiming.etc.rrx1k%1000,
3577                                                                                          (newTiming.interlaced ? "I":"P"));
3578                 }
3579                 else
3580                 {
3581                     NVT_SNPRINTF((char *)newTiming.etc.name, sizeof(newTiming.etc.name), "CTA861-T10RB%d:#%3d:%dx%dx%3d.%03dHz/%s",
3582                                                                                          p6bytesDescriptor->options.timing_formula,
3583                                                                                          (int)NVT_GET_TIMING_STATUS_SEQ(newTiming.etc.status),
3584                                                                                          (int)newTiming.HVisible,
3585                                                                                          (int)newTiming.VVisible,
3586                                                                                          (int)newTiming.etc.rrx1k/1000,
3587                                                                                          (int)newTiming.etc.rrx1k%1000,
3588                                                                                          (newTiming.interlaced ? "I":"P"));
3589                 }
3590                 newTiming.etc.status = NVT_STATUS_CTA861_DID_T10N(NVT_GET_TIMING_STATUS_SEQ(newTiming.etc.status));
3591                 newTiming.etc.name[sizeof(newTiming.etc.name) - 1] = '\0';
3592                 newTiming.etc.rep = 0x1;
3593 
3594                 if (!assignNextAvailableTiming(pInfo, &newTiming))
3595                 {
3596                     break;
3597                 }
3598             }
3599             else
3600             {
3601                 continue;
3602             }
3603         }
3604     }
3605 }
3606 
3607 POP_SEGMENTS
3608