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