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