1 /** @file
2 Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>
3 This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution.  The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
7 
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10 
11 Module Name:
12 
13   UefiCirrusLogic5430GraphicsOutput.c
14 
15 Abstract:
16 
17   This file produces the graphics abstration of Graphics Output Protocol. It is called by
18   CirrusLogic5430.c file which deals with the EFI 1.1 driver model.
19   This file just does graphics.
20 
21 **/
22 #include "CirrusLogic5430.h"
23 #include <IndustryStandard/Acpi.h>
24 
25 
26 STATIC
27 VOID
CirrusLogic5430CompleteModeInfo(OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION * Info)28 CirrusLogic5430CompleteModeInfo (
29   OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info
30   )
31 {
32   Info->Version = 0;
33   Info->PixelFormat = PixelBitMask;
34   Info->PixelInformation.RedMask = PIXEL_RED_MASK;
35   Info->PixelInformation.GreenMask = PIXEL_GREEN_MASK;
36   Info->PixelInformation.BlueMask = PIXEL_BLUE_MASK;
37   Info->PixelInformation.ReservedMask = 0;
38   Info->PixelsPerScanLine = Info->HorizontalResolution;
39 }
40 
41 
42 STATIC
43 EFI_STATUS
CirrusLogic5430CompleteModeData(IN CIRRUS_LOGIC_5430_PRIVATE_DATA * Private,OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE * Mode)44 CirrusLogic5430CompleteModeData (
45   IN  CIRRUS_LOGIC_5430_PRIVATE_DATA    *Private,
46   OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode
47   )
48 {
49   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info;
50   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     *FrameBufDesc;
51 
52   Info = Mode->Info;
53   CirrusLogic5430CompleteModeInfo (Info);
54 
55   Private->PciIo->GetBarAttributes (
56                         Private->PciIo,
57                         0,
58                         NULL,
59                         (VOID**) &FrameBufDesc
60                         );
61 
62   Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin;
63   Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution;
64 
65   return EFI_SUCCESS;
66 }
67 
68 
69 //
70 // Graphics Output Protocol Member Functions
71 //
72 EFI_STATUS
73 EFIAPI
CirrusLogic5430GraphicsOutputQueryMode(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN UINT32 ModeNumber,OUT UINTN * SizeOfInfo,OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ** Info)74 CirrusLogic5430GraphicsOutputQueryMode (
75   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
76   IN  UINT32                                ModeNumber,
77   OUT UINTN                                 *SizeOfInfo,
78   OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
79   )
80 /*++
81 
82 Routine Description:
83 
84   Graphics Output protocol interface to query video mode
85 
86   Arguments:
87     This                  - Protocol instance pointer.
88     ModeNumber            - The mode number to return information on.
89     Info                  - Caller allocated buffer that returns information about ModeNumber.
90     SizeOfInfo            - A pointer to the size, in bytes, of the Info buffer.
91 
92   Returns:
93     EFI_SUCCESS           - Mode information returned.
94     EFI_BUFFER_TOO_SMALL  - The Info buffer was too small.
95     EFI_DEVICE_ERROR      - A hardware error occurred trying to retrieve the video mode.
96     EFI_NOT_STARTED       - Video display is not initialized. Call SetMode ()
97     EFI_INVALID_PARAMETER - One of the input args was NULL.
98 
99 --*/
100 {
101   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private;
102 
103   Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
104 
105   if (Private->HardwareNeedsStarting) {
106     return EFI_NOT_STARTED;
107   }
108 
109   if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
110     return EFI_INVALID_PARAMETER;
111   }
112 
113   *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
114   if (*Info == NULL) {
115     return EFI_OUT_OF_RESOURCES;
116   }
117 
118   *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
119 
120   (*Info)->HorizontalResolution = Private->ModeData[ModeNumber].HorizontalResolution;
121   (*Info)->VerticalResolution   = Private->ModeData[ModeNumber].VerticalResolution;
122   CirrusLogic5430CompleteModeInfo (*Info);
123 
124   return EFI_SUCCESS;
125 }
126 
127 EFI_STATUS
128 EFIAPI
CirrusLogic5430GraphicsOutputSetMode(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN UINT32 ModeNumber)129 CirrusLogic5430GraphicsOutputSetMode (
130   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
131   IN  UINT32                       ModeNumber
132   )
133 /*++
134 
135 Routine Description:
136 
137   Graphics Output protocol interface to set video mode
138 
139   Arguments:
140     This             - Protocol instance pointer.
141     ModeNumber       - The mode number to be set.
142 
143   Returns:
144     EFI_SUCCESS      - Graphics mode was changed.
145     EFI_DEVICE_ERROR - The device had an error and could not complete the request.
146     EFI_UNSUPPORTED  - ModeNumber is not supported by this device.
147 
148 --*/
149 {
150   CIRRUS_LOGIC_5430_PRIVATE_DATA    *Private;
151   CIRRUS_LOGIC_5430_MODE_DATA       *ModeData;
152 
153   Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
154 
155   if (ModeNumber >= This->Mode->MaxMode) {
156     return EFI_UNSUPPORTED;
157   }
158 
159   ModeData = &Private->ModeData[ModeNumber];
160 
161   if (Private->LineBuffer) {
162     gBS->FreePool (Private->LineBuffer);
163   }
164 
165   Private->LineBuffer = NULL;
166   Private->LineBuffer = AllocatePool (ModeData->HorizontalResolution);
167   if (Private->LineBuffer == NULL) {
168     return EFI_OUT_OF_RESOURCES;
169   }
170 
171   InitializeGraphicsMode (Private, &CirrusLogic5430VideoModes[ModeData->ModeNumber]);
172 
173   This->Mode->Mode = ModeNumber;
174   This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
175   This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
176   This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
177 
178   CirrusLogic5430CompleteModeData (Private, This->Mode);
179 
180   Private->HardwareNeedsStarting  = FALSE;
181 
182   return EFI_SUCCESS;
183 }
184 
185 EFI_STATUS
186 EFIAPI
CirrusLogic5430GraphicsOutputBlt(IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL * BltBuffer,OPTIONAL IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,IN UINTN SourceX,IN UINTN SourceY,IN UINTN DestinationX,IN UINTN DestinationY,IN UINTN Width,IN UINTN Height,IN UINTN Delta)187 CirrusLogic5430GraphicsOutputBlt (
188   IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
189   IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL         *BltBuffer, OPTIONAL
190   IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION     BltOperation,
191   IN  UINTN                                 SourceX,
192   IN  UINTN                                 SourceY,
193   IN  UINTN                                 DestinationX,
194   IN  UINTN                                 DestinationY,
195   IN  UINTN                                 Width,
196   IN  UINTN                                 Height,
197   IN  UINTN                                 Delta
198   )
199 /*++
200 
201 Routine Description:
202 
203   Graphics Output protocol instance to block transfer for CirrusLogic device
204 
205 Arguments:
206 
207   This          - Pointer to Graphics Output protocol instance
208   BltBuffer     - The data to transfer to screen
209   BltOperation  - The operation to perform
210   SourceX       - The X coordinate of the source for BltOperation
211   SourceY       - The Y coordinate of the source for BltOperation
212   DestinationX  - The X coordinate of the destination for BltOperation
213   DestinationY  - The Y coordinate of the destination for BltOperation
214   Width         - The width of a rectangle in the blt rectangle in pixels
215   Height        - The height of a rectangle in the blt rectangle in pixels
216   Delta         - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
217                   If a Delta of 0 is used, the entire BltBuffer will be operated on.
218                   If a subrectangle of the BltBuffer is used, then Delta represents
219                   the number of bytes in a row of the BltBuffer.
220 
221 Returns:
222 
223   EFI_INVALID_PARAMETER - Invalid parameter passed in
224   EFI_SUCCESS - Blt operation success
225 
226 --*/
227 {
228   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private;
229   EFI_TPL                         OriginalTPL;
230   UINTN                           DstY;
231   UINTN                           SrcY;
232   EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *Blt;
233   UINTN                           X;
234   UINT8                           Pixel;
235   UINT32                          WidePixel;
236   UINTN                           ScreenWidth;
237   UINTN                           Offset;
238   UINTN                           SourceOffset;
239   UINT32                          CurrentMode;
240 
241   Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
242 
243   if ((UINT32)BltOperation >= EfiGraphicsOutputBltOperationMax) {
244     return EFI_INVALID_PARAMETER;
245   }
246 
247   if (Width == 0 || Height == 0) {
248     return EFI_INVALID_PARAMETER;
249   }
250 
251   //
252   // If Delta is zero, then the entire BltBuffer is being used, so Delta
253   // is the number of bytes in each row of BltBuffer.  Since BltBuffer is Width pixels size,
254   // the number of bytes in each row can be computed.
255   //
256   if (Delta == 0) {
257     Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
258   }
259 
260   //
261   // We need to fill the Virtual Screen buffer with the blt data.
262   // The virtual screen is upside down, as the first row is the bootom row of
263   // the image.
264   //
265 
266   CurrentMode = This->Mode->Mode;
267   //
268   // Make sure the SourceX, SourceY, DestinationX, DestinationY, Width, and Height parameters
269   // are valid for the operation and the current screen geometry.
270   //
271   if (BltOperation == EfiBltVideoToBltBuffer) {
272     //
273     // Video to BltBuffer: Source is Video, destination is BltBuffer
274     //
275     if (SourceY + Height > Private->ModeData[CurrentMode].VerticalResolution) {
276       return EFI_INVALID_PARAMETER;
277     }
278 
279     if (SourceX + Width > Private->ModeData[CurrentMode].HorizontalResolution) {
280       return EFI_INVALID_PARAMETER;
281     }
282   } else {
283     //
284     // BltBuffer to Video: Source is BltBuffer, destination is Video
285     //
286     if (DestinationY + Height > Private->ModeData[CurrentMode].VerticalResolution) {
287       return EFI_INVALID_PARAMETER;
288     }
289 
290     if (DestinationX + Width > Private->ModeData[CurrentMode].HorizontalResolution) {
291       return EFI_INVALID_PARAMETER;
292     }
293   }
294   //
295   // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
296   // We would not want a timer based event (Cursor, ...) to come in while we are
297   // doing this operation.
298   //
299   OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
300 
301   switch (BltOperation) {
302   case EfiBltVideoToBltBuffer:
303     //
304     // Video to BltBuffer: Source is Video, destination is BltBuffer
305     //
306     for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
307 
308       Offset = (SrcY * Private->ModeData[CurrentMode].HorizontalResolution) + SourceX;
309       if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
310         Private->PciIo->Mem.Read (
311                               Private->PciIo,
312                               EfiPciIoWidthUint32,
313                               0,
314                               Offset,
315                               Width >> 2,
316                               Private->LineBuffer
317                               );
318       } else {
319         Private->PciIo->Mem.Read (
320                               Private->PciIo,
321                               EfiPciIoWidthUint8,
322                               0,
323                               Offset,
324                               Width,
325                               Private->LineBuffer
326                               );
327       }
328 
329       for (X = 0; X < Width; X++) {
330         Blt         = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) ((UINT8 *) BltBuffer + (DstY * Delta) + (DestinationX + X) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
331 
332         Blt->Red    = PIXEL_TO_RED_BYTE (Private->LineBuffer[X]);
333         Blt->Green  = PIXEL_TO_GREEN_BYTE (Private->LineBuffer[X]);
334         Blt->Blue   = PIXEL_TO_BLUE_BYTE (Private->LineBuffer[X]);
335       }
336     }
337     break;
338 
339   case EfiBltVideoToVideo:
340     //
341     // Perform hardware acceleration for Video to Video operations
342     //
343     ScreenWidth   = Private->ModeData[CurrentMode].HorizontalResolution;
344     SourceOffset  = (SourceY * Private->ModeData[CurrentMode].HorizontalResolution) + (SourceX);
345     Offset        = (DestinationY * Private->ModeData[CurrentMode].HorizontalResolution) + (DestinationX);
346 
347     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0000);
348     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0010);
349     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0012);
350     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0014);
351 
352     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0001);
353     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0011);
354     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0013);
355     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0015);
356 
357     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((Width << 8) & 0xff00) | 0x20));
358     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((Width & 0xff00) | 0x21));
359     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((Height << 8) & 0xff00) | 0x22));
360     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((Height & 0xff00) | 0x23));
361     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((ScreenWidth << 8) & 0xff00) | 0x24));
362     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((ScreenWidth & 0xff00) | 0x25));
363     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((ScreenWidth << 8) & 0xff00) | 0x26));
364     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((ScreenWidth & 0xff00) | 0x27));
365     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) << 8) & 0xff00) | 0x28));
366     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) >> 0) & 0xff00) | 0x29));
367     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) >> 8) & 0xff00) | 0x2a));
368     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) << 8) & 0xff00) | 0x2c));
369     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) >> 0) & 0xff00) | 0x2d));
370     outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) >> 8) & 0xff00) | 0x2e));
371     outw (Private, GRAPH_ADDRESS_REGISTER, 0x002f);
372     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0030);
373     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0d32);
374     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0033);
375     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0034);
376     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0035);
377 
378     outw (Private, GRAPH_ADDRESS_REGISTER, 0x0231);
379 
380     outb (Private, GRAPH_ADDRESS_REGISTER, 0x31);
381     while ((inb (Private, GRAPH_DATA_REGISTER) & 0x01) == 0x01)
382       ;
383     break;
384 
385   case EfiBltVideoFill:
386     Blt       = BltBuffer;
387     Pixel     = RGB_BYTES_TO_PIXEL (Blt->Red, Blt->Green, Blt->Blue);
388     WidePixel = (Pixel << 8) | Pixel;
389     WidePixel = (WidePixel << 16) | WidePixel;
390 
391     if (DestinationX == 0 && Width == Private->ModeData[CurrentMode].HorizontalResolution) {
392       Offset = DestinationY * Private->ModeData[CurrentMode].HorizontalResolution;
393       if (((Offset & 0x03) == 0) && (((Width * Height) & 0x03) == 0)) {
394         Private->PciIo->Mem.Write (
395                               Private->PciIo,
396                               EfiPciIoWidthFillUint32,
397                               0,
398                               Offset,
399                               (Width * Height) >> 2,
400                               &WidePixel
401                               );
402       } else {
403         Private->PciIo->Mem.Write (
404                               Private->PciIo,
405                               EfiPciIoWidthFillUint8,
406                               0,
407                               Offset,
408                               Width * Height,
409                               &Pixel
410                               );
411       }
412     } else {
413       for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
414         Offset = (DstY * Private->ModeData[CurrentMode].HorizontalResolution) + DestinationX;
415         if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
416           Private->PciIo->Mem.Write (
417                                 Private->PciIo,
418                                 EfiPciIoWidthFillUint32,
419                                 0,
420                                 Offset,
421                                 Width >> 2,
422                                 &WidePixel
423                                 );
424         } else {
425           Private->PciIo->Mem.Write (
426                                 Private->PciIo,
427                                 EfiPciIoWidthFillUint8,
428                                 0,
429                                 Offset,
430                                 Width,
431                                 &Pixel
432                                 );
433         }
434       }
435     }
436     break;
437 
438   case EfiBltBufferToVideo:
439     for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
440 
441       for (X = 0; X < Width; X++) {
442         Blt =
443           (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (
444               (UINT8 *) BltBuffer +
445               (SrcY * Delta) +
446               ((SourceX + X) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))
447             );
448         Private->LineBuffer[X]  =
449           RGB_BYTES_TO_PIXEL (Blt->Red, Blt->Green, Blt->Blue);
450       }
451 
452       Offset = (DstY * Private->ModeData[CurrentMode].HorizontalResolution) + DestinationX;
453 
454       if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
455         Private->PciIo->Mem.Write (
456                               Private->PciIo,
457                               EfiPciIoWidthUint32,
458                               0,
459                               Offset,
460                               Width >> 2,
461                               Private->LineBuffer
462                               );
463       } else {
464         Private->PciIo->Mem.Write (
465                               Private->PciIo,
466                               EfiPciIoWidthUint8,
467                               0,
468                               Offset,
469                               Width,
470                               Private->LineBuffer
471                               );
472       }
473     }
474     break;
475   default:
476     ASSERT (FALSE);
477   }
478 
479   gBS->RestoreTPL (OriginalTPL);
480 
481   return EFI_SUCCESS;
482 }
483 
484 EFI_STATUS
CirrusLogic5430GraphicsOutputConstructor(CIRRUS_LOGIC_5430_PRIVATE_DATA * Private)485 CirrusLogic5430GraphicsOutputConstructor (
486   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private
487   )
488 {
489   EFI_STATUS                   Status;
490   EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
491 
492 
493   GraphicsOutput            = &Private->GraphicsOutput;
494   GraphicsOutput->QueryMode = CirrusLogic5430GraphicsOutputQueryMode;
495   GraphicsOutput->SetMode   = CirrusLogic5430GraphicsOutputSetMode;
496   GraphicsOutput->Blt       = CirrusLogic5430GraphicsOutputBlt;
497 
498   //
499   // Initialize the private data
500   //
501   Status = gBS->AllocatePool (
502                   EfiBootServicesData,
503                   sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
504                   (VOID **) &Private->GraphicsOutput.Mode
505                   );
506   if (EFI_ERROR (Status)) {
507     return Status;
508   }
509   Status = gBS->AllocatePool (
510                   EfiBootServicesData,
511                   sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
512                   (VOID **) &Private->GraphicsOutput.Mode->Info
513                   );
514   if (EFI_ERROR (Status)) {
515     return Status;
516   }
517   Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;
518   Private->GraphicsOutput.Mode->Mode    = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
519   Private->HardwareNeedsStarting        = TRUE;
520   Private->LineBuffer                   = NULL;
521 
522   //
523   // Initialize the hardware
524   //
525   GraphicsOutput->SetMode (GraphicsOutput, 0);
526   ASSERT (Private->GraphicsOutput.Mode->Mode < CIRRUS_LOGIC_5430_MODE_COUNT);
527   DrawLogo (
528     Private,
529     Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,
530     Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution
531     );
532 
533   return EFI_SUCCESS;
534 }
535 
536 EFI_STATUS
CirrusLogic5430GraphicsOutputDestructor(CIRRUS_LOGIC_5430_PRIVATE_DATA * Private)537 CirrusLogic5430GraphicsOutputDestructor (
538   CIRRUS_LOGIC_5430_PRIVATE_DATA  *Private
539   )
540 /*++
541 
542 Routine Description:
543 
544 Arguments:
545 
546 Returns:
547 
548   None
549 
550 --*/
551 {
552   if (Private->GraphicsOutput.Mode != NULL) {
553     if (Private->GraphicsOutput.Mode->Info != NULL) {
554       gBS->FreePool (Private->GraphicsOutput.Mode->Info);
555     }
556     gBS->FreePool (Private->GraphicsOutput.Mode);
557   }
558 
559   return EFI_SUCCESS;
560 }
561 
562 
563