mirror of
https://github.com/NVIDIA/open-gpu-kernel-modules.git
synced 2026-02-01 22:19:46 +00:00
3075 lines
141 KiB
C
3075 lines
141 KiB
C
//*****************************************************************************
|
||
//
|
||
// SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||
// SPDX-License-Identifier: MIT
|
||
//
|
||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||
// copy of this software and associated documentation files (the "Software"),
|
||
// to deal in the Software without restriction, including without limitation
|
||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
// and/or sell copies of the Software, and to permit persons to whom the
|
||
// Software is furnished to do so, subject to the following conditions:
|
||
//
|
||
// The above copyright notice and this permission notice shall be included in
|
||
// all copies or substantial portions of the Software.
|
||
//
|
||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||
// DEALINGS IN THE SOFTWARE.
|
||
//
|
||
// File: nvt_edidext_861.c
|
||
//
|
||
// Purpose: the provide edid 861 extension related services
|
||
//
|
||
//*****************************************************************************
|
||
|
||
#include "nvBinSegment.h"
|
||
#include "nvmisc.h"
|
||
|
||
#include "edid.h"
|
||
|
||
|
||
|
||
PUSH_SEGMENTS
|
||
|
||
#define EIA_TIMING(hv,hfp,hsw,ht,hsp,vv,vfp,vsw,vt,vsp,rrx1k,ip,aspect,rep,format) \
|
||
{hv,0,hfp,hsw,ht,(hsp)=='-',vv,0,vfp,vsw,vt,(vsp)=='-',(ip)=='i' ? NVT_INTERLACED:NVT_PROGRESSIVE,\
|
||
0,{0,((rrx1k)+500)/1000,rrx1k,((1?aspect)<<16)|(0?aspect),rep,{0},{0},{0},{0},NVT_STATUS_EDID_861STn(format),"CEA-861B:#"#format""}}
|
||
|
||
|
||
#define NVT_TIMING(hv,hfp,hsw,ht,hsp,vv,vfp,vsw,vt,vsp,rrx1k,ip,aspect,rep,format,name) \
|
||
{hv,0,hfp,hsw,ht,(hsp)=='-',vv,0,vfp,vsw,vt,(vsp)=='-',(ip)=='i' ? NVT_INTERLACED:NVT_PROGRESSIVE,\
|
||
0,{0,((rrx1k)+500)/1000,rrx1k,((1?aspect)<<16)|(0?aspect),rep,{0},{0},{0},{0},NVT_TYPE_NV_PREDEFINEDn(format),name}}
|
||
|
||
#define HDMI_EXT_TIMING(hv,hfp,hsw,ht,hsp,vv,vfp,vsw,vt,vsp,rrx1k,ip,aspect,rep,format,name) \
|
||
{hv,0,hfp,hsw,ht,(hsp)=='-',vv,0,vfp,vsw,vt,(vsp)=='-',(ip)=='i' ? NVT_INTERLACED:NVT_PROGRESSIVE,\
|
||
0,{0,((rrx1k)+500)/1000,rrx1k,((1?aspect)<<16)|(0?aspect),rep,{0},{0},{0},{0},NVT_STATUS_HDMI_EXTn(format),name}}
|
||
|
||
DATA_SEGMENT(PAGE_DATA)
|
||
CONS_SEGMENT(PAGE_CONS)
|
||
|
||
static const NVT_TIMING EIA861B[]=
|
||
{
|
||
// all 64 EIA/CEA-861E timings
|
||
EIA_TIMING( 640, 16, 96, 800,'-', 480,10,2, 525,'-', 59940,'p', 4:3, 0x1, 1),//640 x 480p @59.94/60 (Format 1)
|
||
EIA_TIMING( 720, 16, 62, 858,'-', 480, 9,6, 525,'-', 59940,'p', 4:3, 0x1, 2),//720 x 480p @59.94/60 (Format 2)
|
||
EIA_TIMING( 720, 16, 62, 858,'-', 480, 9,6, 525,'-', 59940,'p',16:9, 0x1, 3),//720 x 480p @59.94/60 (Format 3)
|
||
EIA_TIMING(1280, 110, 40,1650,'+', 720, 5,5, 750,'+', 59940,'p',16:9, 0x1, 4),//1280 x 720p @59.94/60 (Format 4)
|
||
EIA_TIMING(1920, 88, 44,2200,'+', 540, 2,5, 562,'+', 59940,'i',16:9, 0x1, 5),//1920 x 1080i @59.94/60 (Format 5)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
EIA_TIMING(2880, 76,248,3432,'-', 240, 4,3, 262,'-', 59940,'i', 4:3, 0x3ff,10),//(2880) x 480i @59.94/60 (Format 10)
|
||
EIA_TIMING(2880, 76,248,3432,'-', 240, 4,3, 262,'-', 59940,'i',16:9, 0x3ff,11),//(2880) x 480i @59.94/60 (Format 11)
|
||
EIA_TIMING(2880, 76,248,3432,'-', 240, 5,3, 263,'-', 59940,'p', 4:3, 0x3ff,12),//(2880) x 480p @59.94/60 (Format 12)
|
||
EIA_TIMING(2880, 76,248,3432,'-', 240, 5,3, 263,'-', 59940,'p',16:9, 0x3ff,13),//(2880) x 480p @59.94/60 (Format 13)
|
||
EIA_TIMING(1440, 32,124,1716,'-', 480, 9,6, 525,'-', 59940,'p', 4:3, 0x3,14),//1440 x 480p @59.94/60 (Format 14)
|
||
EIA_TIMING(1440, 32,124,1716,'-', 480, 9,6, 525,'-', 59940,'p',16:9, 0x3,15),//1440 x 480p @59.94/60 (Format 15)
|
||
EIA_TIMING(1920, 88, 44,2200,'+',1080, 4,5,1125,'+', 59940,'p',16:9, 0x1,16),//1920 x 1080p @59.94/60 (Format 16)
|
||
EIA_TIMING( 720, 12, 64, 864,'-', 576, 5,5, 625,'-', 50000,'p', 4:3, 0x1,17),//720 x 576p @50 (Format 17)
|
||
EIA_TIMING( 720, 12, 64, 864,'-', 576, 5,5, 625,'-', 50000,'p',16:9, 0x1,18),//720 x 576p @50 (Format 18)
|
||
EIA_TIMING(1280, 440, 40,1980,'+', 720, 5,5, 750,'+', 50000,'p',16:9, 0x1,19),//1280 x 720p @50 (Format 19)
|
||
EIA_TIMING(1920, 528, 44,2640,'+', 540, 2,5, 562,'+', 50000,'i',16:9, 0x1,20),//1920 x 1080i @50 (Format 20)
|
||
EIA_TIMING(1440, 24,126,1728,'-', 288, 2,3, 312,'-', 50000,'i', 4:3, 0x2,21),//720(1440) x 576i @50 (Format 21)
|
||
EIA_TIMING(1440, 24,126,1728,'-', 288, 2,3, 312,'-', 50000,'i',16:9, 0x2,22),//720(1440) x 576i @50 (Format 22)
|
||
EIA_TIMING(1440, 24,126,1728,'-', 288, 2,3, 312,'-', 50000,'p', 4:3, 0x2,23),//720(1440) x 288p @50 (Format 23)
|
||
EIA_TIMING(1440, 24,126,1728,'-', 288, 2,3, 312,'-', 50000,'p',16:9, 0x2,24),//720(1440) x 288p @50 (Format 24)
|
||
EIA_TIMING(2880, 48,252,3456,'-', 288, 2,3, 312,'-', 50000,'i', 4:3, 0x3ff,25),//(2880) x 576i @50 (Format 25)
|
||
EIA_TIMING(2880, 48,252,3456,'-', 288, 2,3, 312,'-', 50000,'i',16:9, 0x3ff,26),//(2880) x 576i @50 (Format 26)
|
||
EIA_TIMING(2880, 48,252,3456,'-', 288, 2,3, 312,'-', 50000,'p', 4:3, 0x3ff,27),//(2880) x 288p @50 (Format 27)
|
||
EIA_TIMING(2880, 48,252,3456,'-', 288, 2,3, 312,'-', 50000,'p',16:9, 0x3ff,28),//(2880) x 288p @50 (Format 28)
|
||
EIA_TIMING(1440, 24,128,1728,'-', 576, 5,5, 625,'_', 50000,'p', 4:3, 0x3,29),//1440 x 576p @50 (Format 29)
|
||
EIA_TIMING(1440, 24,128,1728,'-', 576, 5,5, 625,'_', 50000,'p',16:9, 0x3,30),//1440 x 576p @50 (Format 30)
|
||
EIA_TIMING(1920, 528, 44,2640,'+',1080, 4,5,1125,'+', 50000,'p',16:9, 0x1,31),//1920 x 1080p @50 (Format 31)
|
||
EIA_TIMING(1920, 638, 44,2750,'+',1080, 4,5,1125,'+', 23976,'p',16:9, 0x1,32),//1920 x 1080p @23.97/24 (Format 32)
|
||
EIA_TIMING(1920, 528, 44,2640,'+',1080, 4,5,1125,'+', 25000,'p',16:9, 0x1,33),//1920 x 1080p @25 (Format 33)
|
||
EIA_TIMING(1920, 88, 44,2200,'+',1080, 4,5,1125,'+', 29970,'p',16:9, 0x1,34),//1920 x 1080p @29.97/30 (Format 34)
|
||
EIA_TIMING(2880, 64,248,3432,'-', 480, 9,6, 525,'-', 59940,'p', 4:3, 0x7,35),//(2880) x 480p @59.94/60 (Format 35)
|
||
EIA_TIMING(2880, 64,248,3432,'-', 480, 9,6, 525,'-', 59940,'p',16:9, 0x7,36),//(2880) x 480p @59.94/60 (Format 36)
|
||
EIA_TIMING(2880, 48,256,3456,'-', 576, 5,5, 625,'-', 50000,'p', 4:3, 0x7,37),//(2880) x 576p @50 (Format 37)
|
||
EIA_TIMING(2880, 48,256,3456,'-', 576, 5,5, 625,'-', 50000,'p',16:9, 0x7,38),//(2880) x 576p @50 (Format 38)
|
||
EIA_TIMING(1920, 32,168,2304,'+', 540,23,5, 625,'-', 50000,'i',16:9, 0x1,39),//1920 x 1080i @50 (Format 39)
|
||
EIA_TIMING(1920, 528, 44,2640,'+', 540, 2,5, 562,'+',100000,'i',16:9, 0x1,40),//1920 x 1080i @100 (Format 40)
|
||
EIA_TIMING(1280, 440, 40,1980,'+', 720, 5,5, 750,'+',100000,'p',16:9, 0x1,41),//1280 x 720p @100 (Format 41)
|
||
EIA_TIMING( 720, 12, 64, 864,'-', 576, 5,5, 625,'-',100000,'p', 4:3, 0x1,42),//720 x 576p @100 (Format 42)
|
||
EIA_TIMING( 720, 12, 64, 864,'-', 576, 5,5, 625,'-',100000,'p',16:9, 0x1,43),//720 x 576p @100 (Format 43)
|
||
EIA_TIMING(1440, 24,126,1728,'-', 288, 2,3, 312,'-',100000,'i', 4:3, 0x2,44),//720(1440) x 576i @100 (Format 44)
|
||
EIA_TIMING(1440, 24,126,1728,'-', 288, 2,3, 312,'-',100000,'i',16:9, 0x2,45),//720(1440) x 576i @100 (Format 45)
|
||
EIA_TIMING(1920, 88, 44,2200,'+', 540, 2,5, 562,'+',119880,'i',16:9, 0x1,46),//1920 x 1080i @119.88/120 (Format 46)
|
||
EIA_TIMING(1280, 110, 40,1650,'+', 720, 5,5, 750,'+',119880,'p',16:9, 0x1,47),//1280 x 720p @119.88/120 (Format 47)
|
||
EIA_TIMING( 720, 16, 62, 858,'-', 480, 9,6, 525,'-',119880,'p', 4:3, 0x1,48),//720 x 480p @119.88/120 (Format 48)
|
||
EIA_TIMING( 720, 16, 62, 858,'-', 480, 9,6, 525,'-',119880,'p',16:9, 0x1,49),//720 x 480p @119.88/120 (Format 49)
|
||
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)
|
||
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)
|
||
EIA_TIMING( 720, 12, 64, 864,'-', 576, 5,5, 625,'-',200000,'p', 4:3, 0x1,52),//720 x 576p @200 (Format 52)
|
||
EIA_TIMING( 720, 12, 64, 864,'-', 576, 5,5, 625,'-',200000,'p',16:9, 0x1,53),//720 x 576p @200 (Format 53)
|
||
EIA_TIMING(1440, 24,126,1728,'-', 288, 2,3, 312,'-',200000,'i', 4:3, 0x2,54),//720(1440) x 576i @200 (Format 54)
|
||
EIA_TIMING(1440, 24,126,1728,'-', 288, 2,3, 312,'-',200000,'i',16:9, 0x2,55),//720(1440) x 576i @200 (Format 55)
|
||
EIA_TIMING( 720, 16, 62, 858,'-', 480, 9,6, 525,'-',239760,'p', 4:3, 0x1,56),//720 x 480p @239.76/240 (Format 56)
|
||
EIA_TIMING( 720, 16, 62, 858,'-', 480, 9,6, 525,'-',239760,'p',16:9, 0x1,57),//720 x 480p @239.76/240 (Format 57)
|
||
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)
|
||
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)
|
||
EIA_TIMING(1280,1760, 40,3300,'+', 720, 5,5, 750,'+',23976, 'p',16:9, 0x1,60),//1280 x 720p @23.97/24 (Format 60)
|
||
EIA_TIMING(1280,2420, 40,3960,'+', 720, 5,5, 750,'+',25000, 'p',16:9, 0x1,61),//1280 x 720p @25 (Format 61)
|
||
EIA_TIMING(1280,1760, 40,3300,'-', 720, 5,5, 750,'+',29970, 'p',16:9, 0x1,62),//1280 x 720p @29.97/30 (Format 62)
|
||
EIA_TIMING(1920, 88, 44,2200,'+',1080, 4,5,1125,'+',119880,'p',16:9, 0x1,63),//1920 x 1080p @119.88/120 (Format 63)
|
||
EIA_TIMING(1920, 528, 44,2640,'+',1080, 4,5,1125,'+',100000,'p',16:9, 0x1,64),//1920 x 1080p @100 (Format 64)
|
||
// Following modes are from CEA-861F
|
||
EIA_TIMING(1280,1760, 40,3300,'+', 720, 5, 5, 750,'+', 23976,'p', 64:27, 0x1, 65),//1280 x 720p @23.98/24 (Format 65)
|
||
EIA_TIMING(1280,2420, 40,3960,'+', 720, 5, 5, 750,'+', 25000,'p', 64:27, 0x1, 66),//1280 x 720p @25 (Format 66)
|
||
EIA_TIMING(1280,1760, 40,3300,'+', 720, 5, 5, 750,'+', 29970,'p', 64:27, 0x1, 67),//1280 x 720p @29.97/30 (Format 67)
|
||
EIA_TIMING(1280, 440, 40,1980,'+', 720, 5, 5, 750,'+', 50000,'p', 64:27, 0x1, 68),//1280 x 720p @50 (Format 68)
|
||
EIA_TIMING(1280, 110, 40,1650,'+', 720, 5, 5, 750,'+', 59940,'p', 64:27, 0x1, 69),//1280 x 720p @59.94/60 (Format 69)
|
||
EIA_TIMING(1280, 440, 40,1980,'+', 720, 5, 5, 750,'+',100000,'p', 64:27, 0x1, 70),//1280 x 720p @100 (Format 70)
|
||
EIA_TIMING(1280, 110, 40,1650,'+', 720, 5, 5, 750,'+',119880,'p', 64:27, 0x1, 71),//1280 x 720p @119.88/120 (Format 71)
|
||
EIA_TIMING(1920, 638, 44,2750,'+',1080, 4, 5,1125,'+', 23976,'p', 64:27, 0x1, 72),//1920 x1080p @23.98/24 (Format 72)
|
||
EIA_TIMING(1920, 528, 44,2640,'+',1080, 4, 5,1125,'+', 25000,'p', 64:27, 0x1, 73),//1920 x1080p @25 (Format 73)
|
||
EIA_TIMING(1920, 88, 44,2200,'+',1080, 4, 5,1125,'+', 29970,'p', 64:27, 0x1, 74),//1920 x1080p @29.97/30 (Format 74)
|
||
EIA_TIMING(1920, 528, 44,2640,'+',1080, 4, 5,1125,'+', 50000,'p', 64:27, 0x1, 75),//1920 x1080p @50 (Format 75)
|
||
EIA_TIMING(1920, 88, 44,2200,'+',1080, 4, 5,1125,'+', 59940,'p', 64:27, 0x1, 76),//1920 x1080p @59.94/60 (Format 76)
|
||
EIA_TIMING(1920, 528, 44,2640,'+',1080, 4, 5,1125,'+',100000,'p', 64:27, 0x1, 77),//1920 x1080p @100 (Format 77)
|
||
EIA_TIMING(1920, 88, 44,2200,'+',1080, 4, 5,1125,'+',119880,'p', 64:27, 0x1, 78),//1920 x1080p @119.88/120 (Format 78)
|
||
EIA_TIMING(1680,1360, 40,3300,'+', 720, 5, 5, 750,'+', 23976,'p', 64:27, 0x1, 79),//1680 x 720p @23.98/24 (Format 79)
|
||
EIA_TIMING(1680,1228, 40,3168,'+', 720, 5, 5, 750,'+', 25000,'p', 64:27, 0x1, 80),//1680 x 720p @25 (Format 80)
|
||
EIA_TIMING(1680, 700, 40,2640,'+', 720, 5, 5, 750,'+', 29970,'p', 64:27, 0x1, 81),//1680 x 720p @29.97/30 (Format 81)
|
||
EIA_TIMING(1680, 260, 40,2200,'+', 720, 5, 5, 750,'+', 50000,'p', 64:27, 0x1, 82),//1680 x 720p @50 (Format 82)
|
||
EIA_TIMING(1680, 260, 40,2200,'+', 720, 5, 5, 750,'+', 59940,'p', 64:27, 0x1, 83),//1680 x 720p @59.94/60 (Format 83)
|
||
EIA_TIMING(1680, 60, 40,2000,'+', 720, 5, 5, 825,'+',100000,'p', 64:27, 0x1, 84),//1680 x 720p @100 (Format 84)
|
||
EIA_TIMING(1680, 60, 40,2000,'+', 720, 5, 5, 825,'+',119880,'p', 64:27, 0x1, 85),//1680 x 720p @119.88/120 (Format 85)
|
||
EIA_TIMING(2560, 998, 44,3750,'+',1080, 4, 5,1100,'+', 23976,'p', 64:27, 0x1, 86),//2560 x1080p @23.98/24 (Format 86)
|
||
EIA_TIMING(2560, 448, 44,3200,'+',1080, 4, 5,1125,'+', 25000,'p', 64:27, 0x1, 87),//2560 x1080p @25 (Format 87)
|
||
EIA_TIMING(2560, 768, 44,3520,'+',1080, 4, 5,1125,'+', 29970,'p', 64:27, 0x1, 88),//2560 x1080p @29.97/30 (Format 88)
|
||
EIA_TIMING(2560, 548, 44,3300,'+',1080, 4, 5,1125,'+', 50000,'p', 64:27, 0x1, 89),//2560 x1080p @50 (Format 89)
|
||
EIA_TIMING(2560, 248, 44,3000,'+',1080, 4, 5,1100,'+', 59940,'p', 64:27, 0x1, 90),//2560 x1080p @59.94/60 (Format 90)
|
||
EIA_TIMING(2560, 218, 44,2970,'+',1080, 4, 5,1250,'+',100000,'p', 64:27, 0x1, 91),//2560 x1080p @100 (Format 91)
|
||
EIA_TIMING(2560, 548, 44,3300,'+',1080, 4, 5,1250,'+',119880,'p', 64:27, 0x1, 92),//2560 x1080p @119.88/120 (Format 92)
|
||
EIA_TIMING(3840,1276, 88,5500,'+',2160, 8,10,2250,'+', 23976,'p', 16:9, 0x1, 93),//3840 x2160p @23.98/24 (Format 93)
|
||
EIA_TIMING(3840,1056, 88,5280,'+',2160, 8,10,2250,'+', 25000,'p', 16:9, 0x1, 94),//3840 x2160p @25 (Format 94)
|
||
EIA_TIMING(3840, 176, 88,4400,'+',2160, 8,10,2250,'+', 29970,'p', 16:9, 0x1, 95),//3840 x2160p @29.97/30 (Format 95)
|
||
EIA_TIMING(3840,1056, 88,5280,'+',2160, 8,10,2250,'+', 50000,'p', 16:9, 0x1, 96),//3840 x2160p @50 (Format 96)
|
||
EIA_TIMING(3840, 176, 88,4400,'+',2160, 8,10,2250,'+', 59940,'p', 16:9, 0x1, 97),//3840 x2160p @59.94/60 (Format 97)
|
||
EIA_TIMING(4096,1020, 88,5500,'+',2160, 8,10,2250,'+', 23976,'p',256:135, 0x1, 98),//4096 x2160p @23.98/24 (Format 98)
|
||
EIA_TIMING(4096, 968, 88,5280,'+',2160, 8,10,2250,'+', 25000,'p',256:135, 0x1, 99),//4096 x2160p @25 (Format 99)
|
||
EIA_TIMING(4096, 88, 88,4400,'+',2160, 8,10,2250,'+', 29970,'p',256:135, 0x1,100),//4096 x2160p @29.97/30 (Format 100)
|
||
EIA_TIMING(4096, 968, 88,5280,'+',2160, 8,10,2250,'+', 50000,'p',256:135, 0x1,101),//4096 x2160p @50 (Format 101)
|
||
EIA_TIMING(4096, 88, 88,4400,'+',2160, 8,10,2250,'+', 59940,'p',256:135, 0x1,102),//4096 x2160p @59.94/60 (Format 102)
|
||
EIA_TIMING(3840,1276, 88,5500,'+',2160, 8,10,2250,'+', 23976,'p', 64:27, 0x1,103),//3840 x2160p @23.98/24 (Format 103)
|
||
EIA_TIMING(3840,1056, 88,5280,'+',2160, 8,10,2250,'+', 25000,'p', 64:27, 0x1,104),//3840 x2160p @25 (Format 104)
|
||
EIA_TIMING(3840, 176, 88,4400,'+',2160, 8,10,2250,'+', 29970,'p', 64:27, 0x1,105),//3840 x2160p @29.97/30 (Format 105)
|
||
EIA_TIMING(3840,1056, 88,5280,'+',2160, 8,10,2250,'+', 50000,'p', 64:27, 0x1,106),//3840 x2160p @50 (Format 106)
|
||
EIA_TIMING(3840, 176, 88,4400,'+',2160, 8,10,2250,'+', 59940,'p', 64:27, 0x1,107),//3840 x2160p @59.94/60 (Format 107)
|
||
// VIC 108-127 timings are from CTA-861-G_FINAL_revised_2018_Errata_2.pdf
|
||
EIA_TIMING(1280, 960, 40, 2500,'+', 720, 5, 5, 750,'+', 47950,'p', 16:9, 0x1,108),//1280 x 720p @47.95/48 (Format 108)
|
||
EIA_TIMING(1280, 960, 40, 2500,'+', 720, 5, 5, 750,'+', 47950,'p', 64:27, 0x1,109),//1280 x 720p @47.95/48 (Format 109)
|
||
EIA_TIMING(1680, 810, 40, 2750,'+', 720, 5, 5, 750,'+', 47950,'p', 64:27, 0x1,110),//1680 x 720p @47.95/48 (Format 110)
|
||
EIA_TIMING(1920, 638, 44, 2750,'+',1080, 4, 5,1125,'+', 47950,'p', 16:9, 0x1,111),//1920 x 1080p @47.95/48 (Format 111)
|
||
EIA_TIMING(1920, 638, 44, 2750,'+',1080, 4, 5,1125,'+', 47950,'p', 64:27, 0x1,112),//1920 x 1080p @47.95/48 (Format 112)
|
||
EIA_TIMING(2560, 998, 44, 3750,'+',1080, 4, 5,1100,'+', 47950,'p', 64:27, 0x1,113),//2560 x 1080p @47.95/48 (Format 113)
|
||
EIA_TIMING(3840,1276, 88, 5500,'+',2160, 8,10,2250,'+', 47950,'p', 16:9, 0x1,114),//3840 x 2160p @47.95/48 (Format 114)
|
||
EIA_TIMING(4096,1020, 88, 5500,'+',2160, 8,10,2250,'+', 47950,'p',256:135, 0x1,115),//4096 x 2160p @47.95/48 (Format 115)
|
||
EIA_TIMING(3840,1276, 88, 5500,'+',2160, 8,10,2250,'+', 47950,'p', 64:27, 0x1,116),//3840 x 2160p @47.95/48 (Format 116)
|
||
EIA_TIMING(3840,1056, 88, 5280,'+',2160, 8,10,2250,'+',100000,'p', 16:9, 0x1,117),//3840 x 2160p @100 (Format 117)
|
||
EIA_TIMING(3840, 176, 88, 4400,'+',2160, 8,10,2250,'+',119880,'p', 16:9, 0x1,118),//3840 x 2160p @119.88/120 (Format 118)
|
||
EIA_TIMING(3840,1056, 88, 5280,'+',2160, 8,10,2250,'+',100000,'p', 64:27, 0x1,119),//3840 x 2160p @100 (Format 119)
|
||
EIA_TIMING(3840, 176, 88, 4400,'+',2160, 8,10,2250,'+',119880,'p', 64:27, 0x1,120),//3840 x 2160p @119.88/120 (Format 120)
|
||
EIA_TIMING(5120,1996, 88, 7500,'+',2160, 8,10,2200,'+', 23976,'p', 64:27, 0x1,121),//5120 x 2160p @23.98/24 (Format 121)
|
||
EIA_TIMING(5120,1696, 88, 7200,'+',2160, 8,10,2200,'+', 25000,'p', 64:27, 0x1,122),//5120 x 2160p @25 (Format 122)
|
||
EIA_TIMING(5120, 664, 88, 6000,'+',2160, 8,10,2200,'+', 29970,'p', 64:27, 0x1,123),//5120 x 2160p @29.97/30 (Format 123)
|
||
EIA_TIMING(5120, 746, 88, 6250,'+',2160, 8,10,2475,'+', 47950,'p', 64:27, 0x1,124),//5120 x 2160p @47.95/48 (Format 124)
|
||
EIA_TIMING(5120,1096, 88, 6600,'+',2160, 8,10,2250,'+', 50000,'p', 64:27, 0x1,125),//5120 x 2160p @50 (Format 125)
|
||
EIA_TIMING(5120, 164, 88, 5500,'+',2160, 8,10,2250,'+', 59940,'p', 64:27, 0x1,126),//5120 x 2160p @59.94/60 (Format 126)
|
||
EIA_TIMING(5120,1096, 88, 6600,'+',2160, 8,10,2250,'+',100000,'p', 64:27, 0x1,127),//5120 x 2160p @100 (Format 127)
|
||
// VIC 128-192 are Forbidden and should be never used. But to simplify the SVD access, put a default timing here.
|
||
// We can remove these after adding a function to access CEA Timings.
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
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)
|
||
// VIC 193-219 timings are from CTA-861-G_FINAL_revised_2018_Errata_2.pdf
|
||
EIA_TIMING( 5120, 164, 88, 5500,'+',2160, 8,10,2250,'+',120000,'p', 64:27,0x1,193),// 5120 x 2160p @119.88/120 (Format 193)
|
||
EIA_TIMING( 7680,2552,176,11000,'+',4320,16,20,4500,'+', 23976,'p', 16:9,0x1,194),// 7680 x 4320p @23.98/24 (Format 194)
|
||
EIA_TIMING( 7680,2352,176,10800,'+',4320,16,20,4400,'+', 25000,'p', 16:9,0x1,195),// 7680 x 4320p @25 (Format 195)
|
||
EIA_TIMING( 7680, 552,176, 9000,'+',4320,16,20,4400,'+', 29970,'p', 16:9,0x1,196),// 7680 x 4320p @29.97/30 (Format 196)
|
||
EIA_TIMING( 7680,2552,176,11000,'+',4320,16,20,4500,'+', 47950,'p', 16:9,0x1,197),// 7680 x 4320p @47.95/48 (Format 197)
|
||
EIA_TIMING( 7680,2352,176,10800,'+',4320,16,20,4400,'+', 50000,'p', 16:9,0x1,198),// 7680 x 4320p @50 (Format 198)
|
||
EIA_TIMING( 7680, 552,176, 9000,'+',4320,16,20,4400,'+', 59940,'p', 16:9,0x1,199),// 7680 x 4320p @59.94/60 (Format 199)
|
||
EIA_TIMING( 7680,2112,176,10560,'+',4320,16,20,4500,'+',100000,'p', 16:9,0x1,200),// 7680 x 4320p @100 (Format 200)
|
||
EIA_TIMING( 7680, 352,176, 8000,'+',4320,16,20,4500,'+',119880,'p', 16:9,0x1,201),// 7680 x 4320p @119.88/120 (Format 201)
|
||
EIA_TIMING( 7680,2552,176,11000,'+',4320,16,20,4500,'+', 23976,'p', 64:27,0x1,202),// 7680 x 4320p @23.98/24 (Format 202)
|
||
EIA_TIMING( 7680,2352,176,10800,'+',4320,16,20,4400,'+', 25000,'p', 64:27,0x1,203),// 7680 x 4320p @25 (Format 203)
|
||
EIA_TIMING( 7680, 552,176, 9000,'+',4320,16,20,4400,'+', 29970,'p', 64:27,0x1,204),// 7680 x 4320p @29.97/30 (Format 204)
|
||
EIA_TIMING( 7680,2552,176,11000,'+',4320,16,20,4500,'+', 47950,'p', 64:27,0x1,205),// 7680 x 4320p @47.95/48 (Format 205)
|
||
EIA_TIMING( 7680,2352,176,10800,'+',4320,16,20,4400,'+', 50000,'p', 64:27,0x1,206),// 7680 x 4320p @50 (Format 206)
|
||
EIA_TIMING( 7680, 552,176, 9000,'+',4320,16,20,4400,'+', 59940,'p', 64:27,0x1,207),// 7680 x 4320p @59.94/60 (Format 207)
|
||
EIA_TIMING( 7680,2112,176,10560,'+',4320,16,20,4500,'+',100000,'p', 64:27,0x1,208),// 7680 x 4320p @100 (Format 208)
|
||
EIA_TIMING( 7680, 352,176, 8800,'+',4500,16,20,4950,'+',119880,'p', 64:27,0x1,209),// 7680 x 4320p @119.88/120 (Format 209)
|
||
EIA_TIMING(10240,1492,176,12500,'+',4320,16,20,4950,'+', 23976,'p', 64:27,0x1,210),//10240 x 4320p @23.98/24 (Format 210)
|
||
EIA_TIMING(10240,2492,176,13500,'+',4320,16,20,4400,'+', 25000,'p', 64:27,0x1,211),//10240 x 4320p @25 (Format 211)
|
||
EIA_TIMING(10240, 288,176,11000,'+',4320,16,20,4500,'+', 29970,'p', 64:27,0x1,212),//10240 x 4320p @29.97/30 (Format 212)
|
||
EIA_TIMING(10240,1492,176,12500,'+',4320,16,20,4950,'+', 47950,'p', 64:27,0x1,213),//10240 x 4320p @47.95/48 (Format 213)
|
||
EIA_TIMING(10240,2492,176,13500,'+',4320,16,20,4400,'+', 44000,'p', 64:27,0x1,214),//10240 x 4320p @50 (Format 214)
|
||
EIA_TIMING(10240, 288,176,11000,'+',4320,16,20,4500,'+', 59940,'p', 64:27,0x1,215),//10240 x 4320p @59.94/60 (Format 215)
|
||
EIA_TIMING(10240,2192,176,13200,'+',4320,16,20,4500,'+',100000,'p', 64:27,0x1,216),//10240 x 4320p @100 (Format 216)
|
||
EIA_TIMING(10240, 288,176,11000,'+',4320,16,20,4500,'+',119880,'p', 64:27,0x1,217),//10240 x 4320p @119.88/120 (Format 217)
|
||
EIA_TIMING( 4096, 800, 88, 5280,'+',2160, 8,10,2250,'+',100000,'p',256:135,0x1,218),// 4096 x 2160p @100 (Format 218)
|
||
EIA_TIMING( 4096, 88, 88, 4400,'+',2160, 8,10,2250,'+',119880,'p',256:135,0x1,219),// 4096 x 2160p @119.88/120 (Format 219)
|
||
// 220-255 Reserved for the Future
|
||
// the end
|
||
EIA_TIMING(0,0,0,0,'-',0,0,0,0,'-',0,'p',4:3,0,0)
|
||
};
|
||
static NvU32 MAX_CEA861B_FORMAT = sizeof(EIA861B)/sizeof(EIA861B[0]) - 1;
|
||
|
||
static const NvU32 EIA861B_DUAL_ASPECT_VICS[][2] =
|
||
{
|
||
{ 2, 3 }, // 720x480p 59.94Hz/60Hz
|
||
{ 4, 69 }, // 1280x720p 59.94Hz/60Hz
|
||
{ 6, 7 }, // 720(1440)x480i 59.94Hz/60Hz
|
||
{ 8, 9 }, // 720(1440)x240p 59.94Hz/60Hz
|
||
|
||
{ 10, 11 }, // 2880x480i 59.94Hz/60Hz
|
||
{ 12, 13 }, // 2880x240p 59.94Hz/60Hz
|
||
{ 14, 15 }, // 1440x480p 59.94Hz/60Hz
|
||
{ 16, 76 }, // 1920x1080p 59.94Hz/60Hz
|
||
{ 17, 18 }, // 720x576p 50Hz
|
||
{ 19, 68 }, // 1280x720p 50Hz
|
||
|
||
{ 21, 22 }, // 720(1440)x576i 50Hz
|
||
{ 23, 24 }, // 720(1440)x288p 50Hz
|
||
{ 25, 26 }, // 2880x576i 50Hz
|
||
{ 27, 28 }, // 2880x288p 50Hz
|
||
{ 29, 30 }, // 1440x576p 50Hz
|
||
|
||
{ 31, 75 }, // 1920x1080p 50Hz
|
||
{ 32, 72 }, // 1920x1080p 23.98Hz/24Hz
|
||
{ 33, 73 }, // 1920x1080p 25Hz
|
||
{ 34, 74 }, // 1920x1080p 29.97Hz/30Hz
|
||
{ 35, 36 }, // 2880x480p 59.94Hz/60Hz
|
||
{ 37, 38 }, // 2880x576p 50Hz
|
||
|
||
{ 41, 70 }, // 1280x720p 100Hz
|
||
{ 42, 43 }, // 720x576p 100Hz
|
||
{ 44, 45 }, // 720(1440)x576i 100Hz
|
||
{ 47, 71 }, // 1280x720p 119.88/120Hz
|
||
{ 48, 49 }, // 720x480p 119.88/120Hz
|
||
|
||
{ 50, 51 }, // 720(1440)x480i 119.88/120Hz
|
||
{ 52, 53 }, // 720x576p 200Hz
|
||
{ 54, 55 }, // 720(1440)x576i 200Hz
|
||
{ 56, 57 }, // 720x480p 239.76/240Hz
|
||
{ 58, 59 }, // 720(1440)x480i 239.76/240Hz
|
||
|
||
{ 60, 65 }, // 1280x720p 23.98Hz/24Hz
|
||
{ 61, 66 }, // 1280x720p 25Hz
|
||
{ 62, 67 }, // 1280x720p 29.97Hz/30Hz
|
||
{ 63, 78 }, // 1920x1080p 119.88/120Hz
|
||
{ 64, 77 }, // 1920x1080p 100Hz
|
||
|
||
{ 93, 103 }, // 3840x2160p 23.98Hz/24Hz
|
||
{ 94, 104 }, // 3840x2160p 25Hz
|
||
{ 95, 105 }, // 3840x2160p 29.97Hz/30Hz
|
||
{ 96, 106 }, // 3840x2160p 50Hz
|
||
{ 97, 107 }, // 3840x2160p 59.94Hz/60Hz
|
||
};
|
||
static NvU32 MAX_EIA861B_DUAL_ASPECT_VICS = sizeof(EIA861B_DUAL_ASPECT_VICS) / sizeof(EIA861B_DUAL_ASPECT_VICS[0]);
|
||
|
||
static const NVT_TIMING PSF_TIMING[]=
|
||
{
|
||
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
|
||
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
|
||
|
||
// the end
|
||
EIA_TIMING(0,0,0,0,'-',0,0,0,0,'-',0,'p',4:3,0,0)
|
||
};
|
||
static NvU32 MAX_PSF_FORMAT = sizeof(PSF_TIMING)/sizeof(PSF_TIMING[0]) - 1;
|
||
|
||
static const NVT_TIMING HDMI_EXT_4Kx2K_TIMING[]=
|
||
{
|
||
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
|
||
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
|
||
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
|
||
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
|
||
|
||
// the end
|
||
EIA_TIMING(0,0,0,0,'-',0,0,0,0,'-',0,'p',4:3,0,0)
|
||
};
|
||
static NvU32 MAX_HDMI_EXT_4Kx2K_FORMAT = sizeof(HDMI_EXT_4Kx2K_TIMING)/sizeof(HDMI_EXT_4Kx2K_TIMING[0]) - 1;
|
||
|
||
// HDMI 1.4a mandatory 3D video formats.
|
||
// From HDMI 1.4a specification page 147 of 201, table 8-15. And HDMI 1.4a Complaince test specification page 190.
|
||
static const HDMI3DDETAILS HDMI_MANDATORY_3D_FORMATS[] =
|
||
{
|
||
{32, NVT_HDMI_3D_SUPPORTED_FRAMEPACK_MASK | NVT_HDMI_3D_SUPPORTED_TOPBOTTOM_MASK, 0}, // 1920 x 1080p @ 24 Hz
|
||
{ 4, NVT_HDMI_3D_SUPPORTED_FRAMEPACK_MASK | NVT_HDMI_3D_SUPPORTED_TOPBOTTOM_MASK, 0}, // 1280 x 720p @ 60 Hz
|
||
{19, NVT_HDMI_3D_SUPPORTED_FRAMEPACK_MASK | NVT_HDMI_3D_SUPPORTED_TOPBOTTOM_MASK, 0}, // 1280 x 720p @ 50 Hz
|
||
{ 5, NVT_HDMI_3D_SUPPORTED_SIDEBYSIDEHALF_MASK, NVT_HDMI_VS_BYTE_OPT1_HDMI_3DEX_SSH}, // 1920 x 1080i @ 60 Hz
|
||
{20, NVT_HDMI_3D_SUPPORTED_SIDEBYSIDEHALF_MASK, NVT_HDMI_VS_BYTE_OPT1_HDMI_3DEX_SSH} // 1920 x 1080i @ 50 Hz
|
||
};
|
||
static NvU32 MAX_HDMI_MANDATORY_3D_FORMAT = sizeof(HDMI_MANDATORY_3D_FORMATS) / sizeof(HDMI_MANDATORY_3D_FORMATS[0]);
|
||
|
||
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};
|
||
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};
|
||
static const NVT_VENDOR_SPECIFIC_INFOFRAME DEFAULT_VENDOR_SPECIFIC_INFOFRAME = {/*header*/{0x01,1,6}, {/*byte1*/3, /*byte2*/0x0c, /*byte3*/0, /*byte4*/0, /*byte5*/0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}};
|
||
|
||
// parse the 861 detailed timing info
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void parse861ExtDetailedTiming(NvU8 *pEdidExt,
|
||
NvU8 basicCaps,
|
||
NVT_EDID_INFO *pInfo)
|
||
{
|
||
NvU32 count = 0;
|
||
EIA861EXTENSION *pEIA861 = (EIA861EXTENSION *) pEdidExt;
|
||
DETAILEDTIMINGDESCRIPTOR *pDTD;
|
||
NVT_TIMING newTiming;
|
||
|
||
// sanity check for CEA ext block
|
||
if ((pEIA861->tag != 0x2) || (0 == pEIA861->offset) || (NVT_CEA861_REV_NONE == pEIA861->revision))
|
||
{
|
||
// no CEA ext block, return
|
||
return;
|
||
}
|
||
|
||
// Get all detailed timings in CEA ext block
|
||
pDTD = (DETAILEDTIMINGDESCRIPTOR *)&pEdidExt[pEIA861->offset];
|
||
|
||
while((NvU8 *)pDTD + sizeof(DETAILEDTIMINGDESCRIPTOR) < (pEdidExt + sizeof(EDIDV1STRUC) - 1) &&
|
||
pDTD->wDTPixelClock != 0)
|
||
{
|
||
NVMISC_MEMSET(&newTiming, 0, sizeof(newTiming));
|
||
|
||
if (parseEdidDetailedTimingDescriptor((NvU8 *)pDTD,
|
||
&newTiming) == NVT_STATUS_SUCCESS)
|
||
{
|
||
NVT_SNPRINTF((char *)newTiming.etc.name, sizeof(newTiming.etc.name),
|
||
"CTA-861Long:%5dx%4dx%3d.%03dHz/%s",
|
||
(int)newTiming.HVisible,
|
||
(int)((newTiming.interlaced ? 2 : 1) * newTiming.VVisible),
|
||
(int)newTiming.etc.rrx1k/1000,
|
||
(int)newTiming.etc.rrx1k%1000,
|
||
(newTiming.interlaced ? "I":"P"));
|
||
newTiming.etc.name[sizeof(newTiming.etc.name)-1] = '\0';
|
||
newTiming.etc.status = NVT_STATUS_EDID_EXT_DTDn(++count);
|
||
|
||
if (!assignNextAvailableTiming(pInfo, &newTiming))
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
pDTD ++;
|
||
}
|
||
}
|
||
|
||
// parse the 861B short timing descriptor
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void parse861bShortTiming(NVT_EDID_CEA861_INFO *pExt861,
|
||
void *pRawInfo,
|
||
NVT_CTA861_ORIGIN flag)
|
||
{
|
||
NvU32 i;
|
||
NvU32 vic, bytePos, bitPos;
|
||
NVT_TIMING newTiming;
|
||
NVT_HDMI_FORUM_INFO *pHfvs = NULL;
|
||
NVT_EDID_INFO *pInfo = NULL;
|
||
NVT_DISPLAYID_2_0_INFO *pDisplayID20 = NULL;
|
||
|
||
NvU8 *pVic = pExt861->video;
|
||
NvU32 total_svd = pExt861->total_svd;
|
||
NvU8 *pYuv420Map = pExt861->valid.y420cmdb ? pExt861->map_y420cmdb : NULL;
|
||
NvU8 yuv420MapCount = pExt861->total_y420cmdb;
|
||
|
||
if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
|
||
{
|
||
pInfo = (NVT_EDID_INFO *)pRawInfo;
|
||
pHfvs = &pInfo->hdmiForumInfo;
|
||
}
|
||
else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
|
||
{
|
||
pDisplayID20 = (NVT_DISPLAYID_2_0_INFO *)pRawInfo;
|
||
pHfvs = &pDisplayID20->vendor_specific.hfvs;
|
||
}
|
||
else
|
||
{
|
||
return;
|
||
}
|
||
|
||
for (i = 0; i < total_svd; i++)
|
||
{
|
||
vic = NVT_GET_CTA_8BIT_VIC(pVic[i]);
|
||
|
||
if (vic == 0 || vic > MAX_CEA861B_FORMAT)
|
||
continue;
|
||
|
||
// assign corresponding CEA format's timing from pre-defined CE timing table, EIA861B
|
||
newTiming = EIA861B[vic-1];
|
||
newTiming.etc.status = NVT_STATUS_EDID_861STn(vic);
|
||
|
||
// set CEA format to location of _CEA_FORMAT. _CEA_FORMAT isn't set in pre-defined CE timing from
|
||
// EIA861B table
|
||
if (NVT_GET_TIMING_STATUS_SEQ(newTiming.etc.status) !=
|
||
NVT_CEA861_640X480P_59940HZ_4X3)
|
||
{
|
||
// Although IT 640x480 video timing has a CE id, it is not a CE timing. See 3.1
|
||
// "General Video Format Requirements" section in CEA-861-E spec
|
||
NVT_SET_CEA_FORMAT(newTiming.etc.status,
|
||
NVT_GET_TIMING_STATUS_SEQ(newTiming.etc.status));
|
||
}
|
||
|
||
// calculate the pixel clock
|
||
newTiming.pclk = RRx1kToPclk(&newTiming);
|
||
|
||
if ((vic <= 64) && (pVic[i] & NVT_CTA861_VIDEO_NATIVE_MASK))
|
||
{
|
||
NVT_SET_NATIVE_TIMING_FLAG(newTiming.etc.status);
|
||
}
|
||
NVT_SNPRINTF((char *)newTiming.etc.name, sizeof(newTiming.etc.name),
|
||
"CTA-861G:#%3d:%5dx%4dx%3d.%03dHz/%s", (int)vic,
|
||
(int)newTiming.HVisible,
|
||
(int)((newTiming.interlaced ? 2 : 1)*newTiming.VVisible),
|
||
(int)newTiming.etc.rrx1k/1000, (int)newTiming.etc.rrx1k%1000,
|
||
(newTiming.interlaced ? "I":"P"));
|
||
newTiming.etc.name[sizeof(newTiming.etc.name)-1] = '\0';
|
||
|
||
// if yuv420 is supported in the video SVDs, it is indicated by CMDB bitmap
|
||
bytePos = i / (8 * sizeof(NvU8));
|
||
if (bytePos < yuv420MapCount)
|
||
{
|
||
bitPos = 1 << (i % (8 * sizeof(NvU8)));
|
||
if (pYuv420Map[bytePos] & bitPos)
|
||
{
|
||
// pHfvs->dcXXX are only for YCbCr420; when bitPos is set, 8bpc yuv420 always supported
|
||
UPDATE_BPC_FOR_COLORFORMAT(newTiming.etc.yuv420, 0, 1,
|
||
pHfvs->dc_30bit_420,
|
||
pHfvs->dc_36bit_420, 0,
|
||
pHfvs->dc_48bit_420);
|
||
}
|
||
}
|
||
|
||
// Y420CMDB with L == 1, implies yuv420MapCount == 0 but all SVDs support 420
|
||
if (pYuv420Map && yuv420MapCount == 0)
|
||
{
|
||
UPDATE_BPC_FOR_COLORFORMAT(newTiming.etc.yuv420, 0, 1,
|
||
pHfvs->dc_30bit_420,
|
||
pHfvs->dc_36bit_420, 0,
|
||
pHfvs->dc_48bit_420);
|
||
}
|
||
|
||
if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
|
||
{
|
||
if (!assignNextAvailableTiming(pInfo, &newTiming))
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
|
||
{
|
||
newTiming.etc.flag |= NVT_FLAG_DISPLAYID_2_0_TIMING;
|
||
|
||
if (!assignNextAvailableDisplayId20Timing(pDisplayID20, &newTiming))
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// parse the 861B short Yuv420 timing descriptor
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void parse861bShortYuv420Timing(NVT_EDID_CEA861_INFO *pExt861,
|
||
void *pRawInfo,
|
||
NVT_CTA861_ORIGIN flag)
|
||
{
|
||
NvU32 i;
|
||
NvU8 vic;
|
||
NVT_TIMING newTiming;
|
||
NVT_HDMI_FORUM_INFO *pHfvs = NULL;
|
||
NVT_EDID_INFO *pInfo = NULL;
|
||
NVT_DISPLAYID_2_0_INFO *pDisplayID20 = NULL;
|
||
NvU8 *pYuv420Vic = pExt861->svd_y420vdb;
|
||
NvU32 total_y420vdb = pExt861->total_y420vdb;
|
||
NvU8 *pVdb = pExt861->video;
|
||
NvU32 total_svd = pExt861->total_svd;
|
||
NvU32 total_timings = 0;
|
||
|
||
if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
|
||
{
|
||
pInfo = (NVT_EDID_INFO *)pRawInfo;
|
||
pHfvs = &pInfo->hdmiForumInfo;
|
||
total_timings = pInfo->total_timings;
|
||
}
|
||
else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
|
||
{
|
||
pDisplayID20 = (NVT_DISPLAYID_2_0_INFO *)pRawInfo;
|
||
pHfvs = &pDisplayID20->vendor_specific.hfvs;
|
||
total_timings = pDisplayID20->total_timings;
|
||
}
|
||
else
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (total_timings == 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
|
||
for (i = 0; i < total_y420vdb; i++)
|
||
{
|
||
vic = NVT_GET_CTA_8BIT_VIC(pYuv420Vic[i]);
|
||
|
||
if (vic == 0 || vic > MAX_CEA861B_FORMAT)
|
||
continue;
|
||
|
||
// assign corresponding CEA format's timing from pre-defined CE timing table, EIA861B
|
||
newTiming = EIA861B[vic-1];
|
||
|
||
// if yuv420 is supported in the video SVDs, it is indicated by yuv420vdb
|
||
if(total_svd > 0)
|
||
{
|
||
NvU8 idx, j;
|
||
NvBool bFound = NV_FALSE;
|
||
for (idx=0; idx < total_svd; idx++)
|
||
{
|
||
if (pVdb[idx] == vic)
|
||
{
|
||
for (j=0; j < total_timings; j++)
|
||
{
|
||
NVT_TIMING *timing = NULL;
|
||
|
||
if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
|
||
{
|
||
timing = &pInfo->timing[j];
|
||
}
|
||
else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
|
||
{
|
||
timing = &pDisplayID20->timing[j];
|
||
}
|
||
|
||
if (NvTiming_IsTimingExactEqual(timing, &newTiming))
|
||
{
|
||
bFound = NV_TRUE;
|
||
// we found one in pExt861->video[]. pHfvs->dcXXX are only for YCbCr420, so we can support:
|
||
// 1. 8bpc yuv420 always supported.
|
||
// 2. only add yuv420 and its deep colour caps into Video Data Block
|
||
UPDATE_BPC_FOR_COLORFORMAT(timing->etc.yuv420, 0, 1,
|
||
pHfvs->dc_30bit_420,
|
||
pHfvs->dc_36bit_420, 0,
|
||
pHfvs->dc_48bit_420);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (bFound) continue;
|
||
}
|
||
|
||
newTiming.etc.status = NVT_STATUS_EDID_861STn(vic);
|
||
|
||
// set CEA format to location of _CEA_FORMAT. _CEA_FORMAT isn't set in pre-defined CE timing from
|
||
// EIA861B table
|
||
if (NVT_GET_TIMING_STATUS_SEQ(newTiming.etc.status) !=
|
||
NVT_CEA861_640X480P_59940HZ_4X3)
|
||
{
|
||
// Although IT 640x480 video timing has a CE id, it is not a CE timing. See 3.1
|
||
// "General Video Format Requirements" section in CEA-861-E spec
|
||
NVT_SET_CEA_FORMAT(newTiming.etc.status,
|
||
NVT_GET_TIMING_STATUS_SEQ(newTiming.etc.status));
|
||
}
|
||
|
||
// calculate the pixel clock
|
||
newTiming.pclk = RRx1kToPclk(&newTiming);
|
||
|
||
// From CTA-861-F: By default, Y420VDB SVDs, when present in the EDID, shall be less preferred than all regular Video Data Block SVDs.
|
||
// So it should use normal VIC code without native flag.
|
||
//if ((vic <= 64) && (pVic[i] & NVT_CTA861_VIDEO_NATIVE_MASK))
|
||
//{
|
||
// NVT_SET_NATIVE_TIMING_FLAG(newTiming.etc.status);
|
||
//}
|
||
NVT_SNPRINTF((char *)newTiming.etc.name, sizeof(newTiming.etc.name),
|
||
"CTA-861G:#%3d:%5dx%4dx%3d.%03dHz/%s", (int)vic,
|
||
(int)newTiming.HVisible,
|
||
(int)((newTiming.interlaced ? 2 : 1)*newTiming.VVisible),
|
||
(int)newTiming.etc.rrx1k/1000, (int)newTiming.etc.rrx1k%1000,
|
||
(newTiming.interlaced ? "I":"P"));
|
||
newTiming.etc.name[sizeof(newTiming.etc.name)-1] = '\0';
|
||
|
||
// update supported color space; any VICs enumerated in the Y420VDB are yuv420 only modes
|
||
// update 8bpc supported color space; other bpc updated once VSDB is parsed
|
||
|
||
// pHfvs->dcXXX are only for YCbCr420; when Vic enumerated here, 8bpc yuv420 always supported
|
||
UPDATE_BPC_FOR_COLORFORMAT(newTiming.etc.yuv420, 0, 1,
|
||
pHfvs->dc_30bit_420,
|
||
pHfvs->dc_36bit_420, 0,
|
||
pHfvs->dc_48bit_420);
|
||
|
||
if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
|
||
{
|
||
if (!assignNextAvailableTiming(pInfo, &newTiming))
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
|
||
{
|
||
newTiming.etc.flag |= NVT_FLAG_DISPLAYID_2_0_TIMING;
|
||
|
||
if (assignNextAvailableDisplayId20Timing(pDisplayID20, &newTiming))
|
||
{
|
||
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Currently, we only focus on the particular application in CEA861-F spec described
|
||
// "One particular application is a Sink that prefers a Video Format that is not listed as an SVD in a VDB
|
||
// but instead listed in a YCBCR 4:2:0 Video Data Block"
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void parse861bShortPreferredTiming(NVT_EDID_CEA861_INFO *pExt861,
|
||
void *pRawInfo,
|
||
NVT_CTA861_ORIGIN flag)
|
||
{
|
||
NvU32 isMatch,i,j = 0;
|
||
|
||
NVT_TIMING preferTiming;
|
||
NVT_EDID_INFO *pInfo = NULL;
|
||
NVT_DISPLAYID_2_0_INFO *pDisplayID20 = NULL;
|
||
NvU8 *pSvr = pExt861->svr_vfpdb;
|
||
NvU8 totalSvr = pExt861->total_vfpdb;
|
||
NvU8 kth = 0;
|
||
NvU8 extKth = 0;
|
||
NvU8 DTDCount = 0;
|
||
NvU8 extDTDCount = 0;
|
||
|
||
if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
|
||
{
|
||
pInfo = (NVT_EDID_INFO *)pRawInfo;
|
||
}
|
||
else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
|
||
{
|
||
pDisplayID20 = (NVT_DISPLAYID_2_0_INFO *)pRawInfo;
|
||
}
|
||
else
|
||
{
|
||
return;
|
||
}
|
||
|
||
// finding all the DTD
|
||
if (flag == FROM_CTA861_EXTENSION)
|
||
{
|
||
for (j = 0; j < pInfo->total_timings; j++)
|
||
{
|
||
if (NVT_IS_DTD(pInfo->timing[j].etc.status))
|
||
{
|
||
DTDCount++;
|
||
}
|
||
else if (NVT_IS_EXT_DTD(pInfo->timing[j].etc.status))
|
||
{
|
||
extDTDCount++;
|
||
}
|
||
}
|
||
}
|
||
|
||
// TODO : this only handle single SVR right now
|
||
for (i = 0; i < totalSvr; i++)
|
||
{
|
||
NvU8 svr = pSvr[i];
|
||
NvU8 vic = 0;
|
||
|
||
if (svr == 0 || svr == 128 || (svr >= 161 && svr <= 192) || svr == 255)
|
||
continue;
|
||
|
||
// Kth 18bytes DTD in the EDID
|
||
if (svr >= 129 && svr <= 144)
|
||
{
|
||
kth = svr - 128;
|
||
// only base EDID and CTA861 can support 18bytes
|
||
if (flag == FROM_CTA861_EXTENSION)
|
||
{
|
||
for (j = 0; j < pInfo->total_timings; j++)
|
||
{
|
||
if (kth <= DTDCount)
|
||
{
|
||
if (NVT_IS_DTDn(pInfo->timing[j].etc.status, kth))
|
||
{
|
||
pInfo->timing[j].etc.flag |= NVT_FLAG_CEA_PREFERRED_TIMING;
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
extKth = kth - DTDCount;
|
||
if (NVT_IS_EXT_DTDn(pInfo->timing[j].etc.status, extKth))
|
||
{
|
||
pInfo->timing[j].etc.flag |= NVT_FLAG_CEA_PREFERRED_TIMING;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (svr >= 145 && svr <= 160)
|
||
{
|
||
// TODO : Interpret as the Nth 20-byte DTD or 6- or 7-byte CVT-based descriptor,
|
||
// where N = SVR – 144 (for N = 1 to 16)
|
||
break;
|
||
}
|
||
else if (svr == 254)
|
||
{
|
||
// TODO : Interpret as the timing format indicated by the first code of the first T8VTDB
|
||
break;
|
||
}
|
||
else // assign corresponding CEA format's timing from pre-defined CE timing table, EIA861B
|
||
{
|
||
// ( SVR >= 1 and SVR <= 127) and (SVR >= 193 and SVR <= 253)
|
||
vic = NVT_GET_CTA_8BIT_VIC(svr);
|
||
preferTiming = EIA861B[vic-1];
|
||
|
||
if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
|
||
{
|
||
for (j = 0; j < pInfo->total_timings; j++)
|
||
{
|
||
isMatch = NvTiming_IsTimingExactEqual(&pInfo->timing[j], &preferTiming);
|
||
if (isMatch && (NVT_GET_TIMING_STATUS_TYPE(pInfo->timing[j].etc.status) == NVT_TYPE_EDID_861ST))
|
||
{
|
||
pInfo->timing[j].etc.flag |= NVT_FLAG_CEA_PREFERRED_TIMING;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
|
||
{
|
||
for (j = 0; j < pDisplayID20->total_timings; j++)
|
||
{
|
||
isMatch = NvTiming_IsTimingExactEqual(&pDisplayID20->timing[j], &preferTiming);
|
||
if (isMatch && (NVT_GET_TIMING_STATUS_TYPE(pDisplayID20->timing[j].etc.status) == NVT_TYPE_EDID_861ST))
|
||
{
|
||
pDisplayID20->timing[j].etc.flag |= NVT_FLAG_CEA_PREFERRED_TIMING | NVT_FLAG_DISPLAYID_2_0_TIMING;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void parseCea861HdrStaticMetadataDataBlock(NVT_EDID_CEA861_INFO *pExt861,
|
||
void *pRawInfo,
|
||
NVT_CTA861_ORIGIN flag)
|
||
{
|
||
NVT_EDID_INFO *pInfo = NULL;
|
||
NVT_DISPLAYID_2_0_INFO *pDisplayID20 = NULL;
|
||
NVT_HDR_STATIC_METADATA *pHdrInfo = NULL;
|
||
|
||
if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
|
||
{
|
||
pInfo = (NVT_EDID_INFO *)pRawInfo;
|
||
pHdrInfo = &pInfo->hdr_static_metadata_info;
|
||
}
|
||
else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
|
||
{
|
||
pDisplayID20 = (NVT_DISPLAYID_2_0_INFO *)pRawInfo;
|
||
pHdrInfo = &pDisplayID20->cta.hdrInfo;
|
||
}
|
||
else
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (pExt861 == NULL || pHdrInfo == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// Parse the EOTF capability information. It's possible to have multiple EOTF
|
||
if (pExt861->hdr_static_metadata.byte1 & NVT_CEA861_EOTF_GAMMA_SDR)
|
||
{
|
||
pHdrInfo->supported_eotf.trad_gamma_sdr_eotf = 1;
|
||
}
|
||
if (pExt861->hdr_static_metadata.byte1 & NVT_CEA861_EOTF_GAMMA_HDR)
|
||
{
|
||
pHdrInfo->supported_eotf.trad_gamma_hdr_eotf = 1;
|
||
}
|
||
if (pExt861->hdr_static_metadata.byte1 & NVT_CEA861_EOTF_SMPTE_ST2084)
|
||
{
|
||
pHdrInfo->supported_eotf.smpte_st_2084_eotf = 1;
|
||
}
|
||
if (pExt861->hdr_static_metadata.byte1 & NVT_CEA861_EOTF_FUTURE)
|
||
{
|
||
pHdrInfo->supported_eotf.future_eotf = 1;
|
||
}
|
||
|
||
// Parse the static metadata descriptor
|
||
if (pExt861->hdr_static_metadata.byte2)
|
||
{
|
||
pHdrInfo->static_metadata_type = 1;
|
||
}
|
||
else
|
||
{
|
||
pHdrInfo->static_metadata_type = 0;
|
||
}
|
||
|
||
pHdrInfo->max_cll = pExt861->hdr_static_metadata.byte3 & NVT_CEA861_MAX_CLL_MASK;
|
||
pHdrInfo->max_fall = pExt861->hdr_static_metadata.byte4 & NVT_CEA861_MAX_FALL_MASK;
|
||
pHdrInfo->min_cll = pExt861->hdr_static_metadata.byte5 & NVT_CEA861_MIN_CLL_MASK;
|
||
}
|
||
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void parseCea861DvStaticMetadataDataBlock(NVT_EDID_CEA861_INFO *pExt861, void *pRawInfo, NVT_CTA861_ORIGIN flag)
|
||
{
|
||
NvU32 vsvdbVersion = 0;
|
||
NVT_DV_STATIC_METADATA_TYPE0 *pDvType0 = NULL;
|
||
NVT_DV_STATIC_METADATA_TYPE1 *pDvType1 = NULL;
|
||
NVT_DV_STATIC_METADATA_TYPE1_1 *pvDvType1_1 = NULL;
|
||
NVT_DV_STATIC_METADATA_TYPE2 *pDvType2 = NULL;
|
||
|
||
NVT_EDID_INFO *pInfo = NULL;
|
||
NVT_DISPLAYID_2_0_INFO *pDisplayID20 = NULL;
|
||
NVT_DV_STATIC_METADATA *pDvInfo = NULL;
|
||
|
||
if (pExt861 == NULL || pRawInfo == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
|
||
{
|
||
pInfo = (NVT_EDID_INFO *)pRawInfo;
|
||
pDvInfo = &pInfo->dv_static_metadata_info;
|
||
}
|
||
else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
|
||
{
|
||
pDisplayID20 = (NVT_DISPLAYID_2_0_INFO *)pRawInfo;
|
||
pDvInfo = &pDisplayID20->cta.dvInfo;
|
||
}
|
||
else
|
||
{
|
||
return;
|
||
}
|
||
|
||
if(pExt861->vsvdb.ieee_id != NVT_CEA861_DV_IEEE_ID)
|
||
{
|
||
return;
|
||
}
|
||
|
||
|
||
//init
|
||
NVMISC_MEMSET(pDvInfo, 0, sizeof(NVT_DV_STATIC_METADATA));
|
||
|
||
// copy ieee id
|
||
pDvInfo->ieee_id = pExt861->vsvdb.ieee_id;
|
||
|
||
vsvdbVersion = (pExt861->vsvdb.vendor_data[0] & NVT_CEA861_VSVDB_VERSION_MASK) >> NVT_CEA861_VSVDB_VERSION_MASK_SHIFT;
|
||
|
||
switch (vsvdbVersion)
|
||
{
|
||
case 0:
|
||
if (pExt861->vsvdb.vendor_data_size < sizeof(NVT_DV_STATIC_METADATA_TYPE0))
|
||
{
|
||
return;
|
||
}
|
||
pDvType0 = (NVT_DV_STATIC_METADATA_TYPE0 *)(&pExt861->vsvdb.vendor_data);
|
||
// copy the data
|
||
pDvInfo->VSVDB_version = pDvType0->VSVDB_version;
|
||
pDvInfo->supports_2160p60hz = pDvType0->supports_2160p60hz;
|
||
pDvInfo->supports_YUV422_12bit = pDvType0->supports_YUV422_12bit;
|
||
pDvInfo->supports_global_dimming = pDvType0->supports_global_dimming;
|
||
pDvInfo->colorimetry = 0; // this field does not exist in type0
|
||
pDvInfo->dm_version = (pDvType0->dm_version_major << 4) | pDvType0->dm_version_minor;
|
||
pDvInfo->target_min_luminance = (pDvType0->target_min_pq_11_4 << 4) | pDvType0->target_min_pq_3_0;
|
||
pDvInfo->target_max_luminance = (pDvType0->target_max_pq_11_4 << 4) | pDvType0->target_max_pq_3_0;
|
||
pDvInfo->cc_red_x = (pDvType0->cc_red_x_11_4 << 4) | pDvType0->cc_red_x_3_0;
|
||
pDvInfo->cc_red_y = (pDvType0->cc_red_y_11_4 << 4) | pDvType0->cc_red_y_3_0;
|
||
pDvInfo->cc_green_x = (pDvType0->cc_green_x_11_4 << 4) | pDvType0->cc_green_x_3_0;
|
||
pDvInfo->cc_green_y = (pDvType0->cc_green_y_11_4 << 4) | pDvType0->cc_green_y_3_0;
|
||
pDvInfo->cc_blue_x = (pDvType0->cc_blue_x_11_4 << 4) | pDvType0->cc_blue_x_3_0;
|
||
pDvInfo->cc_blue_y = (pDvType0->cc_blue_y_11_4 << 4) | pDvType0->cc_blue_y_3_0;
|
||
pDvInfo->cc_white_x = (pDvType0->cc_white_x_11_4 << 4) | pDvType0->cc_white_x_3_0;
|
||
pDvInfo->cc_white_y = (pDvType0->cc_white_y_11_4 << 4) | pDvType0->cc_white_y_3_0;
|
||
pDvInfo->supports_backlight_control = 0;
|
||
pDvInfo->backlt_min_luma = 0;
|
||
pDvInfo->interface_supported_by_sink = 0;
|
||
pDvInfo->supports_10b_12b_444 = 0;
|
||
break;
|
||
case 1:
|
||
if (pExt861->vsvdb.vendor_data_size == sizeof(NVT_DV_STATIC_METADATA_TYPE1))
|
||
{
|
||
pDvType1 = (NVT_DV_STATIC_METADATA_TYPE1 *)(&pExt861->vsvdb.vendor_data);
|
||
// copy the data
|
||
pDvInfo->VSVDB_version = pDvType1->VSVDB_version;
|
||
pDvInfo->supports_2160p60hz = pDvType1->supports_2160p60hz;
|
||
pDvInfo->supports_YUV422_12bit = pDvType1->supports_YUV422_12bit;
|
||
pDvInfo->dm_version = pDvType1->dm_version;
|
||
pDvInfo->supports_global_dimming = pDvType1->supports_global_dimming;
|
||
pDvInfo->colorimetry = pDvType1->colorimetry;
|
||
pDvInfo->target_min_luminance = pDvType1->target_min_luminance;
|
||
pDvInfo->target_max_luminance = pDvType1->target_max_luminance;
|
||
pDvInfo->cc_red_x = pDvType1->cc_red_x;
|
||
pDvInfo->cc_red_y = pDvType1->cc_red_y;
|
||
pDvInfo->cc_green_x = pDvType1->cc_green_x;
|
||
pDvInfo->cc_green_y = pDvType1->cc_green_y;
|
||
pDvInfo->cc_blue_x = pDvType1->cc_blue_x;
|
||
pDvInfo->cc_blue_y = pDvType1->cc_blue_y;
|
||
pDvInfo->supports_backlight_control = 0;
|
||
pDvInfo->backlt_min_luma = 0;
|
||
pDvInfo->interface_supported_by_sink = 0;
|
||
pDvInfo->supports_10b_12b_444 = 0;
|
||
pDvInfo->cc_white_x = 0;
|
||
pDvInfo->cc_white_y = 0;
|
||
}
|
||
else if (pExt861->vsvdb.vendor_data_size == sizeof(NVT_DV_STATIC_METADATA_TYPE1_1))
|
||
{
|
||
pvDvType1_1 = (NVT_DV_STATIC_METADATA_TYPE1_1 *)(&pExt861->vsvdb.vendor_data);
|
||
// copy the data
|
||
pDvInfo->VSVDB_version = pvDvType1_1->VSVDB_version;
|
||
pDvInfo->supports_2160p60hz = pvDvType1_1->supports_2160p60hz;
|
||
pDvInfo->supports_YUV422_12bit = pvDvType1_1->supports_YUV422_12bit;
|
||
pDvInfo->dm_version = pvDvType1_1->dm_version;
|
||
pDvInfo->supports_global_dimming = pvDvType1_1->supports_global_dimming;
|
||
pDvInfo->colorimetry = pvDvType1_1->colorimetry;
|
||
pDvInfo->target_min_luminance = pvDvType1_1->target_min_luminance;
|
||
pDvInfo->target_max_luminance = pvDvType1_1->target_max_luminance;
|
||
pDvInfo->cc_green_x = NVT_DOLBY_CHROMATICITY_MSB_GX | pvDvType1_1->unique_Gx;
|
||
pDvInfo->cc_green_y = NVT_DOLBY_CHROMATICITY_MSB_GY | pvDvType1_1->unique_Gy;
|
||
pDvInfo->cc_blue_x = NVT_DOLBY_CHROMATICITY_MSB_BX | pvDvType1_1->unique_Bx;
|
||
pDvInfo->cc_blue_y = NVT_DOLBY_CHROMATICITY_MSB_BY | pvDvType1_1->unique_By;
|
||
pDvInfo->cc_red_x = NVT_DOLBY_CHROMATICITY_MSB_RX | pvDvType1_1->unique_Rx;
|
||
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));
|
||
pDvInfo->supports_backlight_control = 0;
|
||
pDvInfo->backlt_min_luma = 0;
|
||
pDvInfo->interface_supported_by_sink = pvDvType1_1->interface_supported_by_sink;
|
||
pDvInfo->supports_10b_12b_444 = 0;
|
||
pDvInfo->cc_white_x = 0;
|
||
pDvInfo->cc_white_y = 0;
|
||
}
|
||
else
|
||
{
|
||
return;
|
||
}
|
||
|
||
break;
|
||
case 2:
|
||
if (pExt861->vsvdb.vendor_data_size < sizeof(NVT_DV_STATIC_METADATA_TYPE2))
|
||
{
|
||
return;
|
||
}
|
||
pDvType2 = (NVT_DV_STATIC_METADATA_TYPE2 *)(&pExt861->vsvdb.vendor_data);
|
||
// copy the data
|
||
pDvInfo->VSVDB_version = pDvType2->VSVDB_version;
|
||
pDvInfo->supports_backlight_control = pDvType2->supports_backlight_control;
|
||
pDvInfo->supports_YUV422_12bit = pDvType2->supports_YUV422_12bit;
|
||
pDvInfo->dm_version = pDvType2->dm_version;
|
||
pDvInfo->supports_global_dimming = pDvType2->supports_global_dimming;
|
||
pDvInfo->target_min_luminance = pDvType2->target_min_luminance;
|
||
pDvInfo->interface_supported_by_sink = pDvType2->interface_supported_by_sink;
|
||
pDvInfo->parity = pDvType2->parity;
|
||
pDvInfo->target_max_luminance = pDvType2->target_max_luminance;
|
||
pDvInfo->cc_green_x = NVT_DOLBY_CHROMATICITY_MSB_GX | pDvType2->unique_Gx;
|
||
pDvInfo->cc_green_y = NVT_DOLBY_CHROMATICITY_MSB_GY | pDvType2->unique_Gy;
|
||
pDvInfo->cc_blue_x = NVT_DOLBY_CHROMATICITY_MSB_BX | pDvType2->unique_Bx;
|
||
pDvInfo->cc_blue_y = NVT_DOLBY_CHROMATICITY_MSB_BY | pDvType2->unique_By;
|
||
pDvInfo->cc_red_x = NVT_DOLBY_CHROMATICITY_MSB_RX | pDvType2->unique_Rx;
|
||
pDvInfo->cc_red_y = NVT_DOLBY_CHROMATICITY_MSB_RY | pDvType2->unique_Ry;
|
||
pDvInfo->supports_10b_12b_444 = pDvType2->supports_10b_12b_444_bit0 | (pDvType2->supports_10b_12b_444_bit1 << 1);
|
||
pDvInfo->colorimetry = 0;
|
||
pDvInfo->supports_2160p60hz = 0;
|
||
pDvInfo->cc_white_x = 0;
|
||
pDvInfo->cc_white_y = 0;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
// find both hdmi llc and hdmi forum vendor specific data block and return basic hdmi information
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void parseCta861VsdbBlocks(NVT_EDID_CEA861_INFO *pExt861,
|
||
void *pRawInfo,
|
||
NVT_CTA861_ORIGIN flag
|
||
)
|
||
{
|
||
NvU32 i;
|
||
|
||
NVT_EDID_INFO *pInfo = NULL;
|
||
NVT_DISPLAYID_2_0_INFO *pDisplayID20 = NULL;
|
||
NVT_HDMI_LLC_INFO *pHdmiLlc = NULL;
|
||
NVT_HDMI_FORUM_INFO *pHfvs = NULL;
|
||
NVDA_VSDB_PARSED_INFO *pNvVsdb = NULL;
|
||
MSFT_VSDB_PARSED_INFO *pMsftVsdb = NULL;
|
||
|
||
if (pExt861 == NULL || pRawInfo == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
|
||
{
|
||
pInfo = (NVT_EDID_INFO *)pRawInfo;
|
||
pHdmiLlc = &pInfo->hdmiLlcInfo;
|
||
pHfvs = &pInfo->hdmiForumInfo;
|
||
pNvVsdb = &pInfo->nvdaVsdbInfo;
|
||
pMsftVsdb = &pInfo->msftVsdbInfo;
|
||
}
|
||
else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
|
||
{
|
||
pDisplayID20 = (NVT_DISPLAYID_2_0_INFO *)pRawInfo;
|
||
pHdmiLlc = &pDisplayID20->vendor_specific.hdmiLlc;
|
||
pHfvs = &pDisplayID20->vendor_specific.hfvs;
|
||
pNvVsdb = &pDisplayID20->vendor_specific.nvVsdb;
|
||
pMsftVsdb = &pDisplayID20->vendor_specific.msftVsdb;
|
||
}
|
||
else
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (pHdmiLlc == NULL || pHfvs == NULL || pNvVsdb == NULL || pMsftVsdb == NULL || (pExt861->total_vsdb == 0))
|
||
{
|
||
return;
|
||
}
|
||
|
||
for (i = 0; i < pExt861->total_vsdb; i++)
|
||
{
|
||
// Assumes each vsdb is unique for this CEA block, e.g., no two HDMI_IEEE_ID
|
||
switch (pExt861->vsdb[i].ieee_id)
|
||
{
|
||
case NVT_CEA861_HDMI_IEEE_ID:
|
||
// set any 3D timings and HDMI extended timing specified in the VSDB
|
||
parseEdidHdmiLlcBasicInfo((VSDB_DATA *)(&pExt861->vsdb[i]), pHdmiLlc);
|
||
pExt861->valid.H14B_VSDB = 1;
|
||
break;
|
||
|
||
case NVT_CEA861_HDMI_FORUM_IEEE_ID:
|
||
parseEdidHdmiForumVSDB((VSDB_DATA *)(&pExt861->vsdb[i]), pHfvs);
|
||
pExt861->valid.H20_HF_VSDB = 1;
|
||
break;
|
||
|
||
case NVT_CEA861_NVDA_IEEE_ID:
|
||
parseEdidNvidiaVSDBBlock((VSDB_DATA *)(&pExt861->vsdb[i]), pNvVsdb);
|
||
pExt861->valid.nvda_vsdb = 1;
|
||
break;
|
||
|
||
case NVT_CEA861_MSFT_IEEE_ID:
|
||
parseEdidMsftVsdbBlock((VSDB_DATA *)(&pExt861->vsdb[i]), pMsftVsdb);
|
||
pExt861->valid.msft_vsdb = 1;
|
||
break;
|
||
|
||
}
|
||
}
|
||
|
||
// H20_HF_VSDB shall be listed only if H14B_VSDB is also listed
|
||
// H20_HF_VSDB should not specify > 600MHz
|
||
nvt_assert(!pExt861->valid.H20_HF_VSDB || (pExt861->valid.H14B_VSDB && (pHfvs->max_TMDS_char_rate <= 0x78)));
|
||
|
||
// Done with reading CEA VSDB blocks, sanitize them now
|
||
if (pExt861->valid.SCDB)
|
||
{
|
||
pHdmiLlc->effective_tmds_clock = pExt861->hfscdb[1];
|
||
}
|
||
else if (pExt861->valid.H14B_VSDB)
|
||
{
|
||
// HDMI 2.0 Spec - section 10.3.2
|
||
// The maximum Rate = Max_TMDS_Character_Rate * 5 MHz.
|
||
// If the Sink does not support TMDS Character Rates > 340 Mcsc, then the Sink shall set this field to 0.
|
||
// If the Sink supports TMDS Character Rates > 340 Mcsc, the Sink shall set Max_TMDS_Character_Rate appropriately and non - zero.
|
||
|
||
// Pick updated TMDS clock rate
|
||
pHdmiLlc->effective_tmds_clock = (pExt861->valid.H20_HF_VSDB) ?
|
||
MAX(pHdmiLlc->max_tmds_clock, pHfvs->max_TMDS_char_rate) :
|
||
MIN(pHdmiLlc->max_tmds_clock, 0x44);
|
||
}
|
||
|
||
}
|
||
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void parseCta861HfEeodb(NVT_EDID_CEA861_INFO *pExt861,
|
||
NvU32 *pTotalEdidExtensions)
|
||
{
|
||
// *pTotalEdidExtensions set by the edid extension flag should be >= 1 for HFEEODB to be valid.
|
||
if (pTotalEdidExtensions == NULL || pExt861 == NULL || !pExt861->valid.HF_EEODB || *pTotalEdidExtensions == 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// HDMI 2.1 AmendmentA1 specifies that if EEODB is present sources shall ignore the Extension flag.
|
||
// This effectively overrides the extension count from extension flag.
|
||
*pTotalEdidExtensions = pExt861->hfeeodb;
|
||
}
|
||
|
||
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void parseCta861HfScdb(NVT_EDID_CEA861_INFO *pExt861,
|
||
void *pRawInfo,
|
||
NVT_CTA861_ORIGIN flag)
|
||
{
|
||
NVT_EDID_INFO *pInfo = (NVT_EDID_INFO *)pRawInfo;
|
||
VSDB_DATA vsdbData;
|
||
|
||
if (pExt861 == NULL || pRawInfo == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (!pExt861->valid.SCDB || pExt861->valid.H20_HF_VSDB)
|
||
{
|
||
return;
|
||
}
|
||
NVMISC_MEMSET(&vsdbData, 0, sizeof(vsdbData));
|
||
NVMISC_MEMCPY(&vsdbData.vendor_data, pExt861->hfscdb, sizeof(vsdbData.vendor_data));
|
||
|
||
vsdbData.vendor_data_size = pExt861->hfscdbSize;
|
||
|
||
parseEdidHdmiForumVSDB(&vsdbData, &pInfo->hdmiForumInfo);
|
||
}
|
||
|
||
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void getEdidHDM1_4bVsdbTiming(NVT_EDID_INFO *pInfo)
|
||
{
|
||
NvU32 i = 0, j = 0;
|
||
|
||
for (i = 0; i < 2; ++i)
|
||
{
|
||
NVT_EDID_CEA861_INFO *pExt861 = (0 == i) ? &pInfo->ext861 : &pInfo->ext861_2;
|
||
|
||
for (j = 0; j < pExt861->total_vsdb; ++j)
|
||
{
|
||
switch (pExt861->vsdb[j].ieee_id)
|
||
{
|
||
case NVT_CEA861_HDMI_IEEE_ID:
|
||
{
|
||
NvU32 count = 0;
|
||
// set any 3D timings and HDMI extended timing specified in the VSDB
|
||
parseEdidHDMILLCTiming(pInfo, (VSDB_DATA *)(&pExt861->vsdb[j]), &count, &(pInfo->Hdmi3Dsupport));
|
||
pInfo->HDMI3DSupported = 0 < count;
|
||
break;
|
||
}
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// get the full EDID 861 extension info
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
NVT_STATUS get861ExtInfo(NvU8 *p, NvU32 size, NVT_EDID_CEA861_INFO *p861info)
|
||
{
|
||
|
||
NvU32 dtd_offset;
|
||
// sanity check
|
||
if (p == NULL || size < sizeof(EDIDV1STRUC))
|
||
{
|
||
return NVT_STATUS_ERR;
|
||
}
|
||
|
||
// make sure we have 861 extension
|
||
if (p[0] != 0x2 || p[1] < NVT_CEA861_REV_ORIGINAL)
|
||
{
|
||
return NVT_STATUS_ERR;
|
||
}
|
||
|
||
// DTD offset sanity check
|
||
if (p[2] >= 1 && p[2] <= 3)
|
||
{
|
||
return NVT_STATUS_ERR;
|
||
}
|
||
|
||
// don't do anything further if p861info is NULL
|
||
if (p861info == NULL)
|
||
{
|
||
return NVT_STATUS_SUCCESS;
|
||
}
|
||
|
||
// init
|
||
NVMISC_MEMSET(p861info, 0, sizeof(NVT_EDID_CEA861_INFO));
|
||
|
||
// get the revision number
|
||
p861info->revision = p[1];
|
||
|
||
// no extra info for 861-original, returning from here
|
||
if (p861info->revision == NVT_CEA861_REV_ORIGINAL)
|
||
{
|
||
return NVT_STATUS_SUCCESS;
|
||
}
|
||
|
||
p861info->basic_caps = p[3];
|
||
|
||
// no extra info for 861-A, returning from here
|
||
if (p861info->revision == NVT_CEA861_REV_A)
|
||
{
|
||
return NVT_STATUS_SUCCESS;
|
||
}
|
||
|
||
dtd_offset = (NvU32)p[2];
|
||
if (dtd_offset == 0 || dtd_offset == 4)
|
||
{
|
||
return NVT_STATUS_SUCCESS;
|
||
}
|
||
|
||
// resolve all short descriptors in the reserved block
|
||
// reserved block starts from offset 04 to dtd_offset-1
|
||
return parseCta861DataBlockInfo(&p[4], dtd_offset - 4, p861info);
|
||
}
|
||
|
||
// 1. get the 861 extension tags info
|
||
// 2. or validation purpose if p861info == NULL
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
NVT_STATUS parseCta861DataBlockInfo(NvU8 *p,
|
||
NvU32 size,
|
||
NVT_EDID_CEA861_INFO *p861info)
|
||
{
|
||
NvU32 i, j;
|
||
NvU32 video_index = 0;
|
||
NvU32 audio_index = 0;
|
||
NvU32 speaker_index = 0;
|
||
NvU32 vendor_index = 0;
|
||
NvU32 yuv420vdb_index = 0;
|
||
NvU32 yuv420cmdb_index = 0;
|
||
NvU8 svr_index = 0;
|
||
NvU32 ieee_id = 0;
|
||
NvU32 tag, ext_tag, payload;
|
||
i= 0;
|
||
|
||
while (i < size)
|
||
{
|
||
// get the descriptor's tag and payload size
|
||
tag = NVT_CEA861_GET_SHORT_DESCRIPTOR_TAG(p[i]);
|
||
payload = NVT_CEA861_GET_SHORT_DESCRIPTOR_SIZE(p[i]);
|
||
|
||
/*don't allow data colleciton totally size larger than [127 - 5 (tag, revision, offset, describing native video format, checksum)]*/
|
||
if ((i + payload > size) || (i + payload > 122))
|
||
{
|
||
return NVT_STATUS_ERR;
|
||
}
|
||
// move the pointer to the payload section or extended Tag Code
|
||
i++;
|
||
|
||
// NvTiming_EDIDValidationMask will use the different tag/payload value to make sure each of cta861 data block legal
|
||
if (p861info == NULL)
|
||
{
|
||
switch(tag)
|
||
{
|
||
case NVT_CEA861_TAG_AUDIO:
|
||
case NVT_CEA861_TAG_VIDEO:
|
||
case NVT_CEA861_TAG_SPEAKER_ALLOC:
|
||
case NVT_CEA861_TAG_VESA_DTC:
|
||
case NVT_CEA861_TAG_RSVD:
|
||
case NVT_CEA861_TAG_RSVD1:
|
||
break;
|
||
case NVT_CEA861_TAG_VENDOR:
|
||
if (payload < 3) return NVT_STATUS_ERR;
|
||
break;
|
||
case NVT_CEA861_TAG_EXTENDED_FLAG:
|
||
if (payload >= 1)
|
||
{
|
||
ext_tag = p[i];
|
||
if (ext_tag == NVT_CEA861_EXT_TAG_VIDEO_CAP && payload < 2) return NVT_STATUS_ERR;
|
||
else if (ext_tag == NVT_CEA861_EXT_TAG_COLORIMETRY && payload < 3) return NVT_STATUS_ERR;
|
||
else if (ext_tag == NVT_CEA861_EXT_TAG_VIDEO_FORMAT_PREFERENCE && payload < 2) return NVT_STATUS_ERR;
|
||
else if (ext_tag == NVT_CEA861_EXT_TAG_YCBCR420_VIDEO && payload < 2) return NVT_STATUS_ERR;
|
||
else if (ext_tag == NVT_CEA861_EXT_TAG_YCBCR420_CAP && payload < 1) return NVT_STATUS_ERR;
|
||
else if (ext_tag == NVT_CEA861_EXT_TAG_HDR_STATIC_METADATA && payload < 3) return NVT_STATUS_ERR;
|
||
else if (ext_tag == NVT_CEA861_EXT_TAG_VENDOR_SPECIFIC_VIDEO && payload < 4) return NVT_STATUS_ERR;
|
||
else if (ext_tag == NVT_CTA861_EXT_TAG_SCDB && payload < 7) return NVT_STATUS_ERR;
|
||
else if (ext_tag == NVT_CEA861_EXT_TAG_HF_EEODB && payload != 2) return NVT_STATUS_ERR;
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
return NVT_STATUS_SUCCESS;
|
||
}
|
||
|
||
// loop through all descriptors
|
||
if (tag == NVT_CEA861_TAG_VIDEO)
|
||
{
|
||
// short video descriptor
|
||
for (j = 0; j < payload; j ++, i ++, video_index ++)
|
||
{
|
||
if (video_index < NVT_CEA861_VIDEO_MAX_DESCRIPTOR)
|
||
{
|
||
p861info->video[video_index] = p[i];
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
p861info->total_svd = (NvU8)video_index;
|
||
}
|
||
else if (tag == NVT_CEA861_TAG_AUDIO)
|
||
{
|
||
// short audio descriptor
|
||
for (j = 0; j < payload / 3; j ++, i += 3, audio_index ++)
|
||
{
|
||
if (audio_index < NVT_CEA861_AUDIO_MAX_DESCRIPTOR)
|
||
{
|
||
p861info->audio[audio_index].byte1 = p[i];
|
||
p861info->audio[audio_index].byte2 = p[i+1];
|
||
p861info->audio[audio_index].byte3 = p[i+2];
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
p861info->total_sad = (NvU8)audio_index;
|
||
}
|
||
else if (tag == NVT_CEA861_TAG_SPEAKER_ALLOC)
|
||
{
|
||
// speaker allocation descriptor
|
||
for (j = 0; j < payload / 3; j ++, i += 3, speaker_index ++)
|
||
{
|
||
if (speaker_index < NVT_CEA861_SPEAKER_MAX_DESCRIPTOR)
|
||
{
|
||
p861info->speaker[speaker_index].byte1 = p[i];
|
||
p861info->speaker[speaker_index].byte2 = p[i+1];
|
||
p861info->speaker[speaker_index].byte3 = p[i+2];
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
p861info->total_ssd = (NvU8)speaker_index;
|
||
}
|
||
else if (tag == NVT_CEA861_TAG_VENDOR)
|
||
{
|
||
if (vendor_index < NVT_CEA861_VSDB_MAX_BLOCKS)
|
||
{
|
||
if (payload < 3)
|
||
{
|
||
// This malformed payload will cause a hang below.
|
||
return NVT_STATUS_ERR;
|
||
}
|
||
|
||
p861info->vsdb[vendor_index].ieee_id = p[i]; //IEEE ID low byte
|
||
p861info->vsdb[vendor_index].ieee_id |= (p[i+1]) << 8; //IEEE ID middle byte
|
||
p861info->vsdb[vendor_index].ieee_id |= (p[i+2]) << 16; //IEEE ID high byte
|
||
|
||
p861info->vsdb[vendor_index].vendor_data_size = payload - 3;
|
||
|
||
// move the pointer to the payload
|
||
i += 3;
|
||
|
||
// get the other vendor specific data
|
||
for (j = 0; j < payload - 3; j ++, i ++)
|
||
{
|
||
if (j < NVT_CEA861_VSDB_PAYLOAD_MAX_LENGTH)
|
||
{
|
||
p861info->vsdb[vendor_index].vendor_data[j] = p[i];
|
||
}
|
||
}
|
||
vendor_index++;
|
||
}
|
||
}
|
||
else if (tag == NVT_CEA861_TAG_EXTENDED_FLAG)
|
||
{
|
||
if (payload >= 1)
|
||
{
|
||
ext_tag = p[i];
|
||
if (ext_tag == NVT_CEA861_EXT_TAG_VIDEO_CAP && payload >= 2)
|
||
{
|
||
p861info->video_capability = p[i + 1] & NVT_CEA861_VIDEO_CAPABILITY_MASK;
|
||
p861info->valid.VCDB = 1;
|
||
i += 2;
|
||
}
|
||
else if (ext_tag == NVT_CEA861_EXT_TAG_COLORIMETRY && payload >= 3)
|
||
{
|
||
p861info->colorimetry.byte1 = p[i + 1] & NVT_CEA861_COLORIMETRY_MASK;
|
||
p861info->colorimetry.byte2 = p[i + 2] & NVT_CEA861_GAMUT_METADATA_MASK;
|
||
p861info->valid.colorimetry = 1;
|
||
i += 3;
|
||
}
|
||
else if (ext_tag == NVT_CEA861_EXT_TAG_VIDEO_FORMAT_PREFERENCE && payload >= 2)
|
||
{
|
||
// 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
|
||
// order of SVD preferred modes shall take precedence over preferred modes defined elsewhere in the EDID/CEA861 blocks
|
||
|
||
// exclude the extended tag
|
||
i++; payload--;
|
||
|
||
for (j = 0; (j < payload) && (svr_index < NVT_CEA861_VFPDB_MAX_DESCRIPTOR); j++, i++, svr_index++)
|
||
{
|
||
p861info->svr_vfpdb[svr_index] = p[i];
|
||
}
|
||
p861info->total_vfpdb = svr_index;
|
||
}
|
||
else if (ext_tag == NVT_CEA861_EXT_TAG_YCBCR420_VIDEO && payload >= 2)
|
||
{
|
||
// when present, list SVDs that are only supported in YCbCr 4:2:0
|
||
|
||
// exclude the extended tag
|
||
i++; payload--;
|
||
|
||
for (j = 0; (j < payload) && (yuv420vdb_index < NVT_CEA861_Y420VDB_MAX_DESCRIPTOR); j++, i++, yuv420vdb_index++)
|
||
{
|
||
p861info->svd_y420vdb[yuv420vdb_index] = p[i];
|
||
}
|
||
p861info->total_y420vdb = (NvU8)yuv420vdb_index;
|
||
}
|
||
else if (ext_tag == NVT_CEA861_EXT_TAG_YCBCR420_CAP && payload >= 1)
|
||
{
|
||
// 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
|
||
|
||
// exclude the extended tag
|
||
i++; payload--;
|
||
|
||
for (j = 0; (j < payload) && (yuv420cmdb_index < NVT_CEA861_Y420CMDB_MAX_DESCRIPTOR); j++, i++, yuv420cmdb_index++)
|
||
{
|
||
p861info->map_y420cmdb[yuv420cmdb_index] = p[i];
|
||
}
|
||
p861info->total_y420cmdb = (NvU8)yuv420cmdb_index;
|
||
|
||
p861info->valid.y420cmdb = 1; // total_y420cmdb is not enough as this could be 0. See CEA861-F 7.5.11
|
||
}
|
||
else if(ext_tag == NVT_CEA861_EXT_TAG_HDR_STATIC_METADATA && payload >= 3)
|
||
{
|
||
p861info->hdr_static_metadata.byte1 = p[i + 1] & NVT_CEA861_EOTF_MASK; // This byte has bits which identify which EOTF supported by the sink.
|
||
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.
|
||
|
||
i += 3;
|
||
|
||
if (payload > 3)
|
||
{
|
||
p861info->hdr_static_metadata.byte3 = p[i];
|
||
i++;
|
||
}
|
||
|
||
if (payload > 4)
|
||
{
|
||
p861info->hdr_static_metadata.byte4 = p[i];
|
||
i++;
|
||
}
|
||
|
||
if (payload > 5)
|
||
{
|
||
p861info->hdr_static_metadata.byte5 = p[i];
|
||
i++;
|
||
}
|
||
|
||
p861info->valid.hdr_static_metadata = 1;
|
||
}
|
||
else if(ext_tag == NVT_CEA861_EXT_TAG_VENDOR_SPECIFIC_VIDEO)
|
||
{
|
||
ieee_id = p[i + 1]; //IEEE ID low byte
|
||
ieee_id |= (p[i + 2]) << 8; //IEEE ID middle byte
|
||
ieee_id |= (p[i + 3]) << 16; //IEEE ID high byte
|
||
|
||
if ((ieee_id == NVT_CEA861_DV_IEEE_ID) || (ieee_id == NVT_CEA861_HDR10PLUS_IEEE_ID))
|
||
{
|
||
// exclude the extended tag
|
||
i++; payload--;
|
||
|
||
p861info->vsvdb.ieee_id = ieee_id;
|
||
p861info->vsvdb.vendor_data_size = payload - 3;
|
||
|
||
// move the pointer to the payload
|
||
i += 3;
|
||
|
||
// get the other vendor specific video data
|
||
for (j = 0; j < payload - 3; j++, i++)
|
||
{
|
||
if (j < NVT_CEA861_VSVDB_PAYLOAD_MAX_LENGTH)
|
||
{
|
||
p861info->vsvdb.vendor_data[j] = p[i];
|
||
}
|
||
}
|
||
|
||
if (p861info->vsvdb.ieee_id == NVT_CEA861_DV_IEEE_ID)
|
||
{
|
||
p861info->valid.dv_static_metadata = 1;
|
||
}
|
||
else if (p861info->vsvdb.ieee_id == NVT_CEA861_HDR10PLUS_IEEE_ID)
|
||
{
|
||
p861info->valid.hdr10Plus = 1;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// skip the unsupported extended block
|
||
i += payload;
|
||
}
|
||
}
|
||
else if(ext_tag == NVT_CTA861_EXT_TAG_SCDB && payload >= 7) // sizeof(HDMI Forum Sink Capability Data Block) ranges between 7 to 31 bytes
|
||
{
|
||
// As per HDMI2.1 A1 amendment Sink Capability Data Structure(SCDS) can alternatively be included in HDMI Forum Sink Capability Data Block(HF-SCDB),
|
||
// instead of HF-VSDB, to indicate HDMI2.1 capability.
|
||
// Sinks will expose HF-SCDB if they do not expose HF-VSDB.
|
||
|
||
// move pointer to SCDS
|
||
i += 3;
|
||
|
||
// Copy SCDS over to p861info->vsdb[vendor_index]. Parsing will later be handled in parseEdidHdmiForumVSDB().
|
||
for (j = 0; (j < payload - 3) && (j < NVT_CTA861_EXT_SCDB_PAYLOAD_MAX_LENGTH); j ++, i ++)
|
||
{
|
||
p861info->hfscdb[j] = p[i];
|
||
}
|
||
p861info->hfscdbSize = MIN(payload - 3, NVT_CTA861_EXT_SCDB_PAYLOAD_MAX_LENGTH);
|
||
p861info->valid.SCDB = 1;
|
||
}
|
||
else if (ext_tag == NVT_CEA861_EXT_TAG_HF_EEODB && payload == 2)
|
||
{
|
||
// Skip over extended tag
|
||
i++; payload--;
|
||
|
||
p861info->hfeeodb = p[i];
|
||
p861info->valid.HF_EEODB = 1;
|
||
i += payload;
|
||
}
|
||
else
|
||
{
|
||
// skip the unrecognized extended block
|
||
i += payload;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// reserved block, just skip here
|
||
i += payload;
|
||
}
|
||
}
|
||
|
||
p861info->total_vsdb = (NvU8)vendor_index;
|
||
|
||
return NVT_STATUS_SUCCESS;
|
||
}
|
||
|
||
// enum the EIA/CEA 861B predefined timing
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
NVT_STATUS NvTiming_EnumCEA861bTiming(NvU32 ceaFormat, NVT_TIMING *pT)
|
||
{
|
||
if (pT == NULL || ceaFormat == 0 || ceaFormat > MAX_CEA861B_FORMAT)
|
||
{
|
||
return NVT_STATUS_ERR;
|
||
}
|
||
|
||
ceaFormat = NVT_GET_CTA_8BIT_VIC(ceaFormat);
|
||
|
||
if (ceaFormat ==0)
|
||
return NVT_STATUS_ERR;
|
||
|
||
*pT = EIA861B[ceaFormat - 1];
|
||
|
||
// calculate the pixel clock
|
||
pT->pclk = RRx1kToPclk (pT);
|
||
NVT_SET_CEA_FORMAT(pT->etc.status, ceaFormat);
|
||
|
||
NVT_SNPRINTF((char *)pT->etc.name, sizeof(pT->etc.name), "CTA-861G:#%3d:%dx%dx%3d.%03dHz/%s", (int)ceaFormat, (int)pT->HVisible, (int)((pT->interlaced ? 2 : 1)*pT->VVisible), (int)pT->etc.rrx1k/1000, (int)pT->etc.rrx1k%1000, (pT->interlaced ? "I":"P"));
|
||
pT->etc.name[sizeof(pT->etc.name) - 1] = '\0';
|
||
|
||
return NVT_STATUS_SUCCESS;
|
||
}
|
||
|
||
|
||
// Check whether the given timing is a CEA 861 timing.
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
NvU32 NvTiming_GetCEA861TimingIndex (NVT_TIMING *pT)
|
||
{
|
||
NvU32 i = 0, j = 0;
|
||
NvU32 ceaIndex = 0;
|
||
NvU32 aspect_x;
|
||
NvU32 aspect_y;
|
||
|
||
if (pT == NULL)
|
||
{
|
||
return ceaIndex;
|
||
}
|
||
|
||
if (NVT_GET_CEA_FORMAT(pT->etc.status) != 0)
|
||
{
|
||
// CEA format has been set, done
|
||
return NVT_GET_CEA_FORMAT(pT->etc.status);
|
||
}
|
||
|
||
aspect_x = nvt_aspect_x(pT->etc.aspect);
|
||
aspect_y = nvt_aspect_y(pT->etc.aspect);
|
||
|
||
// loop through the pre-defined CEA 861 table
|
||
// Skip VIC1 - Although IT 640x480 video timing has a CE id, it is not a CE timing. See 3.1
|
||
// "General Video Format Requirements" section in CEA-861-E spec
|
||
for (i = 1; i < MAX_CEA861B_FORMAT; i++)
|
||
{
|
||
if (NvTiming_IsTimingRelaxedEqual(pT, &EIA861B[i]))
|
||
{
|
||
// The timing matches with a CEA 861 timing. Set CEA format to NVT_TIMING.etc.status.
|
||
ceaIndex = NVT_GET_TIMING_STATUS_SEQ(EIA861B[i].etc.status);
|
||
|
||
if (!aspect_x || !aspect_y)
|
||
{
|
||
return ceaIndex;
|
||
}
|
||
|
||
// 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
|
||
for (j = 0; j < MAX_EIA861B_DUAL_ASPECT_VICS; j++)
|
||
{
|
||
if (ceaIndex == EIA861B_DUAL_ASPECT_VICS[j][0])
|
||
{
|
||
NvU32 ceaIndex1 = EIA861B_DUAL_ASPECT_VICS[j][1];
|
||
|
||
NvU32 format1 = axb_div_c(aspect_x, nvt_aspect_y(EIA861B[ceaIndex - 1].etc.aspect), aspect_y);
|
||
NvU32 format2 = axb_div_c(aspect_x, nvt_aspect_y(EIA861B[ceaIndex1 - 1].etc.aspect), aspect_y);
|
||
|
||
NvU32 format_1_diff = abs_delta(format1, nvt_aspect_x(EIA861B[ceaIndex - 1].etc.aspect));
|
||
NvU32 format_2_diff = abs_delta(format2, nvt_aspect_x(EIA861B[ceaIndex1 - 1].etc.aspect));
|
||
|
||
if (format_2_diff < format_1_diff)
|
||
{
|
||
ceaIndex = ceaIndex1;
|
||
}
|
||
break;
|
||
}
|
||
else if (ceaIndex < EIA861B_DUAL_ASPECT_VICS[j][0]) // not a dual-dspect ratio timing
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
return ceaIndex;
|
||
}
|
||
|
||
// calculate 861B based timing
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
NVT_STATUS NvTiming_CalcCEA861bTiming(NvU32 width, NvU32 height, NvU32 rr, NvU32 flag, NvU32 pixelRepeatCount, NVT_TIMING *pT)
|
||
|
||
{
|
||
NvU32 i = 0;
|
||
NvU16 pixelRepeatMask = 1 << (pixelRepeatCount - 1);
|
||
|
||
nvt_assert(pixelRepeatCount > 0 && pixelRepeatCount <= 10);
|
||
|
||
if (pT == NULL)
|
||
{
|
||
return NVT_STATUS_ERR;
|
||
}
|
||
|
||
// loop through the table
|
||
for (i = 0; i < MAX_CEA861B_FORMAT; i ++)
|
||
{
|
||
|
||
if ((EIA861B[i].etc.rep & pixelRepeatMask) == 0)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
if (width == (NvU32)NvTiming_MaxFrameWidth(EIA861B[i].HVisible, pixelRepeatMask) &&
|
||
height == frame_height(EIA861B[i])&&
|
||
rr == EIA861B[i].etc.rr &&
|
||
(!!(flag & NVT_PVT_INTERLACED_MASK)) == (!!EIA861B[i].interlaced))
|
||
{
|
||
*pT = EIA861B[i];
|
||
|
||
// calculate the pixel clock
|
||
pT->pclk = RRx1kToPclk (pT);
|
||
|
||
NVT_SET_CEA_FORMAT(pT->etc.status, NVT_GET_TIMING_STATUS_SEQ(pT->etc.status));
|
||
|
||
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"));
|
||
pT->etc.name[sizeof(pT->etc.name) - 1] = '\0';
|
||
|
||
return NVT_STATUS_SUCCESS;
|
||
}
|
||
}
|
||
|
||
return NVT_STATUS_ERR;
|
||
|
||
}
|
||
|
||
// Assign fields in NVT_VIDEO_INFOFRAME_CTRL, using NVT_TIMING
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
NVT_STATUS NvTiming_ConstructVideoInfoframeCtrl(const NVT_TIMING *pTiming, NVT_VIDEO_INFOFRAME_CTRL *pCtrl)
|
||
{
|
||
// setup VIC code it is not specified
|
||
if (pCtrl->video_format_id == NVT_INFOFRAME_CTRL_DONTCARE ||
|
||
pCtrl->video_format_id == 0 ||
|
||
pCtrl->video_format_id > NVT_CEA861_1920X1080P_29970HZ_16X9)
|
||
{
|
||
// setup video format ID
|
||
pCtrl->video_format_id = (NvU8)NVT_GET_CEA_FORMAT(pTiming->etc.status);
|
||
if (pCtrl->video_format_id < NVT_CEA861_640X480P_59940HZ_4X3 ||
|
||
pCtrl->video_format_id > NVT_CTA861_4096x2160p_119880HZ_256X135)
|
||
{
|
||
// Prior RFE 543088
|
||
if (pCtrl->video_format_id == 0 &&
|
||
NVT_GET_TIMING_STATUS_TYPE(pTiming->etc.status) == NVT_TYPE_EDID_861ST)
|
||
{
|
||
pCtrl->video_format_id = (NvU8)NVT_GET_TIMING_STATUS_SEQ(pTiming->etc.status);
|
||
}
|
||
if (pCtrl->video_format_id == 0 &&
|
||
pTiming->HVisible == 640 &&
|
||
pTiming->VVisible == 480 &&
|
||
pTiming->interlaced == 0 &&
|
||
pTiming->etc.rr == 60)
|
||
{
|
||
pCtrl->video_format_id = NVT_CEA861_640X480P_59940HZ_4X3;
|
||
}
|
||
}
|
||
}
|
||
|
||
// for HDMI_EXT timing, AVI VIC should be 0.
|
||
if (NVT_GET_TIMING_STATUS_TYPE(pTiming->etc.status) == NVT_TYPE_HDMI_EXT)
|
||
{
|
||
pCtrl->video_format_id = 0;
|
||
}
|
||
|
||
// setup aspect ratio it is not specified
|
||
if (pCtrl->pic_aspect_ratio == NVT_INFOFRAME_CTRL_DONTCARE ||
|
||
pCtrl->pic_aspect_ratio == NVT_VIDEO_INFOFRAME_BYTE2_M1M0_NO_DATA ||
|
||
pCtrl->pic_aspect_ratio > NVT_VIDEO_INFOFRAME_BYTE2_M1M0_FUTURE)
|
||
{
|
||
// extract the screen measurements from the DTD aspect ratio.
|
||
// (we pack the height & width in a DWORD to form the aspect ratio)
|
||
|
||
NvU32 x,y;
|
||
x = (pTiming->etc.aspect & 0x0fff);
|
||
y = ((pTiming->etc.aspect >> 16) & 0x0fff);
|
||
|
||
if (axb_div_c(y,3,x) == 4)
|
||
{
|
||
pCtrl->pic_aspect_ratio = NVT_VIDEO_INFOFRAME_BYTE2_M1M0_4X3;
|
||
}
|
||
else if (axb_div_c(y,9,x) == 16)
|
||
{
|
||
pCtrl->pic_aspect_ratio = NVT_VIDEO_INFOFRAME_BYTE2_M1M0_16X9;
|
||
}
|
||
else if (pCtrl->video_format_id == NVT_CEA861_640X480P_59940HZ_4X3)
|
||
{
|
||
pCtrl->pic_aspect_ratio = NVT_VIDEO_INFOFRAME_BYTE2_M1M0_4X3;
|
||
}
|
||
else
|
||
{
|
||
// default to no data, to cover other non-cea modes
|
||
pCtrl->pic_aspect_ratio = NVT_VIDEO_INFOFRAME_BYTE2_M1M0_NO_DATA;
|
||
}
|
||
}
|
||
|
||
if (pCtrl->it_content == NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
// Initialize ITC flag to NVT_VIDEO_INFOFRAME_BYTE3_ITC_IT_CONTENT
|
||
pCtrl->it_content = NVT_VIDEO_INFOFRAME_BYTE3_ITC_IT_CONTENT;
|
||
pCtrl->it_content_type = NVT_VIDEO_INFOFRAME_BYTE5_CN1CN0_GRAPHICS;
|
||
}
|
||
|
||
if (pCtrl->pixel_repeat == NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
// Initialize pixel repetitions
|
||
NvU32 pixelRepeat = pTiming->etc.rep;
|
||
LOWESTBITIDX_32(pixelRepeat);
|
||
pCtrl->pixel_repeat = (NvU8)pixelRepeat;
|
||
}
|
||
|
||
return NVT_STATUS_SUCCESS;
|
||
}
|
||
|
||
|
||
// construct AVI video infoframe based on the user control and the current context state
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
NVT_STATUS NvTiming_ConstructVideoInfoframe(NVT_EDID_INFO *pEdidInfo, NVT_VIDEO_INFOFRAME_CTRL *pCtrl, NVT_VIDEO_INFOFRAME *pContext, NVT_VIDEO_INFOFRAME *pInfoFrame)
|
||
{
|
||
// parameter check
|
||
if (pEdidInfo == NULL || pInfoFrame == NULL)
|
||
{
|
||
return NVT_STATUS_ERR;
|
||
}
|
||
|
||
// infoframe is only supported on 861A and later
|
||
if (pEdidInfo->ext861.revision < NVT_CEA861_REV_A)
|
||
{
|
||
return NVT_STATUS_ERR;
|
||
}
|
||
|
||
// if context state is provided, use it to initialize the infoframe buffer
|
||
if (pContext != NULL)
|
||
{
|
||
*pInfoFrame = *pContext;
|
||
}
|
||
else
|
||
{
|
||
*pInfoFrame = DEFAULT_VIDEO_INFOFRAME;
|
||
}
|
||
|
||
// init the header
|
||
pInfoFrame->type = NVT_INFOFRAME_TYPE_VIDEO;
|
||
|
||
// TODO : This is just to check the version, we still need to change lots of structure
|
||
// "NVT_VIDEO_INFOFRAME" / "VIDEO_INFOFRAME" / "DEFAULT_VIDEO_INFOFRAME" / "NVM_DISP_STATE" etc..
|
||
// to accept the new ACE0-3 bits supported in the future. Right now no any sink to support this.
|
||
//
|
||
// Based on the latest CTA-861-G-Errata.pdf file, we need to do following logic to get the correct CTA861 version
|
||
// When Y2 = 0, the following algorithm shall be used for AVI InfoFrame version selection:
|
||
// if (C=3 and EC=7)
|
||
// Sources shall use AVI InfoFrame Version 4.
|
||
// Else if (VIC>=128)
|
||
// Sources shall use AVI InfoFrame Version 3.
|
||
// Else
|
||
// Sources shall use AVI InfoFrame Version 2.
|
||
// End if
|
||
//
|
||
if (pCtrl)
|
||
{
|
||
if (nvt_get_bits(pInfoFrame->byte1, NVT_VIDEO_INFOFRAME_BYTE1_Y2Y1Y0_MASK, NVT_VIDEO_INFOFRAME_BYTE1_Y2Y1Y0_SHIFT) <= NVT_VIDEO_INFOFRAME_BYTE1_Y2Y1Y0_FUTURE) // this shall be as 0 always.
|
||
{
|
||
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) &&
|
||
//EC2-0 is based on the 7.5.5 at CTA861-G which DCI-P3 bit defined or notat byte4
|
||
(nvt_get_bits(pInfoFrame->byte3, NVT_VIDEO_INFOFRAME_BYTE3_EC_MASK, NVT_VIDEO_INFOFRAME_BYTE3_EC_SHIFT) == NVT_VIDEO_INFOFRAME_BYTE3_EC_AdditionalColorExt))
|
||
{
|
||
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.
|
||
}
|
||
else
|
||
{
|
||
pInfoFrame->version = (((pCtrl->video_format_id & NVT_VIDEO_INFOFRAME_BYTE4_VIC7) == NVT_VIDEO_INFOFRAME_BYTE4_VIC7) ? NVT_VIDEO_INFOFRAME_VERSION_3 :
|
||
((pEdidInfo->ext861.revision >= NVT_CEA861_REV_B) ? NVT_VIDEO_INFOFRAME_VERSION_2 : NVT_VIDEO_INFOFRAME_VERSION_1));
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
pInfoFrame->version = (pEdidInfo->ext861.revision >= NVT_CEA861_REV_B) ? NVT_VIDEO_INFOFRAME_VERSION_2 : NVT_VIDEO_INFOFRAME_VERSION_1;
|
||
}
|
||
pInfoFrame->length = sizeof(NVT_VIDEO_INFOFRAME) - sizeof(NVT_INFOFRAME_HEADER);
|
||
|
||
if (pInfoFrame->version < NVT_VIDEO_INFOFRAME_VERSION_3)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte1, 0, NVT_VIDEO_INFOFRAME_BYTE1_RESERVED_MASK, NVT_VIDEO_INFOFRAME_BYTE1_RESERVED_SHIFT);
|
||
}
|
||
|
||
if (pInfoFrame->version == NVT_VIDEO_INFOFRAME_VERSION_2)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte4, 0, NVT_VIDEO_INFOFRAME_BYTE4_RESERVED_V2_MASK, NVT_VIDEO_INFOFRAME_BYTE4_RESERVED_V2_SHIFT);
|
||
}
|
||
else if (pInfoFrame->version == NVT_VIDEO_INFOFRAME_VERSION_1)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte3, 0, NVT_VIDEO_INFOFRAME_BYTE3_RESERVED_V1_MASK, NVT_VIDEO_INFOFRAME_BYTE3_RESERVED_V1_SHIFT);
|
||
nvt_nvu8_set_bits(pInfoFrame->byte4, 0, NVT_VIDEO_INFOFRAME_BYTE4_RESERVED_V1_MASK, NVT_VIDEO_INFOFRAME_BYTE4_RESERVED_V1_SHIFT);
|
||
nvt_nvu8_set_bits(pInfoFrame->byte5, 0, NVT_VIDEO_INFOFRAME_BYTE5_RESERVED_V1_MASK, NVT_VIDEO_INFOFRAME_BYTE5_RESERVED_V1_SHIFT);
|
||
}
|
||
|
||
// construct the desired infoframe contents based on the control
|
||
if (pCtrl)
|
||
{
|
||
// byte 1
|
||
if (pCtrl->color_space != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte1, pCtrl->color_space, NVT_VIDEO_INFOFRAME_BYTE1_Y2Y1Y0_MASK, NVT_VIDEO_INFOFRAME_BYTE1_Y2Y1Y0_SHIFT);
|
||
}
|
||
|
||
if (pCtrl->active_format_info_present != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte1, pCtrl->active_format_info_present, NVT_VIDEO_INFOFRAME_BYTE1_A0_MASK, NVT_VIDEO_INFOFRAME_BYTE1_A0_SHIFT);
|
||
}
|
||
|
||
if (pCtrl->bar_info != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte1, pCtrl->bar_info, NVT_VIDEO_INFOFRAME_BYTE1_B1B0_MASK, NVT_VIDEO_INFOFRAME_BYTE1_B1B0_SHIFT);
|
||
}
|
||
|
||
if (pCtrl->scan_info != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte1, pCtrl->scan_info, NVT_VIDEO_INFOFRAME_BYTE1_S1S0_MASK, NVT_VIDEO_INFOFRAME_BYTE1_S1S0_SHIFT);
|
||
}
|
||
|
||
// byte 2
|
||
if (pCtrl->colorimetry != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte2, pCtrl->colorimetry, NVT_VIDEO_INFOFRAME_BYTE2_C1C0_MASK, NVT_VIDEO_INFOFRAME_BYTE2_C1C0_SHIFT);
|
||
}
|
||
|
||
if (pCtrl->pic_aspect_ratio != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte2, pCtrl->pic_aspect_ratio, NVT_VIDEO_INFOFRAME_BYTE2_M1M0_MASK, NVT_VIDEO_INFOFRAME_BYTE2_M1M0_SHIFT);
|
||
}
|
||
|
||
if (pCtrl->active_format_aspect_ratio != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte2, pCtrl->active_format_aspect_ratio, NVT_VIDEO_INFOFRAME_BYTE2_R3R2R1R0_MASK, NVT_VIDEO_INFOFRAME_BYTE2_R3R2R1R0_SHIFT);
|
||
}
|
||
|
||
// byte 3
|
||
if (pCtrl->it_content != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte3, pCtrl->it_content, NVT_VIDEO_INFOFRAME_BYTE3_ITC_MASK, NVT_VIDEO_INFOFRAME_BYTE3_ITC_SHIFT);
|
||
}
|
||
|
||
if (pCtrl->extended_colorimetry != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte3, pCtrl->extended_colorimetry, NVT_VIDEO_INFOFRAME_BYTE3_EC_MASK, NVT_VIDEO_INFOFRAME_BYTE3_EC_SHIFT);
|
||
}
|
||
|
||
if (pCtrl->rgb_quantization_range != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte3, pCtrl->rgb_quantization_range, NVT_VIDEO_INFOFRAME_BYTE3_Q1Q0_MASK, NVT_VIDEO_INFOFRAME_BYTE3_Q1Q0_SHIFT);
|
||
}
|
||
|
||
if (pCtrl->nonuniform_scaling != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte3, pCtrl->nonuniform_scaling, NVT_VIDEO_INFOFRAME_BYTE3_SC_MASK, NVT_VIDEO_INFOFRAME_BYTE3_SC_SHIFT);
|
||
}
|
||
|
||
// byte 4 and byte 5 only supported on InfoFrame 2.0
|
||
if (pInfoFrame->version >= NVT_VIDEO_INFOFRAME_VERSION_2)
|
||
{
|
||
// byte 4
|
||
if (pCtrl->video_format_id != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte4, pCtrl->video_format_id, NVT_VIDEO_INFOFRAME_BYTE4_VIC_MASK, NVT_VIDEO_INFOFRAME_BYTE4_VIC_SHIFT);
|
||
}
|
||
|
||
// byte 5
|
||
if (pCtrl->pixel_repeat != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte5, pCtrl->pixel_repeat, NVT_VIDEO_INFOFRAME_BYTE5_PR_MASK, NVT_VIDEO_INFOFRAME_BYTE5_PR_SHIFT);
|
||
}
|
||
|
||
// byte5
|
||
if (pCtrl->it_content_type != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte5, pCtrl->it_content_type, NVT_VIDEO_INFOFRAME_BYTE5_CN1CN0_MASK, NVT_VIDEO_INFOFRAME_BYTE5_CN1CN0_SHIFT);
|
||
}
|
||
}
|
||
|
||
// byte 6~13, bar info
|
||
if (pCtrl->top_bar != 0xFFFF)
|
||
{
|
||
pInfoFrame->top_bar_low = (NvU8)(pCtrl->top_bar % 0x100);
|
||
pInfoFrame->top_bar_high = (NvU8)(pCtrl->top_bar / 0x100);
|
||
}
|
||
if (pCtrl->bottom_bar != 0xFFFF)
|
||
{
|
||
pInfoFrame->bottom_bar_low = (NvU8)(pCtrl->bottom_bar % 0x100);
|
||
pInfoFrame->bottom_bar_high = (NvU8)(pCtrl->bottom_bar / 0x100);
|
||
}
|
||
if (pCtrl->left_bar != 0xFFFF)
|
||
{
|
||
pInfoFrame->left_bar_low = (NvU8)(pCtrl->left_bar % 0x100);
|
||
pInfoFrame->left_bar_high = (NvU8)(pCtrl->left_bar / 0x100);
|
||
}
|
||
if (pCtrl->right_bar != 0xFFFF)
|
||
{
|
||
pInfoFrame->right_bar_low = (NvU8)(pCtrl->right_bar % 0x100);
|
||
pInfoFrame->right_bar_high = (NvU8)(pCtrl->right_bar / 0x100);
|
||
}
|
||
}
|
||
|
||
return NVT_STATUS_SUCCESS;
|
||
}
|
||
|
||
// construct AVI audio infoframe based on the user control and the current context state
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
NVT_STATUS NvTiming_ConstructAudioInfoframe(NVT_AUDIO_INFOFRAME_CTRL *pUserCtrl, NVT_AUDIO_INFOFRAME *pContext, NVT_AUDIO_INFOFRAME *pInfoFrame)
|
||
{
|
||
NVT_AUDIO_INFOFRAME_CTRL ctrl;
|
||
|
||
// parameter check
|
||
if (pInfoFrame == NULL)
|
||
{
|
||
return NVT_STATUS_ERR;
|
||
}
|
||
|
||
// use the user provided control if possible
|
||
if (pUserCtrl)
|
||
{
|
||
ctrl = *pUserCtrl;
|
||
}
|
||
else
|
||
{
|
||
// otherwise use the default control
|
||
NVMISC_MEMSET(&ctrl, NVT_INFOFRAME_CTRL_DONTCARE, sizeof(ctrl));
|
||
}
|
||
|
||
// if context state is provided, use it to initialize the infoframe buffer
|
||
if (pContext != NULL)
|
||
{
|
||
*pInfoFrame = *pContext;
|
||
}
|
||
else
|
||
{
|
||
*pInfoFrame = DEFAULT_AUDIO_INFOFRAME;
|
||
|
||
// if the context state is not provide, we should user EDID info to build a default ctrl
|
||
//buildDefaultAudioInfoframeCtrl(pEdidInfo, &ctrl);
|
||
}
|
||
|
||
// init the header
|
||
pInfoFrame->type = NVT_INFOFRAME_TYPE_AUDIO;
|
||
pInfoFrame->version = NVT_VIDEO_INFOFRAME_VERSION_1;
|
||
pInfoFrame->length = sizeof(NVT_AUDIO_INFOFRAME) - sizeof(NVT_INFOFRAME_HEADER);
|
||
|
||
// init the reserved fields
|
||
nvt_nvu8_set_bits(pInfoFrame->byte1, 0, NVT_AUDIO_INFOFRAME_BYTE1_RESERVED_MASK, NVT_AUDIO_INFOFRAME_BYTE1_RESERVED_SHIFT);
|
||
nvt_nvu8_set_bits(pInfoFrame->byte2, 0, NVT_AUDIO_INFOFRAME_BYTE2_RESERVED_MASK, NVT_AUDIO_INFOFRAME_BYTE2_RESERVED_SHIFT);
|
||
nvt_nvu8_set_bits(pInfoFrame->byte5, 0, NVT_AUDIO_INFOFRAME_BYTE5_RESERVED_MASK, NVT_AUDIO_INFOFRAME_BYTE5_RESERVED_SHIFT);
|
||
pInfoFrame->rsvd_byte6 = 0;
|
||
pInfoFrame->rsvd_byte7 = 0;
|
||
pInfoFrame->rsvd_byte8 = 0;
|
||
pInfoFrame->rsvd_byte9 = 0;
|
||
pInfoFrame->rsvd_byte10 = 0;
|
||
|
||
// byte 1
|
||
if (ctrl.channel_count != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte1, ctrl.channel_count, NVT_AUDIO_INFOFRAME_BYTE1_CC_MASK, NVT_AUDIO_INFOFRAME_BYTE1_CC_SHIFT);
|
||
}
|
||
|
||
if (ctrl.coding_type != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte1, ctrl.coding_type, NVT_AUDIO_INFOFRAME_BYTE1_CT_MASK, NVT_AUDIO_INFOFRAME_BYTE1_CT_SHIFT);
|
||
}
|
||
|
||
// byte 2
|
||
if (ctrl.sample_depth != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte2, ctrl.sample_depth, NVT_AUDIO_INFOFRAME_BYTE2_SS_MASK, NVT_AUDIO_INFOFRAME_BYTE2_SS_SHIFT);
|
||
}
|
||
|
||
if (ctrl.sample_rate != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte2, ctrl.sample_rate, NVT_AUDIO_INFOFRAME_BYTE2_SF_MASK, NVT_AUDIO_INFOFRAME_BYTE2_SF_SHIFT);
|
||
}
|
||
|
||
// byte 3
|
||
pInfoFrame->byte3 = 0;
|
||
|
||
// byte 4
|
||
if (ctrl.speaker_placement != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte4, ctrl.speaker_placement, NVT_AUDIO_INFOFRAME_BYTE4_CA_MASK, NVT_AUDIO_INFOFRAME_BYTE4_CA_SHIFT);
|
||
}
|
||
|
||
// byte 5
|
||
if (ctrl.level_shift != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte5, ctrl.level_shift, NVT_AUDIO_INFOFRAME_BYTE5_LSV_MASK, NVT_AUDIO_INFOFRAME_BYTE5_LSV_SHIFT);
|
||
}
|
||
|
||
if (ctrl.down_mix_inhibit != NVT_INFOFRAME_CTRL_DONTCARE)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->byte5, ctrl.down_mix_inhibit, NVT_AUDIO_INFOFRAME_BYTE5_DM_INH_MASK, NVT_AUDIO_INFOFRAME_BYTE5_DM_INH_SHIFT);
|
||
}
|
||
|
||
|
||
return NVT_STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
// Construct Vendor Specific Infoframe
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
NVT_STATUS NvTiming_ConstructVendorSpecificInfoframe(NVT_EDID_INFO *pEdidInfo, NVT_VENDOR_SPECIFIC_INFOFRAME_CTRL *pCtrl, NVT_VENDOR_SPECIFIC_INFOFRAME *pInfoFrame)
|
||
{
|
||
NVT_STATUS RetCode = NVT_STATUS_SUCCESS;
|
||
NvU8 optIdx = 0;
|
||
NvU8 HDMIFormat;
|
||
|
||
// parameter check
|
||
if (pEdidInfo == NULL || pInfoFrame == NULL)
|
||
{
|
||
return NVT_STATUS_INVALID_PARAMETER;
|
||
}
|
||
|
||
// infoframe is only supported on 861A and later
|
||
if (pEdidInfo->ext861.revision < NVT_CEA861_REV_A)
|
||
{
|
||
return NVT_STATUS_ERR;
|
||
}
|
||
|
||
|
||
// initialize the infoframe buffer
|
||
*pInfoFrame = DEFAULT_VENDOR_SPECIFIC_INFOFRAME;
|
||
|
||
// init the header (mostly done in default Infoframe)
|
||
pInfoFrame->Header.length = offsetof(NVT_VENDOR_SPECIFIC_INFOFRAME_PAYLOAD, optionalBytes);
|
||
|
||
// construct the desired infoframe contents based on the control
|
||
if (pCtrl)
|
||
{
|
||
// clear all static reserved fields
|
||
nvt_nvu8_set_bits(pInfoFrame->Data.byte4, 0, NVT_HDMI_VS_BYTE4_RSVD_MASK, NVT_HDMI_VS_BYTE4_RSVD_SHIFT);
|
||
|
||
// setup the parameters
|
||
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);
|
||
|
||
// determine what the format is -- if disabled, force the format to NONE.
|
||
if (pCtrl->Enable)
|
||
{
|
||
HDMIFormat = pCtrl->HDMIFormat;
|
||
}
|
||
else
|
||
{
|
||
HDMIFormat = NVT_HDMI_VS_BYTE4_HDMI_VID_FMT_NONE;
|
||
}
|
||
|
||
switch(HDMIFormat)
|
||
{
|
||
case NVT_HDMI_VS_BYTE4_HDMI_VID_FMT_NONE:
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->Data.byte5, 0, NVT_HDMI_VS_BYTENv_RSVD_MASK, NVT_HDMI_VS_BYTENv_RSVD_SHIFT);
|
||
break;
|
||
}
|
||
case NVT_HDMI_VS_BYTE4_HDMI_VID_FMT_EXT:
|
||
{
|
||
// Note: extended resolution frames are not yet fully supported
|
||
nvt_nvu8_set_bits(pInfoFrame->Data.byte5, pCtrl->HDMI_VIC, NVT_HDMI_VS_BYTE5_HDMI_VIC_MASK, NVT_HDMI_VS_BYTE5_HDMI_VIC_SHIFT);
|
||
break;
|
||
}
|
||
case NVT_HDMI_VS_BYTE4_HDMI_VID_FMT_3D:
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->Data.byte5, 0, NVT_HDMI_VS_BYTE5_HDMI_RSVD_MASK, NVT_HDMI_VS_BYTE5_HDMI_RSVD_SHIFT);
|
||
nvt_nvu8_set_bits(pInfoFrame->Data.byte5, pCtrl->ThreeDStruc, NVT_HDMI_VS_BYTE5_HDMI_3DS_MASK, NVT_HDMI_VS_BYTE5_HDMI_3DS_SHIFT);
|
||
|
||
// side by side half requires additional format data in the infoframe.
|
||
if (NVT_HDMI_VS_BYTE5_HDMI_3DS_SIDEBYSIDEHALF == pCtrl->ThreeDStruc)
|
||
{
|
||
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);
|
||
optIdx++;
|
||
}
|
||
if (pCtrl->MetadataPresent)
|
||
{
|
||
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);
|
||
|
||
switch(pCtrl->MetadataType)
|
||
{
|
||
case NVT_HDMI_VS_BYTE_OPT2_HDMI_METADATA_TYPE_PARALLAX:
|
||
{
|
||
if (sizeof(pCtrl->Metadata) >= NVT_HDMI_VS_BYTE_OPT2_HDMI_METADATA_LEN_PARALLAX &&
|
||
sizeof(pInfoFrame->Data.optionalBytes) - (optIdx + 1) >= NVT_HDMI_VS_BYTE_OPT2_HDMI_METADATA_LEN_PARALLAX)
|
||
{
|
||
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);
|
||
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);
|
||
++optIdx;
|
||
|
||
NVMISC_MEMCPY(pCtrl->Metadata, &pInfoFrame->Data.optionalBytes[optIdx], NVT_HDMI_VS_BYTE_OPT2_HDMI_METADATA_LEN_PARALLAX);
|
||
optIdx += NVT_HDMI_VS_BYTE_OPT2_HDMI_METADATA_LEN_PARALLAX;
|
||
}
|
||
else
|
||
{
|
||
// not enough data in the control struct or not enough room in the infoframe -- BOTH compile time issues!!
|
||
// ignore metadata.
|
||
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);
|
||
}
|
||
break;
|
||
}
|
||
default:
|
||
{
|
||
// unrecognised metadata, recover the best we can.
|
||
// note -- can not copy whatever is there because type implies length.
|
||
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);
|
||
RetCode = NVT_STATUS_ERR;
|
||
}
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
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);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
// clear last byte of infoframe (reserved per spec).
|
||
pInfoFrame->Header.length += optIdx + 1;
|
||
for (; optIdx < sizeof(pInfoFrame->Data.optionalBytes); ++optIdx)
|
||
{
|
||
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);
|
||
}
|
||
}
|
||
return RetCode;
|
||
}
|
||
|
||
// Construct Extended Metadata Packet Infoframe
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
NVT_STATUS NvTiming_ConstructExtendedMetadataPacketInfoframe(
|
||
NVT_EXTENDED_METADATA_PACKET_INFOFRAME_CTRL *pCtrl,
|
||
NVT_EXTENDED_METADATA_PACKET_INFOFRAME *pInfoFrame)
|
||
{
|
||
NVT_STATUS RetCode = NVT_STATUS_SUCCESS;
|
||
if (!pCtrl || !pInfoFrame)
|
||
{
|
||
return NVT_STATUS_INVALID_PARAMETER;
|
||
}
|
||
|
||
// Initialize the infoframe
|
||
NVMISC_MEMSET(pInfoFrame, 0, sizeof(*pInfoFrame));
|
||
|
||
// Construct an infoframe to enable or disable HDMI 2.1 VRR
|
||
pInfoFrame->Header.type = NVT_INFOFRAME_TYPE_EXTENDED_METADATA_PACKET;
|
||
pInfoFrame->Header.firstLast = NVT_EMP_HEADER_FIRST_LAST;
|
||
pInfoFrame->Header.sequenceIndex = 0x00;
|
||
|
||
nvt_nvu8_set_bits(pInfoFrame->Data.byte1, NVT_HDMI_EMP_BYTE1_VFR_ENABLE,
|
||
NVT_HDMI_EMP_BYTE1_VFR_MASK,
|
||
NVT_HDMI_EMP_BYTE1_VFR_SHIFT);
|
||
|
||
nvt_nvu8_set_bits(pInfoFrame->Data.byte1, NVT_HDMI_EMP_BYTE1_NEW_ENABLE,
|
||
NVT_HDMI_EMP_BYTE1_NEW_MASK,
|
||
NVT_HDMI_EMP_BYTE1_NEW_SHIFT);
|
||
|
||
if (!pCtrl->EnableVRR)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->Data.byte1, NVT_HDMI_EMP_BYTE1_END_ENABLE,
|
||
NVT_HDMI_EMP_BYTE1_END_MASK,
|
||
NVT_HDMI_EMP_BYTE1_END_SHIFT);
|
||
}
|
||
|
||
nvt_nvu8_set_bits(pInfoFrame->Data.byte3,
|
||
NVT_HDMI_EMP_BYTE3_ORGANIZATION_ID_SPEC_DEFINED,
|
||
NVT_HDMI_EMP_BYTE3_ORGANIZATION_ID_MASK,
|
||
NVT_HDMI_EMP_BYTE3_ORGANIZATION_ID_SHIFT);
|
||
|
||
nvt_nvu8_set_bits(pInfoFrame->Data.byte5, 1,
|
||
NVT_HDMI_EMP_BYTE5_DATA_SET_TAG_LSB_MASK,
|
||
NVT_HDMI_EMP_BYTE5_DATA_SET_TAG_LSB_SHIFT);
|
||
|
||
nvt_nvu8_set_bits(pInfoFrame->Data.byte7, (pCtrl->EnableVRR ? 4 : 0),
|
||
NVT_HDMI_EMP_BYTE7_DATA_SET_LENGTH_LSB_MASK,
|
||
NVT_HDMI_EMP_BYTE7_DATA_SET_LENGTH_LSB_SHIFT);
|
||
|
||
if (pCtrl->EnableVRR)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->Data.metadataBytes[0],
|
||
NVT_HDMI_EMP_BYTE8_MD0_VRR_EN_ENABLE,
|
||
NVT_HDMI_EMP_BYTE8_MD0_VRR_EN_MASK,
|
||
NVT_HDMI_EMP_BYTE8_MD0_VRR_EN_SHIFT);
|
||
}
|
||
|
||
if (pCtrl->ITTiming)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->Data.metadataBytes[1],
|
||
pCtrl->BaseVFP,
|
||
NVT_HDMI_EMP_BYTE8_MD1_BASE_VFRONT_MASK,
|
||
NVT_HDMI_EMP_BYTE8_MD1_BASE_VFRONT_SHIFT);
|
||
|
||
// In HDMI2.1, MD2 bit 2 is set when RB timing is used.
|
||
// In HDMI2.1A, MD2 bit 2 is RSVD as 0
|
||
if (pCtrl->version == NVT_EXTENDED_METADATA_PACKET_INFOFRAME_VER_HDMI21)
|
||
{
|
||
nvt_nvu8_set_bits(pInfoFrame->Data.metadataBytes[2],
|
||
pCtrl->ReducedBlanking,
|
||
NVT_HDMI_EMP_BYTE8_MD2_RB_MASK,
|
||
NVT_HDMI_EMP_BYTE8_MD2_RB_SHIFT);
|
||
}
|
||
|
||
// MSB for Base Refresh Rate
|
||
nvt_nvu8_set_bits(pInfoFrame->Data.metadataBytes[2],
|
||
pCtrl->BaseRefreshRate >> 8,
|
||
NVT_HDMI_EMP_BYTE8_MD2_BASE_RR_MSB_MASK,
|
||
NVT_HDMI_EMP_BYTE8_MD2_BASE_RR_MSB_SHIFT);
|
||
|
||
// LSB for Base Refresh Rate
|
||
nvt_nvu8_set_bits(pInfoFrame->Data.metadataBytes[3],
|
||
pCtrl->BaseRefreshRate,
|
||
NVT_HDMI_EMP_BYTE8_MD3_BASE_RR_LSB_MASK,
|
||
NVT_HDMI_EMP_BYTE8_MD3_BASE_RR_LSB_SHIFT);
|
||
}
|
||
|
||
return RetCode;
|
||
}
|
||
|
||
// Enumerate Psf Timing
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
NVT_STATUS NvTiming_EnumNvPsfTiming(NvU32 nvPsfFormat, NVT_TIMING *pT)
|
||
{
|
||
if (pT == NULL || nvPsfFormat == 0 || nvPsfFormat > MAX_PSF_FORMAT)
|
||
{
|
||
return NVT_STATUS_ERR;
|
||
}
|
||
|
||
*pT = PSF_TIMING[nvPsfFormat - 1];
|
||
|
||
// calculate the pixel clock
|
||
pT->pclk = RRx1kToPclk (pT);
|
||
|
||
return NVT_STATUS_SUCCESS;
|
||
}
|
||
|
||
// Set ActiveSpace for HDMI 3D stereo timing
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void SetActiveSpaceForHDMI3DStereo(const NVT_TIMING *pTiming, NVT_EXT_TIMING *pExtTiming)
|
||
{
|
||
// Note -- this assumes that the Timng is the 2D instance.
|
||
NvU16 VBlank;
|
||
|
||
// assume no active space to start.
|
||
pExtTiming->HDMI3D.VActiveSpace[0] = 0;
|
||
pExtTiming->HDMI3D.VActiveSpace[1] = 0;
|
||
|
||
if (NVT_HDMI_VS_BYTE5_HDMI_3DS_FRAMEPACK == pExtTiming->HDMI3D.StereoStructureType)
|
||
{
|
||
VBlank = pTiming->VTotal - pTiming->VVisible;
|
||
if (pTiming->interlaced)
|
||
{
|
||
//++++ This need to be revisited, not sure when active space 1 & 2 should be different.
|
||
// (fortunately, we are not supporting any interlaced packed frame modes yet).
|
||
pExtTiming->HDMI3D.VActiveSpace[0] = VBlank + 1;
|
||
pExtTiming->HDMI3D.VActiveSpace[1] = VBlank - 1;
|
||
}
|
||
else
|
||
{
|
||
pExtTiming->HDMI3D.VActiveSpace[0] = VBlank;
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
// Generate HDMI stereo timing from 2D timing
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void NvTiming_GetHDMIStereoTimingFrom2DTiming(const NVT_TIMING *pTiming, NvU8 StereoStructureType, NvU8 SideBySideHalfDetail, NVT_EXT_TIMING *pExtTiming)
|
||
{
|
||
NvU16 VBlank;
|
||
NvU16 HBlank;
|
||
|
||
if ((NULL == pTiming) || (NULL == pExtTiming) || (!isHdmi3DStereoType(StereoStructureType)))
|
||
{
|
||
return;
|
||
}
|
||
// init the extended timing
|
||
NVMISC_MEMSET(pExtTiming, 0, sizeof(NVT_EXT_TIMING));
|
||
|
||
// copy the 2D timing to the 3D timing.
|
||
pExtTiming->timing = *pTiming;
|
||
|
||
// init the extension w/in the 3D timing
|
||
pExtTiming->HDMI3D.StereoStructureType = StereoStructureType;
|
||
pExtTiming->HDMI3D.SideBySideHalfDetail = SideBySideHalfDetail;
|
||
|
||
|
||
switch(StereoStructureType)
|
||
{
|
||
case NVT_HDMI_VS_BYTE5_HDMI_3DS_FRAMEPACK:
|
||
{
|
||
// calculate VBlank
|
||
VBlank = pTiming->VTotal - pTiming->VVisible;
|
||
|
||
// Use the 2D timing to calculate the Active Space
|
||
SetActiveSpaceForHDMI3DStereo(pTiming, pExtTiming);
|
||
|
||
// Calculate the 3D VVisible size based on the 2D VVisible and the active space.
|
||
if (pTiming->interlaced)
|
||
{
|
||
pExtTiming->timing.VVisible = ((pTiming->VVisible * 4) + (pExtTiming->HDMI3D.VActiveSpace[0]) * 2) + pExtTiming->HDMI3D.VActiveSpace[1];
|
||
}
|
||
else
|
||
{
|
||
pExtTiming->timing.VVisible = (pTiming->VVisible * 2) + pExtTiming->HDMI3D.VActiveSpace[0];
|
||
}
|
||
// Calculate the 3D VTotal from the 3D VVisible & the VBlank.
|
||
pExtTiming->timing.VTotal = pExtTiming->timing.VVisible + VBlank;
|
||
|
||
pExtTiming->timing.etc.status = NVT_SET_TIMING_STATUS_TYPE(pExtTiming->timing.etc.status, NVT_TYPE_HDMI_STEREO);
|
||
|
||
break;
|
||
}
|
||
case NVT_HDMI_VS_BYTE5_HDMI_3DS_SIDEBYSIDEFULL:
|
||
{
|
||
// calculate HBlank before calculating new HVisible
|
||
HBlank = pTiming->HTotal - pTiming->HVisible;
|
||
|
||
pExtTiming->timing.HVisible = pTiming->HVisible * 2;
|
||
|
||
pExtTiming->timing.HTotal = pExtTiming->timing.HVisible + HBlank;
|
||
|
||
pExtTiming->timing.etc.status = NVT_SET_TIMING_STATUS_TYPE(pExtTiming->timing.etc.status, NVT_TYPE_HDMI_STEREO);
|
||
|
||
break;
|
||
}
|
||
case NVT_HDMI_VS_BYTE5_HDMI_3DS_SIDEBYSIDEHALF: // valid formats with no timing changes.
|
||
case NVT_HDMI_VS_BYTE5_HDMI_3DS_TOPBOTTOM:
|
||
{
|
||
break;
|
||
}
|
||
case NVT_HDMI_VS_BYTE5_HDMI_3DS_FIELD_ALT: // formats we are not supporting.
|
||
case NVT_HDMI_VS_BYTE5_HDMI_3DS_LINE_ALT:
|
||
case NVT_HDMI_VS_BYTE5_HDMI_3DS_LDEPTH:
|
||
case NVT_HDMI_VS_BYTE5_HDMI_3DS_LDEPTHGFX:
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
// calculate the pixel clock
|
||
pExtTiming->timing.pclk = RRx1kToPclk (&(pExtTiming->timing));
|
||
return;
|
||
}
|
||
|
||
// Add mode to 3D stereo support map
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void AddModeToSupportMap(HDMI3DSUPPORTMAP * pMap, NvU8 Vic, NvU8 StereoStructureType, NvU8 SideBySideHalfDetail)
|
||
{
|
||
NvU32 i;
|
||
|
||
if (0 < Vic)
|
||
{
|
||
// first check if the vic is already listed.
|
||
for (i = 0; i < pMap->total; ++i)
|
||
{
|
||
if (pMap->map[i].Vic == Vic)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
if (i == pMap->total)
|
||
{
|
||
// vic is not in the map.
|
||
// add it.
|
||
// note that we can't add the VIC to one of the 1st 16 entries.
|
||
// 1st 16 entries in the map are reserved for the vics from the EDID.
|
||
// if we add this VIC to the 1st 16, & there are any optional modes listed,
|
||
// the optional mode(s) will be improperly applied to this VIC as well
|
||
i = MAX(MAX_EDID_ADDRESSABLE_3D_VICS, pMap->total);
|
||
if (i < MAX_3D_VICS_SUPPORTED)
|
||
{
|
||
pMap->map[i].Vic = Vic;
|
||
pMap->total = i + 1;
|
||
}
|
||
}
|
||
nvt_assert(pMap->total <= MAX_3D_VICS_SUPPORTED);
|
||
if (i < pMap->total)
|
||
{
|
||
pMap->map[i].StereoStructureMask = pMap->map[i].StereoStructureMask | NVT_HDMI_3D_SUPPORTED_STRUCT_MASK(StereoStructureType);
|
||
if (NVT_HDMI_VS_BYTE5_HDMI_3DS_SIDEBYSIDEHALF == StereoStructureType)
|
||
{
|
||
pMap->map[i].SideBySideHalfDetail = SideBySideHalfDetail;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void parseEdidHdmiLlcBasicInfo(VSDB_DATA *pVsdb, NVT_HDMI_LLC_INFO *pHdmiLlc)
|
||
{
|
||
NVT_HDMI_LLC_VSDB_PAYLOAD *p;
|
||
if (pVsdb == NULL || pHdmiLlc == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
p = (NVT_HDMI_LLC_VSDB_PAYLOAD *)(&pVsdb->vendor_data);
|
||
|
||
// Minimum vendor_data_size is 2
|
||
pHdmiLlc->addrA = p->A;
|
||
pHdmiLlc->addrB = p->B;
|
||
pHdmiLlc->addrC = p->C;
|
||
pHdmiLlc->addrD = p->D;
|
||
|
||
// If more data is provided, we read it as well each field at a time up to video latency
|
||
if (pVsdb->vendor_data_size >= 3)
|
||
{
|
||
pHdmiLlc->supports_AI = p->Supports_AI;
|
||
pHdmiLlc->dc_48_bit = p->DC_48bit;
|
||
pHdmiLlc->dc_36_bit = p->DC_36bit;
|
||
pHdmiLlc->dc_30_bit = p->DC_30bit;
|
||
pHdmiLlc->dc_y444 = p->DC_Y444;
|
||
pHdmiLlc->dual_dvi = p->DVI_Dual;
|
||
|
||
if (pVsdb->vendor_data_size >= 4)
|
||
{
|
||
pHdmiLlc->max_tmds_clock = p->Max_TMDS_Clock;
|
||
|
||
if (pVsdb->vendor_data_size >= 5)
|
||
{
|
||
pHdmiLlc->latency_field_present = p->Latency_Fields_Present;
|
||
pHdmiLlc->i_latency_field_present = p->I_Latency_Fields_Present;
|
||
pHdmiLlc->hdmi_video_present = p->HDMI_Video_present;
|
||
pHdmiLlc->cnc3 = p->CNC3;
|
||
pHdmiLlc->cnc2 = p->CNC2;
|
||
pHdmiLlc->cnc1 = p->CNC1;
|
||
pHdmiLlc->cnc0 = p->CNC0;
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
// get HDMI 1.4 specific timing (3D stereo timings and extended mode timings)
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void parseEdidHDMILLCTiming(NVT_EDID_INFO *pInfo, VSDB_DATA *pVsdb, NvU32 *pMapSz, HDMI3DSUPPORTMAP * pM)
|
||
{
|
||
NVT_HDMI_LLC_VSDB_PAYLOAD *pHdmiLLC;
|
||
NVT_HDMI_VIDEO *pHDMIVideo;
|
||
NvU32 DataCnt = 0;
|
||
NvU32 DataSz;
|
||
NvU16 i, j, k;
|
||
NvU16 Supports50Hz;
|
||
NvU16 Supports60Hz;
|
||
NvU32 vendorDataSize;
|
||
|
||
if ((NULL == pInfo) || (NULL == pVsdb) || (NULL == pM))
|
||
{
|
||
return;
|
||
}
|
||
|
||
// init the support map
|
||
NVMISC_MEMSET(pM, 0, sizeof(HDMI3DSUPPORTMAP));
|
||
Supports50Hz = 0;
|
||
Supports60Hz = 0;
|
||
|
||
nvt_assert(pInfo->total_timings <= COUNT(pInfo->timing));
|
||
|
||
for (i = 0; i < pInfo->total_timings; ++i)
|
||
{
|
||
if (NVT_GET_TIMING_STATUS_TYPE(pInfo->timing[i].etc.status) == NVT_TYPE_EDID_861ST)
|
||
{
|
||
if (MAX_EDID_ADDRESSABLE_3D_VICS > pM->total)
|
||
{
|
||
// 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
|
||
// -- the optional modes are addressed based on their relative location within the EDID.
|
||
pM->map[pM->total].Vic = (NvU8) NVT_GET_TIMING_STATUS_SEQ(pInfo->timing[i].etc.status);
|
||
++pM->total;
|
||
}
|
||
|
||
// since we are spinning through the timing array anyway,
|
||
// check to see which refresh rates are supported.
|
||
if (50 == pInfo->timing[i].etc.rr)
|
||
{
|
||
Supports50Hz = 1;
|
||
}
|
||
else if (60 == pInfo->timing[i].etc.rr)
|
||
{
|
||
Supports60Hz = 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (0 == pM->total)
|
||
{
|
||
if (NULL != pMapSz)
|
||
{
|
||
*pMapSz = 0;
|
||
}
|
||
}
|
||
|
||
vendorDataSize = pVsdb->vendor_data_size;
|
||
if ((NVT_CEA861_HDMI_IEEE_ID == pVsdb->ieee_id) &&
|
||
(offsetof(NVT_HDMI_LLC_VSDB_PAYLOAD, Data) < vendorDataSize))
|
||
{
|
||
pHdmiLLC = (NVT_HDMI_LLC_VSDB_PAYLOAD *)(&pVsdb->vendor_data);
|
||
DataSz = (NvU32) MIN(vendorDataSize - offsetof(NVT_HDMI_LLC_VSDB_PAYLOAD, Data), sizeof(pHdmiLLC->Data));
|
||
|
||
if (5 <= vendorDataSize)
|
||
{
|
||
if (pHdmiLLC->Latency_Fields_Present)
|
||
{
|
||
DataCnt += (NvU32) sizeof(NVT_CEA861_LATENCY);
|
||
|
||
if (pHdmiLLC->I_Latency_Fields_Present)
|
||
{
|
||
DataCnt += (NvU32) sizeof(NVT_CEA861_LATENCY);
|
||
}
|
||
}
|
||
|
||
if ((pHdmiLLC->HDMI_Video_present) &&
|
||
(DataSz > DataCnt) &&
|
||
(DataSz - DataCnt >= sizeof(NVT_HDMI_VIDEO)))
|
||
{
|
||
pHDMIVideo = (NVT_HDMI_VIDEO *) &pHdmiLLC->Data[DataCnt];
|
||
DataCnt += (NvU32) sizeof(NVT_HDMI_VIDEO);
|
||
|
||
// If 3D is present, then add the basic 3D modes 1st.
|
||
if (pHDMIVideo->ThreeD_Present)
|
||
{
|
||
if ((0 != Supports50Hz) || (0 != Supports60Hz))
|
||
{
|
||
// 50 and / or 60 Hz is supported, add 1920 x 1080 @ 24Hz 3D modes.
|
||
AddModeToSupportMap(pM, 32, NVT_HDMI_VS_BYTE5_HDMI_3DS_FRAMEPACK, 0); // 1920 x 1080p @ 24 Hz
|
||
AddModeToSupportMap(pM, 32, NVT_HDMI_VS_BYTE5_HDMI_3DS_TOPBOTTOM, 0); // 1920 x 1080p @ 24 Hz
|
||
|
||
if (0 != Supports50Hz)
|
||
{
|
||
// add the mandatory modes for 50 Hz
|
||
AddModeToSupportMap(pM, 19, NVT_HDMI_VS_BYTE5_HDMI_3DS_FRAMEPACK, 0); // 1280 x 720p @ 50 Hz
|
||
AddModeToSupportMap(pM, 19, NVT_HDMI_VS_BYTE5_HDMI_3DS_TOPBOTTOM, 0); // 1280 x 720p @ 50 Hz
|
||
// 1920 x 1080i @ 50 Hz
|
||
AddModeToSupportMap(pM, 20, NVT_HDMI_VS_BYTE5_HDMI_3DS_SIDEBYSIDEHALF, NVT_HDMI_VS_BYTE_OPT1_HDMI_3DEX_SSH);
|
||
}
|
||
|
||
if (0 != Supports60Hz)
|
||
{
|
||
// add the mandatory modes for 60 Hz
|
||
AddModeToSupportMap(pM, 4, NVT_HDMI_VS_BYTE5_HDMI_3DS_FRAMEPACK, 0); // 1280 x 720p @ 60 Hz
|
||
AddModeToSupportMap(pM, 4, NVT_HDMI_VS_BYTE5_HDMI_3DS_TOPBOTTOM, 0); // 1280 x 720p @ 60 Hz
|
||
// 1920 x 1080i @ 60 Hz
|
||
AddModeToSupportMap(pM, 5, NVT_HDMI_VS_BYTE5_HDMI_3DS_SIDEBYSIDEHALF, NVT_HDMI_VS_BYTE_OPT1_HDMI_3DEX_SSH);
|
||
}
|
||
}
|
||
}
|
||
|
||
if ((DataSz > DataCnt) &&
|
||
(DataSz - DataCnt >= pHDMIVideo->HDMI_VIC_Len))
|
||
{
|
||
// handle HDMI VIC entries to add HDMI 1.4a 4kx2k extended modes
|
||
NVT_HDMI_VIC_LIST * pVicList = (NVT_HDMI_VIC_LIST *) &pHdmiLLC->Data[DataCnt];
|
||
|
||
for ( k = 0; k < pHDMIVideo->HDMI_VIC_Len; ++k)
|
||
{
|
||
NVT_TIMING newTiming;
|
||
|
||
// extended mode VIC code from 1 - 4.
|
||
if ((0 < pVicList->HDMI_VIC[k]) && (pVicList->HDMI_VIC[k] <= MAX_HDMI_EXT_4Kx2K_FORMAT))
|
||
{
|
||
NVMISC_MEMCPY(&newTiming,
|
||
&HDMI_EXT_4Kx2K_TIMING[pVicList->HDMI_VIC[k] - 1],
|
||
sizeof(newTiming));
|
||
|
||
// Fill in the pixel clock
|
||
newTiming.pclk = RRx1kToPclk(&newTiming);
|
||
|
||
if (!assignNextAvailableTiming(pInfo, &newTiming))
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
DataCnt += pHDMIVideo->HDMI_VIC_Len;
|
||
}
|
||
|
||
// the following code implements parsing the HDMI 3D additional modes (all modes bitmap & additional vic modes)
|
||
// Kepler and above support 3D secondary modes
|
||
if ((pHDMIVideo->ThreeD_Present) &&
|
||
((1 == pHDMIVideo->ThreeD_Multi_Present) || (2 == pHDMIVideo->ThreeD_Multi_Present)) &&
|
||
(0 < pHDMIVideo->HDMI_3D_Len) &&
|
||
(DataSz > (DataCnt + 1)) && //make sure pHdmiLLC->Data[DataCnt + 1] is valid
|
||
(DataSz - DataCnt >= pHDMIVideo->HDMI_3D_Len))
|
||
{
|
||
NvU16 AllVicStructMask;
|
||
NvU16 AllVicIdxMask;
|
||
NvU8 AllVicDetail;
|
||
|
||
// determine which modes to apply to all VICs.
|
||
AllVicStructMask = (pHdmiLLC->Data[DataCnt] << 8) | pHdmiLLC->Data[DataCnt + 1];
|
||
AllVicStructMask = AllVicStructMask & NVT_ALL_HDMI_3D_STRUCT_SUPPORTED_MASK;
|
||
DataCnt += 2;
|
||
|
||
if ((2 == pHDMIVideo->ThreeD_Multi_Present) && (DataSz > (DataCnt+1))) //make sure pHdmiLLC->Data[DataCnt + 1] is valid
|
||
{
|
||
AllVicIdxMask = pHdmiLLC->Data[DataCnt] << 8 | pHdmiLLC->Data[DataCnt + 1];
|
||
DataCnt += 2;
|
||
}
|
||
else
|
||
{
|
||
AllVicIdxMask = 0xffff;
|
||
}
|
||
|
||
// determine what the detail should be.
|
||
AllVicDetail = 0 != (AllVicStructMask & NVT_HDMI_3D_SUPPORTED_SIDEBYSIDEHALF_MASK) ? NVT_HDMI_VS_BYTE_OPT1_HDMI_3DEX_SSH : 0;
|
||
|
||
// add the modes to the Support map for all the listed VICs.
|
||
for (k = 0; k < MIN(MAX_EDID_ADDRESSABLE_3D_VICS, pM->total); ++k)
|
||
{
|
||
if ((0 != (AllVicIdxMask & (1 << k))) && (0 != pM->map[k].Vic))
|
||
{
|
||
pM->map[k].StereoStructureMask = pM->map[k].StereoStructureMask | AllVicStructMask;
|
||
pM->map[k].SideBySideHalfDetail = AllVicDetail;
|
||
}
|
||
}
|
||
}
|
||
|
||
// handle any additional per vic modes listed in the EDID
|
||
while (DataSz > DataCnt)
|
||
{
|
||
// get a pointer to the entry.
|
||
NVT_3D_MULTI_LIST * pMultiListEntry = (NVT_3D_MULTI_LIST *) &pHdmiLLC->Data[DataCnt];
|
||
|
||
// apply the specified structure to the Support Map
|
||
pM->map[pMultiListEntry->TwoD_VIC_order].StereoStructureMask =
|
||
pM->map[pMultiListEntry->TwoD_VIC_order].StereoStructureMask | NVT_HDMI_3D_SUPPORTED_STRUCT_MASK(pMultiListEntry->ThreeD_Structure);
|
||
|
||
// increment the Data count by 2 if this is side by side half,
|
||
// or 1 if it is any other structure.
|
||
if (NVT_HDMI_VS_BYTE5_HDMI_3DS_SIDEBYSIDEHALF <= pMultiListEntry->ThreeD_Structure)
|
||
{
|
||
pM->map[pMultiListEntry->TwoD_VIC_order].SideBySideHalfDetail = pMultiListEntry->ThreeD_Detail;
|
||
DataCnt += 2;
|
||
}
|
||
else
|
||
{
|
||
pM->map[pMultiListEntry->TwoD_VIC_order].SideBySideHalfDetail = 0;
|
||
DataCnt += 1;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
// compress out entries where there is no 3D support.
|
||
for (i = 0, j = 0; i < pM->total; ++i)
|
||
{
|
||
if (0 != pM->map[i].StereoStructureMask)
|
||
{
|
||
pM->map[j] = pM->map[i];
|
||
++j;
|
||
}
|
||
}
|
||
|
||
pM->total = j;
|
||
|
||
if (NULL != pMapSz)
|
||
{
|
||
*pMapSz = pM->total;
|
||
}
|
||
}
|
||
|
||
// get HDMI 1.4 3D mandatory stereo format datail base on the input vic.
|
||
// If the vic is not in the mandatory format list, return error.
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
NVT_STATUS NvTiming_GetHDMIStereoMandatoryFormatDetail(const NvU8 vic, NvU16 *pStereoStructureMask, NvU8 *pSideBySideHalfDetail)
|
||
{
|
||
NvU32 i;
|
||
|
||
if ((vic < 1) || (vic > MAX_CEA861B_FORMAT))
|
||
{
|
||
return NVT_STATUS_ERR;
|
||
}
|
||
|
||
for (i = 0; i < MAX_HDMI_MANDATORY_3D_FORMAT; i++)
|
||
{
|
||
if (vic == HDMI_MANDATORY_3D_FORMATS[i].Vic)
|
||
{
|
||
if (pStereoStructureMask != NULL)
|
||
{
|
||
*pStereoStructureMask = HDMI_MANDATORY_3D_FORMATS[i].StereoStructureMask;
|
||
}
|
||
|
||
if (pSideBySideHalfDetail != NULL)
|
||
{
|
||
*pSideBySideHalfDetail = HDMI_MANDATORY_3D_FORMATS[i].SideBySideHalfDetail;
|
||
}
|
||
|
||
return NVT_STATUS_SUCCESS;
|
||
}
|
||
}
|
||
|
||
return NVT_STATUS_ERR;
|
||
}
|
||
// return the aspect ratio of a given CEA/EIA 861 timing
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
NvU32 getCEA861TimingAspectRatio(NvU32 vic)
|
||
{
|
||
return (vic > 0 && vic < MAX_CEA861B_FORMAT + 1) ? EIA861B[vic-1].etc.aspect : 0;
|
||
}
|
||
|
||
// expose the HDMI extended video timing defined by the HDMI LLC VSDB
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
NVT_STATUS NvTiming_EnumHdmiVsdbExtendedTiming(NvU32 hdmi_vic, NVT_TIMING *pT)
|
||
{
|
||
if (hdmi_vic > MAX_HDMI_EXT_4Kx2K_FORMAT || hdmi_vic == 0 || pT == NULL)
|
||
{
|
||
return NVT_STATUS_ERR;
|
||
}
|
||
*pT = HDMI_EXT_4Kx2K_TIMING[hdmi_vic - 1];
|
||
pT->pclk = RRx1kToPclk(pT);
|
||
return NVT_STATUS_SUCCESS;
|
||
}
|
||
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void parseEdidNvidiaVSDBBlock(VSDB_DATA *pVsdb, NVDA_VSDB_PARSED_INFO *vsdbInfo)
|
||
{
|
||
NVT_NVDA_VSDB_PAYLOAD *pNvda;
|
||
|
||
if ((pVsdb == NULL) || (vsdbInfo == NULL))
|
||
{
|
||
return;
|
||
}
|
||
|
||
if ((NVT_CEA861_NVDA_IEEE_ID == pVsdb->ieee_id) &&
|
||
(pVsdb->vendor_data_size >= sizeof(NVT_NVDA_VSDB_PAYLOAD)))
|
||
{
|
||
pNvda = (NVT_NVDA_VSDB_PAYLOAD *)(&pVsdb->vendor_data);
|
||
|
||
// only version 0x1 is supported
|
||
if (pNvda->opcode == 0x1)
|
||
{
|
||
vsdbInfo->vsdbVersion = pNvda->opcode;
|
||
}
|
||
|
||
switch (vsdbInfo->vsdbVersion)
|
||
{
|
||
case 1:
|
||
vsdbInfo->valid = NV_TRUE;
|
||
vsdbInfo->vrrData.v1.supportsVrr = NV_TRUE;
|
||
vsdbInfo->vrrData.v1.minRefreshRate = pNvda->vrrMinRefreshRate;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void parseEdidMsftVsdbBlock(VSDB_DATA *pVsdb, MSFT_VSDB_PARSED_INFO *pVsdbInfo)
|
||
{
|
||
if ((pVsdb == NULL) || (pVsdbInfo == NULL))
|
||
{
|
||
return;
|
||
}
|
||
|
||
NVMISC_MEMSET(pVsdbInfo, 0, sizeof(MSFT_VSDB_PARSED_INFO));
|
||
|
||
if ((NVT_CEA861_MSFT_IEEE_ID == pVsdb->ieee_id) &&
|
||
(pVsdb->vendor_data_size >= sizeof(NVT_MSFT_VSDB_PAYLOAD)))
|
||
{
|
||
NvU32 i = 0;
|
||
NVT_MSFT_VSDB_PAYLOAD *pMsftVsdbPayload = (NVT_MSFT_VSDB_PAYLOAD *)(&pVsdb->vendor_data);
|
||
|
||
pVsdbInfo->version = pMsftVsdbPayload->version;
|
||
|
||
if (pVsdbInfo->version >= 1)
|
||
{
|
||
for (i = 0; i < MSFT_VSDB_CONTAINER_ID_SIZE; i++)
|
||
{
|
||
pVsdbInfo->containerId[i] = pMsftVsdbPayload->containerId[i];
|
||
}
|
||
|
||
pVsdbInfo->desktopUsage = pMsftVsdbPayload->desktopUsage;
|
||
pVsdbInfo->thirdPartyUsage = pMsftVsdbPayload->thirdPartyUsage;
|
||
pVsdbInfo->valid = NV_TRUE;
|
||
}
|
||
// Version 3 is the latest version of MSFT VSDB at the time of writing this code
|
||
// Any update from newer version will be ignored and be parsed as Version 3, till
|
||
// we have an explicit handling for newer version here.
|
||
if (pVsdbInfo->version >= 3)
|
||
{
|
||
// Primary Use case is valid from Version 3 and is ignored on previous versions.
|
||
pVsdbInfo->primaryUseCase = pMsftVsdbPayload->primaryUseCase;
|
||
}
|
||
}
|
||
}
|
||
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void parseEdidHdmiForumVSDB(VSDB_DATA *pVsdb, NVT_HDMI_FORUM_INFO *pHdmiInfo)
|
||
{
|
||
NVT_HDMI_FORUM_VSDB_PAYLOAD *pHdmiForum;
|
||
NvU32 remainingSize;
|
||
|
||
if ((pVsdb == NULL) || pHdmiInfo == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
pHdmiForum = (NVT_HDMI_FORUM_VSDB_PAYLOAD *)(&pVsdb->vendor_data);
|
||
switch(pHdmiForum->Version)
|
||
{
|
||
case 1:
|
||
// From HDMI spec the payload data size is from 7 to 31
|
||
// In parseCta861DataBlockInfo(), the payload size recorded in pHdmiForum is
|
||
// subtracted by 3. Thus the expected range here is 4 - 28.
|
||
// Assert if the the vendor_data_size < 4.
|
||
nvt_assert(pVsdb->vendor_data_size >= 4);
|
||
|
||
remainingSize = pVsdb->vendor_data_size;
|
||
|
||
// second byte
|
||
pHdmiInfo->max_TMDS_char_rate = pHdmiForum->Max_TMDS_Character_Rate;
|
||
|
||
// third byte
|
||
pHdmiInfo->threeD_Osd_Disparity = pHdmiForum->ThreeD_Osd_Disparity;
|
||
pHdmiInfo->dual_view = pHdmiForum->Dual_View;
|
||
pHdmiInfo->independent_View = pHdmiForum->Independent_View;
|
||
pHdmiInfo->lte_340Mcsc_scramble = pHdmiForum->Lte_340mcsc_Scramble;
|
||
pHdmiInfo->ccbpci = pHdmiForum->CCBPCI;
|
||
pHdmiInfo->cable_status = pHdmiForum->CABLE_STATUS;
|
||
pHdmiInfo->rr_capable = pHdmiForum->RR_Capable;
|
||
pHdmiInfo->scdc_present = pHdmiForum->SCDC_Present;
|
||
|
||
// fourth byte
|
||
pHdmiInfo->dc_30bit_420 = pHdmiForum->DC_30bit_420;
|
||
pHdmiInfo->dc_36bit_420 = pHdmiForum->DC_36bit_420;
|
||
pHdmiInfo->dc_48bit_420 = pHdmiForum->DC_48bit_420;
|
||
pHdmiInfo->uhd_vic = pHdmiForum->UHD_VIC;
|
||
pHdmiInfo->max_FRL_Rate = pHdmiForum->Max_FRL_Rate;
|
||
|
||
remainingSize -= 4;
|
||
|
||
// fifth byte
|
||
if (!remainingSize--)
|
||
{
|
||
break;
|
||
}
|
||
pHdmiInfo->fapa_start_location = pHdmiForum->FAPA_start_location;
|
||
pHdmiInfo->allm = pHdmiForum->ALLM;
|
||
pHdmiInfo->fva = pHdmiForum->FVA;
|
||
pHdmiInfo->cnmvrr = pHdmiForum->CNMVRR;
|
||
pHdmiInfo->cinemaVrr = pHdmiForum->CinemaVRR;
|
||
pHdmiInfo->m_delta = pHdmiForum->M_delta;
|
||
pHdmiInfo->fapa_end_extended = pHdmiForum->FAPA_End_Extended;
|
||
|
||
// sixth byte
|
||
if (!remainingSize--)
|
||
{
|
||
break;
|
||
}
|
||
pHdmiInfo->vrr_min = pHdmiForum->VRR_min;
|
||
pHdmiInfo->vrr_max = ((NvU16)pHdmiForum->VRR_max_high) << 8;
|
||
|
||
// seventh byte
|
||
if (!remainingSize--)
|
||
{
|
||
break;
|
||
}
|
||
pHdmiInfo->vrr_max |= (pHdmiForum->VRR_max_low);
|
||
|
||
// eighth byte
|
||
if (!remainingSize--)
|
||
{
|
||
break;
|
||
}
|
||
pHdmiInfo->dsc_10bpc = pHdmiForum->DSC_10bpc;
|
||
pHdmiInfo->dsc_12bpc = pHdmiForum->DSC_12bpc;
|
||
pHdmiInfo->dsc_16bpc = pHdmiForum->DSC_16bpc;
|
||
pHdmiInfo->dsc_All_bpp = pHdmiForum->DSC_All_bpp;
|
||
pHdmiInfo->dsc_Native_420 = pHdmiForum->DSC_Native_420;
|
||
pHdmiInfo->dsc_1p2 = pHdmiForum->DSC_1p2;
|
||
|
||
// ninth byte
|
||
if (!remainingSize--)
|
||
{
|
||
break;
|
||
}
|
||
pHdmiInfo->dsc_MaxSlices = 0;
|
||
pHdmiInfo->dsc_MaxPclkPerSliceMHz = 0;
|
||
switch(pHdmiForum->DSC_MaxSlices)
|
||
{
|
||
case 7: pHdmiInfo->dsc_MaxSlices = 16; pHdmiInfo->dsc_MaxPclkPerSliceMHz = 400; break;
|
||
case 6: pHdmiInfo->dsc_MaxSlices = 12; pHdmiInfo->dsc_MaxPclkPerSliceMHz = 400; break;
|
||
case 5: pHdmiInfo->dsc_MaxSlices = 8; pHdmiInfo->dsc_MaxPclkPerSliceMHz = 400; break;
|
||
case 4: pHdmiInfo->dsc_MaxSlices = 8; pHdmiInfo->dsc_MaxPclkPerSliceMHz = 340; break;
|
||
case 3: pHdmiInfo->dsc_MaxSlices = 4; pHdmiInfo->dsc_MaxPclkPerSliceMHz = 340; break;
|
||
case 2: pHdmiInfo->dsc_MaxSlices = 2; pHdmiInfo->dsc_MaxPclkPerSliceMHz = 340; break;
|
||
case 1: pHdmiInfo->dsc_MaxSlices = 1; pHdmiInfo->dsc_MaxPclkPerSliceMHz = 340; break;
|
||
default: break;
|
||
}
|
||
|
||
pHdmiInfo->dsc_Max_FRL_Rate = pHdmiForum->DSC_Max_FRL_Rate;
|
||
|
||
// tenth byte
|
||
if (!remainingSize--)
|
||
{
|
||
break;
|
||
}
|
||
|
||
// Per spec, number of bytes has to be computed as 1024 x (1 + DSC_TotalChunkKBytes).
|
||
// For driver parser purposes, add 1 here so that the field means max num of KBytes in a link of chunks
|
||
pHdmiInfo->dsc_totalChunkKBytes = (pHdmiForum->DSC_totalChunkKBytes == 0) ? 0 : pHdmiForum->DSC_totalChunkKBytes + 1;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
|
||
}
|
||
}
|
||
|
||
CODE_SEGMENT(PAGE_DD_CODE)
|
||
void parseCea861Hdr10PlusDataBlock(NVT_EDID_CEA861_INFO *pExt861, void *pRawInfo, NVT_CTA861_ORIGIN flag)
|
||
{
|
||
NVT_EDID_INFO *pInfo = NULL;
|
||
NVT_DISPLAYID_2_0_INFO *pDisplayID20 = NULL;
|
||
NVT_HDR10PLUS_INFO *pHdr10PlusInfo = NULL;
|
||
|
||
if (pExt861 == NULL || pRawInfo == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (flag == FROM_CTA861_EXTENSION || flag == FROM_DISPLAYID_13_DATA_BLOCK)
|
||
{
|
||
pInfo = (NVT_EDID_INFO *)pRawInfo;
|
||
pHdr10PlusInfo = &pInfo->hdr10PlusInfo;
|
||
}
|
||
else if (flag == FROM_DISPLAYID_20_DATA_BLOCK)
|
||
{
|
||
pDisplayID20 = (NVT_DISPLAYID_2_0_INFO *)pRawInfo;
|
||
pHdr10PlusInfo = &pDisplayID20->cta.hdr10PlusInfo;
|
||
}
|
||
else
|
||
{
|
||
return;
|
||
}
|
||
|
||
if(pExt861->vsvdb.ieee_id != NVT_CEA861_HDR10PLUS_IEEE_ID)
|
||
{
|
||
return;
|
||
}
|
||
|
||
NVMISC_MEMSET(pHdr10PlusInfo, 0, sizeof(NVT_HDR10PLUS_INFO));
|
||
|
||
if (pExt861->vsvdb.vendor_data_size < sizeof(NVT_HDR10PLUS_INFO))
|
||
{
|
||
return;
|
||
}
|
||
|
||
NVMISC_MEMCPY(pHdr10PlusInfo, &pExt861->vsvdb.vendor_data, sizeof(NVT_HDR10PLUS_INFO));
|
||
}
|
||
|
||
POP_SEGMENTS
|