Vishal Bhoj | 82c8071 | 2015-12-15 21:13:33 +0530 | [diff] [blame] | 1 | /** @file
|
| 2 | Read EDID information and parse EDID information.
|
| 3 |
|
| 4 | Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
|
| 5 | This program and the accompanying materials
|
| 6 | are licensed and made available under the terms and conditions of the BSD License
|
| 7 | which accompanies this distribution. The full text of the license may be found at
|
| 8 | http://opensource.org/licenses/bsd-license.php
|
| 9 |
|
| 10 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
| 11 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
| 12 |
|
| 13 | **/
|
| 14 |
|
| 15 | #include "CirrusLogic5430.h"
|
| 16 | #include "CirrusLogic5430I2c.h"
|
| 17 |
|
| 18 | //
|
| 19 | // EDID block
|
| 20 | //
|
| 21 | typedef struct {
|
| 22 | UINT8 Header[8]; //EDID header "00 FF FF FF FF FF FF 00"
|
| 23 | UINT16 ManufactureName; //EISA 3-character ID
|
| 24 | UINT16 ProductCode; //Vendor assigned code
|
| 25 | UINT32 SerialNumber; //32-bit serial number
|
| 26 | UINT8 WeekOfManufacture; //Week number
|
| 27 | UINT8 YearOfManufacture; //Year
|
| 28 | UINT8 EdidVersion; //EDID Structure Version
|
| 29 | UINT8 EdidRevision; //EDID Structure Revision
|
| 30 | UINT8 VideoInputDefinition;
|
| 31 | UINT8 MaxHorizontalImageSize; //cm
|
| 32 | UINT8 MaxVerticalImageSize; //cm
|
| 33 | UINT8 DisplayTransferCharacteristic;
|
| 34 | UINT8 FeatureSupport;
|
| 35 | UINT8 RedGreenLowBits; //Rx1 Rx0 Ry1 Ry0 Gx1 Gx0 Gy1Gy0
|
| 36 | UINT8 BlueWhiteLowBits; //Bx1 Bx0 By1 By0 Wx1 Wx0 Wy1 Wy0
|
| 37 | UINT8 RedX; //Red-x Bits 9 - 2
|
| 38 | UINT8 RedY; //Red-y Bits 9 - 2
|
| 39 | UINT8 GreenX; //Green-x Bits 9 - 2
|
| 40 | UINT8 GreenY; //Green-y Bits 9 - 2
|
| 41 | UINT8 BlueX; //Blue-x Bits 9 - 2
|
| 42 | UINT8 BlueY; //Blue-y Bits 9 - 2
|
| 43 | UINT8 WhiteX; //White-x Bits 9 - 2
|
| 44 | UINT8 WhiteY; //White-x Bits 9 - 2
|
| 45 | UINT8 EstablishedTimings[3];
|
| 46 | UINT8 StandardTimingIdentification[16];
|
| 47 | UINT8 DetailedTimingDescriptions[72];
|
| 48 | UINT8 ExtensionFlag; //Number of (optional) 128-byte EDID extension blocks to follow
|
| 49 | UINT8 Checksum;
|
| 50 | } EDID_BLOCK;
|
| 51 |
|
| 52 | #define EDID_BLOCK_SIZE 128
|
| 53 | #define VBE_EDID_ESTABLISHED_TIMING_MAX_NUMBER 17
|
| 54 |
|
| 55 | typedef struct {
|
| 56 | UINT16 HorizontalResolution;
|
| 57 | UINT16 VerticalResolution;
|
| 58 | UINT16 RefreshRate;
|
| 59 | } EDID_TIMING;
|
| 60 |
|
| 61 | typedef struct {
|
| 62 | UINT32 ValidNumber;
|
| 63 | UINT32 Key[VBE_EDID_ESTABLISHED_TIMING_MAX_NUMBER];
|
| 64 | } VALID_EDID_TIMING;
|
| 65 |
|
| 66 | //
|
| 67 | // Standard timing defined by VESA EDID
|
| 68 | //
|
| 69 | EDID_TIMING mVbeEstablishedEdidTiming[] = {
|
| 70 | //
|
| 71 | // Established Timing I
|
| 72 | //
|
| 73 | {800, 600, 60},
|
| 74 | {800, 600, 56},
|
| 75 | {640, 480, 75},
|
| 76 | {640, 480, 72},
|
| 77 | {640, 480, 67},
|
| 78 | {640, 480, 60},
|
| 79 | {720, 400, 88},
|
| 80 | {720, 400, 70},
|
| 81 | //
|
| 82 | // Established Timing II
|
| 83 | //
|
| 84 | {1280, 1024, 75},
|
| 85 | {1024, 768, 75},
|
| 86 | {1024, 768, 70},
|
| 87 | {1024, 768, 60},
|
| 88 | {1024, 768, 87},
|
| 89 | {832, 624, 75},
|
| 90 | {800, 600, 75},
|
| 91 | {800, 600, 72},
|
| 92 | //
|
| 93 | // Established Timing III
|
| 94 | //
|
| 95 | {1152, 870, 75}
|
| 96 | };
|
| 97 |
|
| 98 | /**
|
| 99 | Read EDID information from I2C Bus on CirrusLogic.
|
| 100 |
|
| 101 | @param Private Pointer to CIRRUS_LOGIC_5430_PRIVATE_DATA.
|
| 102 | @param EdidDataBlock Pointer to EDID data block.
|
| 103 | @param EdidSize Returned EDID block size.
|
| 104 |
|
| 105 | @retval EFI_UNSUPPORTED
|
| 106 | @retval EFI_SUCCESS
|
| 107 |
|
| 108 | **/
|
| 109 | EFI_STATUS
|
| 110 | ReadEdidData (
|
| 111 | CIRRUS_LOGIC_5430_PRIVATE_DATA *Private,
|
| 112 | UINT8 **EdidDataBlock,
|
| 113 | UINTN *EdidSize
|
| 114 | )
|
| 115 | {
|
| 116 | UINTN Index;
|
| 117 | UINT8 EdidData[EDID_BLOCK_SIZE * 2];
|
| 118 | UINT8 *ValidEdid;
|
| 119 | UINT64 Signature;
|
| 120 |
|
| 121 | for (Index = 0; Index < EDID_BLOCK_SIZE * 2; Index ++) {
|
| 122 | I2cReadByte (Private->PciIo, 0xa0, (UINT8)Index, &EdidData[Index]);
|
| 123 | }
|
| 124 |
|
| 125 | //
|
| 126 | // Search for the EDID signature
|
| 127 | //
|
| 128 | ValidEdid = &EdidData[0];
|
| 129 | Signature = 0x00ffffffffffff00ull;
|
| 130 | for (Index = 0; Index < EDID_BLOCK_SIZE * 2; Index ++, ValidEdid ++) {
|
| 131 | if (CompareMem (ValidEdid, &Signature, 8) == 0) {
|
| 132 | break;
|
| 133 | }
|
| 134 | }
|
| 135 |
|
| 136 | if (Index == 256) {
|
| 137 | //
|
| 138 | // No EDID signature found
|
| 139 | //
|
| 140 | return EFI_UNSUPPORTED;
|
| 141 | }
|
| 142 |
|
| 143 | *EdidDataBlock = AllocateCopyPool (
|
| 144 | EDID_BLOCK_SIZE,
|
| 145 | ValidEdid
|
| 146 | );
|
| 147 | if (*EdidDataBlock == NULL) {
|
| 148 | return EFI_OUT_OF_RESOURCES;
|
| 149 | }
|
| 150 |
|
| 151 | //
|
| 152 | // Currently only support EDID 1.x
|
| 153 | //
|
| 154 | *EdidSize = EDID_BLOCK_SIZE;
|
| 155 |
|
| 156 | return EFI_SUCCESS;
|
| 157 | }
|
| 158 |
|
| 159 | /**
|
| 160 | Generate a search key for a specified timing data.
|
| 161 |
|
| 162 | @param EdidTiming Pointer to EDID timing
|
| 163 |
|
| 164 | @return The 32 bit unique key for search.
|
| 165 |
|
| 166 | **/
|
| 167 | UINT32
|
| 168 | CalculateEdidKey (
|
| 169 | EDID_TIMING *EdidTiming
|
| 170 | )
|
| 171 | {
|
| 172 | UINT32 Key;
|
| 173 |
|
| 174 | //
|
| 175 | // Be sure no conflicts for all standard timing defined by VESA.
|
| 176 | //
|
| 177 | Key = (EdidTiming->HorizontalResolution * 2) + EdidTiming->VerticalResolution;
|
| 178 | return Key;
|
| 179 | }
|
| 180 |
|
| 181 | /**
|
| 182 | Search a specified Timing in all the valid EDID timings.
|
| 183 |
|
| 184 | @param ValidEdidTiming All valid EDID timing information.
|
| 185 | @param EdidTiming The Timing to search for.
|
| 186 |
|
| 187 | @retval TRUE Found.
|
| 188 | @retval FALSE Not found.
|
| 189 |
|
| 190 | **/
|
| 191 | BOOLEAN
|
| 192 | SearchEdidTiming (
|
| 193 | VALID_EDID_TIMING *ValidEdidTiming,
|
| 194 | EDID_TIMING *EdidTiming
|
| 195 | )
|
| 196 | {
|
| 197 | UINT32 Index;
|
| 198 | UINT32 Key;
|
| 199 |
|
| 200 | Key = CalculateEdidKey (EdidTiming);
|
| 201 |
|
| 202 | for (Index = 0; Index < ValidEdidTiming->ValidNumber; Index ++) {
|
| 203 | if (Key == ValidEdidTiming->Key[Index]) {
|
| 204 | return TRUE;
|
| 205 | }
|
| 206 | }
|
| 207 |
|
| 208 | return FALSE;
|
| 209 | }
|
| 210 |
|
| 211 | /**
|
| 212 | Parse the Established Timing and Standard Timing in EDID data block.
|
| 213 |
|
| 214 | @param EdidBuffer Pointer to EDID data block
|
| 215 | @param ValidEdidTiming Valid EDID timing information
|
| 216 |
|
| 217 | @retval TRUE The EDID data is valid.
|
| 218 | @retval FALSE The EDID data is invalid.
|
| 219 |
|
| 220 | **/
|
| 221 | BOOLEAN
|
| 222 | ParseEdidData (
|
| 223 | UINT8 *EdidBuffer,
|
| 224 | VALID_EDID_TIMING *ValidEdidTiming
|
| 225 | )
|
| 226 | {
|
| 227 | UINT8 CheckSum;
|
| 228 | UINT32 Index;
|
| 229 | UINT32 ValidNumber;
|
| 230 | UINT32 TimingBits;
|
| 231 | UINT8 *BufferIndex;
|
| 232 | UINT16 HorizontalResolution;
|
| 233 | UINT16 VerticalResolution;
|
| 234 | UINT8 AspectRatio;
|
| 235 | UINT8 RefreshRate;
|
| 236 | EDID_TIMING TempTiming;
|
| 237 | EDID_BLOCK *EdidDataBlock;
|
| 238 |
|
| 239 | EdidDataBlock = (EDID_BLOCK *) EdidBuffer;
|
| 240 |
|
| 241 | //
|
| 242 | // Check the checksum of EDID data
|
| 243 | //
|
| 244 | CheckSum = 0;
|
| 245 | for (Index = 0; Index < EDID_BLOCK_SIZE; Index ++) {
|
| 246 | CheckSum = (UINT8) (CheckSum + EdidBuffer[Index]);
|
| 247 | }
|
| 248 | if (CheckSum != 0) {
|
| 249 | return FALSE;
|
| 250 | }
|
| 251 |
|
| 252 | ValidNumber = 0;
|
| 253 | SetMem (ValidEdidTiming, sizeof (VALID_EDID_TIMING), 0);
|
| 254 |
|
| 255 | if ((EdidDataBlock->EstablishedTimings[0] != 0) ||
|
| 256 | (EdidDataBlock->EstablishedTimings[1] != 0) ||
|
| 257 | (EdidDataBlock->EstablishedTimings[2] != 0)
|
| 258 | ) {
|
| 259 | //
|
| 260 | // Established timing data
|
| 261 | //
|
| 262 | TimingBits = EdidDataBlock->EstablishedTimings[0] |
|
| 263 | (EdidDataBlock->EstablishedTimings[1] << 8) |
|
| 264 | ((EdidDataBlock->EstablishedTimings[2] & 0x80) << 9) ;
|
| 265 | for (Index = 0; Index < VBE_EDID_ESTABLISHED_TIMING_MAX_NUMBER; Index ++) {
|
| 266 | if (TimingBits & 0x1) {
|
| 267 | ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&mVbeEstablishedEdidTiming[Index]);
|
| 268 | ValidNumber ++;
|
| 269 | }
|
| 270 | TimingBits = TimingBits >> 1;
|
| 271 | }
|
| 272 | } else {
|
| 273 | //
|
| 274 | // If no Established timing data, read the standard timing data
|
| 275 | //
|
| 276 | BufferIndex = &EdidDataBlock->StandardTimingIdentification[0];
|
| 277 | for (Index = 0; Index < 8; Index ++) {
|
| 278 | if ((BufferIndex[0] != 0x1) && (BufferIndex[1] != 0x1)){
|
| 279 | //
|
| 280 | // A valid Standard Timing
|
| 281 | //
|
| 282 | HorizontalResolution = (UINT16) (BufferIndex[0] * 8 + 248);
|
| 283 | AspectRatio = (UINT8) (BufferIndex[1] >> 6);
|
| 284 | switch (AspectRatio) {
|
| 285 | case 0:
|
| 286 | VerticalResolution = (UINT16) (HorizontalResolution / 16 * 10);
|
| 287 | break;
|
| 288 | case 1:
|
| 289 | VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);
|
| 290 | break;
|
| 291 | case 2:
|
| 292 | VerticalResolution = (UINT16) (HorizontalResolution / 5 * 4);
|
| 293 | break;
|
| 294 | case 3:
|
| 295 | VerticalResolution = (UINT16) (HorizontalResolution / 16 * 9);
|
| 296 | break;
|
| 297 | default:
|
| 298 | VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);
|
| 299 | break;
|
| 300 | }
|
| 301 | RefreshRate = (UINT8) ((BufferIndex[1] & 0x1f) + 60);
|
| 302 | TempTiming.HorizontalResolution = HorizontalResolution;
|
| 303 | TempTiming.VerticalResolution = VerticalResolution;
|
| 304 | TempTiming.RefreshRate = RefreshRate;
|
| 305 | ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming);
|
| 306 | ValidNumber ++;
|
| 307 | }
|
| 308 | BufferIndex += 2;
|
| 309 | }
|
| 310 | }
|
| 311 |
|
| 312 | ValidEdidTiming->ValidNumber = ValidNumber;
|
| 313 | return TRUE;
|
| 314 | }
|
| 315 |
|
| 316 | /**
|
| 317 | Construct the valid video modes for CirrusLogic5430.
|
| 318 |
|
| 319 | **/
|
| 320 | EFI_STATUS
|
| 321 | CirrusLogic5430VideoModeSetup (
|
| 322 | CIRRUS_LOGIC_5430_PRIVATE_DATA *Private
|
| 323 | )
|
| 324 | {
|
| 325 | EFI_STATUS Status;
|
| 326 | UINT32 Index;
|
| 327 | BOOLEAN EdidFound;
|
| 328 | EFI_EDID_OVERRIDE_PROTOCOL *EdidOverride;
|
| 329 | UINT32 EdidAttributes;
|
| 330 | BOOLEAN EdidOverrideFound;
|
| 331 | UINTN EdidOverrideDataSize;
|
| 332 | UINT8 *EdidOverrideDataBlock;
|
| 333 | UINTN EdidDiscoveredDataSize;
|
| 334 | UINT8 *EdidDiscoveredDataBlock;
|
| 335 | UINTN EdidActiveDataSize;
|
| 336 | UINT8 *EdidActiveDataBlock;
|
| 337 | VALID_EDID_TIMING ValidEdidTiming;
|
| 338 | UINT32 ValidModeCount;
|
| 339 | CIRRUS_LOGIC_5430_MODE_DATA *ModeData;
|
| 340 | BOOLEAN TimingMatch;
|
| 341 | CIRRUS_LOGIC_5430_VIDEO_MODES *VideoMode;
|
| 342 | EDID_TIMING TempTiming;
|
| 343 |
|
| 344 | //
|
| 345 | // setup EDID information
|
| 346 | //
|
| 347 | Private->EdidDiscovered.Edid = NULL;
|
| 348 | Private->EdidDiscovered.SizeOfEdid = 0;
|
| 349 | Private->EdidActive.Edid = NULL;
|
| 350 | Private->EdidActive.SizeOfEdid = 0;
|
| 351 |
|
| 352 | EdidFound = FALSE;
|
| 353 | EdidOverrideFound = FALSE;
|
| 354 | EdidAttributes = 0xff;
|
| 355 | EdidOverrideDataSize = 0;
|
| 356 | EdidOverrideDataBlock = NULL;
|
| 357 | EdidActiveDataSize = 0;
|
| 358 | EdidActiveDataBlock = NULL;
|
| 359 | EdidDiscoveredDataBlock = NULL;
|
| 360 |
|
| 361 | //
|
| 362 | // Find EDID Override protocol firstly, this protocol is installed by platform if needed.
|
| 363 | //
|
| 364 | Status = gBS->LocateProtocol (
|
| 365 | &gEfiEdidOverrideProtocolGuid,
|
| 366 | NULL,
|
| 367 | (VOID **) &EdidOverride
|
| 368 | );
|
| 369 | if (!EFI_ERROR (Status)) {
|
| 370 | //
|
| 371 | // Allocate double size of VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE to avoid overflow
|
| 372 | //
|
| 373 | EdidOverrideDataBlock = AllocatePool (EDID_BLOCK_SIZE * 2);
|
| 374 | if (NULL == EdidOverrideDataBlock) {
|
| 375 | Status = EFI_OUT_OF_RESOURCES;
|
| 376 | goto Done;
|
| 377 | }
|
| 378 |
|
| 379 | Status = EdidOverride->GetEdid (
|
| 380 | EdidOverride,
|
| 381 | Private->Handle,
|
| 382 | &EdidAttributes,
|
| 383 | &EdidOverrideDataSize,
|
| 384 | (UINT8 **) &EdidOverrideDataBlock
|
| 385 | );
|
| 386 | if (!EFI_ERROR (Status) &&
|
| 387 | EdidAttributes == 0 &&
|
| 388 | EdidOverrideDataSize != 0) {
|
| 389 | //
|
| 390 | // Succeeded to get EDID Override Data
|
| 391 | //
|
| 392 | EdidOverrideFound = TRUE;
|
| 393 | }
|
| 394 | }
|
| 395 |
|
| 396 | if (EdidOverrideFound != TRUE || EdidAttributes == EFI_EDID_OVERRIDE_DONT_OVERRIDE) {
|
| 397 | //
|
| 398 | // If EDID Override data doesn't exist or EFI_EDID_OVERRIDE_DONT_OVERRIDE returned,
|
| 399 | // read EDID information through I2C Bus
|
| 400 | //
|
| 401 | if (ReadEdidData (Private, &EdidDiscoveredDataBlock, &EdidDiscoveredDataSize) == EFI_SUCCESS) {
|
| 402 | Private->EdidDiscovered.SizeOfEdid = (UINT32) EdidDiscoveredDataSize;
|
| 403 | Private->EdidDiscovered.Edid = (UINT8 *) AllocateCopyPool (
|
| 404 | EdidDiscoveredDataSize,
|
| 405 | EdidDiscoveredDataBlock
|
| 406 | );
|
| 407 |
|
| 408 | if (NULL == Private->EdidDiscovered.Edid) {
|
| 409 | Status = EFI_OUT_OF_RESOURCES;
|
| 410 | goto Done;
|
| 411 | }
|
| 412 |
|
| 413 | EdidActiveDataSize = Private->EdidDiscovered.SizeOfEdid;
|
| 414 | EdidActiveDataBlock = Private->EdidDiscovered.Edid;
|
| 415 |
|
| 416 | EdidFound = TRUE;
|
| 417 | }
|
| 418 | }
|
| 419 |
|
| 420 | if (EdidFound != TRUE && EdidOverrideFound == TRUE) {
|
| 421 | EdidActiveDataSize = EdidOverrideDataSize;
|
| 422 | EdidActiveDataBlock = EdidOverrideDataBlock;
|
| 423 | EdidFound = TRUE;
|
| 424 | }
|
| 425 |
|
| 426 | if (EdidFound == TRUE) {
|
| 427 | //
|
| 428 | // Parse EDID data structure to retrieve modes supported by monitor
|
| 429 | //
|
| 430 | if (ParseEdidData ((UINT8 *) EdidActiveDataBlock, &ValidEdidTiming) == TRUE) {
|
| 431 | //
|
| 432 | // Copy EDID Override Data to EDID Active Data
|
| 433 | //
|
| 434 | Private->EdidActive.SizeOfEdid = (UINT32) EdidActiveDataSize;
|
| 435 | Private->EdidActive.Edid = (UINT8 *) AllocateCopyPool (
|
| 436 | EdidActiveDataSize,
|
| 437 | EdidActiveDataBlock
|
| 438 | );
|
| 439 | if (NULL == Private->EdidActive.Edid) {
|
| 440 | Status = EFI_OUT_OF_RESOURCES;
|
| 441 | goto Done;
|
| 442 | }
|
| 443 | }
|
| 444 | } else {
|
| 445 | Private->EdidActive.SizeOfEdid = 0;
|
| 446 | Private->EdidActive.Edid = NULL;
|
| 447 | EdidFound = FALSE;
|
| 448 | }
|
| 449 |
|
| 450 | if (EdidFound) {
|
| 451 | //
|
| 452 | // Initialize the private mode data with the supported modes.
|
| 453 | //
|
| 454 | ValidModeCount = 0;
|
| 455 | ModeData = &Private->ModeData[0];
|
| 456 | VideoMode = &CirrusLogic5430VideoModes[0];
|
| 457 | for (Index = 0; Index < CIRRUS_LOGIC_5430_MODE_COUNT; Index++) {
|
| 458 |
|
| 459 | TimingMatch = TRUE;
|
| 460 |
|
| 461 | //
|
| 462 | // Check whether match with CirrusLogic5430 video mode
|
| 463 | //
|
| 464 | TempTiming.HorizontalResolution = (UINT16) VideoMode->Width;
|
| 465 | TempTiming.VerticalResolution = (UINT16) VideoMode->Height;
|
| 466 | TempTiming.RefreshRate = (UINT16) VideoMode->RefreshRate;
|
| 467 | if (SearchEdidTiming (&ValidEdidTiming, &TempTiming) != TRUE) {
|
| 468 | TimingMatch = FALSE;
|
| 469 | }
|
| 470 |
|
| 471 | //
|
| 472 | // Not export Mode 0x0 as GOP mode, this is not defined in spec.
|
| 473 | //
|
| 474 | if ((VideoMode->Width == 0) || (VideoMode->Height == 0)) {
|
| 475 | TimingMatch = FALSE;
|
| 476 | }
|
| 477 |
|
| 478 | if (TimingMatch) {
|
| 479 | ModeData->ModeNumber = Index;
|
| 480 | ModeData->HorizontalResolution = VideoMode->Width;
|
| 481 | ModeData->VerticalResolution = VideoMode->Height;
|
| 482 | ModeData->ColorDepth = VideoMode->ColorDepth;
|
| 483 | ModeData->RefreshRate = VideoMode->RefreshRate;
|
| 484 |
|
| 485 | ModeData ++;
|
| 486 | ValidModeCount ++;
|
| 487 | }
|
| 488 |
|
| 489 | VideoMode ++;
|
| 490 | }
|
| 491 |
|
| 492 | Private->MaxMode = ValidModeCount;
|
| 493 |
|
| 494 | } else {
|
| 495 | //
|
| 496 | // If EDID information wasn't found
|
| 497 | //
|
| 498 | ModeData = &Private->ModeData[0];
|
| 499 | VideoMode = &CirrusLogic5430VideoModes[0];
|
| 500 | for (Index = 0; Index < CIRRUS_LOGIC_5430_MODE_COUNT; Index ++) {
|
| 501 | ModeData->ModeNumber = Index;
|
| 502 | ModeData->HorizontalResolution = VideoMode->Width;
|
| 503 | ModeData->VerticalResolution = VideoMode->Height;
|
| 504 | ModeData->ColorDepth = VideoMode->ColorDepth;
|
| 505 | ModeData->RefreshRate = VideoMode->RefreshRate;
|
| 506 |
|
| 507 | ModeData ++ ;
|
| 508 | VideoMode ++;
|
| 509 | }
|
| 510 | Private->MaxMode = CIRRUS_LOGIC_5430_MODE_COUNT;
|
| 511 | }
|
| 512 |
|
| 513 | if (EdidOverrideDataBlock != NULL) {
|
| 514 | FreePool (EdidOverrideDataBlock);
|
| 515 | }
|
| 516 |
|
| 517 | return EFI_SUCCESS;
|
| 518 |
|
| 519 | Done:
|
| 520 | if (EdidOverrideDataBlock != NULL) {
|
| 521 | FreePool (EdidOverrideDataBlock);
|
| 522 | }
|
| 523 | if (Private->EdidDiscovered.Edid != NULL) {
|
| 524 | FreePool (Private->EdidDiscovered.Edid);
|
| 525 | }
|
| 526 | if (Private->EdidDiscovered.Edid != NULL) {
|
| 527 | FreePool (Private->EdidActive.Edid);
|
| 528 | }
|
| 529 |
|
| 530 | return EFI_DEVICE_ERROR;
|
| 531 | }
|