1 /** @file
2   This file contains the platform independent parts of HdLcd
3 
4   Copyright (c) 2011-2018, ARM Ltd. All rights reserved.<BR>
5 
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include <Library/DebugLib.h>
11 #include <Library/IoLib.h>
12 #include <Library/LcdHwLib.h>
13 #include <Library/LcdPlatformLib.h>
14 #include <Library/MemoryAllocationLib.h>
15 #include <Library/PcdLib.h>
16 
17 #include "HdLcd.h"
18 
19 #define BYTES_PER_PIXEL 4
20 
21 /** Initialize display.
22 
23   @param[in]  VramBaseAddress    Address of the framebuffer.
24 
25   @retval EFI_SUCCESS            Display initialization successful.
26 **/
27 EFI_STATUS
LcdInitialize(IN EFI_PHYSICAL_ADDRESS VramBaseAddress)28 LcdInitialize (
29   IN EFI_PHYSICAL_ADDRESS   VramBaseAddress
30   )
31 {
32   // Disable the controller
33   MmioWrite32 (HDLCD_REG_COMMAND, HDLCD_DISABLE);
34 
35   // Disable all interrupts
36   MmioWrite32 (HDLCD_REG_INT_MASK, 0);
37 
38   // Define start of the VRAM. This never changes for any graphics mode
39   MmioWrite32 (HDLCD_REG_FB_BASE, (UINT32)VramBaseAddress);
40 
41   // Setup various registers that never change
42   MmioWrite32 (HDLCD_REG_BUS_OPTIONS,  (4 << 8) | HDLCD_BURST_8);
43 
44   MmioWrite32 (HDLCD_REG_POLARITIES, HDLCD_DEFAULT_POLARITIES);
45 
46   MmioWrite32 (
47     HDLCD_REG_PIXEL_FORMAT,
48     HDLCD_LITTLE_ENDIAN | HDLCD_4BYTES_PER_PIXEL
49     );
50 
51   return EFI_SUCCESS;
52 }
53 
54 /** Set requested mode of the display.
55 
56   @param[in] ModeNumber          Display mode number.
57 
58   @retval EFI_SUCCESS            Display mode set successfully.
59   @retval !(EFI_SUCCESS)         Other errors.
60 **/
61 EFI_STATUS
LcdSetMode(IN UINT32 ModeNumber)62 LcdSetMode (
63   IN UINT32  ModeNumber
64   )
65 {
66   EFI_STATUS        Status;
67   SCAN_TIMINGS      *Horizontal;
68   SCAN_TIMINGS      *Vertical;
69 
70   EFI_GRAPHICS_PIXEL_FORMAT  PixelFormat;
71 
72   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  ModeInfo;
73 
74   // Set the video mode timings and other relevant information
75   Status = LcdPlatformGetTimings (
76              ModeNumber,
77              &Horizontal,
78              &Vertical
79              );
80   if (EFI_ERROR (Status)) {
81     ASSERT_EFI_ERROR (Status);
82     return Status;
83   }
84 
85   ASSERT (Horizontal != NULL);
86   ASSERT (Vertical != NULL);
87 
88   // Get the pixel format information.
89   Status = LcdPlatformQueryMode (ModeNumber, &ModeInfo);
90   if (EFI_ERROR (Status)) {
91     ASSERT_EFI_ERROR (Status);
92     return Status;
93   }
94 
95   // By default PcdArmHdLcdSwapBlueRedSelect is set to false
96   // However on the Juno platform HW lines for BLUE and RED are swapped
97   // Therefore PcdArmHdLcdSwapBlueRedSelect is set to TRUE for the Juno platform
98   PixelFormat = FixedPcdGetBool (PcdArmHdLcdSwapBlueRedSelect)
99                 ? PixelRedGreenBlueReserved8BitPerColor
100                 : PixelBlueGreenRedReserved8BitPerColor;
101 
102   if (ModeInfo.PixelFormat == PixelFormat) {
103     MmioWrite32 (HDLCD_REG_RED_SELECT,  (8 << 8) | 16);
104     MmioWrite32 (HDLCD_REG_BLUE_SELECT, (8 << 8) | 0);
105   } else {
106     MmioWrite32 (HDLCD_REG_BLUE_SELECT, (8 << 8) | 16);
107     MmioWrite32 (HDLCD_REG_RED_SELECT,  (8 << 8) | 0);
108   }
109 
110   MmioWrite32 (HDLCD_REG_GREEN_SELECT, (8 << 8) | 8);
111 
112   // Disable the controller
113   MmioWrite32 (HDLCD_REG_COMMAND, HDLCD_DISABLE);
114 
115   // Update the frame buffer information with the new settings
116   MmioWrite32 (
117     HDLCD_REG_FB_LINE_LENGTH,
118     Horizontal->Resolution * BYTES_PER_PIXEL
119     );
120 
121   MmioWrite32 (
122     HDLCD_REG_FB_LINE_PITCH,
123     Horizontal->Resolution * BYTES_PER_PIXEL
124     );
125 
126   MmioWrite32 (HDLCD_REG_FB_LINE_COUNT, Vertical->Resolution - 1);
127 
128   // Set the vertical timing information
129   MmioWrite32 (HDLCD_REG_V_SYNC,        Vertical->Sync);
130   MmioWrite32 (HDLCD_REG_V_BACK_PORCH,  Vertical->BackPorch);
131   MmioWrite32 (HDLCD_REG_V_DATA,        Vertical->Resolution - 1);
132   MmioWrite32 (HDLCD_REG_V_FRONT_PORCH, Vertical->FrontPorch);
133 
134   // Set the horizontal timing information
135   MmioWrite32 (HDLCD_REG_H_SYNC,        Horizontal->Sync);
136   MmioWrite32 (HDLCD_REG_H_BACK_PORCH,  Horizontal->BackPorch);
137   MmioWrite32 (HDLCD_REG_H_DATA,        Horizontal->Resolution - 1);
138   MmioWrite32 (HDLCD_REG_H_FRONT_PORCH, Horizontal->FrontPorch);
139 
140   // Enable the controller
141   MmioWrite32 (HDLCD_REG_COMMAND, HDLCD_ENABLE);
142 
143   return EFI_SUCCESS;
144 }
145 
146 /** De-initializes the display.
147 **/
148 VOID
LcdShutdown(VOID)149 LcdShutdown (
150   VOID
151   )
152 {
153   // Disable the controller
154   MmioWrite32 (HDLCD_REG_COMMAND, HDLCD_DISABLE);
155 }
156 
157 /** Check for presence of HDLCD.
158 
159   @retval EFI_SUCCESS            Returns success if platform implements a HDLCD
160                                  controller.
161   @retval EFI_NOT_FOUND          HDLCD display controller not found on the
162                                  platform.
163 **/
164 EFI_STATUS
LcdIdentify(VOID)165 LcdIdentify (
166   VOID
167   )
168 {
169   if ((MmioRead32 (HDLCD_REG_VERSION) >> 16) == HDLCD_PRODUCT_ID) {
170     return EFI_SUCCESS;
171   }
172 
173   return EFI_NOT_FOUND;
174 }
175