2 Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>
3 SPDX-License-Identifier: BSD-2-Clause-Patent
7 UefiCirrusLogic5430GraphicsOutput.c
11 This file produces the graphics abstration of Graphics Output Protocol. It is called by
12 CirrusLogic5430.c file which deals with the EFI 1.1 driver model.
13 This file just does graphics.
16 #include "CirrusLogic5430.h"
17 #include <IndustryStandard/Acpi.h>
22 CirrusLogic5430CompleteModeInfo (
23 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
27 Info
->PixelFormat
= PixelBitMask
;
28 Info
->PixelInformation
.RedMask
= PIXEL_RED_MASK
;
29 Info
->PixelInformation
.GreenMask
= PIXEL_GREEN_MASK
;
30 Info
->PixelInformation
.BlueMask
= PIXEL_BLUE_MASK
;
31 Info
->PixelInformation
.ReservedMask
= 0;
32 Info
->PixelsPerScanLine
= Info
->HorizontalResolution
;
38 CirrusLogic5430CompleteModeData (
39 IN CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
,
40 OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*Mode
43 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
44 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*FrameBufDesc
;
47 CirrusLogic5430CompleteModeInfo (Info
);
49 Private
->PciIo
->GetBarAttributes (
53 (VOID
**) &FrameBufDesc
56 Mode
->FrameBufferBase
= FrameBufDesc
->AddrRangeMin
;
57 Mode
->FrameBufferSize
= Info
->HorizontalResolution
* Info
->VerticalResolution
;
64 // Graphics Output Protocol Member Functions
68 CirrusLogic5430GraphicsOutputQueryMode (
69 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
71 OUT UINTN
*SizeOfInfo
,
72 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
78 Graphics Output protocol interface to query video mode
81 This - Protocol instance pointer.
82 ModeNumber - The mode number to return information on.
83 Info - Caller allocated buffer that returns information about ModeNumber.
84 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
87 EFI_SUCCESS - Mode information returned.
88 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
89 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
90 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
91 EFI_INVALID_PARAMETER - One of the input args was NULL.
95 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
;
97 Private
= CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
99 if (Private
->HardwareNeedsStarting
) {
100 return EFI_NOT_STARTED
;
103 if (Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
104 return EFI_INVALID_PARAMETER
;
107 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
109 return EFI_OUT_OF_RESOURCES
;
112 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
114 (*Info
)->HorizontalResolution
= Private
->ModeData
[ModeNumber
].HorizontalResolution
;
115 (*Info
)->VerticalResolution
= Private
->ModeData
[ModeNumber
].VerticalResolution
;
116 CirrusLogic5430CompleteModeInfo (*Info
);
123 CirrusLogic5430GraphicsOutputSetMode (
124 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
131 Graphics Output protocol interface to set video mode
134 This - Protocol instance pointer.
135 ModeNumber - The mode number to be set.
138 EFI_SUCCESS - Graphics mode was changed.
139 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
140 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
144 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
;
145 CIRRUS_LOGIC_5430_MODE_DATA
*ModeData
;
147 Private
= CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
149 if (ModeNumber
>= This
->Mode
->MaxMode
) {
150 return EFI_UNSUPPORTED
;
153 ModeData
= &Private
->ModeData
[ModeNumber
];
155 if (Private
->LineBuffer
) {
156 gBS
->FreePool (Private
->LineBuffer
);
159 Private
->LineBuffer
= NULL
;
160 Private
->LineBuffer
= AllocatePool (ModeData
->HorizontalResolution
);
161 if (Private
->LineBuffer
== NULL
) {
162 return EFI_OUT_OF_RESOURCES
;
165 InitializeGraphicsMode (Private
, &CirrusLogic5430VideoModes
[ModeData
->ModeNumber
]);
167 This
->Mode
->Mode
= ModeNumber
;
168 This
->Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
169 This
->Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
170 This
->Mode
->SizeOfInfo
= sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
172 CirrusLogic5430CompleteModeData (Private
, This
->Mode
);
174 Private
->HardwareNeedsStarting
= FALSE
;
181 CirrusLogic5430GraphicsOutputBlt (
182 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
183 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
184 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
187 IN UINTN DestinationX
,
188 IN UINTN DestinationY
,
197 Graphics Output protocol instance to block transfer for CirrusLogic device
201 This - Pointer to Graphics Output protocol instance
202 BltBuffer - The data to transfer to screen
203 BltOperation - The operation to perform
204 SourceX - The X coordinate of the source for BltOperation
205 SourceY - The Y coordinate of the source for BltOperation
206 DestinationX - The X coordinate of the destination for BltOperation
207 DestinationY - The Y coordinate of the destination for BltOperation
208 Width - The width of a rectangle in the blt rectangle in pixels
209 Height - The height of a rectangle in the blt rectangle in pixels
210 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
211 If a Delta of 0 is used, the entire BltBuffer will be operated on.
212 If a subrectangle of the BltBuffer is used, then Delta represents
213 the number of bytes in a row of the BltBuffer.
217 EFI_INVALID_PARAMETER - Invalid parameter passed in
218 EFI_SUCCESS - Blt operation success
222 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
;
226 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
235 Private
= CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
237 if ((UINT32
)BltOperation
>= EfiGraphicsOutputBltOperationMax
) {
238 return EFI_INVALID_PARAMETER
;
241 if (Width
== 0 || Height
== 0) {
242 return EFI_INVALID_PARAMETER
;
246 // If Delta is zero, then the entire BltBuffer is being used, so Delta
247 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
248 // the number of bytes in each row can be computed.
251 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
255 // We need to fill the Virtual Screen buffer with the blt data.
256 // The virtual screen is upside down, as the first row is the bootom row of
260 CurrentMode
= This
->Mode
->Mode
;
262 // Make sure the SourceX, SourceY, DestinationX, DestinationY, Width, and Height parameters
263 // are valid for the operation and the current screen geometry.
265 if (BltOperation
== EfiBltVideoToBltBuffer
) {
267 // Video to BltBuffer: Source is Video, destination is BltBuffer
269 if (SourceY
+ Height
> Private
->ModeData
[CurrentMode
].VerticalResolution
) {
270 return EFI_INVALID_PARAMETER
;
273 if (SourceX
+ Width
> Private
->ModeData
[CurrentMode
].HorizontalResolution
) {
274 return EFI_INVALID_PARAMETER
;
278 // BltBuffer to Video: Source is BltBuffer, destination is Video
280 if (DestinationY
+ Height
> Private
->ModeData
[CurrentMode
].VerticalResolution
) {
281 return EFI_INVALID_PARAMETER
;
284 if (DestinationX
+ Width
> Private
->ModeData
[CurrentMode
].HorizontalResolution
) {
285 return EFI_INVALID_PARAMETER
;
289 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
290 // We would not want a timer based event (Cursor, ...) to come in while we are
291 // doing this operation.
293 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
295 switch (BltOperation
) {
296 case EfiBltVideoToBltBuffer
:
298 // Video to BltBuffer: Source is Video, destination is BltBuffer
300 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
302 Offset
= (SrcY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + SourceX
;
303 if (((Offset
& 0x03) == 0) && ((Width
& 0x03) == 0)) {
304 Private
->PciIo
->Mem
.Read (
313 Private
->PciIo
->Mem
.Read (
323 for (X
= 0; X
< Width
; X
++) {
324 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ (DstY
* Delta
) + (DestinationX
+ X
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
326 Blt
->Red
= PIXEL_TO_RED_BYTE (Private
->LineBuffer
[X
]);
327 Blt
->Green
= PIXEL_TO_GREEN_BYTE (Private
->LineBuffer
[X
]);
328 Blt
->Blue
= PIXEL_TO_BLUE_BYTE (Private
->LineBuffer
[X
]);
333 case EfiBltVideoToVideo
:
335 // Perform hardware acceleration for Video to Video operations
337 ScreenWidth
= Private
->ModeData
[CurrentMode
].HorizontalResolution
;
338 SourceOffset
= (SourceY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + (SourceX
);
339 Offset
= (DestinationY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + (DestinationX
);
341 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0000);
342 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0010);
343 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0012);
344 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0014);
346 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0001);
347 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0011);
348 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0013);
349 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0015);
351 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) (((Width
<< 8) & 0xff00) | 0x20));
352 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((Width
& 0xff00) | 0x21));
353 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) (((Height
<< 8) & 0xff00) | 0x22));
354 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((Height
& 0xff00) | 0x23));
355 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) (((ScreenWidth
<< 8) & 0xff00) | 0x24));
356 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((ScreenWidth
& 0xff00) | 0x25));
357 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) (((ScreenWidth
<< 8) & 0xff00) | 0x26));
358 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((ScreenWidth
& 0xff00) | 0x27));
359 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((Offset
) << 8) & 0xff00) | 0x28));
360 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((Offset
) >> 0) & 0xff00) | 0x29));
361 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((Offset
) >> 8) & 0xff00) | 0x2a));
362 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((SourceOffset
) << 8) & 0xff00) | 0x2c));
363 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((SourceOffset
) >> 0) & 0xff00) | 0x2d));
364 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((SourceOffset
) >> 8) & 0xff00) | 0x2e));
365 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x002f);
366 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0030);
367 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0d32);
368 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0033);
369 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0034);
370 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0035);
372 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0231);
374 outb (Private
, GRAPH_ADDRESS_REGISTER
, 0x31);
375 while ((inb (Private
, GRAPH_DATA_REGISTER
) & 0x01) == 0x01)
379 case EfiBltVideoFill
:
381 Pixel
= RGB_BYTES_TO_PIXEL (Blt
->Red
, Blt
->Green
, Blt
->Blue
);
382 WidePixel
= (Pixel
<< 8) | Pixel
;
383 WidePixel
= (WidePixel
<< 16) | WidePixel
;
385 if (DestinationX
== 0 && Width
== Private
->ModeData
[CurrentMode
].HorizontalResolution
) {
386 Offset
= DestinationY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
;
387 if (((Offset
& 0x03) == 0) && (((Width
* Height
) & 0x03) == 0)) {
388 Private
->PciIo
->Mem
.Write (
390 EfiPciIoWidthFillUint32
,
393 (Width
* Height
) >> 2,
397 Private
->PciIo
->Mem
.Write (
399 EfiPciIoWidthFillUint8
,
407 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
408 Offset
= (DstY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + DestinationX
;
409 if (((Offset
& 0x03) == 0) && ((Width
& 0x03) == 0)) {
410 Private
->PciIo
->Mem
.Write (
412 EfiPciIoWidthFillUint32
,
419 Private
->PciIo
->Mem
.Write (
421 EfiPciIoWidthFillUint8
,
432 case EfiBltBufferToVideo
:
433 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
435 for (X
= 0; X
< Width
; X
++) {
437 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (
438 (UINT8
*) BltBuffer
+
440 ((SourceX
+ X
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))
442 Private
->LineBuffer
[X
] =
443 RGB_BYTES_TO_PIXEL (Blt
->Red
, Blt
->Green
, Blt
->Blue
);
446 Offset
= (DstY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + DestinationX
;
448 if (((Offset
& 0x03) == 0) && ((Width
& 0x03) == 0)) {
449 Private
->PciIo
->Mem
.Write (
458 Private
->PciIo
->Mem
.Write (
473 gBS
->RestoreTPL (OriginalTPL
);
479 CirrusLogic5430GraphicsOutputConstructor (
480 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
484 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
487 GraphicsOutput
= &Private
->GraphicsOutput
;
488 GraphicsOutput
->QueryMode
= CirrusLogic5430GraphicsOutputQueryMode
;
489 GraphicsOutput
->SetMode
= CirrusLogic5430GraphicsOutputSetMode
;
490 GraphicsOutput
->Blt
= CirrusLogic5430GraphicsOutputBlt
;
493 // Initialize the private data
495 Status
= gBS
->AllocatePool (
497 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
498 (VOID
**) &Private
->GraphicsOutput
.Mode
500 if (EFI_ERROR (Status
)) {
503 Status
= gBS
->AllocatePool (
505 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
506 (VOID
**) &Private
->GraphicsOutput
.Mode
->Info
508 if (EFI_ERROR (Status
)) {
511 Private
->GraphicsOutput
.Mode
->MaxMode
= (UINT32
) Private
->MaxMode
;
512 Private
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
513 Private
->HardwareNeedsStarting
= TRUE
;
514 Private
->LineBuffer
= NULL
;
517 // Initialize the hardware
519 GraphicsOutput
->SetMode (GraphicsOutput
, 0);
520 ASSERT (Private
->GraphicsOutput
.Mode
->Mode
< CIRRUS_LOGIC_5430_MODE_COUNT
);
523 Private
->ModeData
[Private
->GraphicsOutput
.Mode
->Mode
].HorizontalResolution
,
524 Private
->ModeData
[Private
->GraphicsOutput
.Mode
->Mode
].VerticalResolution
531 CirrusLogic5430GraphicsOutputDestructor (
532 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
546 if (Private
->GraphicsOutput
.Mode
!= NULL
) {
547 if (Private
->GraphicsOutput
.Mode
->Info
!= NULL
) {
548 gBS
->FreePool (Private
->GraphicsOutput
.Mode
->Info
);
550 gBS
->FreePool (Private
->GraphicsOutput
.Mode
);