]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.c
ArmPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / ArmPlatformPkg / Library / ArmMaliDp / ArmMaliDp.c
CommitLineData
b99f8126
GP
1/** @file\r
2\r
3 ARM Mali DP 500/550/650 display controller driver\r
4\r
5 Copyright (c) 2017-2018, Arm Limited. All rights reserved.<BR>\r
6\r
7 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 <Library/DebugLib.h>\r
18#include <Library/IoLib.h>\r
19#include <Library/LcdHwLib.h>\r
20#include <Library/LcdPlatformLib.h>\r
21#include <Library/MemoryAllocationLib.h>\r
22\r
23#include "ArmMaliDp.h"\r
24\r
25// CORE_ID of the MALI DP\r
26STATIC UINT32 mDpDeviceId;\r
27\r
28/** Disable the graphics layer\r
29\r
30 This is done by clearing the EN bit of the LG_CONTROL register.\r
31**/\r
32STATIC\r
33VOID\r
34LayerGraphicsDisable (VOID)\r
35{\r
36 MmioAnd32 (DP_BASE + DP_DE_LG_CONTROL, ~DP_DE_LG_ENABLE);\r
37}\r
38\r
39/** Enable the graphics layer\r
40\r
41 This is done by setting the EN bit of the LG_CONTROL register.\r
42**/\r
43STATIC\r
44VOID\r
45LayerGraphicsEnable (VOID)\r
46{\r
47 MmioOr32 (DP_BASE + DP_DE_LG_CONTROL, DP_DE_LG_ENABLE);\r
48}\r
49\r
50/** Set the frame address of the graphics layer.\r
51\r
52 @param[in] FrameBaseAddress Address of the data buffer to be used as\r
53 a framebuffer.\r
54**/\r
55STATIC\r
56VOID\r
57LayerGraphicsSetFrame (\r
58 IN CONST EFI_PHYSICAL_ADDRESS FrameBaseAddress\r
59 )\r
60{\r
61 // Disable the graphics layer.\r
62 LayerGraphicsDisable ();\r
63\r
64 // Set up memory address of the data buffer for graphics layer.\r
65 // write lower bits of the address.\r
66 MmioWrite32 (\r
67 DP_BASE + DP_DE_LG_PTR_LOW,\r
68 DP_DE_LG_PTR_LOW_MASK & FrameBaseAddress\r
69 );\r
70\r
71 // Write higher bits of the address.\r
72 MmioWrite32 (\r
73 DP_BASE + DP_DE_LG_PTR_HIGH,\r
74 (UINT32)(FrameBaseAddress >> DP_DE_LG_PTR_HIGH_SHIFT)\r
75 );\r
76\r
77 // Enable the graphics layer.\r
78 LayerGraphicsEnable ();\r
79}\r
80\r
81/** Configures various graphics layer characteristics.\r
82\r
83 @param[in] UefiGfxPixelFormat This must be either\r
84 PixelBlueGreenRedReserved8BitPerColor\r
85 OR\r
86 PixelRedGreenBlueReserved8BitPerColor\r
87 @param[in] HRes Horizontal resolution of the graphics layer.\r
88 @param[in] VRes Vertical resolution of the graphics layer.\r
89**/\r
90STATIC\r
91VOID\r
92LayerGraphicsConfig (\r
93 IN CONST EFI_GRAPHICS_PIXEL_FORMAT UefiGfxPixelFormat,\r
94 IN CONST UINT32 HRes,\r
95 IN CONST UINT32 VRes\r
96 )\r
97{\r
98 UINT32 PixelFormat;\r
99\r
100 // Disable the graphics layer before configuring any settings.\r
101 LayerGraphicsDisable ();\r
102\r
103 // Setup graphics layer size.\r
104 MmioWrite32 (DP_BASE + DP_DE_LG_IN_SIZE, FRAME_IN_SIZE (HRes, VRes));\r
105\r
106 // Setup graphics layer composition size.\r
107 MmioWrite32 (DP_BASE + DP_DE_LG_CMP_SIZE, FRAME_CMP_SIZE (HRes, VRes));\r
108\r
109 // Setup memory stride (total visible pixels on a line * 4).\r
110 MmioWrite32 (DP_BASE + DP_DE_LG_H_STRIDE, (HRes * sizeof (UINT32)));\r
111\r
112 // Set the format.\r
113\r
114 // In PixelBlueGreenRedReserved8BitPerColor format, byte 0 represents blue,\r
115 // byte 1 represents green, byte 2 represents red, and byte 3 is reserved\r
116 // which is equivalent to XRGB format of the DP500/DP550/DP650. Whereas\r
117 // PixelRedGreenBlueReserved8BitPerColor is equivalent to XBGR of the\r
118 // DP500/DP550/DP650.\r
119 if (UefiGfxPixelFormat == PixelBlueGreenRedReserved8BitPerColor) {\r
120 PixelFormat = (mDpDeviceId == MALIDP_500) ? DP_PIXEL_FORMAT_DP500_XRGB_8888\r
121 : DP_PIXEL_FORMAT_XRGB_8888;\r
122 } else {\r
123 PixelFormat = (mDpDeviceId == MALIDP_500) ? DP_PIXEL_FORMAT_DP500_XBGR_8888\r
124 : DP_PIXEL_FORMAT_XBGR_8888;\r
125 }\r
126\r
127 MmioWrite32 (DP_BASE + DP_DE_LG_FORMAT, PixelFormat);\r
128\r
129 // Enable graphics layer.\r
130 LayerGraphicsEnable ();\r
131}\r
132\r
133/** Configure timing information of the display.\r
134\r
135 @param[in] Horizontal Pointer to horizontal timing parameters.\r
136 (Resolution, Sync, Back porch, Front porch)\r
137 @param[in] Vertical Pointer to vertical timing parameters.\r
138 (Resolution, Sync, Back porch, Front porch)\r
139**/\r
140STATIC\r
141VOID\r
142SetDisplayEngineTiming (\r
143 IN CONST SCAN_TIMINGS * CONST Horizontal,\r
144 IN CONST SCAN_TIMINGS * CONST Vertical\r
145 )\r
146{\r
147 UINTN RegHIntervals;\r
148 UINTN RegVIntervals;\r
149 UINTN RegSyncControl;\r
150 UINTN RegHVActiveSize;\r
151\r
152 if (mDpDeviceId == MALIDP_500) {\r
153 // MALI DP500 timing registers.\r
154 RegHIntervals = DP_BASE + DP_DE_DP500_H_INTERVALS;\r
155 RegVIntervals = DP_BASE + DP_DE_DP500_V_INTERVALS;\r
156 RegSyncControl = DP_BASE + DP_DE_DP500_SYNC_CONTROL;\r
157 RegHVActiveSize = DP_BASE + DP_DE_DP500_HV_ACTIVESIZE;\r
158 } else {\r
159 // MALI DP550/DP650 timing registers.\r
160 RegHIntervals = DP_BASE + DP_DE_H_INTERVALS;\r
161 RegVIntervals = DP_BASE + DP_DE_V_INTERVALS;\r
162 RegSyncControl = DP_BASE + DP_DE_SYNC_CONTROL;\r
163 RegHVActiveSize = DP_BASE + DP_DE_HV_ACTIVESIZE;\r
164 }\r
165\r
166 // Horizontal back porch and front porch.\r
167 MmioWrite32 (\r
168 RegHIntervals,\r
169 H_INTERVALS (Horizontal->FrontPorch, Horizontal->BackPorch)\r
170 );\r
171\r
172 // Vertical back porch and front porch.\r
173 MmioWrite32 (\r
174 RegVIntervals,\r
175 V_INTERVALS (Vertical->FrontPorch, Vertical->BackPorch)\r
176 );\r
177\r
178 // Sync control, Horizontal and Vertical sync.\r
179 MmioWrite32 (\r
180 RegSyncControl,\r
181 SYNC_WIDTH (Horizontal->Sync, Vertical->Sync)\r
182 );\r
183\r
184 // Set up Horizontal and Vertical area size.\r
185 MmioWrite32 (\r
186 RegHVActiveSize,\r
187 HV_ACTIVE (Horizontal->Resolution, Vertical->Resolution)\r
188 );\r
189}\r
190\r
191/** Return CORE_ID of the ARM Mali DP.\r
192\r
193 @retval 0xFFF No Mali DP found.\r
194 @retval 0x500 Mali DP core id for DP500.\r
195 @retval 0x550 Mali DP core id for DP550.\r
196 @retval 0x650 Mali DP core id for DP650.\r
197**/\r
198STATIC\r
199UINT32\r
200ArmMaliDpGetCoreId (\r
201 )\r
202{\r
203 UINT32 DpCoreId;\r
204\r
205 // First check for DP500 as register offset for DP550/DP650 CORE_ID\r
206 // is beyond 3K/4K register space of the DP500.\r
207 DpCoreId = MmioRead32 (DP_BASE + DP_DE_DP500_CORE_ID);\r
208 DpCoreId >>= DP_DE_DP500_CORE_ID_SHIFT;\r
209\r
210 if (DpCoreId == MALIDP_500) {\r
211 return DpCoreId;\r
212 }\r
213\r
214 // Check for DP550 or DP650.\r
215 DpCoreId = MmioRead32 (DP_BASE + DP_DC_CORE_ID);\r
216 DpCoreId >>= DP_DC_CORE_ID_SHIFT;\r
217\r
218 if ((DpCoreId == MALIDP_550) || (DpCoreId == MALIDP_650)) {\r
219 return DpCoreId;\r
220 }\r
221\r
222 return MALIDP_NOT_PRESENT;\r
223}\r
224\r
225/** Check for presence of MALI.\r
226\r
227 This function returns success if the platform implements\r
228 DP500/DP550/DP650 ARM Mali display processor.\r
229\r
230 @retval EFI_SUCCESS DP500/DP550/DP650 display processor found\r
231 on the platform.\r
232 @retval EFI_NOT_FOUND DP500/DP550/DP650 display processor not found\r
233 on the platform.\r
234**/\r
235EFI_STATUS\r
236LcdIdentify (VOID)\r
237{\r
238 DEBUG ((DEBUG_WARN,\r
239 "Probing ARM Mali DP500/DP550/DP650 at base address 0x%p\n",\r
240 DP_BASE\r
241 ));\r
242\r
243 if (mDpDeviceId == 0) {\r
244 mDpDeviceId = ArmMaliDpGetCoreId ();\r
245 }\r
246\r
247 if (mDpDeviceId == MALIDP_NOT_PRESENT) {\r
248 DEBUG ((DEBUG_WARN, "ARM Mali DP not found...\n"));\r
249 return EFI_NOT_FOUND;\r
250 }\r
251\r
252 DEBUG ((DEBUG_WARN, "Found ARM Mali DP %x\n", mDpDeviceId));\r
253 return EFI_SUCCESS;\r
254}\r
255\r
256/** Initialize platform display.\r
257\r
258 @param[in] FrameBaseAddress Address of the frame buffer.\r
259\r
260 @retval EFI_SUCCESS Display initialization successful.\r
261 @retval !(EFI_SUCCESS) Display initialization failure.\r
262**/\r
263EFI_STATUS\r
264LcdInitialize (\r
265 IN CONST EFI_PHYSICAL_ADDRESS FrameBaseAddress\r
266 )\r
267{\r
268 DEBUG ((DEBUG_WARN, "Framebuffer base address = %p\n", FrameBaseAddress));\r
269\r
270 if (mDpDeviceId == 0) {\r
271 mDpDeviceId = ArmMaliDpGetCoreId ();\r
272 }\r
273\r
274 if (mDpDeviceId == MALIDP_NOT_PRESENT) {\r
275 DEBUG ((DEBUG_ERROR, "ARM Mali DP initialization failed,"\r
276 "no ARM Mali DP present\n"));\r
277 return EFI_NOT_FOUND;\r
278 }\r
279\r
280 // We are using graphics layer of the Mali DP as a main framebuffer.\r
281 LayerGraphicsSetFrame (FrameBaseAddress);\r
282\r
283 return EFI_SUCCESS;\r
284}\r
285\r
286/** Set ARM Mali DP in cofiguration mode.\r
287\r
288 The ARM Mali DP must be in the configuration mode for\r
289 configuration of the H_INTERVALS, V_INTERVALS, SYNC_CONTROL\r
290 and HV_ACTIVESIZE.\r
291**/\r
292STATIC\r
293VOID\r
294SetConfigurationMode (VOID)\r
295{\r
296 // Request configuration Mode.\r
297 if (mDpDeviceId == MALIDP_500) {\r
298 MmioOr32 (DP_BASE + DP_DE_DP500_CONTROL, DP_DE_DP500_CONTROL_CONFIG_REQ);\r
299 } else {\r
300 MmioOr32 (DP_BASE + DP_DC_CONTROL, DP_DC_CONTROL_CM_ACTIVE);\r
301 }\r
302}\r
303\r
304/** Set ARM Mali DP in normal mode.\r
305\r
306 Normal mode is the main operating mode of the display processor\r
307 in which display layer data is fetched from framebuffer and\r
308 displayed.\r
309**/\r
310STATIC\r
311VOID\r
312SetNormalMode (VOID)\r
313{\r
314 // Disable configuration Mode.\r
315 if (mDpDeviceId == MALIDP_500) {\r
316 MmioAnd32 (DP_BASE + DP_DE_DP500_CONTROL, ~DP_DE_DP500_CONTROL_CONFIG_REQ);\r
317 } else {\r
318 MmioAnd32 (DP_BASE + DP_DC_CONTROL, ~DP_DC_CONTROL_CM_ACTIVE);\r
319 }\r
320}\r
321\r
322/** Set the global configuration valid flag.\r
323\r
324 Any new configuration parameters written to the display engine are not\r
325 activated until the global configuration valid flag is set in the\r
326 CONFIG_VALID register.\r
327**/\r
328STATIC\r
329VOID\r
330SetConfigValid (VOID)\r
331{\r
332 if (mDpDeviceId == MALIDP_500) {\r
333 MmioOr32 (DP_BASE + DP_DP500_CONFIG_VALID, DP_DC_CONFIG_VALID);\r
334 } else {\r
335 MmioOr32 (DP_BASE + DP_DC_CONFIG_VALID, DP_DC_CONFIG_VALID);\r
336 }\r
337}\r
338\r
339/** Set requested mode of the display.\r
340\r
341 @param[in] ModeNumber Display mode number.\r
342\r
343 @retval EFI_SUCCESS Display mode set successful.\r
344 @retval EFI_DEVICE_ERROR Display mode not found/supported.\r
345**/\r
346EFI_STATUS\r
347LcdSetMode (\r
348 IN CONST UINT32 ModeNumber\r
349 )\r
350{\r
351 EFI_STATUS Status;\r
352 SCAN_TIMINGS *Horizontal;\r
353 SCAN_TIMINGS *Vertical;\r
354\r
355 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ModeInfo;\r
356\r
357 // Get the display mode timings and other relevant information.\r
358 Status = LcdPlatformGetTimings (\r
359 ModeNumber,\r
360 &Horizontal,\r
361 &Vertical\r
362 );\r
363 if (EFI_ERROR (Status)) {\r
364 ASSERT_EFI_ERROR (Status);\r
365 return Status;\r
366 }\r
367\r
368 ASSERT (Horizontal != NULL);\r
369 ASSERT (Vertical != NULL);\r
370\r
371 // Get the pixel format information.\r
372 Status = LcdPlatformQueryMode (ModeNumber, &ModeInfo);\r
373 if (EFI_ERROR (Status)) {\r
374 ASSERT_EFI_ERROR (Status);\r
375 return Status;\r
376 }\r
377\r
378 // Request configuration mode.\r
379 SetConfigurationMode ();\r
380\r
381 // Configure the graphics layer.\r
382 LayerGraphicsConfig (\r
383 ModeInfo.PixelFormat,\r
384 Horizontal->Resolution,\r
385 Vertical->Resolution\r
386 );\r
387\r
388 // Set the display engine timings.\r
389 SetDisplayEngineTiming (Horizontal, Vertical);\r
390\r
391 // After configuration, set Mali DP in normal mode.\r
392 SetNormalMode ();\r
393\r
394 // Any parameters written to the display engine are not activated until\r
395 // CONFIG_VALID is set.\r
396 SetConfigValid ();\r
397\r
398 return EFI_SUCCESS;\r
399}\r
400\r
401/** This function de-initializes the display.\r
402\r
403**/\r
404VOID\r
405LcdShutdown (VOID)\r
406{\r
407 // Disable graphics layer.\r
408 LayerGraphicsDisable ();\r
409}\r