Serenity Operating System
1/*
2 * Copyright (c) 2022, the SerenityOS developers.
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <LibEDID/VIC.h>
8
9namespace EDID {
10
11// Video ID Code details as per CTA-861-G revised 2018 Table 3
12static constexpr VIC::Details s_vic_details[] = {
13 { 1, 640, 480, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_4_3 },
14 { 2, 720, 480, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_4_3 },
15 { 3, 720, 480, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
16 { 4, 1280, 720, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
17 { 5, 1920, 1080, 59940, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_16_9 },
18 { 6, 1440, 480, 59940, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_4_3 },
19 { 7, 1440, 480, 59940, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_16_9 },
20 { 8, 1440, 240, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_4_3 },
21 { 9, 1440, 240, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
22 { 10, 2880, 480, 59940, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_4_3 },
23 { 11, 2880, 480, 59940, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_16_9 },
24 { 12, 2880, 240, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_4_3 },
25 { 13, 2880, 240, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
26 { 14, 1440, 480, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_4_3 },
27 { 15, 1440, 480, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
28 { 16, 1920, 180, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
29 { 17, 720, 576, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_4_3 },
30 { 18, 720, 576, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
31 { 19, 1280, 720, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
32 { 20, 1920, 1080, 50000, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_16_9 },
33 { 21, 1440, 576, 50000, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_4_3 },
34 { 22, 1440, 576, 50000, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_16_9 },
35 { 23, 1440, 288, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_4_3 },
36 { 24, 1440, 288, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
37 { 25, 2880, 576, 50000, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_4_3 },
38 { 26, 2880, 576, 50000, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_16_9 },
39 { 27, 2880, 288, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_4_3 },
40 { 28, 2880, 288, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
41 { 29, 1440, 576, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_4_3 },
42 { 30, 1440, 576, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
43 { 31, 1920, 1080, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
44 { 32, 1920, 1080, 23980, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
45 { 33, 1920, 1080, 25000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
46 { 34, 1920, 1080, 29970, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
47 { 35, 2880, 480, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_4_3 },
48 { 36, 2880, 480, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
49 { 37, 2880, 576, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_4_3 },
50 { 38, 2880, 576, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
51 { 39, 1920, 1080, 50000, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_16_9 },
52 { 40, 1920, 1080, 100000, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_16_9 },
53 { 41, 1280, 720, 100000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
54 { 42, 720, 576, 100000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_4_3 },
55 { 43, 720, 576, 100000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
56 { 44, 1440, 576, 100000, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_4_3 },
57 { 45, 1440, 576, 100000, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_16_9 },
58 { 46, 1920, 1080, 119880, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_16_9 },
59 { 47, 1280, 720, 119880, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
60 { 48, 720, 480, 119880, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_4_3 },
61 { 49, 720, 480, 119880, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
62 { 50, 1440, 480, 119880, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_4_3 },
63 { 51, 1440, 480, 119880, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_16_9 },
64 { 52, 720, 576, 200000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_4_3 },
65 { 53, 720, 576, 200000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
66 { 54, 1440, 576, 200000, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_4_3 },
67 { 55, 1440, 576, 200000, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_16_9 },
68 { 56, 720, 480, 239760, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_4_3 },
69 { 57, 720, 480, 239760, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
70 { 58, 1440, 480, 239760, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_4_3 },
71 { 59, 1440, 480, 239760, VIC::Details::ScanType::Interlaced, VIC::Details::AspectRatio::AR_16_9 },
72 { 60, 1280, 720, 23980, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
73 { 61, 1280, 720, 25000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
74 { 62, 1280, 720, 29970, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
75 { 63, 1920, 1080, 119880, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
76 { 64, 1920, 1080, 100000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
77 { 65, 1280, 720, 23980, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
78 { 66, 1280, 720, 25000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
79 { 67, 1280, 720, 29970, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
80 { 68, 1280, 720, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
81 { 69, 1280, 720, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
82 { 70, 1280, 720, 100000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
83 { 71, 1280, 720, 119880, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
84 { 72, 1920, 1080, 23980, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
85 { 73, 1920, 1080, 25000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
86 { 74, 1920, 1080, 29970, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
87 { 75, 1920, 1080, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
88 { 76, 1920, 1080, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
89 { 77, 1920, 1080, 100000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
90 { 78, 1920, 1080, 119880, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
91 { 79, 1680, 720, 23980, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
92 { 80, 1680, 720, 25000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
93 { 81, 1680, 720, 29970, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
94 { 82, 1680, 720, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
95 { 83, 1680, 720, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
96 { 84, 1680, 720, 100000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
97 { 85, 1680, 720, 119880, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
98 { 86, 2560, 1080, 23980, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
99 { 87, 2560, 1080, 25000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
100 { 88, 2560, 1080, 29970, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
101 { 89, 2560, 1080, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
102 { 90, 2560, 1080, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
103 { 91, 2560, 1080, 100000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
104 { 92, 2560, 1080, 119880, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
105 { 93, 3840, 2160, 23980, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
106 { 94, 3840, 2160, 25000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
107 { 95, 3840, 2160, 29970, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
108 { 96, 3840, 2160, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
109 { 97, 3840, 2160, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
110 { 98, 4096, 2160, 23980, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_256_135 },
111 { 99, 4096, 2160, 25000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_256_135 },
112 { 100, 4096, 2160, 29970, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_256_135 },
113 { 101, 4096, 2160, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_256_135 },
114 { 102, 4096, 2160, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_256_135 },
115 { 103, 3840, 2160, 23980, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
116 { 104, 3840, 2160, 25000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
117 { 105, 3840, 2160, 29970, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
118 { 106, 3840, 2160, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
119 { 107, 3840, 2160, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
120 { 108, 1280, 720, 47950, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
121 { 109, 1280, 720, 47950, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
122 { 110, 1680, 720, 47950, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
123 { 111, 1920, 1080, 47950, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
124 { 112, 1920, 1080, 47950, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
125 { 113, 2560, 1080, 47950, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
126 { 114, 3840, 2160, 47950, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
127 { 115, 4096, 2160, 47950, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_256_135 },
128 { 116, 3840, 2160, 47950, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
129 { 117, 3840, 2160, 100000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
130 { 118, 3840, 2160, 119880, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
131 { 119, 3840, 2160, 100000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
132 { 120, 3840, 2160, 119880, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
133 { 121, 5120, 2160, 23980, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
134 { 122, 5120, 2160, 25000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
135 { 123, 5120, 2160, 29970, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
136 { 124, 5120, 2160, 47950, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
137 { 125, 5120, 2160, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
138 { 126, 5120, 2160, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
139 { 127, 5120, 2160, 100000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
140 // 128...192 forbidden range
141 { 193, 5120, 2160, 119880, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
142 { 194, 7680, 4320, 23980, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
143 { 195, 7680, 4320, 25000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
144 { 196, 7680, 4320, 29970, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
145 { 197, 7680, 4320, 47950, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
146 { 198, 7680, 4320, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
147 { 199, 7680, 4320, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
148 { 200, 7680, 4320, 100000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
149 { 201, 7680, 4320, 119880, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_16_9 },
150 { 202, 7680, 4320, 23980, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
151 { 203, 7680, 4320, 25000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
152 { 204, 7680, 4320, 29970, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
153 { 205, 7680, 4320, 47950, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
154 { 206, 7680, 4320, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
155 { 207, 7680, 4320, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
156 { 208, 7680, 4320, 100000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
157 { 209, 7680, 4320, 119880, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
158 { 210, 10240, 4320, 23980, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
159 { 211, 10240, 4320, 25000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
160 { 212, 10240, 4320, 29970, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
161 { 213, 10240, 4320, 47950, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
162 { 214, 10240, 4320, 50000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
163 { 215, 10240, 4320, 59940, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
164 { 216, 10240, 4320, 100000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
165 { 217, 10240, 4320, 119880, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_64_27 },
166 { 218, 4096, 2160, 100000, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_256_135 },
167 { 219, 4096, 2160, 119880, VIC::Details::ScanType::NonInterlaced, VIC::Details::AspectRatio::AR_256_135 },
168 // 220...255 reserved
169};
170
171static constexpr size_t s_vic_details_count = sizeof(s_vic_details) / sizeof(s_vic_details[0]);
172static constexpr u8 s_reserved_vic_id_start = 220;
173static_assert(s_vic_details[s_vic_details_count - 1].vic_id == s_reserved_vic_id_start - 1);
174
175FixedPoint<16, u32> VIC::Details::refresh_rate_hz() const
176{
177 return FixedPoint<16, u32>(refresh_rate_millihz) / 1000;
178}
179
180auto VIC::find_details_by_vic_id(u8 vic_id) -> Details const*
181{
182 if (vic_id == 0 || (vic_id >= 128 && vic_id <= 192) || vic_id >= s_reserved_vic_id_start)
183 return nullptr;
184
185 u8 table_index = vic_id - 1;
186 if (table_index < 128) {
187 // Before the forbidden block (128...192)
188 VERIFY(s_vic_details[table_index].vic_id == vic_id);
189 return &s_vic_details[table_index];
190 }
191
192 // After the forbidden block range (128...192)
193 table_index = table_index - 192 + 128 - 1;
194 VERIFY(s_vic_details[table_index].vic_id == vic_id);
195 return &s_vic_details[table_index];
196}
197
198}