/** @file

 Copyright (c) 2011-2014, ARM Ltd. All rights reserved.<BR>
 This program and the accompanying materials
 are licensed and made available under the terms and conditions of the BSD License
 which accompanies this distribution.  The full text of the license may be found at
 http://opensource.org/licenses/bsd-license.php

 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

 **/

#include <PiDxe.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DevicePathLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>

#include <Guid/GlobalVariable.h>

#include "LcdGraphicsOutputDxe.h"

/**********************************************************************
 *
 *  This file implements the Graphics Output protocol on ArmVersatileExpress
 *  using the Lcd controller
 *
 **********************************************************************/

//
// Global variables
//

BOOLEAN mDisplayInitialized = FALSE;

LCD_INSTANCE mLcdTemplate = {
  LCD_INSTANCE_SIGNATURE,
  NULL, // Handle
  { // ModeInfo
    0, // Version
    0, // HorizontalResolution
    0, // VerticalResolution
    PixelBltOnly, // PixelFormat
    { 0 }, // PixelInformation
    0, // PixelsPerScanLine
  },
  {
    0, // MaxMode;
    0, // Mode;
    NULL, // Info;
    0, // SizeOfInfo;
    0, // FrameBufferBase;
    0 // FrameBufferSize;
  },
  { // Gop
    LcdGraphicsQueryMode,  // QueryMode
    LcdGraphicsSetMode,    // SetMode
    LcdGraphicsBlt,        // Blt
    NULL                     // *Mode
  },
  { // DevicePath
    {
      {
        HARDWARE_DEVICE_PATH, HW_VENDOR_DP,
        { (UINT8) (sizeof(VENDOR_DEVICE_PATH)), (UINT8) ((sizeof(VENDOR_DEVICE_PATH)) >> 8) },
      },
      // Hardware Device Path for Lcd
      EFI_CALLER_ID_GUID // Use the driver's GUID
    },

    {
      END_DEVICE_PATH_TYPE,
      END_ENTIRE_DEVICE_PATH_SUBTYPE,
      { sizeof(EFI_DEVICE_PATH_PROTOCOL), 0 }
    }
  },
  (EFI_EVENT) NULL // ExitBootServicesEvent
};

EFI_STATUS
LcdInstanceContructor (
  OUT LCD_INSTANCE** NewInstance
  )
{
  LCD_INSTANCE* Instance;

  Instance = AllocateCopyPool (sizeof(LCD_INSTANCE), &mLcdTemplate);
  if (Instance == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  Instance->Gop.Mode          = &Instance->Mode;
  Instance->Gop.Mode->MaxMode = LcdPlatformGetMaxMode ();
  Instance->Mode.Info         = &Instance->ModeInfo;

  *NewInstance = Instance;
  return EFI_SUCCESS;
}

//
// Function Definitions
//

EFI_STATUS
InitializeDisplay (
  IN LCD_INSTANCE* Instance
  )
{
  EFI_STATUS             Status = EFI_SUCCESS;
  EFI_PHYSICAL_ADDRESS   VramBaseAddress;
  UINTN                  VramSize;

  Status = LcdPlatformGetVram (&VramBaseAddress, &VramSize);
  if (EFI_ERROR(Status)) {
    return Status;
  }

  // Setup the LCD
  Status = LcdInitialize (VramBaseAddress);
  if (EFI_ERROR(Status)) {
    goto EXIT_ERROR_LCD_SHUTDOWN;
  }

  Status = LcdPlatformInitializeDisplay (Instance->Handle);
  if (EFI_ERROR(Status)) {
    goto EXIT_ERROR_LCD_SHUTDOWN;
  }

  // Setup all the relevant mode information
  Instance->Gop.Mode->SizeOfInfo      = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
  Instance->Gop.Mode->FrameBufferBase = VramBaseAddress;

  // Set the flag before changing the mode, to avoid infinite loops
  mDisplayInitialized = TRUE;

  // All is ok, so don't deal with any errors
  goto EXIT;

EXIT_ERROR_LCD_SHUTDOWN:
  DEBUG((DEBUG_ERROR, "InitializeDisplay: ERROR - Can not initialise the display. Exit Status=%r\n", Status));
  LcdShutdown ();

EXIT:
  return Status;
}

EFI_STATUS
EFIAPI
LcdGraphicsOutputDxeInitialize (
  IN EFI_HANDLE         ImageHandle,
  IN EFI_SYSTEM_TABLE   *SystemTable
  )
{
  EFI_STATUS  Status = EFI_SUCCESS;
  LCD_INSTANCE* Instance;

  Status = LcdIdentify ();
  if (EFI_ERROR(Status)) {
    goto EXIT;
  }

  Status = LcdInstanceContructor (&Instance);
  if (EFI_ERROR(Status)) {
    goto EXIT;
  }

  // Install the Graphics Output Protocol and the Device Path
  Status = gBS->InstallMultipleProtocolInterfaces(
            &Instance->Handle,
            &gEfiGraphicsOutputProtocolGuid, &Instance->Gop,
            &gEfiDevicePathProtocolGuid,     &Instance->DevicePath,
            NULL
            );

  if (EFI_ERROR(Status)) {
    DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the protocol. Exit Status=%r\n", Status));
    goto EXIT;
  }

  // Register for an ExitBootServicesEvent
  // When ExitBootServices starts, this function here will make sure that the graphics driver will shut down properly,
  // i.e. it will free up all allocated memory and perform any necessary hardware re-configuration.
  Status = gBS->CreateEvent (
            EVT_SIGNAL_EXIT_BOOT_SERVICES,
            TPL_NOTIFY,
            LcdGraphicsExitBootServicesEvent, NULL,
            &Instance->ExitBootServicesEvent
            );

  if (EFI_ERROR(Status)) {
    DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the ExitBootServicesEvent handler. Exit Status=%r\n", Status));
    goto EXIT_ERROR_UNINSTALL_PROTOCOL;
  }

  // To get here, everything must be fine, so just exit
  goto EXIT;

EXIT_ERROR_UNINSTALL_PROTOCOL:
  /* The following function could return an error message,
   * however, to get here something must have gone wrong already,
   * so preserve the original error, i.e. don't change
   * the Status variable, even it fails to uninstall the protocol.
   */
  gBS->UninstallMultipleProtocolInterfaces (
    Instance->Handle,
    &gEfiGraphicsOutputProtocolGuid, &Instance->Gop, // Uninstall Graphics Output protocol
    &gEfiDevicePathProtocolGuid,     &Instance->DevicePath,     // Uninstall device path
    NULL
    );

EXIT:
  return Status;

}

/***************************************
 * This function should be called
 * on Event: ExitBootServices
 * to free up memory, stop the driver
 * and uninstall the protocols
 ***************************************/
VOID
LcdGraphicsExitBootServicesEvent (
  IN EFI_EVENT  Event,
  IN VOID       *Context
  )
{
  // By default, this PCD is FALSE. But if a platform starts a predefined OS that
  // does not use a framebuffer then we might want to disable the display controller
  // to avoid to display corrupted information on the screen.
  if (FeaturePcdGet (PcdGopDisableOnExitBootServices)) {
    // Turn-off the Display controller
    LcdShutdown ();
  }
}

/***************************************
 * GraphicsOutput Protocol function, mapping to
 * EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode
 ***************************************/
EFI_STATUS
EFIAPI
LcdGraphicsQueryMode (
  IN EFI_GRAPHICS_OUTPUT_PROTOCOL            *This,
  IN UINT32                                  ModeNumber,
  OUT UINTN                                  *SizeOfInfo,
  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION   **Info
  )
{
  EFI_STATUS Status = EFI_SUCCESS;
  LCD_INSTANCE *Instance;

  Instance = LCD_INSTANCE_FROM_GOP_THIS(This);

  // Setup the hardware if not already done
  if( !mDisplayInitialized ) {
    Status = InitializeDisplay(Instance);
    if (EFI_ERROR(Status)) {
      goto EXIT;
    }
  }

  // Error checking
  if ( (This == NULL) || (Info == NULL) || (SizeOfInfo == NULL) || (ModeNumber >= This->Mode->MaxMode) ) {
    DEBUG((DEBUG_ERROR, "LcdGraphicsQueryMode: ERROR - For mode number %d : Invalid Parameter.\n", ModeNumber ));
    Status = EFI_INVALID_PARAMETER;
    goto EXIT;
  }

  *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
  if (*Info == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto EXIT;
  }

  *SizeOfInfo = sizeof( EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);

  Status = LcdPlatformQueryMode (ModeNumber,*Info);
  if (EFI_ERROR(Status)) {
    FreePool(*Info);
  }

EXIT:
  return Status;
}

/***************************************
 * GraphicsOutput Protocol function, mapping to
 * EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode
 ***************************************/
EFI_STATUS
EFIAPI
LcdGraphicsSetMode (
  IN EFI_GRAPHICS_OUTPUT_PROTOCOL   *This,
  IN UINT32                         ModeNumber
  )
{
  EFI_STATUS                      Status = EFI_SUCCESS;
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL   FillColour;
  LCD_INSTANCE*                   Instance;
  LCD_BPP                         Bpp;

  Instance = LCD_INSTANCE_FROM_GOP_THIS (This);

  // Setup the hardware if not already done
  if(!mDisplayInitialized) {
    Status = InitializeDisplay (Instance);
    if (EFI_ERROR(Status)) {
      goto EXIT;
    }
  }

  // Check if this mode is supported
  if( ModeNumber >= This->Mode->MaxMode ) {
    DEBUG((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Unsupported mode number %d .\n", ModeNumber ));
    Status = EFI_UNSUPPORTED;
    goto EXIT;
  }

  // Set the oscillator frequency to support the new mode
  Status = LcdPlatformSetMode (ModeNumber);
  if (EFI_ERROR(Status)) {
    Status = EFI_DEVICE_ERROR;
    goto EXIT;
  }

  // Update the UEFI mode information
  This->Mode->Mode = ModeNumber;
  LcdPlatformQueryMode (ModeNumber,&Instance->ModeInfo);
  Status = LcdPlatformGetBpp(ModeNumber, &Bpp);
  if (EFI_ERROR(Status)) {
    DEBUG ((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Couldn't get bytes per pixel, status: %r\n", Status));
    goto EXIT;
  }
  This->Mode->FrameBufferSize =  Instance->ModeInfo.VerticalResolution
                               * Instance->ModeInfo.PixelsPerScanLine
                               * GetBytesPerPixel(Bpp);

  // Set the hardware to the new mode
  Status = LcdSetMode (ModeNumber);
  if (EFI_ERROR(Status)) {
    Status = EFI_DEVICE_ERROR;
    goto EXIT;
  }

  // The UEFI spec requires that we now clear the visible portions of the output display to black.

  // Set the fill colour to black
  SetMem (&FillColour, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);

  // Fill the entire visible area with the same colour.
  Status = This->Blt (
      This,
      &FillColour,
      EfiBltVideoFill,
      0,
      0,
      0,
      0,
      This->Mode->Info->HorizontalResolution,
      This->Mode->Info->VerticalResolution,
      0);

EXIT:
  return Status;
}

UINTN
GetBytesPerPixel (
  IN  LCD_BPP       Bpp
  )
{
  switch(Bpp) {
  case LCD_BITS_PER_PIXEL_24:
    return 4;

  case LCD_BITS_PER_PIXEL_16_565:
  case LCD_BITS_PER_PIXEL_16_555:
  case LCD_BITS_PER_PIXEL_12_444:
    return 2;

  case LCD_BITS_PER_PIXEL_8:
  case LCD_BITS_PER_PIXEL_4:
  case LCD_BITS_PER_PIXEL_2:
  case LCD_BITS_PER_PIXEL_1:
    return 1;

  default:
    return 0;
  }
}
