2 Copyright (c) 2007, Intel Corporation
3 All rights reserved. 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"
25 // Graphics Output Protocol Member Functions
29 CirrusLogic5430GraphicsOutputQueryMode (
30 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
32 OUT UINTN
*SizeOfInfo
,
33 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
39 Graphics Output protocol interface to query video mode
42 This - Protocol instance pointer.
43 ModeNumber - The mode number to return information on.
44 Info - Caller allocated buffer that returns information about ModeNumber.
45 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
48 EFI_SUCCESS - Mode information returned.
49 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
50 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
51 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
52 EFI_INVALID_PARAMETER - One of the input args was NULL.
56 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
;
58 Private
= CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
60 if (Private
->HardwareNeedsStarting
) {
61 return EFI_NOT_STARTED
;
64 if (Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
65 return EFI_INVALID_PARAMETER
;
68 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
70 return EFI_OUT_OF_RESOURCES
;
73 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
76 (*Info
)->HorizontalResolution
= Private
->ModeData
[ModeNumber
].HorizontalResolution
;
77 (*Info
)->VerticalResolution
= Private
->ModeData
[ModeNumber
].VerticalResolution
;
78 (*Info
)->PixelFormat
= PixelBltOnly
;
79 (*Info
)->PixelsPerScanLine
= (*Info
)->HorizontalResolution
;
86 CirrusLogic5430GraphicsOutputSetMode (
87 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
94 Graphics Output protocol interface to set video mode
97 This - Protocol instance pointer.
98 ModeNumber - The mode number to be set.
101 EFI_SUCCESS - Graphics mode was changed.
102 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
103 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
107 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
;
108 CIRRUS_LOGIC_5430_MODE_DATA
*ModeData
;
110 Private
= CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
112 if (ModeNumber
>= This
->Mode
->MaxMode
) {
113 return EFI_UNSUPPORTED
;
116 ModeData
= &Private
->ModeData
[ModeNumber
];
118 if (Private
->LineBuffer
) {
119 gBS
->FreePool (Private
->LineBuffer
);
122 Private
->LineBuffer
= NULL
;
123 Private
->LineBuffer
= AllocatePool (ModeData
->HorizontalResolution
);
124 if (Private
->LineBuffer
== NULL
) {
125 return EFI_OUT_OF_RESOURCES
;
128 InitializeGraphicsMode (Private
, &CirrusLogic5430VideoModes
[ModeData
->ModeNumber
]);
130 This
->Mode
->Mode
= ModeNumber
;
131 This
->Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
132 This
->Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
133 This
->Mode
->Info
->PixelFormat
= PixelBltOnly
;
134 This
->Mode
->Info
->PixelsPerScanLine
= ModeData
->HorizontalResolution
;
135 This
->Mode
->SizeOfInfo
= sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
137 This
->Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)NULL
;
138 This
->Mode
->FrameBufferSize
= 0;
140 Private
->HardwareNeedsStarting
= FALSE
;
147 CirrusLogic5430GraphicsOutputBlt (
148 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
149 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
150 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
153 IN UINTN DestinationX
,
154 IN UINTN DestinationY
,
163 Graphics Output protocol instance to block transfer for CirrusLogic device
167 This - Pointer to Graphics Output protocol instance
168 BltBuffer - The data to transfer to screen
169 BltOperation - The operation to perform
170 SourceX - The X coordinate of the source for BltOperation
171 SourceY - The Y coordinate of the source for BltOperation
172 DestinationX - The X coordinate of the destination for BltOperation
173 DestinationY - The Y coordinate of the destination for BltOperation
174 Width - The width of a rectangle in the blt rectangle in pixels
175 Height - The height of a rectangle in the blt rectangle in pixels
176 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
177 If a Delta of 0 is used, the entire BltBuffer will be operated on.
178 If a subrectangle of the BltBuffer is used, then Delta represents
179 the number of bytes in a row of the BltBuffer.
183 EFI_INVALID_PARAMETER - Invalid parameter passed in
184 EFI_SUCCESS - Blt operation success
188 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
;
192 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
201 Private
= CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
203 if ((BltOperation
< 0) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
204 return EFI_INVALID_PARAMETER
;
207 if (Width
== 0 || Height
== 0) {
208 return EFI_INVALID_PARAMETER
;
212 // If Delta is zero, then the entire BltBuffer is being used, so Delta
213 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
214 // the number of bytes in each row can be computed.
217 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
221 // We need to fill the Virtual Screen buffer with the blt data.
222 // The virtual screen is upside down, as the first row is the bootom row of
226 CurrentMode
= This
->Mode
->Mode
;
228 // Make sure the SourceX, SourceY, DestinationX, DestinationY, Width, and Height parameters
229 // are valid for the operation and the current screen geometry.
231 if (BltOperation
== EfiBltVideoToBltBuffer
) {
233 // Video to BltBuffer: Source is Video, destination is BltBuffer
235 if (SourceY
+ Height
> Private
->ModeData
[CurrentMode
].VerticalResolution
) {
236 return EFI_INVALID_PARAMETER
;
239 if (SourceX
+ Width
> Private
->ModeData
[CurrentMode
].HorizontalResolution
) {
240 return EFI_INVALID_PARAMETER
;
244 // BltBuffer to Video: Source is BltBuffer, destination is Video
246 if (DestinationY
+ Height
> Private
->ModeData
[CurrentMode
].VerticalResolution
) {
247 return EFI_INVALID_PARAMETER
;
250 if (DestinationX
+ Width
> Private
->ModeData
[CurrentMode
].HorizontalResolution
) {
251 return EFI_INVALID_PARAMETER
;
255 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
256 // We would not want a timer based event (Cursor, ...) to come in while we are
257 // doing this operation.
259 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
261 switch (BltOperation
) {
262 case EfiBltVideoToBltBuffer
:
264 // Video to BltBuffer: Source is Video, destination is BltBuffer
266 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
268 Offset
= (SrcY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + SourceX
;
269 if (((Offset
& 0x03) == 0) && ((Width
& 0x03) == 0)) {
270 Private
->PciIo
->Mem
.Read (
279 Private
->PciIo
->Mem
.Read (
289 for (X
= 0; X
< Width
; X
++) {
290 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ (DstY
* Delta
) + (DestinationX
+ X
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
292 Blt
->Red
= (UINT8
) (Private
->LineBuffer
[X
] & 0xe0);
293 Blt
->Green
= (UINT8
) ((Private
->LineBuffer
[X
] & 0x1c) << 3);
294 Blt
->Blue
= (UINT8
) ((Private
->LineBuffer
[X
] & 0x03) << 6);
299 case EfiBltVideoToVideo
:
301 // Perform hardware acceleration for Video to Video operations
303 ScreenWidth
= Private
->ModeData
[CurrentMode
].HorizontalResolution
;
304 SourceOffset
= (SourceY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + (SourceX
);
305 Offset
= (DestinationY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + (DestinationX
);
307 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0000);
308 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0010);
309 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0012);
310 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0014);
312 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0001);
313 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0011);
314 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0013);
315 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0015);
317 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) (((Width
<< 8) & 0xff00) | 0x20));
318 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((Width
& 0xff00) | 0x21));
319 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) (((Height
<< 8) & 0xff00) | 0x22));
320 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((Height
& 0xff00) | 0x23));
321 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) (((ScreenWidth
<< 8) & 0xff00) | 0x24));
322 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((ScreenWidth
& 0xff00) | 0x25));
323 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) (((ScreenWidth
<< 8) & 0xff00) | 0x26));
324 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((ScreenWidth
& 0xff00) | 0x27));
325 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((Offset
) << 8) & 0xff00) | 0x28));
326 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((Offset
) >> 0) & 0xff00) | 0x29));
327 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((Offset
) >> 8) & 0xff00) | 0x2a));
328 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((SourceOffset
) << 8) & 0xff00) | 0x2c));
329 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((SourceOffset
) >> 0) & 0xff00) | 0x2d));
330 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((SourceOffset
) >> 8) & 0xff00) | 0x2e));
331 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x002f);
332 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0030);
333 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0d32);
334 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0033);
335 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0034);
336 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0035);
338 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0231);
340 outb (Private
, GRAPH_ADDRESS_REGISTER
, 0x31);
341 while ((inb (Private
, GRAPH_DATA_REGISTER
) & 0x01) == 0x01)
345 case EfiBltVideoFill
:
347 Pixel
= (UINT8
) ((Blt
->Red
& 0xe0) | ((Blt
->Green
>> 3) & 0x1c) | ((Blt
->Blue
>> 6) & 0x03));
348 WidePixel
= (Pixel
<< 8) | Pixel
;
349 WidePixel
= (WidePixel
<< 16) | WidePixel
;
351 if (DestinationX
== 0 && Width
== Private
->ModeData
[CurrentMode
].HorizontalResolution
) {
352 Offset
= DestinationY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
;
353 if (((Offset
& 0x03) == 0) && (((Width
* Height
) & 0x03) == 0)) {
354 Private
->PciIo
->Mem
.Write (
356 EfiPciIoWidthFillUint32
,
359 (Width
* Height
) >> 2,
363 Private
->PciIo
->Mem
.Write (
365 EfiPciIoWidthFillUint8
,
373 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
374 Offset
= (DstY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + DestinationX
;
375 if (((Offset
& 0x03) == 0) && ((Width
& 0x03) == 0)) {
376 Private
->PciIo
->Mem
.Write (
378 EfiPciIoWidthFillUint32
,
385 Private
->PciIo
->Mem
.Write (
387 EfiPciIoWidthFillUint8
,
398 case EfiBltBufferToVideo
:
399 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
401 for (X
= 0; X
< Width
; X
++) {
402 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ (SrcY
* Delta
) + (SourceX
+ X
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
403 Private
->LineBuffer
[X
] = (UINT8
) ((Blt
->Red
& 0xe0) | ((Blt
->Green
>> 3) & 0x1c) | ((Blt
->Blue
>> 6) & 0x03));
406 Offset
= (DstY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + DestinationX
;
408 if (((Offset
& 0x03) == 0) && ((Width
& 0x03) == 0)) {
409 Private
->PciIo
->Mem
.Write (
418 Private
->PciIo
->Mem
.Write (
433 gBS
->RestoreTPL (OriginalTPL
);
439 CirrusLogic5430GraphicsOutputConstructor (
440 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
444 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
447 GraphicsOutput
= &Private
->GraphicsOutput
;
448 GraphicsOutput
->QueryMode
= CirrusLogic5430GraphicsOutputQueryMode
;
449 GraphicsOutput
->SetMode
= CirrusLogic5430GraphicsOutputSetMode
;
450 GraphicsOutput
->Blt
= CirrusLogic5430GraphicsOutputBlt
;
453 // Initialize the private data
455 Status
= gBS
->AllocatePool (
457 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
458 (VOID
**) &Private
->GraphicsOutput
.Mode
460 if (EFI_ERROR (Status
)) {
463 Status
= gBS
->AllocatePool (
465 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
466 (VOID
**) &Private
->GraphicsOutput
.Mode
->Info
468 if (EFI_ERROR (Status
)) {
471 Private
->GraphicsOutput
.Mode
->MaxMode
= (UINT32
) Private
->MaxMode
;
472 Private
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
473 Private
->HardwareNeedsStarting
= TRUE
;
474 Private
->LineBuffer
= NULL
;
477 // Initialize the hardware
479 GraphicsOutput
->SetMode (GraphicsOutput
, 0);
482 Private
->ModeData
[Private
->GraphicsOutput
.Mode
->Mode
].HorizontalResolution
,
483 Private
->ModeData
[Private
->GraphicsOutput
.Mode
->Mode
].VerticalResolution
490 CirrusLogic5430GraphicsOutputDestructor (
491 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
505 if (Private
->GraphicsOutput
.Mode
!= NULL
) {
506 if (Private
->GraphicsOutput
.Mode
->Info
!= NULL
) {
507 gBS
->FreePool (Private
->GraphicsOutput
.Mode
->Info
);
509 gBS
->FreePool (Private
->GraphicsOutput
.Mode
);