]> git.proxmox.com Git - mirror_edk2.git/blob - OptionRomPkg/CirrusLogic5430Dxe/CirrusLogic5430GraphicsOutput.c
fceb419198a3822b8252e1679fc20b18a910910b
[mirror_edk2.git] / OptionRomPkg / CirrusLogic5430Dxe / CirrusLogic5430GraphicsOutput.c
1 /** @file
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
7
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.
10
11 Module Name:
12
13 UefiCirrusLogic5430GraphicsOutput.c
14
15 Abstract:
16
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.
20
21 **/
22 #include "CirrusLogic5430.h"
23
24 //
25 // Graphics Output Protocol Member Functions
26 //
27 EFI_STATUS
28 EFIAPI
29 CirrusLogic5430GraphicsOutputQueryMode (
30 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
31 IN UINT32 ModeNumber,
32 OUT UINTN *SizeOfInfo,
33 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
34 )
35 /*++
36
37 Routine Description:
38
39 Graphics Output protocol interface to query video mode
40
41 Arguments:
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.
46
47 Returns:
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.
53
54 --*/
55 {
56 CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
57
58 Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
59
60 if (Private->HardwareNeedsStarting) {
61 return EFI_NOT_STARTED;
62 }
63
64 if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
65 return EFI_INVALID_PARAMETER;
66 }
67
68 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
69 if (*Info == NULL) {
70 return EFI_OUT_OF_RESOURCES;
71 }
72
73 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
74
75 (*Info)->Version = 0;
76 (*Info)->HorizontalResolution = Private->ModeData[ModeNumber].HorizontalResolution;
77 (*Info)->VerticalResolution = Private->ModeData[ModeNumber].VerticalResolution;
78 (*Info)->PixelFormat = PixelBltOnly;
79 (*Info)->PixelsPerScanLine = (*Info)->HorizontalResolution;
80
81 return EFI_SUCCESS;
82 }
83
84 EFI_STATUS
85 EFIAPI
86 CirrusLogic5430GraphicsOutputSetMode (
87 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
88 IN UINT32 ModeNumber
89 )
90 /*++
91
92 Routine Description:
93
94 Graphics Output protocol interface to set video mode
95
96 Arguments:
97 This - Protocol instance pointer.
98 ModeNumber - The mode number to be set.
99
100 Returns:
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.
104
105 --*/
106 {
107 CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
108 CIRRUS_LOGIC_5430_MODE_DATA *ModeData;
109
110 Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
111
112 if (ModeNumber >= This->Mode->MaxMode) {
113 return EFI_UNSUPPORTED;
114 }
115
116 ModeData = &Private->ModeData[ModeNumber];
117
118 if (Private->LineBuffer) {
119 gBS->FreePool (Private->LineBuffer);
120 }
121
122 Private->LineBuffer = NULL;
123 Private->LineBuffer = AllocatePool (ModeData->HorizontalResolution);
124 if (Private->LineBuffer == NULL) {
125 return EFI_OUT_OF_RESOURCES;
126 }
127
128 InitializeGraphicsMode (Private, &CirrusLogic5430VideoModes[ModeData->ModeNumber]);
129
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);
136
137 This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS)(UINTN)NULL;
138 This->Mode->FrameBufferSize = 0;
139
140 Private->HardwareNeedsStarting = FALSE;
141
142 return EFI_SUCCESS;
143 }
144
145 EFI_STATUS
146 EFIAPI
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,
151 IN UINTN SourceX,
152 IN UINTN SourceY,
153 IN UINTN DestinationX,
154 IN UINTN DestinationY,
155 IN UINTN Width,
156 IN UINTN Height,
157 IN UINTN Delta
158 )
159 /*++
160
161 Routine Description:
162
163 Graphics Output protocol instance to block transfer for CirrusLogic device
164
165 Arguments:
166
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.
180
181 Returns:
182
183 EFI_INVALID_PARAMETER - Invalid parameter passed in
184 EFI_SUCCESS - Blt operation success
185
186 --*/
187 {
188 CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
189 EFI_TPL OriginalTPL;
190 UINTN DstY;
191 UINTN SrcY;
192 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
193 UINTN X;
194 UINT8 Pixel;
195 UINT32 WidePixel;
196 UINTN ScreenWidth;
197 UINTN Offset;
198 UINTN SourceOffset;
199 UINT32 CurrentMode;
200
201 Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
202
203 if ((BltOperation < 0) || (BltOperation >= EfiGraphicsOutputBltOperationMax)) {
204 return EFI_INVALID_PARAMETER;
205 }
206
207 if (Width == 0 || Height == 0) {
208 return EFI_INVALID_PARAMETER;
209 }
210
211 //
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.
215 //
216 if (Delta == 0) {
217 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
218 }
219
220 //
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
223 // the image.
224 //
225
226 CurrentMode = This->Mode->Mode;
227 //
228 // Make sure the SourceX, SourceY, DestinationX, DestinationY, Width, and Height parameters
229 // are valid for the operation and the current screen geometry.
230 //
231 if (BltOperation == EfiBltVideoToBltBuffer) {
232 //
233 // Video to BltBuffer: Source is Video, destination is BltBuffer
234 //
235 if (SourceY + Height > Private->ModeData[CurrentMode].VerticalResolution) {
236 return EFI_INVALID_PARAMETER;
237 }
238
239 if (SourceX + Width > Private->ModeData[CurrentMode].HorizontalResolution) {
240 return EFI_INVALID_PARAMETER;
241 }
242 } else {
243 //
244 // BltBuffer to Video: Source is BltBuffer, destination is Video
245 //
246 if (DestinationY + Height > Private->ModeData[CurrentMode].VerticalResolution) {
247 return EFI_INVALID_PARAMETER;
248 }
249
250 if (DestinationX + Width > Private->ModeData[CurrentMode].HorizontalResolution) {
251 return EFI_INVALID_PARAMETER;
252 }
253 }
254 //
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.
258 //
259 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
260
261 switch (BltOperation) {
262 case EfiBltVideoToBltBuffer:
263 //
264 // Video to BltBuffer: Source is Video, destination is BltBuffer
265 //
266 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
267
268 Offset = (SrcY * Private->ModeData[CurrentMode].HorizontalResolution) + SourceX;
269 if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
270 Private->PciIo->Mem.Read (
271 Private->PciIo,
272 EfiPciIoWidthUint32,
273 0,
274 Offset,
275 Width >> 2,
276 Private->LineBuffer
277 );
278 } else {
279 Private->PciIo->Mem.Read (
280 Private->PciIo,
281 EfiPciIoWidthUint8,
282 0,
283 Offset,
284 Width,
285 Private->LineBuffer
286 );
287 }
288
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));
291
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);
295 }
296 }
297 break;
298
299 case EfiBltVideoToVideo:
300 //
301 // Perform hardware acceleration for Video to Video operations
302 //
303 ScreenWidth = Private->ModeData[CurrentMode].HorizontalResolution;
304 SourceOffset = (SourceY * Private->ModeData[CurrentMode].HorizontalResolution) + (SourceX);
305 Offset = (DestinationY * Private->ModeData[CurrentMode].HorizontalResolution) + (DestinationX);
306
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);
311
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);
316
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);
337
338 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0231);
339
340 outb (Private, GRAPH_ADDRESS_REGISTER, 0x31);
341 while ((inb (Private, GRAPH_DATA_REGISTER) & 0x01) == 0x01)
342 ;
343 break;
344
345 case EfiBltVideoFill:
346 Blt = BltBuffer;
347 Pixel = (UINT8) ((Blt->Red & 0xe0) | ((Blt->Green >> 3) & 0x1c) | ((Blt->Blue >> 6) & 0x03));
348 WidePixel = (Pixel << 8) | Pixel;
349 WidePixel = (WidePixel << 16) | WidePixel;
350
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 (
355 Private->PciIo,
356 EfiPciIoWidthFillUint32,
357 0,
358 Offset,
359 (Width * Height) >> 2,
360 &WidePixel
361 );
362 } else {
363 Private->PciIo->Mem.Write (
364 Private->PciIo,
365 EfiPciIoWidthFillUint8,
366 0,
367 Offset,
368 Width * Height,
369 &Pixel
370 );
371 }
372 } else {
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 (
377 Private->PciIo,
378 EfiPciIoWidthFillUint32,
379 0,
380 Offset,
381 Width >> 2,
382 &WidePixel
383 );
384 } else {
385 Private->PciIo->Mem.Write (
386 Private->PciIo,
387 EfiPciIoWidthFillUint8,
388 0,
389 Offset,
390 Width,
391 &Pixel
392 );
393 }
394 }
395 }
396 break;
397
398 case EfiBltBufferToVideo:
399 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
400
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));
404 }
405
406 Offset = (DstY * Private->ModeData[CurrentMode].HorizontalResolution) + DestinationX;
407
408 if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
409 Private->PciIo->Mem.Write (
410 Private->PciIo,
411 EfiPciIoWidthUint32,
412 0,
413 Offset,
414 Width >> 2,
415 Private->LineBuffer
416 );
417 } else {
418 Private->PciIo->Mem.Write (
419 Private->PciIo,
420 EfiPciIoWidthUint8,
421 0,
422 Offset,
423 Width,
424 Private->LineBuffer
425 );
426 }
427 }
428 break;
429 default:
430 ASSERT (FALSE);
431 }
432
433 gBS->RestoreTPL (OriginalTPL);
434
435 return EFI_SUCCESS;
436 }
437
438 EFI_STATUS
439 CirrusLogic5430GraphicsOutputConstructor (
440 CIRRUS_LOGIC_5430_PRIVATE_DATA *Private
441 )
442 {
443 EFI_STATUS Status;
444 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
445
446
447 GraphicsOutput = &Private->GraphicsOutput;
448 GraphicsOutput->QueryMode = CirrusLogic5430GraphicsOutputQueryMode;
449 GraphicsOutput->SetMode = CirrusLogic5430GraphicsOutputSetMode;
450 GraphicsOutput->Blt = CirrusLogic5430GraphicsOutputBlt;
451
452 //
453 // Initialize the private data
454 //
455 Status = gBS->AllocatePool (
456 EfiBootServicesData,
457 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
458 (VOID **) &Private->GraphicsOutput.Mode
459 );
460 if (EFI_ERROR (Status)) {
461 return Status;
462 }
463 Status = gBS->AllocatePool (
464 EfiBootServicesData,
465 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
466 (VOID **) &Private->GraphicsOutput.Mode->Info
467 );
468 if (EFI_ERROR (Status)) {
469 return Status;
470 }
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;
475
476 //
477 // Initialize the hardware
478 //
479 GraphicsOutput->SetMode (GraphicsOutput, 0);
480 DrawLogo (
481 Private,
482 Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,
483 Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution
484 );
485
486 return EFI_SUCCESS;
487 }
488
489 EFI_STATUS
490 CirrusLogic5430GraphicsOutputDestructor (
491 CIRRUS_LOGIC_5430_PRIVATE_DATA *Private
492 )
493 /*++
494
495 Routine Description:
496
497 Arguments:
498
499 Returns:
500
501 None
502
503 --*/
504 {
505 if (Private->GraphicsOutput.Mode != NULL) {
506 if (Private->GraphicsOutput.Mode->Info != NULL) {
507 gBS->FreePool (Private->GraphicsOutput.Mode->Info);
508 }
509 gBS->FreePool (Private->GraphicsOutput.Mode);
510 }
511
512 return EFI_SUCCESS;
513 }
514
515