Fix comparisons of enumerated types which may cause warnings for some compilers.
[mirror_edk2.git] / OptionRomPkg / CirrusLogic5430Dxe / CirrusLogic5430UgaDraw.c
1 /** @file
2 This file produces the graphics abstration of UGA Draw. It is called by
3 CirrusLogic5430.c file which deals with the EFI 1.1 driver model.
4 This file just does graphics.
5
6 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16
17 #include "CirrusLogic5430.h"
18
19 //
20 // UGA Draw Protocol Member Functions
21 //
22 EFI_STATUS
23 EFIAPI
24 CirrusLogic5430UgaDrawGetMode (
25 IN EFI_UGA_DRAW_PROTOCOL *This,
26 OUT UINT32 *HorizontalResolution,
27 OUT UINT32 *VerticalResolution,
28 OUT UINT32 *ColorDepth,
29 OUT UINT32 *RefreshRate
30 )
31 {
32 CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
33
34 Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
35
36 if (Private->HardwareNeedsStarting) {
37 return EFI_NOT_STARTED;
38 }
39
40 if ((HorizontalResolution == NULL) ||
41 (VerticalResolution == NULL) ||
42 (ColorDepth == NULL) ||
43 (RefreshRate == NULL)) {
44 return EFI_INVALID_PARAMETER;
45 }
46
47 *HorizontalResolution = Private->ModeData[Private->CurrentMode].HorizontalResolution;
48 *VerticalResolution = Private->ModeData[Private->CurrentMode].VerticalResolution;
49 *ColorDepth = Private->ModeData[Private->CurrentMode].ColorDepth;
50 *RefreshRate = Private->ModeData[Private->CurrentMode].RefreshRate;
51
52 return EFI_SUCCESS;
53 }
54
55 EFI_STATUS
56 EFIAPI
57 CirrusLogic5430UgaDrawSetMode (
58 IN EFI_UGA_DRAW_PROTOCOL *This,
59 IN UINT32 HorizontalResolution,
60 IN UINT32 VerticalResolution,
61 IN UINT32 ColorDepth,
62 IN UINT32 RefreshRate
63 )
64 {
65 CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
66 UINTN Index;
67
68 Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
69
70 for (Index = 0; Index < Private->MaxMode; Index++) {
71
72 if (HorizontalResolution != Private->ModeData[Index].HorizontalResolution) {
73 continue;
74 }
75
76 if (VerticalResolution != Private->ModeData[Index].VerticalResolution) {
77 continue;
78 }
79
80 if (ColorDepth != Private->ModeData[Index].ColorDepth) {
81 continue;
82 }
83
84 if (RefreshRate != Private->ModeData[Index].RefreshRate) {
85 continue;
86 }
87
88 if (Private->LineBuffer) {
89 gBS->FreePool (Private->LineBuffer);
90 }
91
92 Private->LineBuffer = NULL;
93 Private->LineBuffer = AllocatePool (HorizontalResolution);
94 if (Private->LineBuffer == NULL) {
95 return EFI_OUT_OF_RESOURCES;
96 }
97
98 InitializeGraphicsMode (Private, &CirrusLogic5430VideoModes[Private->ModeData[Index].ModeNumber]);
99
100 Private->CurrentMode = Index;
101
102 Private->HardwareNeedsStarting = FALSE;
103
104 return EFI_SUCCESS;
105 }
106
107 return EFI_NOT_FOUND;
108 }
109
110 EFI_STATUS
111 EFIAPI
112 CirrusLogic5430UgaDrawBlt (
113 IN EFI_UGA_DRAW_PROTOCOL *This,
114 IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL
115 IN EFI_UGA_BLT_OPERATION BltOperation,
116 IN UINTN SourceX,
117 IN UINTN SourceY,
118 IN UINTN DestinationX,
119 IN UINTN DestinationY,
120 IN UINTN Width,
121 IN UINTN Height,
122 IN UINTN Delta
123 )
124 {
125 CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
126 EFI_TPL OriginalTPL;
127 UINTN DstY;
128 UINTN SrcY;
129 EFI_UGA_PIXEL *Blt;
130 UINTN X;
131 UINT8 Pixel;
132 UINT32 WidePixel;
133 UINTN ScreenWidth;
134 UINTN Offset;
135 UINTN SourceOffset;
136
137 Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
138
139 if ((UINT32)BltOperation >= EfiUgaBltMax) {
140 return EFI_INVALID_PARAMETER;
141 }
142
143 if (Width == 0 || Height == 0) {
144 return EFI_INVALID_PARAMETER;
145 }
146
147 //
148 // If Delta is zero, then the entire BltBuffer is being used, so Delta
149 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
150 // the number of bytes in each row can be computed.
151 //
152 if (Delta == 0) {
153 Delta = Width * sizeof (EFI_UGA_PIXEL);
154 }
155
156 //
157 // We need to fill the Virtual Screen buffer with the blt data.
158 // The virtual screen is upside down, as the first row is the bootom row of
159 // the image.
160 //
161
162 //
163 // Make sure the SourceX, SourceY, DestinationX, DestinationY, Width, and Height parameters
164 // are valid for the operation and the current screen geometry.
165 //
166 if (BltOperation == EfiUgaVideoToBltBuffer) {
167 //
168 // Video to BltBuffer: Source is Video, destination is BltBuffer
169 //
170 if (SourceY + Height > Private->ModeData[Private->CurrentMode].VerticalResolution) {
171 return EFI_INVALID_PARAMETER;
172 }
173
174 if (SourceX + Width > Private->ModeData[Private->CurrentMode].HorizontalResolution) {
175 return EFI_INVALID_PARAMETER;
176 }
177 } else {
178 //
179 // BltBuffer to Video: Source is BltBuffer, destination is Video
180 //
181 if (DestinationY + Height > Private->ModeData[Private->CurrentMode].VerticalResolution) {
182 return EFI_INVALID_PARAMETER;
183 }
184
185 if (DestinationX + Width > Private->ModeData[Private->CurrentMode].HorizontalResolution) {
186 return EFI_INVALID_PARAMETER;
187 }
188 }
189 //
190 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
191 // We would not want a timer based event (Cursor, ...) to come in while we are
192 // doing this operation.
193 //
194 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
195
196 switch (BltOperation) {
197 case EfiUgaVideoToBltBuffer:
198 //
199 // Video to BltBuffer: Source is Video, destination is BltBuffer
200 //
201 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
202
203 Offset = (SrcY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + SourceX;
204 if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
205 Private->PciIo->Mem.Read (
206 Private->PciIo,
207 EfiPciIoWidthUint32,
208 0,
209 Offset,
210 Width >> 2,
211 Private->LineBuffer
212 );
213 } else {
214 Private->PciIo->Mem.Read (
215 Private->PciIo,
216 EfiPciIoWidthUint8,
217 0,
218 Offset,
219 Width,
220 Private->LineBuffer
221 );
222 }
223
224 for (X = 0; X < Width; X++) {
225 Blt = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + (DstY * Delta) + (DestinationX + X) * sizeof (EFI_UGA_PIXEL));
226
227 Blt->Red = (UINT8) (Private->LineBuffer[X] & 0xe0);
228 Blt->Green = (UINT8) ((Private->LineBuffer[X] & 0x1c) << 3);
229 Blt->Blue = (UINT8) ((Private->LineBuffer[X] & 0x03) << 6);
230 }
231 }
232 break;
233
234 case EfiUgaVideoToVideo:
235 //
236 // Perform hardware acceleration for Video to Video operations
237 //
238 ScreenWidth = Private->ModeData[Private->CurrentMode].HorizontalResolution;
239 SourceOffset = (SourceY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + (SourceX);
240 Offset = (DestinationY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + (DestinationX);
241
242 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0000);
243 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0010);
244 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0012);
245 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0014);
246
247 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0001);
248 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0011);
249 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0013);
250 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0015);
251
252 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((Width << 8) & 0xff00) | 0x20));
253 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((Width & 0xff00) | 0x21));
254 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((Height << 8) & 0xff00) | 0x22));
255 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((Height & 0xff00) | 0x23));
256 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((ScreenWidth << 8) & 0xff00) | 0x24));
257 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((ScreenWidth & 0xff00) | 0x25));
258 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((ScreenWidth << 8) & 0xff00) | 0x26));
259 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((ScreenWidth & 0xff00) | 0x27));
260 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) << 8) & 0xff00) | 0x28));
261 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) >> 0) & 0xff00) | 0x29));
262 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) >> 8) & 0xff00) | 0x2a));
263 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) << 8) & 0xff00) | 0x2c));
264 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) >> 0) & 0xff00) | 0x2d));
265 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) >> 8) & 0xff00) | 0x2e));
266 outw (Private, GRAPH_ADDRESS_REGISTER, 0x002f);
267 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0030);
268 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0d32);
269 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0033);
270 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0034);
271 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0035);
272
273 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0231);
274
275 outb (Private, GRAPH_ADDRESS_REGISTER, 0x31);
276 while ((inb (Private, GRAPH_DATA_REGISTER) & 0x01) == 0x01)
277 ;
278 break;
279
280 case EfiUgaVideoFill:
281 Blt = BltBuffer;
282 Pixel = (UINT8) ((Blt->Red & 0xe0) | ((Blt->Green >> 3) & 0x1c) | ((Blt->Blue >> 6) & 0x03));
283 WidePixel = (Pixel << 8) | Pixel;
284 WidePixel = (WidePixel << 16) | WidePixel;
285
286 if (DestinationX == 0 && Width == Private->ModeData[Private->CurrentMode].HorizontalResolution) {
287 Offset = DestinationY * Private->ModeData[Private->CurrentMode].HorizontalResolution;
288 if (((Offset & 0x03) == 0) && (((Width * Height) & 0x03) == 0)) {
289 Private->PciIo->Mem.Write (
290 Private->PciIo,
291 EfiPciIoWidthFillUint32,
292 0,
293 Offset,
294 (Width * Height) >> 2,
295 &WidePixel
296 );
297 } else {
298 Private->PciIo->Mem.Write (
299 Private->PciIo,
300 EfiPciIoWidthFillUint8,
301 0,
302 Offset,
303 Width * Height,
304 &Pixel
305 );
306 }
307 } else {
308 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
309 Offset = (DstY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + DestinationX;
310 if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
311 Private->PciIo->Mem.Write (
312 Private->PciIo,
313 EfiPciIoWidthFillUint32,
314 0,
315 Offset,
316 Width >> 2,
317 &WidePixel
318 );
319 } else {
320 Private->PciIo->Mem.Write (
321 Private->PciIo,
322 EfiPciIoWidthFillUint8,
323 0,
324 Offset,
325 Width,
326 &Pixel
327 );
328 }
329 }
330 }
331 break;
332
333 case EfiUgaBltBufferToVideo:
334 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
335
336 for (X = 0; X < Width; X++) {
337 Blt = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + (SrcY * Delta) + (SourceX + X) * sizeof (EFI_UGA_PIXEL));
338 Private->LineBuffer[X] = (UINT8) ((Blt->Red & 0xe0) | ((Blt->Green >> 3) & 0x1c) | ((Blt->Blue >> 6) & 0x03));
339 }
340
341 Offset = (DstY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + DestinationX;
342
343 if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
344 Private->PciIo->Mem.Write (
345 Private->PciIo,
346 EfiPciIoWidthUint32,
347 0,
348 Offset,
349 Width >> 2,
350 Private->LineBuffer
351 );
352 } else {
353 Private->PciIo->Mem.Write (
354 Private->PciIo,
355 EfiPciIoWidthUint8,
356 0,
357 Offset,
358 Width,
359 Private->LineBuffer
360 );
361 }
362 }
363 break;
364
365 default:
366 break;
367 }
368
369 gBS->RestoreTPL (OriginalTPL);
370
371 return EFI_SUCCESS;
372 }
373
374 //
375 // Construction and Destruction functions
376 //
377 EFI_STATUS
378 CirrusLogic5430UgaDrawConstructor (
379 CIRRUS_LOGIC_5430_PRIVATE_DATA *Private
380 )
381 {
382 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
383
384 //
385 // Fill in Private->UgaDraw protocol
386 //
387 UgaDraw = &Private->UgaDraw;
388
389 UgaDraw->GetMode = CirrusLogic5430UgaDrawGetMode;
390 UgaDraw->SetMode = CirrusLogic5430UgaDrawSetMode;
391 UgaDraw->Blt = CirrusLogic5430UgaDrawBlt;
392
393 //
394 // Initialize the private data
395 //
396 Private->CurrentMode = 0;
397 Private->HardwareNeedsStarting = TRUE;
398 Private->LineBuffer = NULL;
399
400 //
401 // Initialize the hardware
402 //
403 UgaDraw->SetMode (
404 UgaDraw,
405 Private->ModeData[Private->CurrentMode].HorizontalResolution,
406 Private->ModeData[Private->CurrentMode].VerticalResolution,
407 Private->ModeData[Private->CurrentMode].ColorDepth,
408 Private->ModeData[Private->CurrentMode].RefreshRate
409 );
410 DrawLogo (
411 Private,
412 Private->ModeData[Private->CurrentMode].HorizontalResolution,
413 Private->ModeData[Private->CurrentMode].VerticalResolution
414 );
415
416 return EFI_SUCCESS;
417 }
418