2 Read EDID information and parse EDID information.
4 Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "CirrusLogic5430.h"
10 #include "CirrusLogic5430I2c.h"
16 UINT8 Header
[8]; //EDID header "00 FF FF FF FF FF FF 00"
17 UINT16 ManufactureName
; //EISA 3-character ID
18 UINT16 ProductCode
; //Vendor assigned code
19 UINT32 SerialNumber
; //32-bit serial number
20 UINT8 WeekOfManufacture
; //Week number
21 UINT8 YearOfManufacture
; //Year
22 UINT8 EdidVersion
; //EDID Structure Version
23 UINT8 EdidRevision
; //EDID Structure Revision
24 UINT8 VideoInputDefinition
;
25 UINT8 MaxHorizontalImageSize
; //cm
26 UINT8 MaxVerticalImageSize
; //cm
27 UINT8 DisplayTransferCharacteristic
;
29 UINT8 RedGreenLowBits
; //Rx1 Rx0 Ry1 Ry0 Gx1 Gx0 Gy1Gy0
30 UINT8 BlueWhiteLowBits
; //Bx1 Bx0 By1 By0 Wx1 Wx0 Wy1 Wy0
31 UINT8 RedX
; //Red-x Bits 9 - 2
32 UINT8 RedY
; //Red-y Bits 9 - 2
33 UINT8 GreenX
; //Green-x Bits 9 - 2
34 UINT8 GreenY
; //Green-y Bits 9 - 2
35 UINT8 BlueX
; //Blue-x Bits 9 - 2
36 UINT8 BlueY
; //Blue-y Bits 9 - 2
37 UINT8 WhiteX
; //White-x Bits 9 - 2
38 UINT8 WhiteY
; //White-x Bits 9 - 2
39 UINT8 EstablishedTimings
[3];
40 UINT8 StandardTimingIdentification
[16];
41 UINT8 DetailedTimingDescriptions
[72];
42 UINT8 ExtensionFlag
; //Number of (optional) 128-byte EDID extension blocks to follow
46 #define EDID_BLOCK_SIZE 128
47 #define VBE_EDID_ESTABLISHED_TIMING_MAX_NUMBER 17
50 UINT16 HorizontalResolution
;
51 UINT16 VerticalResolution
;
57 UINT32 Key
[VBE_EDID_ESTABLISHED_TIMING_MAX_NUMBER
];
61 // Standard timing defined by VESA EDID
63 EDID_TIMING mVbeEstablishedEdidTiming
[] = {
65 // Established Timing I
76 // Established Timing II
87 // Established Timing III
93 Read EDID information from I2C Bus on CirrusLogic.
95 @param Private Pointer to CIRRUS_LOGIC_5430_PRIVATE_DATA.
96 @param EdidDataBlock Pointer to EDID data block.
97 @param EdidSize Returned EDID block size.
99 @retval EFI_UNSUPPORTED
105 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
,
106 UINT8
**EdidDataBlock
,
111 UINT8 EdidData
[EDID_BLOCK_SIZE
* 2];
115 for (Index
= 0; Index
< EDID_BLOCK_SIZE
* 2; Index
++) {
116 I2cReadByte (Private
->PciIo
, 0xa0, (UINT8
)Index
, &EdidData
[Index
]);
120 // Search for the EDID signature
122 ValidEdid
= &EdidData
[0];
123 Signature
= 0x00ffffffffffff00ull
;
124 for (Index
= 0; Index
< EDID_BLOCK_SIZE
* 2; Index
++, ValidEdid
++) {
125 if (CompareMem (ValidEdid
, &Signature
, 8) == 0) {
132 // No EDID signature found
134 return EFI_UNSUPPORTED
;
137 *EdidDataBlock
= AllocateCopyPool (
141 if (*EdidDataBlock
== NULL
) {
142 return EFI_OUT_OF_RESOURCES
;
146 // Currently only support EDID 1.x
148 *EdidSize
= EDID_BLOCK_SIZE
;
154 Generate a search key for a specified timing data.
156 @param EdidTiming Pointer to EDID timing
158 @return The 32 bit unique key for search.
163 EDID_TIMING
*EdidTiming
169 // Be sure no conflicts for all standard timing defined by VESA.
171 Key
= (EdidTiming
->HorizontalResolution
* 2) + EdidTiming
->VerticalResolution
;
176 Search a specified Timing in all the valid EDID timings.
178 @param ValidEdidTiming All valid EDID timing information.
179 @param EdidTiming The Timing to search for.
182 @retval FALSE Not found.
187 VALID_EDID_TIMING
*ValidEdidTiming
,
188 EDID_TIMING
*EdidTiming
194 Key
= CalculateEdidKey (EdidTiming
);
196 for (Index
= 0; Index
< ValidEdidTiming
->ValidNumber
; Index
++) {
197 if (Key
== ValidEdidTiming
->Key
[Index
]) {
206 Parse the Established Timing and Standard Timing in EDID data block.
208 @param EdidBuffer Pointer to EDID data block
209 @param ValidEdidTiming Valid EDID timing information
211 @retval TRUE The EDID data is valid.
212 @retval FALSE The EDID data is invalid.
218 VALID_EDID_TIMING
*ValidEdidTiming
226 UINT16 HorizontalResolution
;
227 UINT16 VerticalResolution
;
230 EDID_TIMING TempTiming
;
231 EDID_BLOCK
*EdidDataBlock
;
233 EdidDataBlock
= (EDID_BLOCK
*) EdidBuffer
;
236 // Check the checksum of EDID data
239 for (Index
= 0; Index
< EDID_BLOCK_SIZE
; Index
++) {
240 CheckSum
= (UINT8
) (CheckSum
+ EdidBuffer
[Index
]);
247 SetMem (ValidEdidTiming
, sizeof (VALID_EDID_TIMING
), 0);
249 if ((EdidDataBlock
->EstablishedTimings
[0] != 0) ||
250 (EdidDataBlock
->EstablishedTimings
[1] != 0) ||
251 (EdidDataBlock
->EstablishedTimings
[2] != 0)
254 // Established timing data
256 TimingBits
= EdidDataBlock
->EstablishedTimings
[0] |
257 (EdidDataBlock
->EstablishedTimings
[1] << 8) |
258 ((EdidDataBlock
->EstablishedTimings
[2] & 0x80) << 9) ;
259 for (Index
= 0; Index
< VBE_EDID_ESTABLISHED_TIMING_MAX_NUMBER
; Index
++) {
260 if (TimingBits
& 0x1) {
261 ValidEdidTiming
->Key
[ValidNumber
] = CalculateEdidKey (&mVbeEstablishedEdidTiming
[Index
]);
264 TimingBits
= TimingBits
>> 1;
268 // If no Established timing data, read the standard timing data
270 BufferIndex
= &EdidDataBlock
->StandardTimingIdentification
[0];
271 for (Index
= 0; Index
< 8; Index
++) {
272 if ((BufferIndex
[0] != 0x1) && (BufferIndex
[1] != 0x1)){
274 // A valid Standard Timing
276 HorizontalResolution
= (UINT16
) (BufferIndex
[0] * 8 + 248);
277 AspectRatio
= (UINT8
) (BufferIndex
[1] >> 6);
278 switch (AspectRatio
) {
280 VerticalResolution
= (UINT16
) (HorizontalResolution
/ 16 * 10);
283 VerticalResolution
= (UINT16
) (HorizontalResolution
/ 4 * 3);
286 VerticalResolution
= (UINT16
) (HorizontalResolution
/ 5 * 4);
289 VerticalResolution
= (UINT16
) (HorizontalResolution
/ 16 * 9);
292 VerticalResolution
= (UINT16
) (HorizontalResolution
/ 4 * 3);
295 RefreshRate
= (UINT8
) ((BufferIndex
[1] & 0x1f) + 60);
296 TempTiming
.HorizontalResolution
= HorizontalResolution
;
297 TempTiming
.VerticalResolution
= VerticalResolution
;
298 TempTiming
.RefreshRate
= RefreshRate
;
299 ValidEdidTiming
->Key
[ValidNumber
] = CalculateEdidKey (&TempTiming
);
306 ValidEdidTiming
->ValidNumber
= ValidNumber
;
311 Construct the valid video modes for CirrusLogic5430.
315 CirrusLogic5430VideoModeSetup (
316 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
322 EFI_EDID_OVERRIDE_PROTOCOL
*EdidOverride
;
323 UINT32 EdidAttributes
;
324 BOOLEAN EdidOverrideFound
;
325 UINTN EdidOverrideDataSize
;
326 UINT8
*EdidOverrideDataBlock
;
327 UINTN EdidDiscoveredDataSize
;
328 UINT8
*EdidDiscoveredDataBlock
;
329 UINTN EdidActiveDataSize
;
330 UINT8
*EdidActiveDataBlock
;
331 VALID_EDID_TIMING ValidEdidTiming
;
332 UINT32 ValidModeCount
;
333 CIRRUS_LOGIC_5430_MODE_DATA
*ModeData
;
335 CIRRUS_LOGIC_5430_VIDEO_MODES
*VideoMode
;
336 EDID_TIMING TempTiming
;
339 // setup EDID information
341 Private
->EdidDiscovered
.Edid
= NULL
;
342 Private
->EdidDiscovered
.SizeOfEdid
= 0;
343 Private
->EdidActive
.Edid
= NULL
;
344 Private
->EdidActive
.SizeOfEdid
= 0;
347 EdidOverrideFound
= FALSE
;
348 EdidAttributes
= 0xff;
349 EdidOverrideDataSize
= 0;
350 EdidOverrideDataBlock
= NULL
;
351 EdidActiveDataSize
= 0;
352 EdidActiveDataBlock
= NULL
;
353 EdidDiscoveredDataBlock
= NULL
;
356 // Find EDID Override protocol firstly, this protocol is installed by platform if needed.
358 Status
= gBS
->LocateProtocol (
359 &gEfiEdidOverrideProtocolGuid
,
361 (VOID
**) &EdidOverride
363 if (!EFI_ERROR (Status
)) {
365 // Allocate double size of VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE to avoid overflow
367 EdidOverrideDataBlock
= AllocatePool (EDID_BLOCK_SIZE
* 2);
368 if (NULL
== EdidOverrideDataBlock
) {
369 Status
= EFI_OUT_OF_RESOURCES
;
373 Status
= EdidOverride
->GetEdid (
377 &EdidOverrideDataSize
,
378 (UINT8
**) &EdidOverrideDataBlock
380 if (!EFI_ERROR (Status
) &&
381 EdidAttributes
== 0 &&
382 EdidOverrideDataSize
!= 0) {
384 // Succeeded to get EDID Override Data
386 EdidOverrideFound
= TRUE
;
390 if (EdidOverrideFound
!= TRUE
|| EdidAttributes
== EFI_EDID_OVERRIDE_DONT_OVERRIDE
) {
392 // If EDID Override data doesn't exist or EFI_EDID_OVERRIDE_DONT_OVERRIDE returned,
393 // read EDID information through I2C Bus
395 if (ReadEdidData (Private
, &EdidDiscoveredDataBlock
, &EdidDiscoveredDataSize
) == EFI_SUCCESS
) {
396 Private
->EdidDiscovered
.SizeOfEdid
= (UINT32
) EdidDiscoveredDataSize
;
397 Private
->EdidDiscovered
.Edid
= (UINT8
*) AllocateCopyPool (
398 EdidDiscoveredDataSize
,
399 EdidDiscoveredDataBlock
402 if (NULL
== Private
->EdidDiscovered
.Edid
) {
403 Status
= EFI_OUT_OF_RESOURCES
;
407 EdidActiveDataSize
= Private
->EdidDiscovered
.SizeOfEdid
;
408 EdidActiveDataBlock
= Private
->EdidDiscovered
.Edid
;
414 if (EdidFound
!= TRUE
&& EdidOverrideFound
== TRUE
) {
415 EdidActiveDataSize
= EdidOverrideDataSize
;
416 EdidActiveDataBlock
= EdidOverrideDataBlock
;
420 if (EdidFound
== TRUE
) {
422 // Parse EDID data structure to retrieve modes supported by monitor
424 if (ParseEdidData ((UINT8
*) EdidActiveDataBlock
, &ValidEdidTiming
) == TRUE
) {
426 // Copy EDID Override Data to EDID Active Data
428 Private
->EdidActive
.SizeOfEdid
= (UINT32
) EdidActiveDataSize
;
429 Private
->EdidActive
.Edid
= (UINT8
*) AllocateCopyPool (
433 if (NULL
== Private
->EdidActive
.Edid
) {
434 Status
= EFI_OUT_OF_RESOURCES
;
439 Private
->EdidActive
.SizeOfEdid
= 0;
440 Private
->EdidActive
.Edid
= NULL
;
446 // Initialize the private mode data with the supported modes.
449 ModeData
= &Private
->ModeData
[0];
450 VideoMode
= &CirrusLogic5430VideoModes
[0];
451 for (Index
= 0; Index
< CIRRUS_LOGIC_5430_MODE_COUNT
; Index
++) {
456 // Check whether match with CirrusLogic5430 video mode
458 TempTiming
.HorizontalResolution
= (UINT16
) VideoMode
->Width
;
459 TempTiming
.VerticalResolution
= (UINT16
) VideoMode
->Height
;
460 TempTiming
.RefreshRate
= (UINT16
) VideoMode
->RefreshRate
;
461 if (SearchEdidTiming (&ValidEdidTiming
, &TempTiming
) != TRUE
) {
466 // Not export Mode 0x0 as GOP mode, this is not defined in spec.
468 if ((VideoMode
->Width
== 0) || (VideoMode
->Height
== 0)) {
473 ModeData
->ModeNumber
= Index
;
474 ModeData
->HorizontalResolution
= VideoMode
->Width
;
475 ModeData
->VerticalResolution
= VideoMode
->Height
;
476 ModeData
->ColorDepth
= VideoMode
->ColorDepth
;
477 ModeData
->RefreshRate
= VideoMode
->RefreshRate
;
486 Private
->MaxMode
= ValidModeCount
;
490 // If EDID information wasn't found
492 ModeData
= &Private
->ModeData
[0];
493 VideoMode
= &CirrusLogic5430VideoModes
[0];
494 for (Index
= 0; Index
< CIRRUS_LOGIC_5430_MODE_COUNT
; Index
++) {
495 ModeData
->ModeNumber
= Index
;
496 ModeData
->HorizontalResolution
= VideoMode
->Width
;
497 ModeData
->VerticalResolution
= VideoMode
->Height
;
498 ModeData
->ColorDepth
= VideoMode
->ColorDepth
;
499 ModeData
->RefreshRate
= VideoMode
->RefreshRate
;
504 Private
->MaxMode
= CIRRUS_LOGIC_5430_MODE_COUNT
;
507 if (EdidOverrideDataBlock
!= NULL
) {
508 FreePool (EdidOverrideDataBlock
);
514 if (EdidOverrideDataBlock
!= NULL
) {
515 FreePool (EdidOverrideDataBlock
);
517 if (Private
->EdidDiscovered
.Edid
!= NULL
) {
518 FreePool (Private
->EdidDiscovered
.Edid
);
520 if (Private
->EdidDiscovered
.Edid
!= NULL
) {
521 FreePool (Private
->EdidActive
.Edid
);
524 return EFI_DEVICE_ERROR
;