3 Copyright (c) 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 UefiCirrusLogic5430GraphicsOutput.c
18 This file produces the graphics abstration of Graphics Output Protocol. It is called by
19 CirrusLogic5430.c file which deals with the EFI 1.1 driver model.
20 This file just does graphics.
24 #include "CirrusLogic5430.h"
27 // Graphics Output Protocol Member Functions
31 CirrusLogic5430GraphicsOutputQueryMode (
32 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
34 OUT UINTN
*SizeOfInfo
,
35 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
41 Graphics Output protocol interface to query video mode
44 This - Protocol instance pointer.
45 ModeNumber - The mode number to return information on.
46 Info - Caller allocated buffer that returns information about ModeNumber.
47 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
50 EFI_SUCCESS - Mode information returned.
51 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
52 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
53 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
54 EFI_INVALID_PARAMETER - One of the input args was NULL.
58 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
;
60 Private
= CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
62 if (Private
->HardwareNeedsStarting
) {
63 return EFI_NOT_STARTED
;
66 if (Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
67 return EFI_INVALID_PARAMETER
;
70 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
72 return EFI_OUT_OF_RESOURCES
;
75 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
78 (*Info
)->HorizontalResolution
= Private
->ModeData
[ModeNumber
].HorizontalResolution
;
79 (*Info
)->VerticalResolution
= Private
->ModeData
[ModeNumber
].VerticalResolution
;
80 (*Info
)->PixelFormat
= PixelBltOnly
;
81 (*Info
)->PixelsPerScanLine
= (*Info
)->HorizontalResolution
;
88 CirrusLogic5430GraphicsOutputSetMode (
89 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
96 Graphics Output protocol interface to set video mode
99 This - Protocol instance pointer.
100 ModeNumber - The mode number to be set.
103 EFI_SUCCESS - Graphics mode was changed.
104 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
105 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
109 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
;
110 CIRRUS_LOGIC_5430_MODE_DATA
*ModeData
;
112 Private
= CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
114 if (ModeNumber
>= This
->Mode
->MaxMode
) {
115 return EFI_UNSUPPORTED
;
118 ModeData
= &Private
->ModeData
[ModeNumber
];
120 if (Private
->LineBuffer
) {
121 gBS
->FreePool (Private
->LineBuffer
);
124 Private
->LineBuffer
= NULL
;
125 Private
->LineBuffer
= AllocatePool (ModeData
->HorizontalResolution
);
126 if (Private
->LineBuffer
== NULL
) {
127 return EFI_OUT_OF_RESOURCES
;
130 InitializeGraphicsMode (Private
, &CirrusLogic5430VideoModes
[ModeData
->ModeNumber
]);
132 This
->Mode
->Mode
= ModeNumber
;
133 This
->Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
134 This
->Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
135 This
->Mode
->Info
->PixelFormat
= PixelBltOnly
;
136 This
->Mode
->Info
->PixelsPerScanLine
= ModeData
->HorizontalResolution
;
137 This
->Mode
->SizeOfInfo
= sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
139 This
->Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)NULL
;
140 This
->Mode
->FrameBufferSize
= 0;
142 Private
->HardwareNeedsStarting
= FALSE
;
149 CirrusLogic5430GraphicsOutputBlt (
150 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
151 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
152 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
155 IN UINTN DestinationX
,
156 IN UINTN DestinationY
,
165 Graphics Output protocol instance to block transfer for CirrusLogic device
169 This - Pointer to Graphics Output protocol instance
170 BltBuffer - The data to transfer to screen
171 BltOperation - The operation to perform
172 SourceX - The X coordinate of the source for BltOperation
173 SourceY - The Y coordinate of the source for BltOperation
174 DestinationX - The X coordinate of the destination for BltOperation
175 DestinationY - The Y coordinate of the destination for BltOperation
176 Width - The width of a rectangle in the blt rectangle in pixels
177 Height - The height of a rectangle in the blt rectangle in pixels
178 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
179 If a Delta of 0 is used, the entire BltBuffer will be operated on.
180 If a subrectangle of the BltBuffer is used, then Delta represents
181 the number of bytes in a row of the BltBuffer.
185 EFI_INVALID_PARAMETER - Invalid parameter passed in
186 EFI_SUCCESS - Blt operation success
190 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
;
194 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
203 Private
= CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
205 if ((BltOperation
< 0) || (BltOperation
>= EfiGraphicsOutputBltOperationMax
)) {
206 return EFI_INVALID_PARAMETER
;
209 if (Width
== 0 || Height
== 0) {
210 return EFI_INVALID_PARAMETER
;
214 // If Delta is zero, then the entire BltBuffer is being used, so Delta
215 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
216 // the number of bytes in each row can be computed.
219 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
223 // We need to fill the Virtual Screen buffer with the blt data.
224 // The virtual screen is upside down, as the first row is the bootom row of
228 CurrentMode
= This
->Mode
->Mode
;
230 // Make sure the SourceX, SourceY, DestinationX, DestinationY, Width, and Height parameters
231 // are valid for the operation and the current screen geometry.
233 if (BltOperation
== EfiBltVideoToBltBuffer
) {
235 // Video to BltBuffer: Source is Video, destination is BltBuffer
237 if (SourceY
+ Height
> Private
->ModeData
[CurrentMode
].VerticalResolution
) {
238 return EFI_INVALID_PARAMETER
;
241 if (SourceX
+ Width
> Private
->ModeData
[CurrentMode
].HorizontalResolution
) {
242 return EFI_INVALID_PARAMETER
;
246 // BltBuffer to Video: Source is BltBuffer, destination is Video
248 if (DestinationY
+ Height
> Private
->ModeData
[CurrentMode
].VerticalResolution
) {
249 return EFI_INVALID_PARAMETER
;
252 if (DestinationX
+ Width
> Private
->ModeData
[CurrentMode
].HorizontalResolution
) {
253 return EFI_INVALID_PARAMETER
;
257 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
258 // We would not want a timer based event (Cursor, ...) to come in while we are
259 // doing this operation.
261 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
263 switch (BltOperation
) {
264 case EfiBltVideoToBltBuffer
:
266 // Video to BltBuffer: Source is Video, destination is BltBuffer
268 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
270 Offset
= (SrcY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + SourceX
;
271 if (((Offset
& 0x03) == 0) && ((Width
& 0x03) == 0)) {
272 Private
->PciIo
->Mem
.Read (
281 Private
->PciIo
->Mem
.Read (
291 for (X
= 0; X
< Width
; X
++) {
292 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ (DstY
* Delta
) + (DestinationX
+ X
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
294 Blt
->Red
= (UINT8
) (Private
->LineBuffer
[X
] & 0xe0);
295 Blt
->Green
= (UINT8
) ((Private
->LineBuffer
[X
] & 0x1c) << 3);
296 Blt
->Blue
= (UINT8
) ((Private
->LineBuffer
[X
] & 0x03) << 6);
301 case EfiBltVideoToVideo
:
303 // Perform hardware acceleration for Video to Video operations
305 ScreenWidth
= Private
->ModeData
[CurrentMode
].HorizontalResolution
;
306 SourceOffset
= (SourceY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + (SourceX
);
307 Offset
= (DestinationY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + (DestinationX
);
309 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0000);
310 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0010);
311 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0012);
312 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0014);
314 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0001);
315 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0011);
316 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0013);
317 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0015);
319 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) (((Width
<< 8) & 0xff00) | 0x20));
320 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((Width
& 0xff00) | 0x21));
321 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) (((Height
<< 8) & 0xff00) | 0x22));
322 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((Height
& 0xff00) | 0x23));
323 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) (((ScreenWidth
<< 8) & 0xff00) | 0x24));
324 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((ScreenWidth
& 0xff00) | 0x25));
325 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) (((ScreenWidth
<< 8) & 0xff00) | 0x26));
326 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((ScreenWidth
& 0xff00) | 0x27));
327 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((Offset
) << 8) & 0xff00) | 0x28));
328 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((Offset
) >> 0) & 0xff00) | 0x29));
329 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((Offset
) >> 8) & 0xff00) | 0x2a));
330 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((SourceOffset
) << 8) & 0xff00) | 0x2c));
331 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((SourceOffset
) >> 0) & 0xff00) | 0x2d));
332 outw (Private
, GRAPH_ADDRESS_REGISTER
, (UINT16
) ((((SourceOffset
) >> 8) & 0xff00) | 0x2e));
333 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x002f);
334 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0030);
335 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0d32);
336 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0033);
337 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0034);
338 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0035);
340 outw (Private
, GRAPH_ADDRESS_REGISTER
, 0x0231);
342 outb (Private
, GRAPH_ADDRESS_REGISTER
, 0x31);
343 while ((inb (Private
, GRAPH_DATA_REGISTER
) & 0x01) == 0x01)
347 case EfiBltVideoFill
:
349 Pixel
= (UINT8
) ((Blt
->Red
& 0xe0) | ((Blt
->Green
>> 3) & 0x1c) | ((Blt
->Blue
>> 6) & 0x03));
350 WidePixel
= (Pixel
<< 8) | Pixel
;
351 WidePixel
= (WidePixel
<< 16) | WidePixel
;
353 if (DestinationX
== 0 && Width
== Private
->ModeData
[CurrentMode
].HorizontalResolution
) {
354 Offset
= DestinationY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
;
355 if (((Offset
& 0x03) == 0) && (((Width
* Height
) & 0x03) == 0)) {
356 Private
->PciIo
->Mem
.Write (
358 EfiPciIoWidthFillUint32
,
361 (Width
* Height
) >> 2,
365 Private
->PciIo
->Mem
.Write (
367 EfiPciIoWidthFillUint8
,
375 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
376 Offset
= (DstY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + DestinationX
;
377 if (((Offset
& 0x03) == 0) && ((Width
& 0x03) == 0)) {
378 Private
->PciIo
->Mem
.Write (
380 EfiPciIoWidthFillUint32
,
387 Private
->PciIo
->Mem
.Write (
389 EfiPciIoWidthFillUint8
,
400 case EfiBltBufferToVideo
:
401 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
403 for (X
= 0; X
< Width
; X
++) {
404 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) ((UINT8
*) BltBuffer
+ (SrcY
* Delta
) + (SourceX
+ X
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
405 Private
->LineBuffer
[X
] = (UINT8
) ((Blt
->Red
& 0xe0) | ((Blt
->Green
>> 3) & 0x1c) | ((Blt
->Blue
>> 6) & 0x03));
408 Offset
= (DstY
* Private
->ModeData
[CurrentMode
].HorizontalResolution
) + DestinationX
;
410 if (((Offset
& 0x03) == 0) && ((Width
& 0x03) == 0)) {
411 Private
->PciIo
->Mem
.Write (
420 Private
->PciIo
->Mem
.Write (
435 gBS
->RestoreTPL (OriginalTPL
);
441 CirrusLogic5430GraphicsOutputConstructor (
442 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
446 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
449 GraphicsOutput
= &Private
->GraphicsOutput
;
450 GraphicsOutput
->QueryMode
= CirrusLogic5430GraphicsOutputQueryMode
;
451 GraphicsOutput
->SetMode
= CirrusLogic5430GraphicsOutputSetMode
;
452 GraphicsOutput
->Blt
= CirrusLogic5430GraphicsOutputBlt
;
455 // Initialize the private data
457 Status
= gBS
->AllocatePool (
459 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
460 (VOID
**) &Private
->GraphicsOutput
.Mode
462 if (EFI_ERROR (Status
)) {
465 Status
= gBS
->AllocatePool (
467 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
468 (VOID
**) &Private
->GraphicsOutput
.Mode
->Info
470 if (EFI_ERROR (Status
)) {
473 Private
->GraphicsOutput
.Mode
->MaxMode
= (UINT32
) Private
->MaxMode
;
474 Private
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
475 Private
->HardwareNeedsStarting
= TRUE
;
476 Private
->LineBuffer
= NULL
;
479 // Initialize the hardware
481 GraphicsOutput
->SetMode (GraphicsOutput
, 0);
484 Private
->ModeData
[Private
->GraphicsOutput
.Mode
->Mode
].HorizontalResolution
,
485 Private
->ModeData
[Private
->GraphicsOutput
.Mode
->Mode
].VerticalResolution
492 CirrusLogic5430GraphicsOutputDestructor (
493 CIRRUS_LOGIC_5430_PRIVATE_DATA
*Private
507 if (Private
->GraphicsOutput
.Mode
!= NULL
) {
508 if (Private
->GraphicsOutput
.Mode
->Info
!= NULL
) {
509 gBS
->FreePool (Private
->GraphicsOutput
.Mode
->Info
);
511 gBS
->FreePool (Private
->GraphicsOutput
.Mode
);