]> git.proxmox.com Git - mirror_edk2.git/blob - OptionRomPkg/CirrusLogic5430Dxe/CirrusLogic5430GraphicsOutput.c
b74d84b13119bba9569226f931470683b6e96224
[mirror_edk2.git] / OptionRomPkg / CirrusLogic5430Dxe / CirrusLogic5430GraphicsOutput.c
1 /** @file
2 Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>
3 SPDX-License-Identifier: BSD-2-Clause-Patent
4
5 Module Name:
6
7 UefiCirrusLogic5430GraphicsOutput.c
8
9 Abstract:
10
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.
14
15 **/
16 #include "CirrusLogic5430.h"
17 #include <IndustryStandard/Acpi.h>
18
19
20 STATIC
21 VOID
22 CirrusLogic5430CompleteModeInfo (
23 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info
24 )
25 {
26 Info->Version = 0;
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;
33 }
34
35
36 STATIC
37 EFI_STATUS
38 CirrusLogic5430CompleteModeData (
39 IN CIRRUS_LOGIC_5430_PRIVATE_DATA *Private,
40 OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode
41 )
42 {
43 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
44 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *FrameBufDesc;
45
46 Info = Mode->Info;
47 CirrusLogic5430CompleteModeInfo (Info);
48
49 Private->PciIo->GetBarAttributes (
50 Private->PciIo,
51 0,
52 NULL,
53 (VOID**) &FrameBufDesc
54 );
55
56 Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin;
57 Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution;
58
59 return EFI_SUCCESS;
60 }
61
62
63 //
64 // Graphics Output Protocol Member Functions
65 //
66 EFI_STATUS
67 EFIAPI
68 CirrusLogic5430GraphicsOutputQueryMode (
69 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
70 IN UINT32 ModeNumber,
71 OUT UINTN *SizeOfInfo,
72 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
73 )
74 /*++
75
76 Routine Description:
77
78 Graphics Output protocol interface to query video mode
79
80 Arguments:
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.
85
86 Returns:
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.
92
93 --*/
94 {
95 CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
96
97 Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
98
99 if (Private->HardwareNeedsStarting) {
100 return EFI_NOT_STARTED;
101 }
102
103 if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
104 return EFI_INVALID_PARAMETER;
105 }
106
107 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
108 if (*Info == NULL) {
109 return EFI_OUT_OF_RESOURCES;
110 }
111
112 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
113
114 (*Info)->HorizontalResolution = Private->ModeData[ModeNumber].HorizontalResolution;
115 (*Info)->VerticalResolution = Private->ModeData[ModeNumber].VerticalResolution;
116 CirrusLogic5430CompleteModeInfo (*Info);
117
118 return EFI_SUCCESS;
119 }
120
121 EFI_STATUS
122 EFIAPI
123 CirrusLogic5430GraphicsOutputSetMode (
124 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
125 IN UINT32 ModeNumber
126 )
127 /*++
128
129 Routine Description:
130
131 Graphics Output protocol interface to set video mode
132
133 Arguments:
134 This - Protocol instance pointer.
135 ModeNumber - The mode number to be set.
136
137 Returns:
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.
141
142 --*/
143 {
144 CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
145 CIRRUS_LOGIC_5430_MODE_DATA *ModeData;
146
147 Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
148
149 if (ModeNumber >= This->Mode->MaxMode) {
150 return EFI_UNSUPPORTED;
151 }
152
153 ModeData = &Private->ModeData[ModeNumber];
154
155 if (Private->LineBuffer) {
156 gBS->FreePool (Private->LineBuffer);
157 }
158
159 Private->LineBuffer = NULL;
160 Private->LineBuffer = AllocatePool (ModeData->HorizontalResolution);
161 if (Private->LineBuffer == NULL) {
162 return EFI_OUT_OF_RESOURCES;
163 }
164
165 InitializeGraphicsMode (Private, &CirrusLogic5430VideoModes[ModeData->ModeNumber]);
166
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);
171
172 CirrusLogic5430CompleteModeData (Private, This->Mode);
173
174 Private->HardwareNeedsStarting = FALSE;
175
176 return EFI_SUCCESS;
177 }
178
179 EFI_STATUS
180 EFIAPI
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,
185 IN UINTN SourceX,
186 IN UINTN SourceY,
187 IN UINTN DestinationX,
188 IN UINTN DestinationY,
189 IN UINTN Width,
190 IN UINTN Height,
191 IN UINTN Delta
192 )
193 /*++
194
195 Routine Description:
196
197 Graphics Output protocol instance to block transfer for CirrusLogic device
198
199 Arguments:
200
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.
214
215 Returns:
216
217 EFI_INVALID_PARAMETER - Invalid parameter passed in
218 EFI_SUCCESS - Blt operation success
219
220 --*/
221 {
222 CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
223 EFI_TPL OriginalTPL;
224 UINTN DstY;
225 UINTN SrcY;
226 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
227 UINTN X;
228 UINT8 Pixel;
229 UINT32 WidePixel;
230 UINTN ScreenWidth;
231 UINTN Offset;
232 UINTN SourceOffset;
233 UINT32 CurrentMode;
234
235 Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
236
237 if ((UINT32)BltOperation >= EfiGraphicsOutputBltOperationMax) {
238 return EFI_INVALID_PARAMETER;
239 }
240
241 if (Width == 0 || Height == 0) {
242 return EFI_INVALID_PARAMETER;
243 }
244
245 //
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.
249 //
250 if (Delta == 0) {
251 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
252 }
253
254 //
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
257 // the image.
258 //
259
260 CurrentMode = This->Mode->Mode;
261 //
262 // Make sure the SourceX, SourceY, DestinationX, DestinationY, Width, and Height parameters
263 // are valid for the operation and the current screen geometry.
264 //
265 if (BltOperation == EfiBltVideoToBltBuffer) {
266 //
267 // Video to BltBuffer: Source is Video, destination is BltBuffer
268 //
269 if (SourceY + Height > Private->ModeData[CurrentMode].VerticalResolution) {
270 return EFI_INVALID_PARAMETER;
271 }
272
273 if (SourceX + Width > Private->ModeData[CurrentMode].HorizontalResolution) {
274 return EFI_INVALID_PARAMETER;
275 }
276 } else {
277 //
278 // BltBuffer to Video: Source is BltBuffer, destination is Video
279 //
280 if (DestinationY + Height > Private->ModeData[CurrentMode].VerticalResolution) {
281 return EFI_INVALID_PARAMETER;
282 }
283
284 if (DestinationX + Width > Private->ModeData[CurrentMode].HorizontalResolution) {
285 return EFI_INVALID_PARAMETER;
286 }
287 }
288 //
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.
292 //
293 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
294
295 switch (BltOperation) {
296 case EfiBltVideoToBltBuffer:
297 //
298 // Video to BltBuffer: Source is Video, destination is BltBuffer
299 //
300 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
301
302 Offset = (SrcY * Private->ModeData[CurrentMode].HorizontalResolution) + SourceX;
303 if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
304 Private->PciIo->Mem.Read (
305 Private->PciIo,
306 EfiPciIoWidthUint32,
307 0,
308 Offset,
309 Width >> 2,
310 Private->LineBuffer
311 );
312 } else {
313 Private->PciIo->Mem.Read (
314 Private->PciIo,
315 EfiPciIoWidthUint8,
316 0,
317 Offset,
318 Width,
319 Private->LineBuffer
320 );
321 }
322
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));
325
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]);
329 }
330 }
331 break;
332
333 case EfiBltVideoToVideo:
334 //
335 // Perform hardware acceleration for Video to Video operations
336 //
337 ScreenWidth = Private->ModeData[CurrentMode].HorizontalResolution;
338 SourceOffset = (SourceY * Private->ModeData[CurrentMode].HorizontalResolution) + (SourceX);
339 Offset = (DestinationY * Private->ModeData[CurrentMode].HorizontalResolution) + (DestinationX);
340
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);
345
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);
350
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);
371
372 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0231);
373
374 outb (Private, GRAPH_ADDRESS_REGISTER, 0x31);
375 while ((inb (Private, GRAPH_DATA_REGISTER) & 0x01) == 0x01)
376 ;
377 break;
378
379 case EfiBltVideoFill:
380 Blt = BltBuffer;
381 Pixel = RGB_BYTES_TO_PIXEL (Blt->Red, Blt->Green, Blt->Blue);
382 WidePixel = (Pixel << 8) | Pixel;
383 WidePixel = (WidePixel << 16) | WidePixel;
384
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 (
389 Private->PciIo,
390 EfiPciIoWidthFillUint32,
391 0,
392 Offset,
393 (Width * Height) >> 2,
394 &WidePixel
395 );
396 } else {
397 Private->PciIo->Mem.Write (
398 Private->PciIo,
399 EfiPciIoWidthFillUint8,
400 0,
401 Offset,
402 Width * Height,
403 &Pixel
404 );
405 }
406 } else {
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 (
411 Private->PciIo,
412 EfiPciIoWidthFillUint32,
413 0,
414 Offset,
415 Width >> 2,
416 &WidePixel
417 );
418 } else {
419 Private->PciIo->Mem.Write (
420 Private->PciIo,
421 EfiPciIoWidthFillUint8,
422 0,
423 Offset,
424 Width,
425 &Pixel
426 );
427 }
428 }
429 }
430 break;
431
432 case EfiBltBufferToVideo:
433 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
434
435 for (X = 0; X < Width; X++) {
436 Blt =
437 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (
438 (UINT8 *) BltBuffer +
439 (SrcY * Delta) +
440 ((SourceX + X) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))
441 );
442 Private->LineBuffer[X] =
443 RGB_BYTES_TO_PIXEL (Blt->Red, Blt->Green, Blt->Blue);
444 }
445
446 Offset = (DstY * Private->ModeData[CurrentMode].HorizontalResolution) + DestinationX;
447
448 if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
449 Private->PciIo->Mem.Write (
450 Private->PciIo,
451 EfiPciIoWidthUint32,
452 0,
453 Offset,
454 Width >> 2,
455 Private->LineBuffer
456 );
457 } else {
458 Private->PciIo->Mem.Write (
459 Private->PciIo,
460 EfiPciIoWidthUint8,
461 0,
462 Offset,
463 Width,
464 Private->LineBuffer
465 );
466 }
467 }
468 break;
469 default:
470 ASSERT (FALSE);
471 }
472
473 gBS->RestoreTPL (OriginalTPL);
474
475 return EFI_SUCCESS;
476 }
477
478 EFI_STATUS
479 CirrusLogic5430GraphicsOutputConstructor (
480 CIRRUS_LOGIC_5430_PRIVATE_DATA *Private
481 )
482 {
483 EFI_STATUS Status;
484 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
485
486
487 GraphicsOutput = &Private->GraphicsOutput;
488 GraphicsOutput->QueryMode = CirrusLogic5430GraphicsOutputQueryMode;
489 GraphicsOutput->SetMode = CirrusLogic5430GraphicsOutputSetMode;
490 GraphicsOutput->Blt = CirrusLogic5430GraphicsOutputBlt;
491
492 //
493 // Initialize the private data
494 //
495 Status = gBS->AllocatePool (
496 EfiBootServicesData,
497 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
498 (VOID **) &Private->GraphicsOutput.Mode
499 );
500 if (EFI_ERROR (Status)) {
501 return Status;
502 }
503 Status = gBS->AllocatePool (
504 EfiBootServicesData,
505 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
506 (VOID **) &Private->GraphicsOutput.Mode->Info
507 );
508 if (EFI_ERROR (Status)) {
509 return Status;
510 }
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;
515
516 //
517 // Initialize the hardware
518 //
519 GraphicsOutput->SetMode (GraphicsOutput, 0);
520 ASSERT (Private->GraphicsOutput.Mode->Mode < CIRRUS_LOGIC_5430_MODE_COUNT);
521 DrawLogo (
522 Private,
523 Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,
524 Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution
525 );
526
527 return EFI_SUCCESS;
528 }
529
530 EFI_STATUS
531 CirrusLogic5430GraphicsOutputDestructor (
532 CIRRUS_LOGIC_5430_PRIVATE_DATA *Private
533 )
534 /*++
535
536 Routine Description:
537
538 Arguments:
539
540 Returns:
541
542 None
543
544 --*/
545 {
546 if (Private->GraphicsOutput.Mode != NULL) {
547 if (Private->GraphicsOutput.Mode->Info != NULL) {
548 gBS->FreePool (Private->GraphicsOutput.Mode->Info);
549 }
550 gBS->FreePool (Private->GraphicsOutput.Mode);
551 }
552
553 return EFI_SUCCESS;
554 }
555
556