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