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
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.
13 UefiCirrusLogic5430GraphicsOutput.c
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.
22 #include "CirrusLogic5430.h"
23 #include <IndustryStandard/Acpi.h>
28 CirrusLogic5430CompleteModeInfo (
29 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
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
;
44 CirrusLogic5430CompleteModeData (
45 IN CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
,
46 OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*Mode
49 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
50 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*FrameBufDesc
;
53 CirrusLogic5430CompleteModeInfo (Info
);
55 Private
->PciIo
->GetBarAttributes (
59 (VOID
**) &FrameBufDesc
62 Mode
->FrameBufferBase
= FrameBufDesc
->AddrRangeMin
;
63 Mode
->FrameBufferSize
= Info
->HorizontalResolution
* Info
->VerticalResolution
;
70 // Graphics Output Protocol Member Functions
74 CirrusLogic5430GraphicsOutputQueryMode (
75 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
77 OUT UINTN
*SizeOfInfo
,
78 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
84 Graphics Output protocol interface to query video mode
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.
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.
101 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
;
103 Private
= CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
105 if (Private
->HardwareNeedsStarting
) {
106 return EFI_NOT_STARTED
;
109 if (Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
110 return EFI_INVALID_PARAMETER
;
113 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
115 return EFI_OUT_OF_RESOURCES
;
118 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
120 (*Info
)->HorizontalResolution
= Private
->ModeData
[ModeNumber
].HorizontalResolution
;
121 (*Info
)->VerticalResolution
= Private
->ModeData
[ModeNumber
].VerticalResolution
;
122 CirrusLogic5430CompleteModeInfo (*Info
);
129 CirrusLogic5430GraphicsOutputSetMode (
130 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
137 Graphics Output protocol interface to set video mode
140 This - Protocol instance pointer.
141 ModeNumber - The mode number to be set.
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.
150 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
;
151 CIRRUS_LOGIC_5430_MODE_DATA
*ModeData
;
153 Private
= CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
155 if (ModeNumber
>= This
->Mode
->MaxMode
) {
156 return EFI_UNSUPPORTED
;
159 ModeData
= &Private
->ModeData
[ModeNumber
];
161 if (Private
->LineBuffer
) {
162 gBS
->FreePool (Private
->LineBuffer
);
165 Private
->LineBuffer
= NULL
;
166 Private
->LineBuffer
= AllocatePool (ModeData
->HorizontalResolution
);
167 if (Private
->LineBuffer
== NULL
) {
168 return EFI_OUT_OF_RESOURCES
;
171 InitializeGraphicsMode (Private
, &CirrusLogic5430VideoModes
[ModeData
->ModeNumber
]);
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
);
178 CirrusLogic5430CompleteModeData (Private
, This
->Mode
);
180 Private
->HardwareNeedsStarting
= FALSE
;
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
,
193 IN UINTN DestinationX
,
194 IN UINTN DestinationY
,
203 Graphics Output protocol instance to block transfer for CirrusLogic device
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.
223 EFI_INVALID_PARAMETER - Invalid parameter passed in
224 EFI_SUCCESS - Blt operation success
228 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
;
232 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
241 Private
= CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
243 if ((UINT32
)BltOperation
>= EfiGraphicsOutputBltOperationMax
) {
244 return EFI_INVALID_PARAMETER
;
247 if (Width
== 0 || Height
== 0) {
248 return EFI_INVALID_PARAMETER
;
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.
257 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
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
266 CurrentMode
= This
->Mode
->Mode
;
268 // Make sure the SourceX, SourceY, DestinationX, DestinationY, Width, and Height parameters
269 // are valid for the operation and the current screen geometry.
271 if (BltOperation
== EfiBltVideoToBltBuffer
) {
273 // Video to BltBuffer: Source is Video, destination is BltBuffer
275 if (SourceY
+ Height
> Private
->ModeData
[CurrentMode
].VerticalResolution
) {
276 return EFI_INVALID_PARAMETER
;
279 if (SourceX
+ Width
> Private
->ModeData
[CurrentMode
].HorizontalResolution
) {
280 return EFI_INVALID_PARAMETER
;
284 // BltBuffer to Video: Source is BltBuffer, destination is Video
286 if (DestinationY
+ Height
> Private
->ModeData
[CurrentMode
].VerticalResolution
) {
287 return EFI_INVALID_PARAMETER
;
290 if (DestinationX
+ Width
> Private
->ModeData
[CurrentMode
].HorizontalResolution
) {
291 return EFI_INVALID_PARAMETER
;
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.
299 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
301 switch (BltOperation
) {
302 case EfiBltVideoToBltBuffer
:
304 // Video to BltBuffer: Source is Video, destination is BltBuffer
306 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
308 Offset
= (SrcY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + SourceX
;
309 if (((Offset
& 0x03) == 0) && ((Width
& 0x03) == 0)) {
310 Private
->PciIo
->Mem
.Read (
319 Private
->PciIo
->Mem
.Read (
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
));
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
]);
339 case EfiBltVideoToVideo
:
341 // Perform hardware acceleration for Video to Video operations
343 ScreenWidth
= Private
->ModeData
[CurrentMode
].HorizontalResolution
;
344 SourceOffset
= (SourceY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + (SourceX
);
345 Offset
= (DestinationY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + (DestinationX
);
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);
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);
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);
378 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0231);
380 outb (Private
, GRAPH_ADDRESS_REGISTER
, 0x31);
381 while ((inb (Private
, GRAPH_DATA_REGISTER
) & 0x01) == 0x01)
385 case EfiBltVideoFill
:
387 Pixel
= RGB_BYTES_TO_PIXEL (Blt
->Red
, Blt
->Green
, Blt
->Blue
);
388 WidePixel
= (Pixel
<< 8) | Pixel
;
389 WidePixel
= (WidePixel
<< 16) | WidePixel
;
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 (
396 EfiPciIoWidthFillUint32
,
399 (Width
* Height
) >> 2,
403 Private
->PciIo
->Mem
.Write (
405 EfiPciIoWidthFillUint8
,
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 (
418 EfiPciIoWidthFillUint32
,
425 Private
->PciIo
->Mem
.Write (
427 EfiPciIoWidthFillUint8
,
438 case EfiBltBufferToVideo
:
439 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
441 for (X
= 0; X
< Width
; X
++) {
443 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (
444 (UINT8
*) BltBuffer
+
446 ((SourceX
+ X
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
))
448 Private
->LineBuffer
[X
] =
449 RGB_BYTES_TO_PIXEL (Blt
->Red
, Blt
->Green
, Blt
->Blue
);
452 Offset
= (DstY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + DestinationX
;
454 if (((Offset
& 0x03) == 0) && ((Width
& 0x03) == 0)) {
455 Private
->PciIo
->Mem
.Write (
464 Private
->PciIo
->Mem
.Write (
479 gBS
->RestoreTPL (OriginalTPL
);
485 CirrusLogic5430GraphicsOutputConstructor (
486 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
490 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
493 GraphicsOutput
= &Private
->GraphicsOutput
;
494 GraphicsOutput
->QueryMode
= CirrusLogic5430GraphicsOutputQueryMode
;
495 GraphicsOutput
->SetMode
= CirrusLogic5430GraphicsOutputSetMode
;
496 GraphicsOutput
->Blt
= CirrusLogic5430GraphicsOutputBlt
;
499 // Initialize the private data
501 Status
= gBS
->AllocatePool (
503 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
504 (VOID
**) &Private
->GraphicsOutput
.Mode
506 if (EFI_ERROR (Status
)) {
509 Status
= gBS
->AllocatePool (
511 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
512 (VOID
**) &Private
->GraphicsOutput
.Mode
->Info
514 if (EFI_ERROR (Status
)) {
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
;
523 // Initialize the hardware
525 GraphicsOutput
->SetMode (GraphicsOutput
, 0);
526 ASSERT (Private
->GraphicsOutput
.Mode
->Mode
< CIRRUS_LOGIC_5430_MODE_COUNT
);
529 Private
->ModeData
[Private
->GraphicsOutput
.Mode
->Mode
].HorizontalResolution
,
530 Private
->ModeData
[Private
->GraphicsOutput
.Mode
->Mode
].VerticalResolution
537 CirrusLogic5430GraphicsOutputDestructor (
538 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
552 if (Private
->GraphicsOutput
.Mode
!= NULL
) {
553 if (Private
->GraphicsOutput
.Mode
->Info
!= NULL
) {
554 gBS
->FreePool (Private
->GraphicsOutput
.Mode
->Info
);
556 gBS
->FreePool (Private
->GraphicsOutput
.Mode
);