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