1 //*****************************************************************************
2 //
3 // SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4 // SPDX-License-Identifier: MIT
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 // DEALINGS IN THE SOFTWARE.
23 //
24 // File: nvt_edidext_displayid.c
25 //
26 // Purpose: the provide edid related services
27 //
28 //*****************************************************************************
29
30 #include "nvBinSegment.h"
31 #include "nvmisc.h"
32
33 #include "edid.h"
34
35 PUSH_SEGMENTS
36
37 static NVT_STATUS parseDisplayIdSection(DISPLAYID_SECTION * section,
38 NvU32 max_length,
39 NVT_EDID_INFO *pEdidInfo);
40
41 // Specific blocks that can be parsed based on DisplayID
42 static NVT_STATUS parseDisplayIdProdIdentityBlock(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
43 static NVT_STATUS parseDisplayIdParam(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
44 static NVT_STATUS parseDisplayIdColorChar(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
45 static NVT_STATUS parseDisplayIdTiming1(NvU8 * block, NVT_EDID_INFO *pEdidInfo);
46 static NVT_STATUS parseDisplayIdTiming2(NvU8 * block, NVT_EDID_INFO *pEdidInfo);
47 static NVT_STATUS parseDisplayIdTiming3(NvU8 * block, NVT_EDID_INFO *pEdidInfo);
48 static NVT_STATUS parseDisplayIdTiming4(NvU8 * block, NVT_EDID_INFO *pEdidInfo);
49 static NVT_STATUS parseDisplayIdTiming5(NvU8 * block, NVT_EDID_INFO *pEdidInfo);
50 static NVT_STATUS parseDisplayIdTimingVesa(NvU8 * block, NVT_EDID_INFO *pEdidInfo);
51 static NVT_STATUS parseDisplayIdTimingEIA(NvU8 * block, NVT_EDID_INFO *pEdidInfo);
52 static NVT_STATUS parseDisplayIdRangeLimits(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
53 static NVT_STATUS parseDisplayIdSerialNumber(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
54 static NVT_STATUS parseDisplayIdAsciiString(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
55 static NVT_STATUS parseDisplayIdDeviceData(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
56 static NVT_STATUS parseDisplayIdInterfacePower(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
57 static NVT_STATUS parseDisplayIdTransferChar(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
58 static NVT_STATUS parseDisplayIdDisplayInterface(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
59 static NVT_STATUS parseDisplayIdStereo(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
60 static NVT_STATUS parseDisplayIdTiledDisplay(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
61 static NVT_STATUS parseDisplayIdCtaData(NvU8 * block, NVT_EDID_INFO *pInfo);
62 static NVT_STATUS parseDisplayIdDisplayInterfaceFeatures(NvU8 * block, NVT_DISPLAYID_INFO *pInfo);
63
64 static NVT_STATUS parseDisplayIdTiming1Descriptor(DISPLAYID_TIMING_1_DESCRIPTOR * desc, NVT_TIMING *pT);
65 static NVT_STATUS parseDisplayIdTiming2Descriptor(DISPLAYID_TIMING_2_DESCRIPTOR * desc, NVT_TIMING *pT);
66 static NVT_STATUS parseDisplayIdTiming3Descriptor(DISPLAYID_TIMING_3_DESCRIPTOR * desc, NVT_TIMING *pT);
67 static NVT_STATUS parseDisplayIdTiming5Descriptor(DISPLAYID_TIMING_5_DESCRIPTOR * desc, NVT_TIMING *pT);
68
69 /**
70 * @brief Parses a displayID Extension block, with timings stored in pT and
71 * other info stored in pInfo
72 * @param p The EDID Extension Block (With a DisplayID in it)
73 * @param size Size of the displayID Extension Block
74 * @param pEdidInfo EDID struct containing DisplayID information and
75 * the timings
76 */
CODE_SEGMENT(PAGE_DD_CODE)77 CODE_SEGMENT(PAGE_DD_CODE)
78 NVT_STATUS getDisplayIdEDIDExtInfo(NvU8 *p, NvU32 size,
79 NVT_EDID_INFO *pEdidInfo)
80 {
81 DISPLAYID_SECTION * section;
82
83 if (p == NULL || size < sizeof(EDIDV1STRUC))
84 return NVT_STATUS_ERR;
85 if (p[0] != NVT_EDID_EXTENSION_DISPLAYID)
86 return NVT_STATUS_ERR;
87
88 section = (DISPLAYID_SECTION *)(p + 1);
89 pEdidInfo->ext_displayid.version = section->version;
90 if (section->product_type > NVT_DISPLAYID_PROD_MAX_NUMBER)
91 return NVT_STATUS_ERR;
92
93 return parseDisplayIdSection(section, sizeof(EDIDV1STRUC) - 1, pEdidInfo);
94 }
95
96 /**
97 * @brief updates the color format for each bpc for each timing
98 * @param pInfo EDID struct containing DisplayID information and
99 * the timings
100 * @param timingIdx Index of the first display ID timing in the
101 * pInfo->timing[] timing array.
102 */
CODE_SEGMENT(PAGE_DD_CODE)103 CODE_SEGMENT(PAGE_DD_CODE)
104 void updateColorFormatForDisplayIdExtnTimings(NVT_EDID_INFO *pInfo,
105 NvU32 timingIdx)
106 {
107 // pDisplayIdInfo is the parsed display ID info
108 NVT_DISPLAYID_INFO *pDisplayIdInfo = &pInfo->ext_displayid;
109 NVT_TIMING *pT = &pInfo->timing[timingIdx];
110
111 nvt_assert((timingIdx) <= COUNT(pInfo->timing));
112
113 if ((pInfo->input.u.digital.video_interface == NVT_EDID_DIGITAL_VIDEO_INTERFACE_STANDARD_HDMI_A_SUPPORTED ||
114 pInfo->input.u.digital.video_interface == NVT_EDID_DIGITAL_VIDEO_INTERFACE_STANDARD_HDMI_B_SUPPORTED ||
115 pInfo->ext861.valid.H14B_VSDB || pInfo->ext861.valid.H20_HF_VSDB) && pInfo->ext861.revision >= NVT_CEA861_REV_A)
116 {
117 if (!pInfo->ext_displayid.supported_displayId2_0)
118 {
119 UPDATE_BPC_FOR_COLORFORMAT(pT->etc.rgb444, 0,
120 1,
121 pDisplayIdInfo->u4.display_interface.rgb_depth.support_10b,
122 pDisplayIdInfo->u4.display_interface.rgb_depth.support_12b,
123 pDisplayIdInfo->u4.display_interface.rgb_depth.support_14b,
124 pDisplayIdInfo->u4.display_interface.rgb_depth.support_16b);
125 }
126 else
127 {
128 // rgb444 (always support 6bpc and 8bpc as per DP spec 5.1.1.1.1 RGB Colorimetry)
129 UPDATE_BPC_FOR_COLORFORMAT(pT->etc.rgb444, 0,
130 1,
131 pDisplayIdInfo->u4.display_interface_features.rgb_depth.support_10b,
132 pDisplayIdInfo->u4.display_interface_features.rgb_depth.support_12b,
133 pDisplayIdInfo->u4.display_interface_features.rgb_depth.support_14b,
134 pDisplayIdInfo->u4.display_interface_features.rgb_depth.support_16b);
135 }
136 }
137 else // DP
138 {
139 if (!pInfo->ext_displayid.supported_displayId2_0)
140 {
141 UPDATE_BPC_FOR_COLORFORMAT(pT->etc.rgb444, 1,
142 1,
143 pDisplayIdInfo->u4.display_interface.rgb_depth.support_10b,
144 pDisplayIdInfo->u4.display_interface.rgb_depth.support_12b,
145 pDisplayIdInfo->u4.display_interface.rgb_depth.support_14b,
146 pDisplayIdInfo->u4.display_interface.rgb_depth.support_16b);
147 }
148 else
149 {
150 // rgb444 (always support 6bpc and 8bpc as per DP spec 5.1.1.1.1 RGB Colorimetry)
151 UPDATE_BPC_FOR_COLORFORMAT(pT->etc.rgb444, 1,
152 1,
153 pDisplayIdInfo->u4.display_interface_features.rgb_depth.support_10b,
154 pDisplayIdInfo->u4.display_interface_features.rgb_depth.support_12b,
155 pDisplayIdInfo->u4.display_interface_features.rgb_depth.support_14b,
156 pDisplayIdInfo->u4.display_interface_features.rgb_depth.support_16b);
157 }
158 }
159
160 if (!pInfo->ext_displayid.supported_displayId2_0)
161 {
162 // yuv444
163 UPDATE_BPC_FOR_COLORFORMAT(pT->etc.yuv444, 0, /* yuv444 does not support 6bpc */
164 pDisplayIdInfo->u4.display_interface.ycbcr444_depth.support_8b,
165 pDisplayIdInfo->u4.display_interface.ycbcr444_depth.support_10b,
166 pDisplayIdInfo->u4.display_interface.ycbcr444_depth.support_12b,
167 pDisplayIdInfo->u4.display_interface.ycbcr444_depth.support_14b,
168 pDisplayIdInfo->u4.display_interface.ycbcr444_depth.support_16b);
169 // yuv422
170 UPDATE_BPC_FOR_COLORFORMAT(pT->etc.yuv422, 0, /* yuv422 does not support 6bpc */
171 pDisplayIdInfo->u4.display_interface.ycbcr422_depth.support_8b,
172 pDisplayIdInfo->u4.display_interface.ycbcr422_depth.support_10b,
173 pDisplayIdInfo->u4.display_interface.ycbcr422_depth.support_12b,
174 pDisplayIdInfo->u4.display_interface.ycbcr422_depth.support_14b,
175 pDisplayIdInfo->u4.display_interface.ycbcr422_depth.support_16b);
176 }
177 else
178 {
179 // yuv444
180 UPDATE_BPC_FOR_COLORFORMAT(pT->etc.yuv444, 0, /* yuv444 does not support 6bpc */
181 pDisplayIdInfo->u4.display_interface_features.ycbcr444_depth.support_8b,
182 pDisplayIdInfo->u4.display_interface_features.ycbcr444_depth.support_10b,
183 pDisplayIdInfo->u4.display_interface_features.ycbcr444_depth.support_12b,
184 pDisplayIdInfo->u4.display_interface_features.ycbcr444_depth.support_14b,
185 pDisplayIdInfo->u4.display_interface_features.ycbcr444_depth.support_16b);
186 // yuv422
187 UPDATE_BPC_FOR_COLORFORMAT(pT->etc.yuv422, 0, /* yuv422 does not support 6bpc */
188 pDisplayIdInfo->u4.display_interface_features.ycbcr422_depth.support_8b,
189 pDisplayIdInfo->u4.display_interface_features.ycbcr422_depth.support_10b,
190 pDisplayIdInfo->u4.display_interface_features.ycbcr422_depth.support_12b,
191 pDisplayIdInfo->u4.display_interface_features.ycbcr422_depth.support_14b,
192 pDisplayIdInfo->u4.display_interface_features.ycbcr422_depth.support_16b);
193 // yuv420
194 UPDATE_BPC_FOR_COLORFORMAT(pT->etc.yuv420, 0, /* yuv420 does not support 6bpc */
195 pDisplayIdInfo->u4.display_interface_features.ycbcr420_depth.support_8b,
196 pDisplayIdInfo->u4.display_interface_features.ycbcr420_depth.support_10b,
197 pDisplayIdInfo->u4.display_interface_features.ycbcr420_depth.support_12b,
198 pDisplayIdInfo->u4.display_interface_features.ycbcr420_depth.support_14b,
199 pDisplayIdInfo->u4.display_interface_features.ycbcr420_depth.support_16b);
200 }
201 }
202
203 /**
204 * @brief Parses a displayID Section
205 * @param section The DisplayID Section to parse
206 * @param max_length The indicated total length of the displayID as given (or
207 * sizeof(EDIDV1STRUCT) for an extension block)
208 * @param pEdidInfo EDID struct containing DisplayID information and
209 * the timings
210 */
CODE_SEGMENT(PAGE_DD_CODE)211 CODE_SEGMENT(PAGE_DD_CODE)
212 static NVT_STATUS parseDisplayIdSection(DISPLAYID_SECTION * section,
213 NvU32 max_length,
214 NVT_EDID_INFO *pEdidInfo)
215 {
216 NvU8 block_location = 0;
217 NvU8 section_length;
218 NvU8 remaining_length;
219
220 if (section == NULL || max_length <= NVT_DISPLAYID_SECTION_HEADER_LEN)
221 return NVT_STATUS_ERR;
222 if (section->section_bytes > max_length - NVT_DISPLAYID_SECTION_HEADER_LEN)
223 return NVT_STATUS_ERR;
224
225 remaining_length = section->section_bytes;
226
227 while (block_location < section->section_bytes)
228 {
229 DISPLAYID_DATA_BLOCK_HEADER * hdr = (DISPLAYID_DATA_BLOCK_HEADER *) (section->data + block_location);
230 NvBool is_prod_id = remaining_length > 3 && block_location == 0 && hdr->type == 0 && hdr->data_bytes > 0;
231 NvU8 i;
232
233 // Check the padding.
234 if (hdr->type == 0 && !is_prod_id)
235 {
236 for (i = 1 ; i < remaining_length; i++)
237 {
238 // All remaining bytes must all be 0.
239 if (section->data[block_location + i] != 0)
240 {
241 return NVT_STATUS_ERR;
242 }
243 }
244
245 section_length = remaining_length;
246 }
247 else
248 {
249 if (parseDisplayIdBlock((NvU8 *)(section->data + block_location),
250 section->section_bytes - block_location,
251 §ion_length,
252 pEdidInfo) != NVT_STATUS_SUCCESS)
253 return NVT_STATUS_ERR;
254 }
255
256 block_location += section_length;
257 remaining_length -= section_length;
258 }
259
260 return NVT_STATUS_SUCCESS;
261 }
262
263 /**
264 * @brief Parses a displayID data block
265 * @param block The DisplayID data block to parse
266 * @param max_length The indicated total length of the each data block for checking
267 * @param pLength return the indicated length of the each data block
268 * @param pEdidInfo EDID struct containing DisplayID information and
269 * the timings or validation purpose if it is NULL
270 */
CODE_SEGMENT(PAGE_DD_CODE)271 CODE_SEGMENT(PAGE_DD_CODE)
272 NVT_STATUS parseDisplayIdBlock(NvU8* pBlock,
273 NvU8 max_length,
274 NvU8* pLength,
275 NVT_EDID_INFO *pEdidInfo)
276 {
277 DISPLAYID_DATA_BLOCK_HEADER * hdr = (DISPLAYID_DATA_BLOCK_HEADER *) pBlock;
278 NVT_STATUS ret = NVT_STATUS_SUCCESS;
279 NVT_DISPLAYID_INFO *pInfo;
280
281 if (pBlock == NULL || max_length <= NVT_DISPLAYID_DATABLOCK_HEADER_LEN)
282 return NVT_STATUS_ERR;
283
284 if (hdr->data_bytes > max_length - NVT_DISPLAYID_DATABLOCK_HEADER_LEN)
285 return NVT_STATUS_ERR;
286
287 pInfo = pEdidInfo == NULL ? NULL : &pEdidInfo->ext_displayid;
288
289 *pLength = hdr->data_bytes + NVT_DISPLAYID_DATABLOCK_HEADER_LEN;
290
291 switch (hdr->type)
292 {
293 case NVT_DISPLAYID_BLOCK_TYPE_PRODUCT_IDENTITY:
294 ret = parseDisplayIdProdIdentityBlock(pBlock, pInfo);
295 break;
296 case NVT_DISPLAYID_BLOCK_TYPE_DISPLAY_PARAM:
297 ret = parseDisplayIdParam(pBlock, pInfo);
298 break;
299 case NVT_DISPLAYID_BLOCK_TYPE_COLOR_CHAR:
300 ret = parseDisplayIdColorChar(pBlock, pInfo);
301 break;
302 case NVT_DISPLAYID_BLOCK_TYPE_TIMING_1:
303 ret = parseDisplayIdTiming1(pBlock, pEdidInfo);
304 break;
305 case NVT_DISPLAYID_BLOCK_TYPE_TIMING_2:
306 ret = parseDisplayIdTiming2(pBlock, pEdidInfo);
307 break;
308 case NVT_DISPLAYID_BLOCK_TYPE_TIMING_3:
309 ret = parseDisplayIdTiming3(pBlock, pEdidInfo);
310 break;
311 case NVT_DISPLAYID_BLOCK_TYPE_TIMING_4:
312 ret = parseDisplayIdTiming4(pBlock, pEdidInfo);
313 break;
314 case NVT_DISPLAYID_BLOCK_TYPE_TIMING_5:
315 ret = parseDisplayIdTiming5(pBlock, pEdidInfo);
316 break;
317 case NVT_DISPLAYID_BLOCK_TYPE_TIMING_VESA:
318 ret = parseDisplayIdTimingVesa(pBlock, pEdidInfo);
319 break;
320 case NVT_DISPLAYID_BLOCK_TYPE_TIMING_CEA:
321 ret = parseDisplayIdTimingEIA(pBlock, pEdidInfo);
322 break;
323 case NVT_DISPLAYID_BLOCK_TYPE_RANGE_LIMITS:
324 ret = parseDisplayIdRangeLimits(pBlock, pInfo);
325 break;
326 case NVT_DISPLAYID_BLOCK_TYPE_SERIAL_NUMBER:
327 ret = parseDisplayIdSerialNumber(pBlock, pInfo);
328 break;
329 case NVT_DISPLAYID_BLOCK_TYPE_ASCII_STRING:
330 ret = parseDisplayIdAsciiString(pBlock, pInfo);
331 break;
332 case NVT_DISPLAYID_BLOCK_TYPE_DEVICE_DATA:
333 ret = parseDisplayIdDeviceData(pBlock, pInfo);
334 break;
335 case NVT_DISPLAYID_BLOCK_TYPE_INTERFACE_POWER:
336 ret = parseDisplayIdInterfacePower(pBlock, pInfo);
337 break;
338 case NVT_DISPLAYID_BLOCK_TYPE_TRANSFER_CHAR:
339 ret = parseDisplayIdTransferChar(pBlock, pInfo);
340 break;
341 case NVT_DISPLAYID_BLOCK_TYPE_DISPLAY_INTERFACE:
342 ret = parseDisplayIdDisplayInterface(pBlock, pInfo);
343 break;
344 case NVT_DISPLAYID_BLOCK_TYPE_STEREO:
345 ret = parseDisplayIdStereo(pBlock, pInfo);
346 break;
347 case NVT_DISPLAYID_BLOCK_TYPE_TILEDDISPLAY:
348 ret = parseDisplayIdTiledDisplay(pBlock, pInfo);
349 break;
350 case NVT_DISPLAYID_BLOCK_TYPE_CTA_DATA:
351 ret = parseDisplayIdCtaData(pBlock, pEdidInfo);
352 break;
353 case NVT_DISPLAYID_BLOCK_TYPE_DISPLAY_INTERFACE_FEATURES:
354 ret = parseDisplayIdDisplayInterfaceFeatures(pBlock, pInfo);
355 break;
356 default:
357 ret = NVT_STATUS_ERR;
358 break;
359 }
360
361 if (pEdidInfo == NULL) return ret;
362
363 return NVT_STATUS_SUCCESS;
364 }
CODE_SEGMENT(PAGE_DD_CODE)365 CODE_SEGMENT(PAGE_DD_CODE)
366 static NVT_STATUS parseDisplayIdColorChar(NvU8 * block, NVT_DISPLAYID_INFO *pInfo)
367 {
368 NvU32 i, j;
369 NvU16 x_p, y_p;
370 DISPLAYID_COLOR_CHAR_BLOCK * blk = (DISPLAYID_COLOR_CHAR_BLOCK *)block;
371
372 /** unused flag - uncomment if you wish to use it in the future
373 NvU8 isTemp = DRF_VAL(T_DISPLAYID, _COLOR, _TEMPORAL, blk->point_info);
374 */
375 NvU8 wp_num = DRF_VAL(T_DISPLAYID, _COLOR, _WHITE_POINTS, blk->point_info);
376 NvU8 prim_num = DRF_VAL(T_DISPLAYID, _COLOR, _PRIMARIES, blk->point_info);
377
378 if ((prim_num + wp_num) * sizeof(DISPLAYID_COLOR_POINT) + 1 != blk->header.data_bytes)
379 {
380 // Assert since this error is ignored
381 nvt_assert(0);
382 return NVT_STATUS_ERR;
383 }
384
385 if (pInfo == NULL) return NVT_STATUS_SUCCESS;
386
387 for (i = 0; i < prim_num; i++)
388 {
389 x_p = (blk->points)[i].color_x_bits_low +
390 (DRF_VAL(T_DISPLAYID, _COLOR, _POINT_X, (blk->points)[i].color_bits_mid) << 8);
391 y_p = DRF_VAL(T_DISPLAYID, _COLOR, _POINT_Y, (blk->points)[i].color_bits_mid) +
392 ((blk->points)[i].color_y_bits_high << 4);
393 pInfo->primaries[i].x = x_p;
394 pInfo->primaries[i].y = y_p;
395 }
396
397 for (j = 0; j < wp_num; j++)
398 {
399 x_p = (blk->points)[i].color_x_bits_low +
400 (DRF_VAL(T_DISPLAYID, _COLOR, _POINT_X, (blk->points)[i].color_bits_mid) << 8);
401 y_p = DRF_VAL(T_DISPLAYID, _COLOR, _POINT_Y, (blk->points)[i].color_bits_mid) +
402 ((blk->points)[i].color_y_bits_high << 4);
403 pInfo->white_points[pInfo->total_primaries + j].x = x_p;
404 pInfo->white_points[pInfo->total_primaries + j].y = y_p;
405
406 i++;
407 }
408 pInfo->total_primaries = prim_num;
409 pInfo->total_white_points += wp_num;
410 return NVT_STATUS_SUCCESS;
411 }
412
CODE_SEGMENT(PAGE_DD_CODE)413 CODE_SEGMENT(PAGE_DD_CODE)
414 static NVT_STATUS parseDisplayIdProdIdentityBlock(NvU8 * block, NVT_DISPLAYID_INFO *pInfo)
415 {
416 DISPLAYID_PROD_IDENTIFICATION_BLOCK * blk = (DISPLAYID_PROD_IDENTIFICATION_BLOCK *)block;
417 if (blk->header.data_bytes - blk->productid_string_size != NVT_DISPLAYID_PRODUCT_IDENTITY_MIN_LEN)
418 {
419 // Assert since this error is ignored
420 nvt_assert(0);
421 return NVT_STATUS_ERR;
422 }
423
424 if (pInfo == NULL) return NVT_STATUS_SUCCESS;
425
426 pInfo->vendor_id = (blk->vendor)[2] | ((blk->vendor)[1] << 8) | ((blk->vendor)[0] << 16);
427 pInfo->product_id = blk->product_code;
428 pInfo->serial_number = blk->serial_number;
429 pInfo->week = blk->model_tag;
430 pInfo->year = blk->model_year;
431
432 if (blk->productid_string_size != 0)
433 NVMISC_STRNCPY((char *)pInfo->product_string, (const char *)blk->productid_string, blk->productid_string_size);
434 pInfo->product_string[blk->productid_string_size] = '\0';
435
436 return NVT_STATUS_SUCCESS;
437 }
438
CODE_SEGMENT(PAGE_DD_CODE)439 CODE_SEGMENT(PAGE_DD_CODE)
440 static NVT_STATUS parseDisplayIdParam(NvU8 * block, NVT_DISPLAYID_INFO *pInfo)
441 {
442 DISPLAYID_DISPLAY_PARAM_BLOCK * blk = (DISPLAYID_DISPLAY_PARAM_BLOCK *)block;
443 if (blk->header.data_bytes != NVT_DISPLAYID_DISPLAY_PARAM_BLOCK_LEN)
444 {
445 // Assert since this error is ignored
446 nvt_assert(0);
447 return NVT_STATUS_ERR;
448 }
449
450 if (pInfo == NULL) return NVT_STATUS_SUCCESS;
451
452 pInfo->horiz_size = blk->horizontal_image_size;
453 pInfo->vert_size = blk->vertical_image_size;
454 pInfo->horiz_pixels = blk->horizontal_pixel_count;
455 pInfo->vert_pixels = blk->vertical_pixel_count;
456
457 pInfo->support_audio = DRF_VAL(T_DISPLAYID, _DISPLAY_PARAM, _SUPPORT_AUDIO, blk->feature);
458 pInfo->separate_audio = DRF_VAL(T_DISPLAYID, _DISPLAY_PARAM, _SEPARATE_AUDIO, blk->feature);
459 pInfo->audio_override = DRF_VAL(T_DISPLAYID, _DISPLAY_PARAM, _AUDIO_INPUT_OVERRIDE, blk->feature);
460 pInfo->power_management = DRF_VAL(T_DISPLAYID, _DISPLAY_PARAM, _POWER_MANAGEMENT, blk->feature);
461 pInfo->fixed_timing = DRF_VAL(T_DISPLAYID, _DISPLAY_PARAM, _FIXED_TIMING, blk->feature);
462 pInfo->fixed_pixel_format = DRF_VAL(T_DISPLAYID, _DISPLAY_PARAM, _FIXED_PIXEL_FORMAT, blk->feature);
463 pInfo->deinterlace = DRF_VAL(T_DISPLAYID, _DISPLAY_PARAM, _DEINTERLACING, blk->feature);
464
465 pInfo->gamma = (NvU16)(blk->transfer_char_gamma - 1) * 100;
466 pInfo->aspect_ratio = blk->aspect_ratio;
467
468 pInfo->depth_overall = DRF_VAL(T_DISPLAYID, _DISPLAY_PARAM, _DEPTH_OVERALL, blk->color_bit_depth);
469 pInfo->depth_native = DRF_VAL(T_DISPLAYID, _DISPLAY_PARAM, _DEPTH_NATIVE, blk->color_bit_depth);
470
471 return NVT_STATUS_SUCCESS;
472 }
473
CODE_SEGMENT(PAGE_DD_CODE)474 CODE_SEGMENT(PAGE_DD_CODE)
475 static NVT_STATUS parseDisplayIdTiming1(NvU8 * block, NVT_EDID_INFO *pEdidInfo)
476 {
477 NvU16 i;
478 NVT_TIMING newTiming;
479 DISPLAYID_TIMING_1_BLOCK * blk = (DISPLAYID_TIMING_1_BLOCK *)block;
480 if (blk->header.data_bytes % sizeof(DISPLAYID_TIMING_1_DESCRIPTOR) != 0)
481 {
482 // Assert since this error is ignored
483 nvt_assert(0);
484 return NVT_STATUS_ERR;
485 }
486
487 for (i = 0; i * sizeof(DISPLAYID_TIMING_1_DESCRIPTOR) < blk->header.data_bytes; i++)
488 {
489 NVMISC_MEMSET(&newTiming, 0, sizeof(newTiming));
490
491 if (parseDisplayIdTiming1Descriptor(blk->descriptors + i,
492 &newTiming) == NVT_STATUS_SUCCESS)
493 {
494 if (pEdidInfo == NULL) continue;
495
496 if (!assignNextAvailableTiming(pEdidInfo, &newTiming))
497 {
498 break;
499 }
500 }
501 else
502 {
503 if (pEdidInfo == NULL) return NVT_STATUS_ERR;
504 }
505 }
506 return NVT_STATUS_SUCCESS;
507 }
CODE_SEGMENT(PAGE_DD_CODE)508 CODE_SEGMENT(PAGE_DD_CODE)
509 static NVT_STATUS parseDisplayIdTiming1Descriptor(DISPLAYID_TIMING_1_DESCRIPTOR * type1, NVT_TIMING *pT)
510 {
511 if (type1 == NULL || pT == NULL)
512 return NVT_STATUS_ERR;
513
514 // the pixel clock
515 pT->pclk = (NvU32)((type1->pixel_clock_high << 16) + (type1->pixel_clock_mid << 8) + type1->pixel_clock_low_minus_0_01MHz + 1);
516
517 // the DisplayID spec does not support border
518 pT->HBorder = pT->VBorder = 0;
519
520 // get horizontal timing parameters
521 pT->HVisible = (NvU16)((type1->horizontal.active_image_pixels_high << 8) + type1->horizontal.active_image_pixels_low_minus_1 + 1);
522 pT->HTotal = (NvU16)((type1->horizontal.blank_pixels_high << 8) + type1->horizontal.blank_pixels_low_minus_1 + 1) + pT->HVisible;
523 pT->HFrontPorch = (NvU16)((type1->horizontal.front_porch_high << 8) + type1->horizontal.front_porch_low_minus_1 + 1);
524 pT->HSyncWidth = (NvU16)((type1->horizontal.sync_width_high << 8) + type1->horizontal.sync_width_low_minus_1 + 1);
525 pT->HSyncPol = type1->horizontal.sync_polarity ? NVT_H_SYNC_POSITIVE : NVT_H_SYNC_NEGATIVE;
526
527 // get vertical timings
528 pT->VVisible = (NvU16)((type1->vertical.active_image_lines_high << 8) + type1->vertical.active_image_lines_low_minus_1 + 1);
529 pT->VTotal = (NvU16)((type1->vertical.blank_lines_high << 8) + type1->vertical.blank_lines_low_minus_1 + 1) + pT->VVisible;
530 pT->VFrontPorch = (NvU16)((type1->vertical.front_porch_lines_high << 8) + type1->vertical.front_porch_lines_low_minus_1 + 1);
531 pT->VSyncWidth = (NvU16)((type1->vertical.sync_width_lines_high << 8) + type1->vertical.sync_width_lines_low_minus_1 + 1);
532 pT->VSyncPol = type1->vertical.sync_polarity ? NVT_V_SYNC_POSITIVE : NVT_V_SYNC_NEGATIVE;
533
534 // EDID used in DP1.4 Compliance test had incorrect HBlank listed, leading to wrong raster sizes being set by driver (bug 2714607)
535 // Filter incorrect timings here. HTotal must cover sufficient blanking time
536 if (pT->HTotal < (pT->HVisible + pT->HFrontPorch + pT->HSyncWidth))
537 {
538 return NVT_STATUS_ERR;
539 }
540
541 // the frame scanning type
542 pT->interlaced = type1->options.interface_frame_scanning_type;
543
544 // the aspect ratio
545 switch (type1->options.aspect_ratio)
546 {
547 case NVT_DISPLAYID_TIMING_ASPECT_RATIO_1_1:
548 pT->etc.aspect = (1 << 16) | 1;
549 break;
550 case NVT_DISPLAYID_TIMING_ASPECT_RATIO_5_4:
551 pT->etc.aspect = (5 << 16) | 4;
552 break;
553 case NVT_DISPLAYID_TIMING_ASPECT_RATIO_4_3:
554 pT->etc.aspect = (4 << 16) | 3;
555 break;
556 case NVT_DISPLAYID_TIMING_ASPECT_RATIO_15_9:
557 pT->etc.aspect = (15 << 16) | 9;
558 break;
559 case NVT_DISPLAYID_TIMING_ASPECT_RATIO_16_9:
560 pT->etc.aspect = (16 << 16) | 9;
561 break;
562 case NVT_DISPLAYID_TIMING_ASPECT_RATIO_16_10:
563 pT->etc.aspect = (16 << 16) | 10;
564 break;
565 default:
566 pT->etc.aspect = 0;
567 break;
568 }
569
570 // the refresh rate
571 pT->etc.rr = NvTiming_CalcRR(pT->pclk, pT->interlaced, pT->HTotal, pT->VTotal);
572 pT->etc.rrx1k = NvTiming_CalcRRx1k(pT->pclk, pT->interlaced, pT->HTotal, pT->VTotal);
573 pT->etc.name[39] = '\0';
574 pT->etc.rep = 0x1; // bit mask for no pixel repetition
575
576 pT->etc.status = NVT_STATUS_DISPLAYID_1;
577 // Unlike the PTM in EDID base block, DisplayID type I/II preferred timing does not have dependency on sequence
578 // so we'll just update the preferred flag, not sequence them
579 //pT->etc.status = NVT_STATUS_DISPLAYID_1N(1);
580 pT->etc.flag |= type1->options.is_preferred_detailed_timing ? NVT_FLAG_DISPLAYID_DTD_PREFERRED_TIMING : 0;
581
582 /* Fields currently not used. Uncomment them for future use
583 type1->options.stereo_support;
584 */
585
586 // the DisplayID spec covers the timing parameter(Visible/FrontPorch/SyncWidth/Total) range from 1~65536 while our NVT_TIMING structure which is mostly based on NvU16 only covers 0~65535
587 nvt_assert(pT->HVisible != 0);
588 nvt_assert(pT->HFrontPorch != 0);
589 nvt_assert(pT->HSyncWidth != 0);
590 nvt_assert(pT->VVisible != 0);
591 nvt_assert(pT->VFrontPorch != 0);
592 nvt_assert(pT->VSyncWidth != 0);
593
594 // cover the possible overflow
595 nvt_assert(pT->HTotal > pT->HVisible);
596 nvt_assert(pT->VTotal > pT->VVisible);
597
598 return NVT_STATUS_SUCCESS;
599 }
600
CODE_SEGMENT(PAGE_DD_CODE)601 CODE_SEGMENT(PAGE_DD_CODE)
602 static NVT_STATUS parseDisplayIdTiming2(NvU8 * block, NVT_EDID_INFO *pEdidInfo)
603 {
604 NvU16 i;
605 DISPLAYID_TIMING_2_BLOCK * blk = (DISPLAYID_TIMING_2_BLOCK *)block;
606 NVT_TIMING newTiming;
607
608 if (blk->header.data_bytes % sizeof(DISPLAYID_TIMING_2_DESCRIPTOR) != 0)
609 {
610 // Assert since this error is ignored
611 nvt_assert(0);
612 return NVT_STATUS_ERR;
613 }
614
615 for (i = 0; i * sizeof(DISPLAYID_TIMING_2_DESCRIPTOR) < blk->header.data_bytes; i++)
616 {
617 NVMISC_MEMSET(&newTiming, 0, sizeof(newTiming));
618
619 if (parseDisplayIdTiming2Descriptor(blk->descriptors + i,
620 &newTiming) == NVT_STATUS_SUCCESS)
621 {
622 if (pEdidInfo == NULL) continue;
623
624 if (!assignNextAvailableTiming(pEdidInfo, &newTiming))
625 {
626 break;
627 }
628 }
629 else
630 {
631 if (pEdidInfo == NULL) return NVT_STATUS_ERR;
632 }
633 }
634 return NVT_STATUS_SUCCESS;
635 }
636
CODE_SEGMENT(PAGE_DD_CODE)637 CODE_SEGMENT(PAGE_DD_CODE)
638 static NVT_STATUS parseDisplayIdTiming2Descriptor(DISPLAYID_TIMING_2_DESCRIPTOR * type2, NVT_TIMING *pT)
639 {
640 if (type2 == NULL || pT == NULL)
641 return NVT_STATUS_ERR;
642
643 // the pixel clock
644 pT->pclk = (NvU32)((type2->pixel_clock_high << 16) + (type2->pixel_clock_mid << 8) + type2->pixel_clock_low_minus_0_01MHz + 1);
645
646 // the DisplayID spec does not support border
647 pT->HBorder = pT->VBorder = 0;
648
649 // get horizontal timing parameters
650 pT->HVisible = (NvU16)((type2->horizontal.active_image_in_char_high << 8) + type2->horizontal.active_image_in_char_minus_1 + 1) * NVT_DISPLAYID_CHAR_WIDTH_IN_PIXELS;
651 pT->HTotal = (NvU16)(type2->horizontal.blank_in_char_minus_1 + 1) * NVT_DISPLAYID_CHAR_WIDTH_IN_PIXELS + pT->HVisible;
652 pT->HFrontPorch = (NvU16)(type2->horizontal.front_porch_in_char_minus_1 + 1) * NVT_DISPLAYID_CHAR_WIDTH_IN_PIXELS;
653 pT->HSyncWidth = (NvU16)(type2->horizontal.sync_width_in_char_minus_1 + 1) * NVT_DISPLAYID_CHAR_WIDTH_IN_PIXELS;
654 pT->HSyncPol = type2->options.hsync_polarity ? NVT_H_SYNC_POSITIVE : NVT_H_SYNC_NEGATIVE;
655
656 // get vertical timing parameters
657 pT->VVisible = (NvU16)((type2->vertical.active_image_lines_high << 8) + type2->vertical.active_image_lines_low_minus_1 + 1);
658 pT->VTotal = (NvU16)(type2->vertical.blank_lines_minus_1 + 1) + pT->VVisible;
659 pT->VFrontPorch = (NvU16)(type2->vertical.front_porch_lines_minus_1 + 1);
660 pT->VSyncWidth = (NvU16)(type2->vertical.sync_width_lines_minus_1 + 1);
661 pT->VSyncPol = type2->options.vsync_polarity ? NVT_V_SYNC_POSITIVE : NVT_V_SYNC_NEGATIVE;
662
663 // the frame scanning type
664 pT->interlaced = type2->options.interface_frame_scanning_type;
665
666 // the refresh rate
667 pT->etc.rr = NvTiming_CalcRR(pT->pclk, pT->interlaced, pT->HTotal, pT->VTotal);
668 pT->etc.rrx1k = NvTiming_CalcRRx1k(pT->pclk, pT->interlaced, pT->HTotal, pT->VTotal);
669
670 pT->etc.aspect = 0;
671 pT->etc.name[39] = '\0';
672 pT->etc.rep = 0x1; // Bit mask for no pixel repetition
673
674 pT->etc.status = NVT_STATUS_DISPLAYID_2;
675 // Unlike the PTM in EDID base block, DisplayID type I/II preferred timing does not have dependency on sequence
676 // so we'll just update the preferred flag, not sequence them
677 //pT->etc.status = NVT_STATUS_DISPLAYID_1N(1);
678 pT->etc.flag |= type2->options.is_preferred_detailed_timing ? NVT_FLAG_DISPLAYID_DTD_PREFERRED_TIMING : 0;
679
680 /* Fields currently not used. Uncomment them for future use
681 type1->options.stereo_support;
682 */
683
684 // the DisplayID spec covers the timing parameter(Visible/FrontPorch/SyncWidth/Total) range from 1~65536 while our NVT_TIMING structure which is mostly based on NvU16 only covers 0~65535
685 nvt_assert(pT->HVisible != 0);
686 nvt_assert(pT->HFrontPorch != 0);
687 nvt_assert(pT->HSyncWidth != 0);
688 nvt_assert(pT->VVisible != 0);
689 nvt_assert(pT->VFrontPorch != 0);
690 nvt_assert(pT->VSyncWidth != 0);
691
692 // cover the possible overflow
693 nvt_assert(pT->HTotal > pT->HVisible);
694 nvt_assert(pT->VTotal > pT->VVisible);
695
696 return NVT_STATUS_SUCCESS;
697 }
698
CODE_SEGMENT(PAGE_DD_CODE)699 CODE_SEGMENT(PAGE_DD_CODE)
700 static NVT_STATUS parseDisplayIdTiming3Descriptor(DISPLAYID_TIMING_3_DESCRIPTOR * desc,
701 NVT_TIMING *pT)
702 {
703 NvU8 formula, aspect;
704 NvU32 horiz, vert, rr;
705 NvU32 interlace;
706 if (desc == NULL || pT == NULL)
707 return NVT_STATUS_ERR;
708
709 formula = DRF_VAL(T_DISPLAYID, _TIMING_3, _FORMULA, desc->optns);
710 /* Fields currently not used, uncomment for use
711 preferred = DRF_VAL(T_DISPLAYID, _TIMING, _PREFERRED, desc->optns);
712 */
713 aspect = DRF_VAL(T_DISPLAYID, _TIMING_3, _ASPECT_RATIO, desc->optns);
714 interlace = DRF_VAL(T_DISPLAYID, _TIMING_3, _INTERLACE, desc->transfer) ? NVT_INTERLACED : NVT_PROGRESSIVE;
715 rr = (NvU32)(DRF_VAL(T_DISPLAYID, _TIMING_3, _REFRESH_RATE, desc->transfer) + 1);
716
717 horiz = (NvU32)((desc->horizontal_active_pixels + 1) << 3);
718
719 switch (aspect)
720 {
721 case NVT_DISPLAYID_TIMING_3_ASPECT_RATIO_1_1:
722 vert = horiz;
723 break;
724 case NVT_DISPLAYID_TIMING_3_ASPECT_RATIO_5_4:
725 vert = horiz * 4 / 5;
726 break;
727 case NVT_DISPLAYID_TIMING_3_ASPECT_RATIO_4_3:
728 vert = horiz * 3 / 4;
729 break;
730 case NVT_DISPLAYID_TIMING_3_ASPECT_RATIO_15_9:
731 vert = horiz * 9 / 15;
732 break;
733 case NVT_DISPLAYID_TIMING_3_ASPECT_RATIO_16_9:
734 vert = horiz * 9 / 16;
735 break;
736 case NVT_DISPLAYID_TIMING_3_ASPECT_RATIO_16_10:
737 vert = horiz * 10 / 16;
738 break;
739 default:
740 return NVT_STATUS_ERR;
741 }
742
743 switch (formula)
744 {
745 case NVT_DISPLAYID_TIMING_3_FORMULA_STANDARD:
746 if (NvTiming_CalcCVT(horiz, vert, rr, interlace, pT) != NVT_STATUS_SUCCESS)
747 return NVT_STATUS_ERR;
748 break;
749 case NVT_DISPLAYID_TIMING_3_FORMULA_REDUCED_BLANKING:
750 if (NvTiming_CalcCVT_RB(horiz, vert, rr, interlace, pT) != NVT_STATUS_SUCCESS)
751 return NVT_STATUS_ERR;
752 break;
753 default:
754 return NVT_STATUS_ERR;
755 }
756
757 return NVT_STATUS_SUCCESS;
758 }
759
CODE_SEGMENT(PAGE_DD_CODE)760 CODE_SEGMENT(PAGE_DD_CODE)
761 static NVT_STATUS parseDisplayIdTiming3(NvU8 * block, NVT_EDID_INFO *pEdidInfo)
762 {
763 NvU16 i;
764 DISPLAYID_TIMING_3_BLOCK * blk = (DISPLAYID_TIMING_3_BLOCK *)block;
765 NVT_TIMING newTiming;
766
767 if (blk->header.data_bytes % sizeof(DISPLAYID_TIMING_3_DESCRIPTOR) != 0)
768 {
769 // Assert since this error is ignored
770 nvt_assert(0);
771 return NVT_STATUS_ERR;
772 }
773
774 for (i = 0; i * sizeof(DISPLAYID_TIMING_3_DESCRIPTOR) < blk->header.data_bytes; i++)
775 {
776 NVMISC_MEMSET(&newTiming, 0, sizeof(newTiming));
777
778 if (parseDisplayIdTiming3Descriptor(blk->descriptors + i,
779 &newTiming) == NVT_STATUS_SUCCESS)
780 {
781 if (pEdidInfo == NULL) continue;
782
783 if (!assignNextAvailableTiming(pEdidInfo, &newTiming))
784 {
785 break;
786 }
787 }
788 else
789 {
790 if (pEdidInfo == NULL) return NVT_STATUS_ERR;
791 }
792 }
793 return NVT_STATUS_SUCCESS;
794 }
795
CODE_SEGMENT(PAGE_DD_CODE)796 CODE_SEGMENT(PAGE_DD_CODE)
797 static NVT_STATUS parseDisplayIdTiming4(NvU8 * block, NVT_EDID_INFO *pEdidInfo)
798 {
799 NvU16 i;
800 NVT_TIMING newTiming;
801 DISPLAYID_TIMING_4_BLOCK * blk = (DISPLAYID_TIMING_4_BLOCK *)block;
802 if (blk->header.data_bytes < 1 || blk->header.data_bytes > NVT_DISPLAYID_DATABLOCK_MAX_PAYLOAD_LEN)
803 {
804 // Assert since this error is ignored
805 nvt_assert(0);
806 return NVT_STATUS_ERR;
807 }
808
809 for (i = 0; i < blk->header.data_bytes; i++)
810 {
811 NVMISC_MEMSET(&newTiming, 0, sizeof(newTiming));
812
813 if (NvTiming_EnumDMT((NvU32)(blk->timing_codes[i]),
814 &newTiming) == NVT_STATUS_SUCCESS)
815 {
816 if (pEdidInfo == NULL) continue;
817
818 if (!assignNextAvailableTiming(pEdidInfo, &newTiming))
819 {
820 break;
821 }
822 }
823 else
824 {
825 if (pEdidInfo == NULL) return NVT_STATUS_ERR;
826 }
827 }
828 return NVT_STATUS_SUCCESS;
829 }
830
CODE_SEGMENT(PAGE_DD_CODE)831 CODE_SEGMENT(PAGE_DD_CODE)
832 static NVT_STATUS parseDisplayIdTiming5Descriptor(DISPLAYID_TIMING_5_DESCRIPTOR * desc, NVT_TIMING *pT)
833 {
834 NvU32 width, height, rr;
835 NvBool is1000div1001 = NV_FALSE;
836
837 // we don't handle stereo type nor custom reduced blanking yet
838 //NvU8 stereoType, formula;
839 //stereoType = (desc->optns & NVT_DISPLAYID_TIMING_5_STEREO_SUPPORT_MASK);
840 //formula = desc->optns & NVT_DISPLAYID_TIMING_5_FORMULA_SUPPORT_MASK;
841
842 if (desc->optns & NVT_DISPLAYID_TIMING_5_FRACTIONAL_RR_SUPPORT_MASK)
843 {
844 is1000div1001 = NV_TRUE;
845 }
846 width = ((desc->horizontal_active_pixels_high << 8) | desc->horizontal_active_pixels_low) + 1;
847 height = ((desc->vertical_active_pixels_high << 8) | desc->vertical_active_pixels_low) + 1;
848 rr = desc->refresh_rate + 1;
849 return NvTiming_CalcCVT_RB2(width, height, rr, is1000div1001, pT);
850 }
851
CODE_SEGMENT(PAGE_DD_CODE)852 CODE_SEGMENT(PAGE_DD_CODE)
853 static NVT_STATUS parseDisplayIdTiming5(NvU8 * block, NVT_EDID_INFO *pEdidInfo)
854 {
855 NvU16 i;
856 NVT_TIMING newTiming;
857 DISPLAYID_TIMING_5_BLOCK * blk = (DISPLAYID_TIMING_5_BLOCK *)block;
858 if (blk->header.data_bytes < 1 || blk->header.data_bytes > NVT_DISPLAYID_DATABLOCK_MAX_PAYLOAD_LEN)
859 {
860 // Assert since this error is ignored
861 nvt_assert(0);
862 return NVT_STATUS_ERR;
863 }
864 for (i = 0; i * sizeof(DISPLAYID_TIMING_5_DESCRIPTOR) < blk->header.data_bytes; i++)
865 {
866 NVMISC_MEMSET(&newTiming, 0, sizeof(newTiming));
867
868 if (parseDisplayIdTiming5Descriptor(blk->descriptors + i, &newTiming) == NVT_STATUS_SUCCESS)
869 {
870 if (pEdidInfo == NULL) continue;
871
872 if (!assignNextAvailableTiming(pEdidInfo, &newTiming))
873 {
874 break;
875 }
876 }
877 else
878 {
879 if (pEdidInfo == NULL) return NVT_STATUS_ERR;
880 }
881 }
882 return NVT_STATUS_SUCCESS;
883 }
884
CODE_SEGMENT(PAGE_DD_CODE)885 CODE_SEGMENT(PAGE_DD_CODE)
886 static NVT_STATUS parseDisplayIdTimingVesa(NvU8 * block, NVT_EDID_INFO *pEdidInfo)
887 {
888 NvU8 i, j;
889 NVT_TIMING newTiming;
890 DISPLAYID_TIMING_MODE_BLOCK * blk = (DISPLAYID_TIMING_MODE_BLOCK *)block;
891 if (blk->header.data_bytes != DISPLAYID_TIMING_VESA_BLOCK_SIZE)
892 {
893 // Assert since this error is ignored
894 nvt_assert(0);
895 return NVT_STATUS_ERR;
896 }
897
898 for (i = 0; i < DISPLAYID_TIMING_VESA_BLOCK_SIZE; i++)
899 {
900 for (j = 0; j < 8; j++)
901 {
902 if (blk->timing_modes[i] & (1 << j))
903 {
904 NVMISC_MEMSET(&newTiming, 0, sizeof(newTiming));
905
906 if (NvTiming_EnumDMT((NvU32)(i * 8 + j + 1),
907 &newTiming) == NVT_STATUS_SUCCESS)
908 {
909 if (pEdidInfo == NULL) continue;
910
911 if (!assignNextAvailableTiming(pEdidInfo, &newTiming))
912 {
913 break;
914 }
915 }
916 else
917 {
918 if (pEdidInfo == NULL) return NVT_STATUS_ERR;
919 }
920 }
921 }
922 }
923 return NVT_STATUS_SUCCESS;
924 }
925
CODE_SEGMENT(PAGE_DD_CODE)926 CODE_SEGMENT(PAGE_DD_CODE)
927 static NVT_STATUS parseDisplayIdTimingEIA(NvU8 * block, NVT_EDID_INFO *pEdidInfo)
928 {
929 NvU8 i, j;
930 NVT_TIMING newTiming;
931 DISPLAYID_TIMING_MODE_BLOCK * blk = (DISPLAYID_TIMING_MODE_BLOCK *)block;
932 if (blk->header.data_bytes != DISPLAYID_TIMING_CEA_BLOCK_SIZE)
933 {
934 // Assert since this error is ignored
935 nvt_assert(0);
936 return NVT_STATUS_ERR;
937 }
938
939 for (i = 0; i < DISPLAYID_TIMING_CEA_BLOCK_SIZE; i++)
940 {
941 for (j = 0; j < 8; j++)
942 {
943 if (blk->timing_modes[i] & (1 << j))
944 {
945 NVMISC_MEMSET(&newTiming, 0, sizeof(newTiming));
946
947 if (NvTiming_EnumCEA861bTiming((NvU32)(i * 8 + j + 1),
948 &newTiming) == NVT_STATUS_SUCCESS)
949 {
950 if (pEdidInfo == NULL) continue;
951
952 if (!assignNextAvailableTiming(pEdidInfo, &newTiming))
953 {
954 break;
955 }
956 }
957 else
958 {
959 if (pEdidInfo == NULL) return NVT_STATUS_ERR;
960 }
961 }
962 }
963 }
964 return NVT_STATUS_SUCCESS;
965 }
966
CODE_SEGMENT(PAGE_DD_CODE)967 CODE_SEGMENT(PAGE_DD_CODE)
968 static NVT_STATUS parseDisplayIdRangeLimits(NvU8 * block, NVT_DISPLAYID_INFO *pInfo)
969 {
970 NVT_DISPLAYID_RANGE_LIMITS * rl;
971 DISPLAYID_RANGE_LIMITS_BLOCK * blk = (DISPLAYID_RANGE_LIMITS_BLOCK *)block;
972 NVT_STATUS status = NVT_STATUS_SUCCESS;
973 NvU32 minPclk = 0;
974 NvU32 maxPclk = 0;
975
976 if (blk->header.data_bytes != DISPLAYID_RANGE_LIMITS_BLOCK_LEN)
977 {
978 // Assert since this error is ignored
979 nvt_assert(0);
980 return NVT_STATUS_ERR;
981 }
982
983 minPclk = blk->pixel_clock_min[0] | (blk->pixel_clock_min[1] << 8) | (blk->pixel_clock_min[2] << 16);
984 maxPclk = blk->pixel_clock_max[0] | (blk->pixel_clock_max[1] << 8) | (blk->pixel_clock_max[2] << 16);
985
986 if (blk->vertical_refresh_rate_min == 0 || blk->vertical_refresh_rate_max == 0 ||
987 blk->vertical_refresh_rate_min > blk->vertical_refresh_rate_max ||
988 minPclk > maxPclk)
989 {
990 nvt_assert(0 && "wrong range limit");
991 status = NVT_STATUS_ERR;
992 }
993
994 if (pInfo == NULL) return status;
995
996 if (pInfo->rl_num >= NVT_DISPLAYID_RANGE_LIMITS_MAX_COUNT)
997 {
998 // Assert since this error is ignored
999 nvt_assert(0);
1000 return NVT_STATUS_ERR;
1001 }
1002
1003 rl = pInfo->range_limits + pInfo->rl_num;
1004 (pInfo->rl_num)++;
1005
1006 rl->pclk_min = minPclk;
1007 rl->pclk_max = maxPclk;
1008
1009 rl->interlaced = DRF_VAL(T_DISPLAYID, _RANGE_LIMITS, _INTERLACE, blk->optns);
1010 rl->cvt = DRF_VAL(T_DISPLAYID, _RANGE_LIMITS, _CVT_STANDARD, blk->optns);
1011 rl->cvt_reduced = DRF_VAL(T_DISPLAYID, _RANGE_LIMITS, _CVT_REDUCED, blk->optns);
1012 rl->dfd = DRF_VAL(T_DISPLAYID, _RANGE_LIMITS, _DFD, blk->optns);
1013
1014 rl->hfreq_min = blk->horizontal_frequency_min;
1015 rl->hfreq_max = blk->horizontal_frequency_max;
1016 rl->hblank_min = blk->horizontal_blanking_min;
1017 rl->vfreq_min = blk->vertical_refresh_rate_min;
1018 rl->vfreq_max = blk->vertical_refresh_rate_max;
1019 rl->vblank_min = blk->vertical_blanking_min;
1020
1021 return NVT_STATUS_SUCCESS;
1022 }
1023
CODE_SEGMENT(PAGE_DD_CODE)1024 CODE_SEGMENT(PAGE_DD_CODE)
1025 static NVT_STATUS parseDisplayIdSerialNumber(NvU8 * block, NVT_DISPLAYID_INFO *pInfo)
1026 {
1027 DISPLAYID_ASCII_STRING_BLOCK * blk = (DISPLAYID_ASCII_STRING_BLOCK *)block;
1028 if (blk->header.data_bytes > NVT_DISPLAYID_DATABLOCK_MAX_PAYLOAD_LEN)
1029 {
1030 // Assert since this error is ignored
1031 nvt_assert(0);
1032 return NVT_STATUS_ERR;
1033 }
1034
1035 if (pInfo == NULL) return NVT_STATUS_SUCCESS;
1036
1037 // Nothing is currently done to store any ASCII Serial Number, if it is
1038 // required. Code here may need to be modified sometime in the future, along
1039 // with NVT_DISPLAYID_INFO struct
1040 return NVT_STATUS_SUCCESS;
1041 }
1042
CODE_SEGMENT(PAGE_DD_CODE)1043 CODE_SEGMENT(PAGE_DD_CODE)
1044 static NVT_STATUS parseDisplayIdAsciiString(NvU8 * block, NVT_DISPLAYID_INFO *pInfo)
1045 {
1046 DISPLAYID_ASCII_STRING_BLOCK * blk = (DISPLAYID_ASCII_STRING_BLOCK *)block;
1047 if (blk->header.data_bytes > NVT_DISPLAYID_DATABLOCK_MAX_PAYLOAD_LEN)
1048 {
1049 // Assert since this error is ignored
1050 nvt_assert(0);
1051 return NVT_STATUS_ERR;
1052 }
1053
1054 if (pInfo == NULL) return NVT_STATUS_SUCCESS;
1055
1056 // Nothing is currently done to store any ASCII String Data, if it is
1057 // required. Code here may need to be modified sometime in the future, along
1058 // with NVT_DISPLAYID_INFO struct
1059 return NVT_STATUS_SUCCESS;
1060 }
1061
CODE_SEGMENT(PAGE_DD_CODE)1062 CODE_SEGMENT(PAGE_DD_CODE)
1063 static NVT_STATUS parseDisplayIdDeviceData(NvU8 * block, NVT_DISPLAYID_INFO *pInfo)
1064 {
1065 DISPLAYID_DEVICE_DATA_BLOCK * blk = (DISPLAYID_DEVICE_DATA_BLOCK *)block;
1066 if (blk->header.data_bytes != DISPLAYID_DEVICE_DATA_BLOCK_LEN)
1067 {
1068 // Assert since this error is ignored
1069 nvt_assert(0);
1070 return NVT_STATUS_ERR;
1071 }
1072
1073 if (pInfo == NULL) return NVT_STATUS_SUCCESS;
1074
1075 pInfo->tech_type = blk->technology;
1076
1077 pInfo->device_op_mode = DRF_VAL(T_DISPLAYID, _DEVICE, _OPERATING_MODE, blk->operating_mode);
1078 pInfo->support_backlight = DRF_VAL(T_DISPLAYID, _DEVICE, _BACKLIGHT, blk->operating_mode);
1079 pInfo->support_intensity = DRF_VAL(T_DISPLAYID, _DEVICE, _INTENSITY, blk->operating_mode);
1080
1081 pInfo->horiz_pixel_count = blk->horizontal_pixel_count;
1082 pInfo->vert_pixel_count = blk->vertical_pixel_count;
1083
1084 pInfo->orientation = DRF_VAL(T_DISPLAYID, _DEVICE, _ORIENTATION, blk->orientation);
1085 pInfo->rotation = DRF_VAL(T_DISPLAYID, _DEVICE, _ROTATION, blk->orientation);
1086 pInfo->zero_pixel = DRF_VAL(T_DISPLAYID, _DEVICE, _ZERO_PIXEL, blk->orientation);
1087 pInfo->scan_direction = DRF_VAL(T_DISPLAYID, _DEVICE, _SCAN, blk->orientation);
1088
1089 pInfo->subpixel_info = blk->subpixel_info;
1090 pInfo->horiz_pitch = blk->horizontal_pitch;
1091 pInfo->vert_pitch = blk->vertical_pitch;
1092
1093 pInfo->color_bit_depth = DRF_VAL(T_DISPLAYID, _DEVICE, _COLOR_DEPTH, blk->color_bit_depth);
1094 pInfo->white_to_black = DRF_VAL(T_DISPLAYID, _DEVICE, _WHITE_BLACK, blk->response_time);
1095 pInfo->response_time = DRF_VAL(T_DISPLAYID, _DEVICE, _RESPONSE_TIME, blk->response_time);
1096
1097 return NVT_STATUS_SUCCESS;
1098 }
1099
CODE_SEGMENT(PAGE_DD_CODE)1100 CODE_SEGMENT(PAGE_DD_CODE)
1101 static NVT_STATUS parseDisplayIdInterfacePower(NvU8 * block, NVT_DISPLAYID_INFO *pInfo)
1102 {
1103 DISPLAYID_INTERFACE_POWER_BLOCK * blk = (DISPLAYID_INTERFACE_POWER_BLOCK *)block;
1104 if (blk->header.data_bytes != DISPLAYID_INTERFACE_POWER_BLOCK_LEN)
1105 {
1106 // Assert since this error is ignored
1107 nvt_assert(0);
1108 return NVT_STATUS_ERR;
1109 }
1110
1111 if (pInfo == NULL) return NVT_STATUS_SUCCESS;
1112
1113 // Note specifically that the data inside T1/T2 variables are the exact
1114 // interface power data. the millisecond increments are dependent on the
1115 // DisplayID specification.
1116 pInfo->t1_min = DRF_VAL(T_DISPLAYID, _POWER, _T1_MIN, blk->power_sequence_T1);
1117 pInfo->t1_max = DRF_VAL(T_DISPLAYID, _POWER, _T1_MAX, blk->power_sequence_T1);
1118 pInfo->t2_max = DRF_VAL(T_DISPLAYID, _POWER, _T2, blk->power_sequence_T2);
1119 pInfo->t3_max = DRF_VAL(T_DISPLAYID, _POWER, _T3, blk->power_sequence_T3);
1120 pInfo->t4_min = DRF_VAL(T_DISPLAYID, _POWER, _T4_MIN, blk->power_sequence_T4_min);
1121 pInfo->t5_min = DRF_VAL(T_DISPLAYID, _POWER, _T5_MIN, blk->power_sequence_T5_min);
1122 pInfo->t6_min = DRF_VAL(T_DISPLAYID, _POWER, _T6_MIN, blk->power_sequence_T6_min);
1123
1124 return NVT_STATUS_SUCCESS;
1125 }
1126
CODE_SEGMENT(PAGE_DD_CODE)1127 CODE_SEGMENT(PAGE_DD_CODE)
1128 static NVT_STATUS parseDisplayIdTransferChar(NvU8 * block, NVT_DISPLAYID_INFO *pInfo)
1129 {
1130 if (pInfo == NULL) return NVT_STATUS_SUCCESS;
1131
1132 // Transfer Characteristics are currently not supported, but parsing of the
1133 // block should be added in the future when more specifications on monitors
1134 // that require this information is located here.
1135 return NVT_STATUS_SUCCESS;
1136 }
1137
CODE_SEGMENT(PAGE_DD_CODE)1138 CODE_SEGMENT(PAGE_DD_CODE)
1139 static NVT_STATUS parseDisplayIdDisplayInterface(NvU8 * block, NVT_DISPLAYID_INFO *pInfo)
1140 {
1141 DISPLAYID_INTERFACE_DATA_BLOCK * blk = (DISPLAYID_INTERFACE_DATA_BLOCK *)block;
1142 if (blk->header.data_bytes != DISPLAYID_INTERFACE_DATA_BLOCK_LEN)
1143 {
1144 // Assert since this error is ignored
1145 nvt_assert(0);
1146 return NVT_STATUS_ERR;
1147 }
1148
1149 if (pInfo == NULL) return NVT_STATUS_SUCCESS;
1150
1151 pInfo->supported_displayId2_0 = 0;
1152
1153 // Type/Link Info
1154 pInfo->u4.display_interface.interface_type = DRF_VAL(T_DISPLAYID, _INTERFACE, _TYPE, blk->info);
1155 pInfo->u4.display_interface.u1.digital_num_links = DRF_VAL(T_DISPLAYID, _INTERFACE, _NUMLINKS, blk->info);
1156 pInfo->u4.display_interface.interface_version = blk->version;
1157
1158 // Color Depths
1159 pInfo->u4.display_interface.rgb_depth.support_16b = DRF_VAL(T_DISPLAYID, _INTERFACE, _RGB16, blk->color_depth_rgb);
1160 pInfo->u4.display_interface.rgb_depth.support_14b = DRF_VAL(T_DISPLAYID, _INTERFACE, _RGB14, blk->color_depth_rgb);
1161 pInfo->u4.display_interface.rgb_depth.support_12b = DRF_VAL(T_DISPLAYID, _INTERFACE, _RGB12, blk->color_depth_rgb);
1162 pInfo->u4.display_interface.rgb_depth.support_10b = DRF_VAL(T_DISPLAYID, _INTERFACE, _RGB10, blk->color_depth_rgb);
1163 pInfo->u4.display_interface.rgb_depth.support_8b = DRF_VAL(T_DISPLAYID, _INTERFACE, _RGB8, blk->color_depth_rgb);
1164 pInfo->u4.display_interface.rgb_depth.support_6b = DRF_VAL(T_DISPLAYID, _INTERFACE, _RGB6, blk->color_depth_rgb);
1165 pInfo->u4.display_interface.ycbcr444_depth.support_16b = DRF_VAL(T_DISPLAYID, _INTERFACE, _YCBCR444_16, blk->color_depth_ycbcr444);
1166 pInfo->u4.display_interface.ycbcr444_depth.support_14b = DRF_VAL(T_DISPLAYID, _INTERFACE, _YCBCR444_14, blk->color_depth_ycbcr444);
1167 pInfo->u4.display_interface.ycbcr444_depth.support_12b = DRF_VAL(T_DISPLAYID, _INTERFACE, _YCBCR444_12, blk->color_depth_ycbcr444);
1168 pInfo->u4.display_interface.ycbcr444_depth.support_10b = DRF_VAL(T_DISPLAYID, _INTERFACE, _YCBCR444_10, blk->color_depth_ycbcr444);
1169 pInfo->u4.display_interface.ycbcr444_depth.support_8b = DRF_VAL(T_DISPLAYID, _INTERFACE, _YCBCR444_8, blk->color_depth_ycbcr444);
1170 pInfo->u4.display_interface.ycbcr444_depth.support_6b = DRF_VAL(T_DISPLAYID, _INTERFACE, _YCBCR444_6, blk->color_depth_ycbcr444);
1171 pInfo->u4.display_interface.ycbcr422_depth.support_16b = DRF_VAL(T_DISPLAYID, _INTERFACE, _YCBCR422_16, blk->color_depth_ycbcr422);
1172 pInfo->u4.display_interface.ycbcr422_depth.support_14b = DRF_VAL(T_DISPLAYID, _INTERFACE, _YCBCR422_14, blk->color_depth_ycbcr422);
1173 pInfo->u4.display_interface.ycbcr422_depth.support_12b = DRF_VAL(T_DISPLAYID, _INTERFACE, _YCBCR422_12, blk->color_depth_ycbcr422);
1174 pInfo->u4.display_interface.ycbcr422_depth.support_10b = DRF_VAL(T_DISPLAYID, _INTERFACE, _YCBCR422_10, blk->color_depth_ycbcr422);
1175 pInfo->u4.display_interface.ycbcr422_depth.support_8b = DRF_VAL(T_DISPLAYID, _INTERFACE, _YCBCR422_8, blk->color_depth_ycbcr422);
1176
1177 // Content Protection
1178 pInfo->u4.display_interface.content_protection = DRF_VAL(T_DISPLAYID, _INTERFACE, _CONTENT, blk->content_protection);
1179 pInfo->u4.display_interface.content_protection_version = blk->content_protection_version;
1180
1181 // Spread
1182 pInfo->u4.display_interface.spread_spectrum = DRF_VAL(T_DISPLAYID, _INTERFACE, _SPREAD_TYPE, blk->spread);
1183 pInfo->u4.display_interface.spread_percent = DRF_VAL(T_DISPLAYID, _INTERFACE, _SPREAD_PER, blk->spread);
1184
1185 // Proprietary Information
1186 switch (pInfo->u4.display_interface.interface_type)
1187 {
1188 case NVT_DISPLAYID_INTERFACE_TYPE_LVDS:
1189 pInfo->u2.lvds.color_map = DRF_VAL(T_DISPLAYID, _LVDS, _COLOR, blk->interface_attribute_1);
1190 pInfo->u2.lvds.support_2_8v = DRF_VAL(T_DISPLAYID, _LVDS, _2_8, blk->interface_attribute_1);
1191 pInfo->u2.lvds.support_12v = DRF_VAL(T_DISPLAYID, _LVDS, _12, blk->interface_attribute_1);
1192 pInfo->u2.lvds.support_5v = DRF_VAL(T_DISPLAYID, _LVDS, _5, blk->interface_attribute_1);
1193 pInfo->u2.lvds.support_3_3v = DRF_VAL(T_DISPLAYID, _LVDS, _3_3, blk->interface_attribute_1);
1194 pInfo->u2.lvds.DE_mode = DRF_VAL(T_DISPLAYID, _INTERFACE, _DE, blk->interface_attribute_2);
1195 pInfo->u2.lvds.polarity = DRF_VAL(T_DISPLAYID, _INTERFACE, _POLARITY, blk->interface_attribute_2);
1196 pInfo->u2.lvds.data_strobe = DRF_VAL(T_DISPLAYID, _INTERFACE, _STROBE, blk->interface_attribute_2);
1197 break;
1198 case NVT_DISPLAYID_INTERFACE_TYPE_PROPRIETARY:
1199 pInfo->u2.proprietary.DE_mode = DRF_VAL(T_DISPLAYID, _INTERFACE, _DE, blk->interface_attribute_1);
1200 pInfo->u2.proprietary.polarity = DRF_VAL(T_DISPLAYID, _INTERFACE, _POLARITY, blk->interface_attribute_1);
1201 pInfo->u2.proprietary.data_strobe = DRF_VAL(T_DISPLAYID, _INTERFACE, _STROBE, blk->interface_attribute_1);
1202 break;
1203 default:
1204 break;
1205 }
1206 return NVT_STATUS_SUCCESS;
1207 }
1208
CODE_SEGMENT(PAGE_DD_CODE)1209 CODE_SEGMENT(PAGE_DD_CODE)
1210 static NVT_STATUS parseDisplayIdStereo(NvU8 * block, NVT_DISPLAYID_INFO *pInfo)
1211 {
1212 NvU8 * sub;
1213
1214 DISPLAYID_STEREO_INTERFACE_METHOD_BLOCK * blk = (DISPLAYID_STEREO_INTERFACE_METHOD_BLOCK *)block;
1215 if (blk->header.data_bytes > NVT_DISPLAYID_DATABLOCK_MAX_PAYLOAD_LEN)
1216 {
1217 // Assert since this error is ignored
1218 nvt_assert(0);
1219 return NVT_STATUS_ERR;
1220 }
1221
1222 if (pInfo == NULL) return NVT_STATUS_SUCCESS;
1223
1224 sub = blk->timing_sub_block;
1225
1226 pInfo->stereo_code = blk->stereo_code;
1227 switch (blk->stereo_code)
1228 {
1229 case NVT_DISPLAYID_STEREO_FIELD_SEQUENTIAL:
1230 pInfo->u3.field_sequential.stereo_polarity = sub[0];
1231 break;
1232 case NVT_DISPLAYID_STEREO_SIDE_BY_SIDE:
1233 pInfo->u3.side_by_side.view_identity = sub[0];
1234 break;
1235 case NVT_DISPLAYID_STEREO_PIXEL_INTERLEAVED:
1236 NVMISC_MEMCPY(pInfo->u3.pixel_interleaved.interleave_pattern, sub, 8);
1237 break;
1238 case NVT_DISPLAYID_STEREO_DUAL_INTERFACE:
1239 pInfo->u3.left_right_separate.mirroring = DRF_VAL(T_DISPLAYID, _STEREO, _MIRRORING, sub[0]);
1240 pInfo->u3.left_right_separate.polarity = DRF_VAL(T_DISPLAYID, _STEREO, _POLARITY, sub[0]);
1241 break;
1242 case NVT_DISPLAYID_STEREO_MULTIVIEW:
1243 pInfo->u3.multiview.num_views = sub[0];
1244 pInfo->u3.multiview.code = sub[1];
1245 break;
1246 case NVT_DISPLAYID_STEREO_PROPRIETARY:
1247 break;
1248 default:
1249 // Assert since this error is ignored
1250 nvt_assert(0);
1251 return NVT_STATUS_ERR;
1252 }
1253
1254 return NVT_STATUS_SUCCESS;
1255 }
1256
CODE_SEGMENT(PAGE_DD_CODE)1257 CODE_SEGMENT(PAGE_DD_CODE)
1258 static NVT_STATUS parseDisplayIdTiledDisplay(NvU8 * block, NVT_DISPLAYID_INFO *pInfo)
1259 {
1260 DISPLAYID_TILED_DISPLAY_BLOCK * blk = (DISPLAYID_TILED_DISPLAY_BLOCK *)block;
1261 if (blk->header.data_bytes > NVT_DISPLAYID_DATABLOCK_MAX_PAYLOAD_LEN)
1262 {
1263 // Assert since this error is ignored
1264 nvt_assert(0);
1265 return NVT_STATUS_ERR;
1266 }
1267
1268 if (pInfo == NULL) return NVT_STATUS_SUCCESS;
1269
1270 // For revision 0, we only allow one tiled display data block.
1271 if (!blk->header.revision && pInfo->tile_topology_id.vendor_id)
1272 return NVT_STATUS_SUCCESS;
1273
1274 pInfo->tiled_display_revision = blk->header.revision;
1275
1276 pInfo->tile_capability.bSingleEnclosure = blk->capability.single_enclosure;
1277 pInfo->tile_capability.bHasBezelInfo = blk->capability.has_bezel_info;
1278 pInfo->tile_capability.multi_tile_behavior = blk->capability.multi_tile_behavior;
1279 pInfo->tile_capability.single_tile_behavior = blk->capability.single_tile_behavior;
1280
1281 pInfo->tile_topology.row = ((blk->topo_loc_high.row << 5) | blk->topology_low.row) + 1;
1282 pInfo->tile_topology.col = ((blk->topo_loc_high.col << 5) | blk->topology_low.col) + 1;
1283
1284 pInfo->tile_location.x = (blk->topo_loc_high.x << 5) | blk->location_low.x;
1285 pInfo->tile_location.y = (blk->topo_loc_high.y << 5) | blk->location_low.y;
1286
1287 pInfo->native_resolution.width = ((blk->native_resolution.width_high<<8)|blk->native_resolution.width_low) + 1;
1288 pInfo->native_resolution.height = ((blk->native_resolution.height_high<<8)|blk->native_resolution.height_low) + 1;
1289
1290 pInfo->bezel_info.pixel_density = blk->bezel_info.pixel_density;
1291 pInfo->bezel_info.top = (blk->bezel_info.top * blk->bezel_info.pixel_density) / 10;
1292 pInfo->bezel_info.bottom = (blk->bezel_info.bottom * blk->bezel_info.pixel_density) / 10;
1293 pInfo->bezel_info.right = (blk->bezel_info.right * blk->bezel_info.pixel_density) / 10;
1294 pInfo->bezel_info.left = (blk->bezel_info.left * blk->bezel_info.pixel_density) / 10;
1295
1296 pInfo->tile_topology_id.vendor_id = (blk->topology_id.vendor_id[2] << 16) |
1297 (blk->topology_id.vendor_id[1] << 8 ) |
1298 blk->topology_id.vendor_id[0];
1299
1300 pInfo->tile_topology_id.product_id = (blk->topology_id.product_id[1] << 8) | blk->topology_id.product_id[0];
1301
1302 pInfo->tile_topology_id.serial_number = (blk->topology_id.serial_number[3] << 24) |
1303 (blk->topology_id.serial_number[2] << 16) |
1304 (blk->topology_id.serial_number[1] << 8 ) |
1305 blk->topology_id.serial_number[0];
1306
1307 return NVT_STATUS_SUCCESS;
1308 }
1309
CODE_SEGMENT(PAGE_DD_CODE)1310 CODE_SEGMENT(PAGE_DD_CODE)
1311 static NVT_STATUS parseDisplayIdCtaData(NvU8 * block, NVT_EDID_INFO *pInfo)
1312 {
1313 DISPLAYID_DATA_BLOCK_HEADER * blk = (DISPLAYID_DATA_BLOCK_HEADER*)block;
1314 NVT_EDID_CEA861_INFO *p861info;
1315 if (blk->data_bytes > NVT_DISPLAYID_DATABLOCK_MAX_PAYLOAD_LEN)
1316 {
1317 // Assert since this error is ignored
1318 nvt_assert(0);
1319 return NVT_STATUS_ERR;
1320 }
1321
1322 if (pInfo == NULL) return NVT_STATUS_SUCCESS;
1323
1324 p861info = &pInfo->ext861;
1325
1326 pInfo->ext_displayid.cea_data_block_present = 1;
1327 p861info->revision = blk->revision;
1328
1329 //parse CEA tags which starts at 3rd byte from block
1330 parseCta861DataBlockInfo(&block[3], blk->data_bytes, p861info);
1331
1332 // update pInfo with basic hdmi info
1333 // assumes each edid will only have one such block across multiple cta861 blocks (otherwise may create declaration conflict)
1334 // in case of multiple such blocks, the last one takes precedence
1335 parseCta861VsdbBlocks(p861info, pInfo, FROM_DISPLAYID_13_DATA_BLOCK);
1336
1337 parseCta861HfScdb(p861info, pInfo, FROM_DISPLAYID_13_DATA_BLOCK);
1338
1339 //parse HDR related information from the HDR static metadata data block
1340 parseCea861HdrStaticMetadataDataBlock(p861info, pInfo, FROM_DISPLAYID_13_DATA_BLOCK);
1341
1342 // base video
1343 parse861bShortTiming(p861info, pInfo, FROM_DISPLAYID_13_DATA_BLOCK);
1344 // yuv420-only video
1345 parse861bShortYuv420Timing(p861info, pInfo, FROM_DISPLAYID_13_DATA_BLOCK);
1346 // CEA861-F at 7.5.12 section about VFPDB block.
1347 if (p861info->total_svr != 0)
1348 {
1349 parseCta861NativeOrPreferredTiming(p861info, pInfo, FROM_DISPLAYID_13_DATA_BLOCK);
1350 }
1351
1352 return NVT_STATUS_SUCCESS;
1353 }
1354
CODE_SEGMENT(PAGE_DD_CODE)1355 CODE_SEGMENT(PAGE_DD_CODE)
1356 static NVT_STATUS parseDisplayIdDisplayInterfaceFeatures(NvU8 * block, NVT_DISPLAYID_INFO *pInfo)
1357 {
1358 NvU8 i;
1359 DISPLAYID_INTERFACE_FEATURES_DATA_BLOCK * blk = (DISPLAYID_INTERFACE_FEATURES_DATA_BLOCK *)block;
1360 if (blk->header.data_bytes > DISPLAYID_INTERFACE_FEATURES_DATA_BLOCK_MAX_LEN)
1361 {
1362 // Assert since this error is ignored
1363 nvt_assert(0);
1364 return NVT_STATUS_ERR;
1365 }
1366
1367 if (pInfo == NULL) return NVT_STATUS_SUCCESS;
1368
1369 pInfo->supported_displayId2_0 = 1;
1370
1371 // Color Depths
1372 pInfo->u4.display_interface_features.rgb_depth.support_16b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _RGB16, blk->supported_color_depth_rgb);
1373 pInfo->u4.display_interface_features.rgb_depth.support_14b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _RGB14, blk->supported_color_depth_rgb);
1374 pInfo->u4.display_interface_features.rgb_depth.support_12b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _RGB12, blk->supported_color_depth_rgb);
1375 pInfo->u4.display_interface_features.rgb_depth.support_10b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _RGB10, blk->supported_color_depth_rgb);
1376 pInfo->u4.display_interface_features.rgb_depth.support_8b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _RGB8, blk->supported_color_depth_rgb);
1377 pInfo->u4.display_interface_features.rgb_depth.support_6b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _RGB6, blk->supported_color_depth_rgb);
1378 pInfo->u4.display_interface_features.ycbcr444_depth.support_16b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _YCBCR444_16, blk->supported_color_depth_ycbcr444);
1379 pInfo->u4.display_interface_features.ycbcr444_depth.support_14b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _YCBCR444_14, blk->supported_color_depth_ycbcr444);
1380 pInfo->u4.display_interface_features.ycbcr444_depth.support_12b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _YCBCR444_12, blk->supported_color_depth_ycbcr444);
1381 pInfo->u4.display_interface_features.ycbcr444_depth.support_10b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _YCBCR444_10, blk->supported_color_depth_ycbcr444);
1382 pInfo->u4.display_interface_features.ycbcr444_depth.support_8b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _YCBCR444_8, blk->supported_color_depth_ycbcr444);
1383 pInfo->u4.display_interface_features.ycbcr444_depth.support_6b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _YCBCR444_6, blk->supported_color_depth_ycbcr444);
1384 pInfo->u4.display_interface_features.ycbcr422_depth.support_16b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _YCBCR422_16, blk->supported_color_depth_ycbcr422);
1385 pInfo->u4.display_interface_features.ycbcr422_depth.support_14b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _YCBCR422_14, blk->supported_color_depth_ycbcr422);
1386 pInfo->u4.display_interface_features.ycbcr422_depth.support_12b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _YCBCR422_12, blk->supported_color_depth_ycbcr422);
1387 pInfo->u4.display_interface_features.ycbcr422_depth.support_10b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _YCBCR422_10, blk->supported_color_depth_ycbcr422);
1388 pInfo->u4.display_interface_features.ycbcr422_depth.support_8b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _YCBCR422_8, blk->supported_color_depth_ycbcr422);
1389 pInfo->u4.display_interface_features.ycbcr420_depth.support_16b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _YCBCR420_16, blk->supported_color_depth_ycbcr420);
1390 pInfo->u4.display_interface_features.ycbcr420_depth.support_14b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _YCBCR420_14, blk->supported_color_depth_ycbcr420);
1391 pInfo->u4.display_interface_features.ycbcr420_depth.support_12b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _YCBCR420_12, blk->supported_color_depth_ycbcr420);
1392 pInfo->u4.display_interface_features.ycbcr420_depth.support_10b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _YCBCR420_10, blk->supported_color_depth_ycbcr420);
1393 pInfo->u4.display_interface_features.ycbcr420_depth.support_8b = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _YCBCR420_8, blk->supported_color_depth_ycbcr420);
1394
1395 // Minimum Pixel Rate at Which YCbCr 4:2:0 Encoding Is Supported
1396 pInfo->u4.display_interface_features.minimum_pixel_rate_ycbcr420 = blk->minimum_pixel_rate_ycbcr420;
1397
1398 // Audio capability
1399 pInfo->u4.display_interface_features.audio_capability.support_32khz = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _AUDIO_SUPPORTED_32KHZ, blk->supported_audio_capability);
1400 pInfo->u4.display_interface_features.audio_capability.support_44_1khz = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _AUDIO_SUPPORTED_44_1KHZ, blk->supported_audio_capability);
1401 pInfo->u4.display_interface_features.audio_capability.support_48khz = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _AUDIO_SUPPORTED_48KHZ, blk->supported_audio_capability);
1402
1403 // Colorspace and EOTF combination
1404 pInfo->u4.display_interface_features.colorspace_eotf_combination_1.support_colorspace_bt2020_eotf_smpte_st2084 = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _COLORSPACE_BT2020_EOTF_SMPTE_ST2084, blk->supported_colorspace_eotf_combination_1);
1405 pInfo->u4.display_interface_features.colorspace_eotf_combination_1.support_colorspace_bt2020_eotf_bt2020 = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _COLORSPACE_BT2020_EOTF_BT2020, blk->supported_colorspace_eotf_combination_1);
1406 pInfo->u4.display_interface_features.colorspace_eotf_combination_1.support_colorspace_dci_p3_eotf_dci_p3 = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _COLORSPACE_DCI_P3_EOTF_DCI_P3, blk->supported_colorspace_eotf_combination_1);
1407 pInfo->u4.display_interface_features.colorspace_eotf_combination_1.support_colorspace_adobe_rgb_eotf_adobe_rgb = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _COLORSPACE_ADOBE_RGB_EOTF_ADOBE_RGB, blk->supported_colorspace_eotf_combination_1);
1408 pInfo->u4.display_interface_features.colorspace_eotf_combination_1.support_colorspace_bt709_eotf_bt1886 = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _COLORSPACE_BT709_EOTF_BT1886, blk->supported_colorspace_eotf_combination_1);
1409 pInfo->u4.display_interface_features.colorspace_eotf_combination_1.support_colorspace_bt601_eotf_bt601 = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _COLORSPACE_BT601_EOTF_BT601, blk->supported_colorspace_eotf_combination_1);
1410 pInfo->u4.display_interface_features.colorspace_eotf_combination_1.support_colorspace_srgb_eotf_srgb = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _COLORSPACE_SRGB_EOTF_SRGB, blk->supported_colorspace_eotf_combination_1);
1411
1412 // Additional support Colorspace and EOTF
1413 pInfo->u4.display_interface_features.total_additional_colorspace_eotf.total = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _ADDITIONAL_SUPPORTED_COLORSPACE_EOTF_TOTAL, blk->additional_supported_colorspace_eotf_total);
1414
1415 for (i = 0; i < pInfo->u4.display_interface_features.total_additional_colorspace_eotf.total; i++)
1416 {
1417 pInfo->u4.display_interface_features.additional_colorspace_eotf[i].support_colorspace = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _ADDITIONAL_SUPPORTED_COLORSPACE, blk->additional_supported_colorspace_eotf[i]);
1418 pInfo->u4.display_interface_features.additional_colorspace_eotf[i].support_eotf = DRF_VAL(T_DISPLAYID, _INTERFACE_FEATURES, _ADDITIONAL_SUPPORTED_EOTF, blk->additional_supported_colorspace_eotf[i]);
1419
1420 }
1421 return NVT_STATUS_SUCCESS;
1422 }
1423
1424 POP_SEGMENTS
1425