1 /** @file
2   This file contains the platform independent parts of PL111Lcd
3 
4   Copyright (c) 2011-2018, ARM Ltd. All rights reserved.<BR>
5 
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 #include <Library/DebugLib.h>
10 #include <Library/IoLib.h>
11 #include <Library/LcdHwLib.h>
12 #include <Library/LcdPlatformLib.h>
13 #include <Library/MemoryAllocationLib.h>
14 
15 #include "PL111Lcd.h"
16 
17 /** Check for presence of PL111.
18 
19   @retval EFI_SUCCESS          Returns success if platform implements a
20                                PL111 controller.
21 
22   @retval EFI_NOT_FOUND        PL111 display controller not found the plaform.
23 **/
24 EFI_STATUS
LcdIdentify(VOID)25 LcdIdentify (
26   VOID
27   )
28 {
29   DEBUG ((EFI_D_WARN, "Probing ID registers at 0x%lx for a PL111\n",
30     PL111_REG_CLCD_PERIPH_ID_0));
31 
32   // Check if this is a PL111
33   if (MmioRead8 (PL111_REG_CLCD_PERIPH_ID_0) == PL111_CLCD_PERIPH_ID_0 &&
34       MmioRead8 (PL111_REG_CLCD_PERIPH_ID_1) == PL111_CLCD_PERIPH_ID_1 &&
35      (MmioRead8 (PL111_REG_CLCD_PERIPH_ID_2) & 0xf) == PL111_CLCD_PERIPH_ID_2 &&
36       MmioRead8 (PL111_REG_CLCD_PERIPH_ID_3) == PL111_CLCD_PERIPH_ID_3 &&
37       MmioRead8 (PL111_REG_CLCD_P_CELL_ID_0) == PL111_CLCD_P_CELL_ID_0 &&
38       MmioRead8 (PL111_REG_CLCD_P_CELL_ID_1) == PL111_CLCD_P_CELL_ID_1 &&
39       MmioRead8 (PL111_REG_CLCD_P_CELL_ID_2) == PL111_CLCD_P_CELL_ID_2 &&
40       MmioRead8 (PL111_REG_CLCD_P_CELL_ID_3) == PL111_CLCD_P_CELL_ID_3) {
41     return EFI_SUCCESS;
42   }
43   return EFI_NOT_FOUND;
44 }
45 
46 /** Initialize display.
47 
48   @param[in]  VramBaseAddress    Address of the framebuffer.
49 
50   @retval EFI_SUCCESS            Initialization of display successful.
51 **/
52 EFI_STATUS
LcdInitialize(IN EFI_PHYSICAL_ADDRESS VramBaseAddress)53 LcdInitialize (
54   IN EFI_PHYSICAL_ADDRESS   VramBaseAddress
55   )
56 {
57   // Define start of the VRAM. This never changes for any graphics mode
58   MmioWrite32 (PL111_REG_LCD_UP_BASE, (UINT32)VramBaseAddress);
59   MmioWrite32 (PL111_REG_LCD_LP_BASE, 0); // We are not using a double buffer
60 
61   // Disable all interrupts from the PL111
62   MmioWrite32 (PL111_REG_LCD_IMSC, 0);
63 
64   return EFI_SUCCESS;
65 }
66 
67 /** Set requested mode of the display.
68 
69   @param[in] ModeNumbe           Display mode number.
70 
71   @retval EFI_SUCCESS            Display mode set successfuly.
72   @retval !(EFI_SUCCESS)         Other errors.
73 **/
74 EFI_STATUS
LcdSetMode(IN UINT32 ModeNumber)75 LcdSetMode (
76   IN UINT32  ModeNumber
77   )
78 {
79   EFI_STATUS        Status;
80   SCAN_TIMINGS      *Horizontal;
81   SCAN_TIMINGS      *Vertical;
82   UINT32            LcdControl;
83   LCD_BPP           LcdBpp;
84 
85   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  ModeInfo;
86 
87   // Set the video mode timings and other relevant information
88   Status = LcdPlatformGetTimings (
89              ModeNumber,
90              &Horizontal,
91              &Vertical
92              );
93   if (EFI_ERROR (Status)) {
94     ASSERT_EFI_ERROR (Status);
95     return Status;
96   }
97 
98   ASSERT (Horizontal != NULL);
99   ASSERT (Vertical != NULL);
100 
101   Status = LcdPlatformGetBpp (ModeNumber, &LcdBpp);
102   if (EFI_ERROR (Status)) {
103     ASSERT_EFI_ERROR (Status);
104     return Status;
105   }
106 
107   // Get the pixel format information
108   Status = LcdPlatformQueryMode (ModeNumber, &ModeInfo);
109   if (EFI_ERROR (Status)) {
110     ASSERT_EFI_ERROR (Status);
111     return Status;
112   }
113 
114   // Disable the CLCD_LcdEn bit
115   MmioAnd32 (PL111_REG_LCD_CONTROL, ~PL111_CTRL_LCD_EN);
116 
117   // Set Timings
118   MmioWrite32 (
119     PL111_REG_LCD_TIMING_0,
120     HOR_AXIS_PANEL (
121       Horizontal->BackPorch,
122       Horizontal->FrontPorch,
123       Horizontal->Sync,
124       Horizontal->Resolution
125       )
126     );
127 
128   MmioWrite32 (
129     PL111_REG_LCD_TIMING_1,
130     VER_AXIS_PANEL (
131       Vertical->BackPorch,
132       Vertical->FrontPorch,
133       Vertical->Sync,
134       Vertical->Resolution
135       )
136     );
137 
138   MmioWrite32 (
139     PL111_REG_LCD_TIMING_2,
140     CLK_SIG_POLARITY (Horizontal->Resolution)
141     );
142 
143   MmioWrite32 (PL111_REG_LCD_TIMING_3, 0);
144 
145   // PL111_REG_LCD_CONTROL
146   LcdControl = PL111_CTRL_LCD_EN | PL111_CTRL_LCD_BPP (LcdBpp) |
147                PL111_CTRL_LCD_TFT | PL111_CTRL_LCD_PWR;
148   if (ModeInfo.PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
149     LcdControl |= PL111_CTRL_BGR;
150   }
151   MmioWrite32 (PL111_REG_LCD_CONTROL, LcdControl);
152 
153   return EFI_SUCCESS;
154 }
155 
156 /** De-initializes the display.
157 */
158 VOID
LcdShutdown(VOID)159 LcdShutdown (
160   VOID
161   )
162 {
163   // Disable the controller
164   MmioAnd32 (PL111_REG_LCD_CONTROL, ~PL111_CTRL_LCD_EN);
165 }
166