From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2a00:1450:4864:20::442; helo=mail-wr1-x442.google.com; envelope-from=leif.lindholm@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-wr1-x442.google.com (mail-wr1-x442.google.com [IPv6:2a00:1450:4864:20::442]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id E6085211A45A6 for ; Fri, 14 Dec 2018 14:37:48 -0800 (PST) Received: by mail-wr1-x442.google.com with SMTP id q18so6869103wrx.9 for ; Fri, 14 Dec 2018 14:37:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=1iZOcWCslN4w0BBLKrUNc47vONKBG9joBqUXxSQ7JXI=; b=MjP2JEnTrfM6gT5fVVZbNo7kyNN/tNx1k4W+RCjOROIWfZv4MfDbWj1tr+sNrxlYFr RfIh6DXP2zROlgQFv+2PicTwG/dTn8fsXokDiwSFYK85myF+gp0ALxU/IrYMnhOzNV9M Mm/06Sda1GLRR4QdxmdxArkWofB7bZQUnaZVE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=1iZOcWCslN4w0BBLKrUNc47vONKBG9joBqUXxSQ7JXI=; b=cwrOkgMhrG7GvwoTMVbwiqZ/1C/YFAiqm1DRhaYfWB0j6jsxvnPqYn+1zxL6EgXW15 kulNAXlg/N5zIQ6SPr+liHL1RFbBdAZAlgJtL+a6lKhEBKKmcmGRupy5GImW+qkcuUR4 wUTSfc6q/b2nmZrZHuc6DHlO/XJ+qZGKtHTnIA7bdDSX8sM9uVIJb9zqvwnREvQ6jG32 Uhju1J4ZjthMEv2tQOSGfxFsEyYCAPYGQy6TBx8divUfTjWwizlrgeSLt11zZuzeJksR 9kZFbG6YqkmZHJx6anoIfULcvmsPdUYC0zKe14HFVIDkdr95Dlx0j1zYueLP6JjUScZU FASw== X-Gm-Message-State: AA+aEWYeBPj707mEqU0bsDz5F9xRw07l+NqcPTesEtf3AeYjlkFbHt78 +B0zCIWrZIsx/B+FVp7G0A53fg== X-Google-Smtp-Source: AFSGD/U9pazA8NPCHgYU+q2n+9ZLgBrzcrPguTxld2CZnlGAkKJNOCMir5RdGbP+MmjS+BhIYX7k6Q== X-Received: by 2002:adf:ef0d:: with SMTP id e13mr3912421wro.29.1544827065825; Fri, 14 Dec 2018 14:37:45 -0800 (PST) Received: from bivouac.eciton.net (bivouac.eciton.net. [2a00:1098:0:86:1000:23:0:2]) by smtp.gmail.com with ESMTPSA id e12sm13698454wmf.22.2018.12.14.14.37.44 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 14 Dec 2018 14:37:44 -0800 (PST) Date: Fri, 14 Dec 2018 22:37:43 +0000 From: Leif Lindholm To: Chris Co Cc: "edk2-devel@lists.01.org" , Ard Biesheuvel , Michael D Kinney Message-ID: <20181214223743.b6txd5zchffy6apr@bivouac.eciton.net> References: <20180921082542.35768-1-christopher.co@microsoft.com> <20180921082542.35768-23-christopher.co@microsoft.com> MIME-Version: 1.0 In-Reply-To: <20180921082542.35768-23-christopher.co@microsoft.com> User-Agent: NeoMutt/20170113 (1.7.2) Subject: Re: [PATCH edk2-platforms 22/27] Silicon/NXP: Add i.MX6 GOP driver X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Dec 2018 22:37:49 -0000 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Fri, Sep 21, 2018 at 08:26:15AM +0000, Chris Co wrote: > This adds GOP display support for NXP i.MX6 SoCs. It has support for > HDMI, LVDS, IPU, and parses EDID using I2C. > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Christopher Co > Cc: Ard Biesheuvel > Cc: Leif Lindholm > Cc: Michael D Kinney This patch is massive. I would be lying if I said I have given it a proper review - but I do have some comments sprinkled below. > --- > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c | 423 +++++++++++ > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h | 277 +++++++ > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c | 69 ++ > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h | 28 + > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c | 455 ++++++++++++ > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h | 175 +++++ > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c | 399 ++++++++++ > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h | 331 +++++++++ > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c | 458 ++++++++++++ > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h | 195 +++++ > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c | 96 +++ > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h | 33 + > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c | 475 ++++++++++++ > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h | 20 + > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf | 70 ++ > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c | 761 ++++++++++++++++++++ > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h | 529 ++++++++++++++ > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c | 88 +++ > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h | 32 + > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h | 236 ++++++ > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c | 93 +++ > Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h | 67 ++ > 22 files changed, 5310 insertions(+) > > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c > new file mode 100644 > index 000000000000..a8ab78128719 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.c What does CP stand for? Worth adding to the file header. > @@ -0,0 +1,423 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* > +* 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 > + > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +#include "Display.h" > +#include "CPMem.h" > +#include "GopDxe.h" > +#include "Ipu.h" > + > +CPMEM_PARAM *CpMemParamBasePtr = (CPMEM_PARAM *)(IPU1_BASE + CSP_IPUV3_CPMEM_REGS_OFFSET); Is this meant to be externally visible, or could it be STATIC? It needs a g- or m-prefix. > + > +STATIC CONST UINT8 ChannelMap[] = { Please add m-prefix. > + 5, 0, > + 11, 2, > + 12, 4, > + 14, 6, > + 15, 8, > + 20, 10, > + 21, 12, > + 22, 14, > + 23, 16, > + 27, 18, > + 28, 20, > + 45, 0, > + 46, 2, > + 47, 4, > + 48, 6, > + 49, 8, > + 50, 10, > +}; > + > +#ifdef DEBUG > +VOID > +DumpCpmemParamPack ( > + IN CPMEM_PARAM *ParamPtr > + ) > +{ > + DEBUG ((DEBUG_VERBOSE, "%a: --WORD0--\n", __FUNCTION__)); > + DEBUG ((DEBUG_VERBOSE, "%a: XVVirtualCoordinate 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.XVVirtualCoordinate)); > + DEBUG ((DEBUG_VERBOSE, "%a: YVVirtualCoordinate 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.YVVirtualCoordinate)); > + DEBUG ((DEBUG_VERBOSE, "%a: XBinnerBlockCoordinate 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.XBinnerBlockCoordinate)); > + DEBUG ((DEBUG_VERBOSE, "%a: YBinnerBlockCoordinate 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.YBinnerBlockCoordinate)); > + DEBUG ((DEBUG_VERBOSE, "%a: NewSubBlock 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.NewSubBlock)); > + DEBUG ((DEBUG_VERBOSE, "%a: CurrentField 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.CurrentField)); > + DEBUG ((DEBUG_VERBOSE, "%a: ScrollXCounter 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.ScrollXCounter)); > + DEBUG ((DEBUG_VERBOSE, "%a: ScrollYCounter 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.ScrollYCounter)); > + DEBUG ((DEBUG_VERBOSE, "%a: NumberOfScroll 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.NumberOfScroll)); > + DEBUG ((DEBUG_VERBOSE, "%a: ScrollDeltaX 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.ScrollDeltaX)); > + DEBUG ((DEBUG_VERBOSE, "%a: ScrollMax 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.ScrollMax)); > + DEBUG ((DEBUG_VERBOSE, "%a: ScrollingConfiguration 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.ScrollingConfiguration)); > + DEBUG ((DEBUG_VERBOSE, "%a: ScrollingEnable 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.ScrollingEnable)); > + DEBUG ((DEBUG_VERBOSE, "%a: ScrollDeltaY 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.ScrollDeltaY)); > + DEBUG ((DEBUG_VERBOSE, "%a: ScrollHorizontalDirection 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.ScrollHorizontalDirection)); > + DEBUG ((DEBUG_VERBOSE, "%a: ScrollVerticalDirection 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.ScrollVerticalDirection)); > + DEBUG ((DEBUG_VERBOSE, "%a: BitsPerPixel 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.BitsPerPixel)); > + DEBUG ((DEBUG_VERBOSE, "%a: DecodeAddressSelect 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.DecodeAddressSelect)); > + DEBUG ((DEBUG_VERBOSE, "%a: AccessDimension 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.AccessDimension)); > + DEBUG ((DEBUG_VERBOSE, "%a: ScanOrder 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.ScanOrder)); > + DEBUG ((DEBUG_VERBOSE, "%a: BandMode 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.BandMode)); > + DEBUG ((DEBUG_VERBOSE, "%a: BlockMode 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.BlockMode)); > + DEBUG ((DEBUG_VERBOSE, "%a: Rotation 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.Rotation)); > + DEBUG ((DEBUG_VERBOSE, "%a: HorizontalFlip 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.HorizontalFlip)); > + DEBUG ((DEBUG_VERBOSE, "%a: VerticalFlip 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.VerticalFlip)); > + DEBUG ((DEBUG_VERBOSE, "%a: ThresholdEnable 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.ThresholdEnable)); > + DEBUG ((DEBUG_VERBOSE, "%a: ConditionalAccessPolarity 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.ConditionalAccessPolarity)); > + DEBUG ((DEBUG_VERBOSE, "%a: ConditionalAccessEnable 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.ConditionalAccessEnable)); > + DEBUG ((DEBUG_VERBOSE, "%a: FrameWidth 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.FrameWidth)); > + DEBUG ((DEBUG_VERBOSE, "%a: FrameHeight 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.FrameHeight)); > + DEBUG ((DEBUG_VERBOSE, "%a: EndOfLineInterrupt 0x%08x\n", __FUNCTION__, > + ParamPtr->Word0Pack.EndOfLineInterrupt)); > + > + DEBUG ((DEBUG_VERBOSE, "%a: --WORD1--\n", __FUNCTION__)); > + DEBUG ((DEBUG_VERBOSE, "%a: ExtMemBuffer0Address 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.ExtMemBuffer0Address)); > + DEBUG ((DEBUG_VERBOSE, "%a: ExtMemBuffer1Address 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.ExtMemBuffer1Address)); > + DEBUG ((DEBUG_VERBOSE, "%a: InterlaceOffset 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.InterlaceOffset)); > + DEBUG ((DEBUG_VERBOSE, "%a: NumberOfPixelsInWholeBurstAccess 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.NumberOfPixelsInWholeBurstAccess)); > + DEBUG ((DEBUG_VERBOSE, "%a: PixelFormatSelect 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.PixelFormatSelect)); > + DEBUG ((DEBUG_VERBOSE, "%a: AlphaUsed 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.AlphaUsed)); > + DEBUG ((DEBUG_VERBOSE, "%a: AlphaChannelMapping 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.AlphaChannelMapping)); > + DEBUG ((DEBUG_VERBOSE, "%a: AxiId 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.AxiId)); > + DEBUG ((DEBUG_VERBOSE, "%a: Threshold 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.Threshold)); > + DEBUG ((DEBUG_VERBOSE, "%a: StrideLine 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.StrideLine)); > + DEBUG ((DEBUG_VERBOSE, "%a: Width0 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.Width0)); > + DEBUG ((DEBUG_VERBOSE, "%a: Width1 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.Width1)); > + DEBUG ((DEBUG_VERBOSE, "%a: Width2 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.Width2)); > + DEBUG ((DEBUG_VERBOSE, "%a: Width3 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.Width3)); > + DEBUG ((DEBUG_VERBOSE, "%a: Offset0 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.Offset0)); > + DEBUG ((DEBUG_VERBOSE, "%a: Offset1 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.Offset1)); > + DEBUG ((DEBUG_VERBOSE, "%a: Offset2 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.Offset2)); > + DEBUG ((DEBUG_VERBOSE, "%a: Offset3 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.Offset3)); > + DEBUG ((DEBUG_VERBOSE, "%a: SelectSXSYSet 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.SelectSXSYSet)); > + DEBUG ((DEBUG_VERBOSE, "%a: ConditionalReadEnable 0x%08x\n", __FUNCTION__, > + ParamPtr->Word1Pack.ConditionalReadEnable)); > +} > + > +VOID > +DumpBasicCpmemReg ( > + IN CPMEM_PARAM *pCpmemChannel > + ) > +{ > + DEBUG ((DEBUG_VERBOSE, "%a: ---------- CPMEM Register Dump ----------\n", > + __FUNCTION__)); > + DEBUG ((DEBUG_VERBOSE, "%a: CPMEM\n", __FUNCTION__)); > + DEBUG ((DEBUG_VERBOSE, "%a: IDMAC_CHANNEL_DP_PRIMARY_FLOW_MAIN_PLANE\n", > + __FUNCTION__)); > + DumpCpmemParamPack (pCpmemChannel); > + DEBUG ((DEBUG_VERBOSE, "%a: ------------------------------------\n", > + __FUNCTION__)); > +} > +#endif /* DEBUG */ > + > +// Enable IDMAC lock setting, which optimises memory accesses and reduces > +// power consumption > +VOID > +SetIdmacLockEn ( > + IN DISPLAY_INTERFACE_CONTEXT *DisplayInterfaceContextPtr, > + IN UINT32 Channel, > + IN UINT32 Setting > + ) > +{ > + UINT32 i; > + UINTN LockReg; > + UINT32 Shift; > + UINT32 Value; > + > + Shift = -1; > + > + for (i = 0; i < ARRAYSIZE (ChannelMap); i += 2) { > + if (ChannelMap[i] == Channel) { > + Shift = ChannelMap[i + 1]; > + break; > + } > + } > + > + if (Shift == -1) { > + DEBUG ((DEBUG_WARN, "%a: Channel %d does not have lock bits\n", > + __FUNCTION__, Channel)); > + return; > + } > + > + if (Channel < 29) { > + LockReg = (UINTN)DisplayInterfaceContextPtr->IpuMmioBasePtr + IPU_IDMAC_LOCK_EN_1; > + } else { > + LockReg = (UINTN)DisplayInterfaceContextPtr->IpuMmioBasePtr + IPU_IDMAC_LOCK_EN_2; > + } > + > + Value = MmioRead32 ((UINT32)LockReg); > + Value &= ~(0x3 << Shift); > + Value |= (Setting & 0x3) << Shift; > + MmioWrite32 ((UINT32)LockReg, Value); > +} > + > +EFI_STATUS > +ConfigureCpmemFrameBuffer ( > + IN DISPLAY_INTERFACE_CONTEXT *DisplayInterfaceContextPtr, > + IN UINT32 Channel, > + IN SURFACE_INFO *FrameBufferPtr > + ) > +{ > + CPMEM_PARAM *pCpmemChannel; > + EFI_STATUS Status; > + CPMEM_WORD0_PACKED_REG CpmemWord0PackedReg; > + CPMEM_WORD1_PACKED_REG CpmemWord1PackedReg; > + CPMEM_DEC_SEL DecodeAddressSelect; > + UINT32 PixelBurst; > + CPMEM_PFS_PACKED PixelFormatSelector; > + UINT32 Width0; > + UINT32 Width1; > + UINT32 Width2; > + UINT32 Width3; > + UINT32 Offset0; > + UINT32 Offset1; > + UINT32 Offset2; > + UINT32 Offset3; > + UINT32 BytesPerPixel; > + > + pCpmemChannel = DisplayInterfaceContextPtr->CpMemParamBasePtr; > + Status = EFI_SUCCESS; > + PixelBurst = 1; > + DecodeAddressSelect = CPMEM_DEC_SEL_0_15; // Only applicable for 4 bpp > + ZeroMem (&CpmemWord0PackedReg, sizeof (CpmemWord0PackedReg)); > + ZeroMem (&CpmemWord1PackedReg, sizeof (CpmemWord1PackedReg)); > + > + switch (FrameBufferPtr->PixelFormat) { > + case PIXEL_FORMAT_BGRA32: > + PixelBurst = 15; // 16 Pixel. Valid range is 1 - 64 pixel > + PixelFormatSelector = CPMEM_PFS_RGB; > + Offset0 = 8; > + Offset1 = 16; > + Offset2 = 24; > + Offset3 = 0; > + BytesPerPixel = 4; > + break; > + default: > + ASSERT (FALSE); > + Status = EFI_UNSUPPORTED; > + break; > + } > + if (EFI_ERROR (Status)) { > + goto Exit; > + } > + > + switch (FrameBufferPtr->Bpp) { > + case 8: > + Width0 = 0; > + Width1 = 0; > + Width2 = 0; > + Width3 = 0; > + break; > + case 32: > + if (PixelFormatSelector == CPMEM_PFS_RGB) { > + Width0 = 7; > + Width1 = 7; > + Width2 = 7; > + Width3 = 7; > + } else { > + Width0 = 0; > + Width1 = 0; > + Width2 = 0; > + Width3 = 0; > + } > + break; > + default: > + ASSERT (FALSE); > + Status = EFI_UNSUPPORTED; > + break; > + } > + if (EFI_ERROR (Status)) { > + goto Exit; > + } > + // Setting up CPMEM word 0 > + CpmemWord0PackedReg.XVVirtualCoordinate = 0; > + CpmemWord0PackedReg.YVVirtualCoordinate = 0; > + > + // Subblock is unused although expect to have some Value after write > + CpmemWord0PackedReg.XBinnerBlockCoordinate = 0; > + CpmemWord0PackedReg.YBinnerBlockCoordinate = 0; > + CpmemWord0PackedReg.NewSubBlock = 0; > + > + // Verify "current field" definition > + CpmemWord0PackedReg.CurrentField = 0; > + > + // Disable scrolling > + CpmemWord0PackedReg.ScrollXCounter = 0; > + CpmemWord0PackedReg.ScrollYCounter = 0; > + CpmemWord0PackedReg.NumberOfScroll = 0; > + CpmemWord0PackedReg.ScrollDeltaX = 0; > + CpmemWord0PackedReg.ScrollMax = 0; > + CpmemWord0PackedReg.ScrollingConfiguration = 0; > + CpmemWord0PackedReg.ScrollingEnable = 0; > + CpmemWord0PackedReg.ScrollDeltaY = 0; > + CpmemWord0PackedReg.ScrollHorizontalDirection = 0; > + CpmemWord0PackedReg.ScrollVerticalDirection = 0; > + > + // Bits per pixel > + CpmemWord0PackedReg.BitsPerPixel = FrameBufferPtr->Bpp; > + > + // Decode Address Select > + CpmemWord0PackedReg.DecodeAddressSelect = DecodeAddressSelect; > + > + // Scan order is progressive no support for interlace mode > + CpmemWord0PackedReg.ScanOrder = CPMEM_SO_PROGRESSIVE; > + > + // Band mode is sub frame double buffering > + CpmemWord0PackedReg.BandMode = CPMEM_BNDM_DISABLE; > + > + // Block mode used for post filtering and rotation > + CpmemWord0PackedReg.BlockMode = CPMEM_BM_DISABLE; > + > + // No support for rotation and flipping for now > + CpmemWord0PackedReg.Rotation = CPMEM_ROT_NO_ROTATION; > + CpmemWord0PackedReg.HorizontalFlip = CPMEM_HF_NO_HFLIP; > + CpmemWord0PackedReg.VerticalFlip = CPMEM_HF_NO_VFLIP; > + CpmemWord0PackedReg.ThresholdEnable = CPMEM_THE_DISABLE; > + > + // Disable conditional access > + CpmemWord0PackedReg.ConditionalAccessEnable = CPMEM_CAP_SKIP_LOW; > + CpmemWord0PackedReg.ConditionalAccessPolarity = CPMEM_CAE_DISABLE; > + > + // Frame width and height, minus one as 0 == 1 pixel > + CpmemWord0PackedReg.FrameWidth = FrameBufferPtr->Width - 1; > + CpmemWord0PackedReg.FrameHeight = FrameBufferPtr->Height - 1; > + > + // No interrupt required at the end of line > + CpmemWord0PackedReg.EndOfLineInterrupt = CPMEM_EOLI_DISABLE; > + > + // Setting up CPMEM word 1 > + // Buffer 0, use the [31:3] bit address > + CpmemWord1PackedReg.ExtMemBuffer0Address = FrameBufferPtr->PhyAddr >> 3; > + > + // Buffer 1, use the same buffer for now > + CpmemWord1PackedReg.ExtMemBuffer1Address = FrameBufferPtr->PhyAddr >> 3; > + > + // Currently do not support interlace mode > + CpmemWord1PackedReg.InterlaceOffset = 0; > + > + // Pixel format and burst > + CpmemWord1PackedReg.NumberOfPixelsInWholeBurstAccess = PixelBurst; > + CpmemWord1PackedReg.PixelFormatSelect = PixelFormatSelector; > + > + // Alpha config > + CpmemWord1PackedReg.AlphaUsed = CPMEM_ALU_SAME_BUFFER; > + > + // AXI ID 0 should be okay, we don't have anything else contending for it > + CpmemWord1PackedReg.AxiId = CPMEM_ID_ID_0; > + > + CpmemWord1PackedReg.Threshold = CPMEM_THE_DISABLE; > + > + // Stride, width and offset > + CpmemWord1PackedReg.StrideLine = (FrameBufferPtr->Pitch * BytesPerPixel) - 1; > + CpmemWord1PackedReg.Width0 = Width0; > + CpmemWord1PackedReg.Width1 = Width1; > + CpmemWord1PackedReg.Width2 = Width2; > + CpmemWord1PackedReg.Width3 = Width3; > + CpmemWord1PackedReg.Offset0 = Offset0; > + CpmemWord1PackedReg.Offset1 = Offset1; > + CpmemWord1PackedReg.Offset2 = Offset2; > + CpmemWord1PackedReg.Offset3 = Offset3; > + > + // SX SY is ignored since scrolling is disabled > + CpmemWord1PackedReg.SelectSXSYSet = 0; > + > + // Conditional read is always enabled so fully transperant pixel are > + // not read. > + CpmemWord1PackedReg.ConditionalReadEnable = CPMEM_CRE_ENABLE; > + > + // Finally write into cpmem IDMAC channel > + pCpmemChannel = (pCpmemChannel + Channel); > + > + CopyMem ( > + &pCpmemChannel->Word0Pack, > + &CpmemWord0PackedReg, > + sizeof (pCpmemChannel->Word0Pack) > + ); > + > + CopyMem ( > + &pCpmemChannel->Word1Pack, > + &CpmemWord1PackedReg, > + sizeof (pCpmemChannel->Word1Pack) > + ); > + > + // IDMAC will generate 8 AXI bursts upon assertion of the DMA request > + // This significantly reduces memory activity and power consumption > + SetIdmacLockEn (DisplayInterfaceContextPtr, Channel, 0x3); > + > +#ifdef DEBUG > + DumpBasicCpmemReg (pCpmemChannel); > +#endif /* DEBUG */ > + > +Exit: > + return Status; > +} > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h > new file mode 100644 > index 000000000000..06e96538f2d1 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/CPMem.h > @@ -0,0 +1,277 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* > +* 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. > +* > +**/ > + > +#ifndef _CPMEM_H_ > +#define _CPMEM_H_ Please add an IMX6 prefix. > + > +// IDMAC channel definition > +#define IDMAC_CHANNEL_CSI_0 0 > +#define IDMAC_CHANNEL_CSI_1 1 > +#define IDMAC_CHANNEL_CSI_2 2 > +#define IDMAC_CHANNEL_CSI_3 3 > +#define IDMAC_CHANNEL_VDIC_VF1_VF2 5 > +#define IDMAC_CHANNEL_VDIC_PREVIOUS_FIELD 8 > +#define IDMAC_CHANNEL_VDIC_CURRENT_FIELD 9 > +#define IDMAC_CHANNEL_VDIC_NEXT_FIELD 10 > +#define IDMAC_CHANNEL_IC_VIDEO_POST_PROCESSSING 11 > +#define IDMAC_CHANNEL_IC_VIDEO_PRP_TASK 12 > + > +#define IDMAC_CHANNEL_DP_PRIMARY_FLOW_MAIN_PLANE 23 > + > +typedef enum { > + CPMEM_SO_PROGRESSIVE, > + CPMEM_SO_INTERLACE, > +} CPMEM_SO; > + > +typedef enum { > + CPMEM_BNDM_DISABLE, > + CPMEM_BNDM_BAND_HEIGHT_4, > + CPMEM_BNDM_BAND_HEIGHT_8, > + CPMEM_BNDM_BAND_HEIGHT_16, > + CPMEM_BNDM_BAND_HEIGHT_32, > + CPMEM_BNDM_BAND_HEIGHT_64, > + CPMEM_BNDM_BAND_HEIGHT_128, > + CPMEM_BNDM_BAND_HEIGHT_256, > +} CPMEM_BNDM; > + > +typedef enum { > + CPMEM_BM_DISABLE, > + CPMEM_BM_BW_BH_8, > + CPMEM_BM_BW_BH_16, > + CPMEM_BM_UNUSED, > +} CPMEM_BM; > + > +typedef enum { > + CPMEM_ROT_NO_ROTATION, > + CPMEM_ROT_90_ROTATION, > +} CPMEM_ROT; > + > +typedef enum { > + CPMEM_HF_NO_HFLIP, > + CPMEM_HF_HFLIP_ENABLE, > +} CPMEM_HF; > + > +typedef enum { > + CPMEM_HF_NO_VFLIP, > + CPMEM_HF_VFLIP_ENABLE, > +} CPMEM_VF; > + > +typedef enum { > + CPMEM_THE_DISABLE, > + CPMEM_THE_ENABLE, > +} CPMEM_THE; > + > +typedef enum { > + CPMEM_CAP_SKIP_LOW, > + CPMEM_CAP_SKIP_HIGH, > +} CPMEM_CAP; > + > +typedef enum { > + CPMEM_CAE_DISABLE, > + CPMEM_CAE_ENABLE, > +} CPMEM_CAE; > + > +typedef enum { > + CPMEM_EOLI_DISABLE, > + CPMEM_EOLI_ENABLE, > +} CPMEM_EOLI; > + > +typedef enum { > + CPMEM_PFS_NON_INT_444, > + CPMEM_PFS_NON_INT_422, > + CPMEM_PFS_NON_INT_420, > + CPMEM_PFS_PAR_INT_422, > + CPMEM_PFS_PAR_INT_420, > +} CPMEM_PFS_PLANAR; > + > +typedef enum { > + CPMEM_DEC_SEL_0_15, > + CPMEM_DEC_SEL_64_79, > + CPMEM_DEC_SEL_128_143, > + CPMEM_DEC_SEL_192_207, > +} CPMEM_DEC_SEL; > + > +typedef enum { > + CPMEM_PFS_CODE = 5, > + CPMEM_PFS_GENERIC_DATA, > + CPMEM_PFS_RGB, > + CPMEM_PFS_INT_422_Y1U1Y2V1, > + CPMEM_PFS_INT_422_Y2U1Y1V1, > + CPMEM_PFS_INT_422_U1Y1V1Y2, > + CPMEM_PFS_INT_422_U1Y2V1Y1, > +} CPMEM_PFS_PACKED; > + > +typedef enum { > + CPMEM_ALU_SAME_BUFFER, > + CPMEM_ALU_SEPERATE_BUFFER, > +} CPMEM_ALU; > + > +typedef enum { > + CPMEM_ID_ID_0, > + CPMEM_ID_ID_1, > + CPMEM_ID_ID_2, > + CPMEM_ID_ID_3, > +} CPMEM_ID; > + > +typedef enum { > + CPMEM_CRE_DISABLE, > + CPMEM_CRE_ENABLE, > +} CPMEM_CRE; > + > +#pragma pack(push, 1) > + > +// CPMEM_WORD0_PLANAR - Non interlaved > +typedef union { > + struct { > + UINT32 XVVirtualCoordinate : 10; > + UINT32 YVVirtualCoordinate : 9; > + UINT32 XBinnerBlockCoordinate : 13; > + UINT32 YBinnerBlockCoordinate : 12; > + UINT32 NewSubBlock : 1; > + UINT32 CurrentField : 1; > + UINT32 MemUBufferOffset : 22; > + UINT32 MemVBufferOffset : 22; > + UINT32 InitialOffsetX : 4; > + UINT32 ReduceDoubleReadOrWrites : 1; > + UINT32 Reserved1 : 18; > + UINT32 ScanOrder : 1; > + UINT32 BandMode : 3; > + UINT32 BlockMode : 2; > + UINT32 Rotation : 1; > + UINT32 HorizontalFlip : 1; > + UINT32 VerticalFlip : 1; > + UINT32 ThresholdEnable : 1; > + UINT32 ConditionalAccessPolarity : 1; > + UINT32 ConditionalAccessEnable : 1; > + UINT32 FrameWidth : 13; // Max 8192 Pixel > + UINT32 FrameHeight : 12; // Max 4096 Pixel > + UINT32 EndOfLineInterrupt : 1; > + UINT32 Reserved2 : 9; > + }; > + UINT32 Word0[5]; > +} CPMEM_WORD0_PLANAR_REG; > + > +// CPMEM_WORD1_PLANAR - Non interleaved > +typedef union { > + struct { > + UINT32 ExtMemBuffer0Address : 29; > + UINT32 ExtMemBuffer1Address : 29; > + UINT32 InterlaceOffset : 20; > + UINT32 NumberOfPixelsInWholeBurstAccess : 7; > + UINT32 PixelFormatSelect : 4; > + UINT32 AlphaUsed : 1; > + UINT32 AlphaChannelMapping : 3; > + UINT32 AxiId : 2; > + UINT32 Threshold : 7; > + UINT32 StrideLine : 14; > + UINT32 Reserved1 : 9; > + UINT32 Width3 : 3; > + UINT32 StrideLineUV : 14; > + UINT32 Reserved2 : 7; > + UINT32 ConditionalReadEnable : 1; > + UINT32 Reserved3 : 10; > + }; > + UINT32 Word1[5]; > +} CPMEM_WORD1_PLANAR_REG; > + > +// CPMEM_WORD0_PACKED - Interlaved > +typedef union { > + struct { > + UINT32 XVVirtualCoordinate : 10; > + UINT32 YVVirtualCoordinate : 9; > + UINT32 XBinnerBlockCoordinate : 13; > + UINT32 YBinnerBlockCoordinate : 12; > + UINT32 NewSubBlock : 1; > + UINT32 CurrentField : 1; > + UINT32 ScrollXCounter : 12; > + UINT32 ScrollYCounter : 11; > + UINT32 NumberOfScroll : 10; > + UINT32 ScrollDeltaX : 7; > + UINT32 ScrollMax : 10; > + UINT32 ScrollingConfiguration : 1; > + UINT32 ScrollingEnable : 1; > + UINT32 ScrollDeltaY : 7; > + UINT32 ScrollHorizontalDirection : 1; > + UINT32 ScrollVerticalDirection : 1; > + UINT32 BitsPerPixel : 3; > + UINT32 DecodeAddressSelect : 2; > + UINT32 AccessDimension : 1; > + UINT32 ScanOrder : 1; > + UINT32 BandMode : 3; > + UINT32 BlockMode : 2; > + UINT32 Rotation : 1; > + UINT32 HorizontalFlip : 1; > + UINT32 VerticalFlip : 1; > + UINT32 ThresholdEnable : 1; > + UINT32 ConditionalAccessPolarity : 1; > + UINT32 ConditionalAccessEnable : 1; > + UINT32 FrameWidth : 13; // Max 8192 Pixel > + UINT32 FrameHeight : 12; // Max 4096 Pixel > + UINT32 EndOfLineInterrupt : 1; > + UINT32 Reserved2 : 9; > + }; > + UINT32 Word0[5]; > +} CPMEM_WORD0_PACKED_REG; > + > +// CPMEM_WORD1_PACKED - Non interleaved > +typedef union { > + struct { > + UINT32 ExtMemBuffer0Address : 29; > + UINT32 ExtMemBuffer1Address : 29; > + UINT32 InterlaceOffset : 20; > + UINT32 NumberOfPixelsInWholeBurstAccess : 7; > + UINT32 PixelFormatSelect : 4; > + UINT32 AlphaUsed : 1; > + UINT32 AlphaChannelMapping : 3; > + UINT32 AxiId : 2; > + UINT32 Threshold : 7; > + UINT32 StrideLine : 14; > + UINT32 Width0 : 3; > + UINT32 Width1 : 3; > + UINT32 Width2 : 3; > + UINT32 Width3 : 3; > + UINT32 Offset0 : 5; > + UINT32 Offset1 : 5; > + UINT32 Offset2 : 5; > + UINT32 Offset3 : 5; > + UINT32 SelectSXSYSet : 1; > + UINT32 ConditionalReadEnable : 1; > + UINT32 Reserved1 : 10; > + }; > + UINT32 Word1[5]; > +} CPMEM_WORD1_PACKED_REG; > + > +typedef struct _CPMEM_PARAM { > + union { > + CPMEM_WORD0_PLANAR_REG Word0Planar; > + CPMEM_WORD0_PACKED_REG Word0Pack; > + }; > + UINT32 Reserved1[3]; > + union { > + CPMEM_WORD1_PLANAR_REG Word1Planar; > + CPMEM_WORD1_PACKED_REG Word1Pack; > + }; > + UINT32 Reserved2[3]; > +} CPMEM_PARAM, *PCPMEM_PARAM; > + > +#pragma pack(pop) > + > +EFI_STATUS > +ConfigureCpmemFrameBuffer ( > + IN DISPLAY_INTERFACE_CONTEXT *DisplayInterfaceContextPtr, > + IN UINT32 Channel, > + IN SURFACE_INFO *FrameBufferPtr > + ); > + > +#endif /* _CPMEM_H_ */ > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c > new file mode 100644 > index 000000000000..30b737b2f4f5 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.c > @@ -0,0 +1,69 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* Copyright 2018 NXP > +* > +* 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 > + > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +#include "Display.h" > +#include "Edid.h" > +#include "Ddc.h" > +#include "Hdmi.h" > +#include "Lvds.h" > + > +EFI_STATUS > +Imx6DdcRead ( > + IN DISPLAY_CONTEXT *DisplayContextPtr, > + IN DISPLAY_INTERFACE_TYPE DisplayInterface, > + IN UINT8 SlaveAddress, > + IN UINT8 RegisterAddress, > + IN UINT32 ReadSize, > + IN UINT8 *DataReadPtr > + ) > +{ > + EFI_STATUS Status; > + > + switch (DisplayInterface) { > + case HdmiDisplay: > + Status = HdmiDdcRead ( > + &DisplayContextPtr->DiContext[HdmiDisplay], > + SlaveAddress, > + RegisterAddress, > + ReadSize, > + HDMI_DDC_STANDARD_MODE, > + DataReadPtr > + ); > + if (Status != EFI_SUCCESS) { > + DEBUG ((DEBUG_ERROR, "%a: HdmiDdcRead failed\n", __FUNCTION__)); > + } > + break; > + case MipiDisplay: > + case Lvds0Display: > + case Lvds1Display: > + default: > + Status = EFI_UNSUPPORTED; > + break; > + } > + > + return Status; > +} > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h > new file mode 100644 > index 000000000000..5a10f3d0c26c > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ddc.h > @@ -0,0 +1,28 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* > +* 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. > +* > +**/ > + > +#ifndef _DDC_H_ > +#define _DDC_H_ IMX_ prefix please. > + > +EFI_STATUS > +Imx6DdcRead ( > + IN DISPLAY_CONTEXT *DisplayContextPtr, > + IN DISPLAY_INTERFACE_TYPE DisplayInterface, > + IN UINT8 SlaveAddress, > + IN UINT8 RegisterAddress, > + IN UINT32 ReadSize, > + IN UINT8 *DataReadPtr > + ); > + > +#endif /* _DDC_H_ */ > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c > new file mode 100644 > index 000000000000..334e7362d3b8 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.c > @@ -0,0 +1,455 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* Copyright 2018 NXP > +* > +* 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 > + > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +// Display muxing register > +#include "iMX6.h" Is this not the same iMX6.h as 5 lines up? > + > +#include "Display.h" > +#include "Edid.h" > +#include "Hdmi.h" > +#include "Lvds.h" > +#include "DisplayInterface.h" > +#include "DisplayController.h" > +#include "CPMem.h" > +#include "Ipu.h" > +#include "IoMux.h" > + > +DISPLAY_TIMING DefaultTiming = { > + 65000000, // PixelClock > + 1024, // HActive > + 320, // HBlank > + 768, // VActive > + 38, // VBlank > + 136, // HSync > + 6, // VSync > + 24, // HSyncOffset; > + 3, // VSyncOffset; > + 1024, // HImageSize > + 768, // VImageSize > + 0, // HBorder > + 0, // VBorder > + 0, // EdidFlags > + 0, // Flags > + 1, // PixelRepetition > + 32, // Bpp > + PIXEL_FORMAT_BGRA32, // PixelFormat > +}; > + > +DISPLAY_TIMING Hannstar_XGA = { > + 65000000, // PixelClock > + 1024, // HActive > + 320, // HBlank > + 768, // VActive > + 38, // VBlank > + 60, // HSync > + 10, // VSync > + 24, // HSyncOffset; > + 3, // VSyncOffset; > + 1024, // HImageSize > + 768, // VImageSize > + 0, // HBorder > + 0, // VBorder > + 0, // EdidFlags > + 0, // Flags > + 1, // PixelRepetition > + 32, // Bpp > + PIXEL_FORMAT_BGRA32, // PixelFormat > +}; > + > +EFI_STATUS > +GetPreferredTiming ( > + IN UINT8 *EdidDataPtr, > + IN UINT32 EdidDataSize, > + IN DISPLAY_TIMING *PreferredTimingPtr > + ) > +{ > + EFI_STATUS Status; > + > + if (FeaturePcdGet (PcdLvdsEnable)) { > + *PreferredTimingPtr = Hannstar_XGA; > + Status = EFI_SUCCESS; > + } else { > + Status = GetEdidPreferredTiming (EdidDataPtr, EdidDataSize, PreferredTimingPtr); > + if (Status != EFI_SUCCESS) { > + // If EDID is unavailable use the default timing > + Status = EFI_SUCCESS; > + *PreferredTimingPtr = DefaultTiming; > + DEBUG ((DEBUG_WARN, > + "%a: EDID data not available, falling back to default timing\n", > + __FUNCTION__)); > + } > + } > + > + // Only support 8 bit per pixel and no pixel repetition for now > + PreferredTimingPtr->PixelRepetition = 1; > + PreferredTimingPtr->PixelFormat = PIXEL_FORMAT_BGRA32; > + PreferredTimingPtr->Bpp = 32; > + > +#ifdef DEBUG > + PrintDisplayTiming ("Preferred Timing", PreferredTimingPtr); > +#endif /* DEBUG */ > + DEBUG ((DEBUG_WARN, "%a: --GetPreferredTiming\n", __FUNCTION__)); > + return Status; > +} > + > +EFI_STATUS > +InitDisplay ( > + IN DISPLAY_CONTEXT **DisplayConfigPPtr > + ) > +{ > + DISPLAY_CONTEXT *pTempDisplayContext; > + DISPLAY_INTERFACE_TYPE DisplayCounter; > + EFI_STATUS Status; > + > + pTempDisplayContext = AllocateRuntimePool (sizeof (*pTempDisplayContext)); > + if (pTempDisplayContext == NULL) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to allocate display context\n", __FUNCTION__)); > + Status = EFI_OUT_OF_RESOURCES; > + goto Exit; > + } > + > + ZeroMem (pTempDisplayContext, sizeof (*pTempDisplayContext)); > + > + pTempDisplayContext->IoMuxMmioBasePtr = (VOID *)IOMUXC_GPR_BASE_ADDRESS; > + if (pTempDisplayContext->IoMuxMmioBasePtr == NULL) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to map IO Mux register\n", __FUNCTION__)); > + Status = EFI_OUT_OF_RESOURCES; > + goto Exit; > + } > + > + pTempDisplayContext->IpuMmioBasePtr[IPU1] = (VOID *)IPU1_BASE; > + if (pTempDisplayContext->IoMuxMmioBasePtr == NULL) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to map IPU1 IO Mux register\n", __FUNCTION__)); > + Status = EFI_OUT_OF_RESOURCES; > + goto Exit; > + } > +#if !defined(CPU_IMX6SDL) > + pTempDisplayContext->IpuMmioBasePtr[IPU2] = (VOID *)IPU2_BASE; > + if (pTempDisplayContext->IoMuxMmioBasePtr == NULL) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to map IPU2 IO Mux register\n", __FUNCTION__)); > + Status = EFI_OUT_OF_RESOURCES; > + goto Exit; > + } > +#endif > + for (DisplayCounter = HdmiDisplay; DisplayCounter < DisplayTypeMax; ++DisplayCounter) { > + pTempDisplayContext->DiContext[DisplayCounter].displayInterface = > + DisplayCounter; > + } > + > + if (FeaturePcdGet (PcdLvdsEnable)) { > + Status = InitLvds (pTempDisplayContext); > + if (Status != EFI_SUCCESS) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to intialize LVDS\n", __FUNCTION__)); > + goto Exit; > + } > + } else { > + Status = InitHdmi (pTempDisplayContext); > + if (Status != EFI_SUCCESS) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to intialize HDMI\n", __FUNCTION__)); > + goto Exit; > + } > + } > + > + *DisplayConfigPPtr = pTempDisplayContext; > + > +Exit: > + return Status; > +} > + > +EFI_STATUS > +ValidateDisplayConfig ( > + IN DISPLAY_CONTEXT *DisplayContextPtr, > + IN DISPLAY_MODE DisplayMode, > + IN DISPLAY_INTERFACE_TYPE *DiOrder > + ) > +{ > + DISPLAY_INTERFACE_TYPE DisplayDevice; > + EFI_STATUS Status; > + > + if (FeaturePcdGet (PcdLvdsEnable)) { > + DisplayDevice = Lvds0Display; > + } else { > + DisplayDevice = HdmiDisplay; > + } > + > + // Currently only support single display mode on HDMI/LVDS > + if (DisplayMode != SINGLE_MODE && DiOrder[0] != DisplayDevice) { > + Status = EFI_UNSUPPORTED; > + goto Exit; > + } > + > + // Currently going to a very simplistic approach of enabling HDMI/LVDS single > + // display on HDMI/LVDS port. This configuration is applied regardless if > + // there is a monitor connected. No hot plug, monitor detection support. > + Status = EFI_SUCCESS; > + > +Exit: > + return Status; > +} > + > +EFI_STATUS > +SetDisplayConfig ( > + IN OUT DISPLAY_CONTEXT *DisplayContextPtr, > + IN DISPLAY_MODE DisplayMode, > + IN DISPLAY_INTERFACE_TYPE *DiOrder > + ) > +{ > + DISPLAY_INTERFACE_CONTEXT *pDisplayInterfaceContext; > + DISPLAY_INTERFACE_INDEX DisplayInterfaceIndex; > + UINT32 DisplayInterfaceOffset[DisplayInterfaceMax]; > + UINT32 DisplayModeIndex; > + IPU_INDEX IpuIndex; > + EFI_STATUS Status; > + > + DisplayInterfaceOffset[0] = IPU_DISPLAY_INTERFACE_0_OFFSET; > + DisplayInterfaceOffset[1] = IPU_DISPLAY_INTERFACE_1_OFFSET; > + Status = ValidateDisplayConfig (DisplayContextPtr, DisplayMode, DiOrder); > + if (Status != EFI_SUCCESS) { > + DisplayContextPtr->DisplayConfig.DisplayMode = UNKNOWN_MODE; > + ZeroMem ( > + DisplayContextPtr->DisplayConfig.DiOrder, > + sizeof (DisplayContextPtr->DisplayConfig.DiOrder) > + ); > + DEBUG ((DEBUG_ERROR, "%a: Unsupported display configuration\n", __FUNCTION__)); > + Status = EFI_UNSUPPORTED; > + goto Exit; > + } > + > + DisplayContextPtr->DisplayConfig.DisplayMode = DisplayMode; > + ZeroMem ( > + DisplayContextPtr->DisplayConfig.DiOrder, > + sizeof (DisplayContextPtr->DisplayConfig.DiOrder) > + ); > + > + // Assigning display interface in order. Require mode information on IPU > + // and Display Interface valid combination > + DisplayModeIndex = 0; > + for (IpuIndex = IPU1; IpuIndex < IPU_TOTAL; IpuIndex++) { > + for (DisplayInterfaceIndex = DisplayInterface0; > + DisplayInterfaceIndex < DisplayInterfaceMax; > + DisplayInterfaceIndex++) > + { > + if (DisplayModeIndex >= (UINT32)DisplayMode) { > + break; > + } > + DisplayModeIndex++; > + > + DisplayContextPtr->DisplayConfig.DiOrder[DisplayInterfaceIndex] = > + DiOrder[DisplayInterfaceIndex]; > + pDisplayInterfaceContext = > + &DisplayContextPtr->DiContext[DiOrder[DisplayInterfaceIndex]]; > + pDisplayInterfaceContext->IpuMmioBasePtr = > + DisplayContextPtr->IpuMmioBasePtr[IpuIndex]; > + pDisplayInterfaceContext->IpuDiRegsPtr = > + (IPU_DIx_REGS *)(((UINTN)DisplayContextPtr->IpuMmioBasePtr[IpuIndex]) + > + DisplayInterfaceOffset[DisplayInterfaceIndex]); > + pDisplayInterfaceContext->CpMemParamBasePtr = > + (VOID *)(((UINTN)pDisplayInterfaceContext->IpuMmioBasePtr) + > + CSP_IPUV3_CPMEM_REGS_OFFSET); > + } > + } > + > + Status = EFI_SUCCESS; > + > +Exit: > + return Status; > +} > + > +EFI_STATUS > +ApplyDisplayConfig ( > + IN OUT DISPLAY_CONTEXT *DisplayContextPtr, > + IN DISPLAY_MODE DisplayMode, > + IN DISPLAY_INTERFACE_TYPE *DiOrder > + ) > +{ > + DISPLAY_TIMING *pCurrentDisplayTiming; > + DISPLAY_CONFIG *pDisplayConfig; > + DISPLAY_INTERFACE_CONTEXT *pDisplayInterfaceContext; No Hungarian notation please, throughout. > + UINT32 CurrentDisplayInterface; > + UINT32 DisplayModeIndex; > + EFI_STATUS Status; > + > + Status = EFI_SUCCESS; > + pDisplayConfig = &DisplayContextPtr->DisplayConfig; > + Status = SetDisplayConfig (DisplayContextPtr, DisplayMode, DiOrder); > + if (Status != EFI_SUCCESS) { > + DEBUG ((DEBUG_ERROR, > + "%a: Fail to set display configuration %d\n", > + __FUNCTION__, DisplayMode)); > + Status = EFI_UNSUPPORTED; > + goto Exit; > + } > + > + // Setup muxing first before configuring DI and DC > + Status = SetupDisplayMux (DisplayContextPtr); > + if (Status != EFI_SUCCESS) { if (EFI_ERROR (Status)) { is more idiomatic. Could you replace throughout? > + DEBUG ((DEBUG_ERROR, "%a: SetDisplayMux failed \n", __FUNCTION__)); > + goto Exit; > + } > + > + for (DisplayModeIndex = 0; > + DisplayModeIndex < (UINT32)pDisplayConfig->DisplayMode; > + ++DisplayModeIndex) > + { > + CurrentDisplayInterface = pDisplayConfig->DiOrder[DisplayModeIndex]; > + pDisplayInterfaceContext = &DisplayContextPtr->DiContext[CurrentDisplayInterface]; > + pCurrentDisplayTiming = &pDisplayConfig->DisplayTiming[DisplayModeIndex]; > + > + Status = ConfigureDisplayControllerChannel ( > + pDisplayInterfaceContext, > + CurrentDisplayInterface, > + DisplayModeIndex, > + pCurrentDisplayTiming > + ); > + if (Status != EFI_SUCCESS) { > + DEBUG ((DEBUG_ERROR, > + "%a:ConfigureDisplayControllerChannel fail display %d index %d\n", > + __FUNCTION__, CurrentDisplayInterface, DisplayModeIndex)); > + goto Exit; > + } > + > + Status = ConfigureDisplayInterface ( > + pDisplayInterfaceContext, > + DisplayModeIndex, > + pCurrentDisplayTiming > + ); > + if (Status != EFI_SUCCESS) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to configure DI\n", __FUNCTION__)); > + goto Exit; > + } > + > + switch (CurrentDisplayInterface) { > + case HdmiDisplay: > + Status = SetHdmiDisplay (pDisplayInterfaceContext, pCurrentDisplayTiming); > + if (Status != EFI_SUCCESS) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to set HDMI timing\n", __FUNCTION__)); > + goto Exit; > + } > + break; > + case Lvds0Display: > + case Lvds1Display: > + break; > + default: > + Status = EFI_UNSUPPORTED; > + break; > + } > + if (EFI_ERROR (Status)) { > + goto Exit; > + } > + > + Status = ConfigureFrameBuffer ( > + pDisplayInterfaceContext, > + &pDisplayConfig->DisplaySurface[DisplayModeIndex] > + ); > + if (Status != EFI_SUCCESS) { > + DEBUG ((DEBUG_ERROR, > + "%a: Fail to configure frame buffer (%d)\n", > + __FUNCTION__, DisplayModeIndex)); > + goto Exit; > + } > + } > + > +Exit: > + return Status; > +} > + > +EFI_STATUS > +AllocateFrameBuffer ( > + IN OUT SURFACE_INFO *SurfaceInfoPtr > + ) > +{ > + EFI_STATUS Status; > + > + DEBUG ((DEBUG_INFO, "%a: Enter\n", __FUNCTION__)); > + if ((SurfaceInfoPtr->Width == 0) || (SurfaceInfoPtr->Height == 0)) { > + Status = EFI_INVALID_PARAMETER; > + goto Exit; > + } > + > + DEBUG ((DEBUG_INFO, "%a: Frame Buffer AddrP=%Xh\n", > + __FUNCTION__, FixedPcdGet32 (PcdFrameBufferBase))); > + DEBUG ((DEBUG_INFO, "%a: Frame Buffer Size=%Xh\n", > + __FUNCTION__, FixedPcdGet32 (PcdFrameBufferSize))); > + > + SurfaceInfoPtr->VirtAddrPtr = (VOID *)(UINTN)FixedPcdGet32 (PcdFrameBufferBase); > + SurfaceInfoPtr->PhyAddr = (UINT32)(SurfaceInfoPtr->VirtAddrPtr); > + SurfaceInfoPtr->Pitch = SurfaceInfoPtr->Width; > + > + DEBUG ((DEBUG_INFO, > + "%a: Allocate FB PhyAddr %x VirtAddr %x\n", > + __FUNCTION__, SurfaceInfoPtr->PhyAddr, SurfaceInfoPtr->VirtAddrPtr)); > + > + Status = EFI_SUCCESS; > + > +Exit: > + DEBUG ((DEBUG_INFO, "%a: Exit = %Xh\n", > + __FUNCTION__, Status)); > + return Status; > +} > + > +EFI_STATUS > +ConfigureFrameBuffer ( > + IN DISPLAY_INTERFACE_CONTEXT *DisplayInterfaceContextPtr, > + IN SURFACE_INFO *FrameBufferPtr > + ) > +{ > + EFI_STATUS Status; > + > + // Only support single display for now > + Status = ConfigureCpmemFrameBuffer ( > + DisplayInterfaceContextPtr, > + IDMAC_CHANNEL_DP_PRIMARY_FLOW_MAIN_PLANE, > + FrameBufferPtr > + ); > + if (Status != EFI_SUCCESS) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to configure CPMEM\n", __FUNCTION__)); > + goto Exit; > + } > + > +Exit: > + return Status; > +} > + > +UINT32 > +GetColorDepth ( > + IN PIXEL_FORMAT PixelFormat > + ) > +{ > + UINT32 BitDepth; > + > + switch (PixelFormat) { > + case PIXEL_FORMAT_ARGB32: > + case PIXEL_FORMAT_BGRA32: > + BitDepth = 8; > + break; > + default: > + BitDepth = 0; > + break; > + } > + > + return BitDepth; > +} > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h > new file mode 100644 > index 000000000000..cbcea1219743 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Display.h > @@ -0,0 +1,175 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* Copyright 2018 NXP > +* > +* 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. > +* > +**/ > + > +#ifndef _DISPLAY_H_ > +#define _DISPLAY_H_ IMX_ prefix. > + > +typedef enum { > + UNKNOWN_MODE, > + SINGLE_MODE, > + DUAL_MODE, > +} DISPLAY_MODE; > + > +typedef enum { > + IPU1, > +#if !defined(CPU_IMX6SDL) > + IPU2, > +#endif > + IPU_TOTAL, > +} IPU_INDEX; > + > +typedef enum { > + DisplayInterface0, > + DisplayInterface1, > + DisplayInterfaceMax, > +} DISPLAY_INTERFACE_INDEX; > + > +typedef enum { > + HdmiDisplay, > + MipiDisplay, > + Lvds0Display, > + Lvds1Display, > + DisplayTypeMax, // Only 4 display types supported by IPU > + NoDisplayType = DisplayTypeMax, > +} DISPLAY_INTERFACE_TYPE; > + > +typedef struct _SURFACE_INFO { > + UINT32 PhyAddr; > + UINT32 *VirtAddrPtr; > + UINT32 Width; > + UINT32 Height; > + UINT32 Pitch; > + UINT32 Bpp; > + PIXEL_FORMAT PixelFormat; > +} SURFACE_INFO, *PSURFACE_INFO; > + > +typedef struct _IPU_DIx_REGS { > + UINT32 DIxGENERAL; > + UINT32 DIxBS_CLKGEN0; > + UINT32 DIxBS_CLKGEN1; > + UINT32 DIxSW_GEN0_1; > + UINT32 DIxSW_GEN0_2; > + UINT32 DIxSW_GEN0_3; > + UINT32 DIxSW_GEN0_4; > + UINT32 DIxSW_GEN0_5; > + UINT32 DIxSW_GEN0_6; > + UINT32 DIxSW_GEN0_7; > + UINT32 DIxSW_GEN0_8; > + UINT32 DIxSW_GEN0_9; > + UINT32 DIxSW_GEN1_1; > + UINT32 DIxSW_GEN1_2; > + UINT32 DIxSW_GEN1_3; > + UINT32 DIxSW_GEN1_4; > + UINT32 DIxSW_GEN1_5; > + UINT32 DIxSW_GEN1_6; > + UINT32 DIxSW_GEN1_7; > + UINT32 DIxSW_GEN1_8; > + UINT32 DIxSW_GEN1_9; > + UINT32 DIxSYNC_AS_GEN; > + UINT32 DIxDW_GEN[12]; > + UINT32 DIxDW_SET0[12]; > + UINT32 DIxDW_SET1[12]; > + UINT32 DIxDW_SET2[12]; > + UINT32 DIxDW_SET3[12]; > + UINT32 DIxSTP_REP[4]; > + UINT32 DIxSTP_REP_9; > + UINT32 DIxSER_CONF; > + UINT32 DIxSSC; > + UINT32 DIxPOL; > + UINT32 DIxAW0; > + UINT32 DIxAW1; > + UINT32 DIxSCR_CONF; > + UINT32 DIxSTAT; > +} IPU_DIx_REGS, *PIPU_DIx_REGS; > + > +typedef struct _DISPLAY_INTERFACE_CONTEXT { > + DISPLAY_INTERFACE_TYPE displayInterface; > + > + VOID *MmioBasePtr; > + VOID *IpuMmioBasePtr; > + VOID *CpMemParamBasePtr; > + IPU_DIx_REGS *IpuDiRegsPtr; > + UINT32 EdidDataSize; > + UINT8 EdidData[256]; > + DISPLAY_TIMING PreferredTiming; > +} DISPLAY_INTERFACE_CONTEXT, *PDISPLAY_INTERFACE_CONTEXT; > + > +typedef struct _DISPLAY_CONFIG { > + DISPLAY_MODE DisplayMode; > + DISPLAY_INTERFACE_TYPE DiOrder[DisplayTypeMax]; > + SURFACE_INFO DisplaySurface[DisplayTypeMax]; > + DISPLAY_TIMING DisplayTiming[DisplayTypeMax]; > + UINT32 OsHandle[DisplayTypeMax]; > +} DISPLAY_CONFIG, *PDISPLAY_CONFIG; > + > +typedef struct _DISPLAY_CONTEXT { > + DISPLAY_CONFIG DisplayConfig; > + VOID *IoMuxMmioBasePtr; > + VOID *IpuMmioBasePtr[IPU_TOTAL]; > + DISPLAY_INTERFACE_CONTEXT DiContext[DisplayTypeMax]; > +} DISPLAY_CONTEXT, *PDISPLAY_CONTEXT; > + > +extern DISPLAY_TIMING DefaultTiming; g- or m- prefix for an exported variable. > + > +EFI_STATUS > +GetPreferredTiming ( > + IN UINT8 *EdidDataPtr, > + IN UINT32 EdidDataSize, > + IN DISPLAY_TIMING *PreferredTimingPtr > + ); > + > +EFI_STATUS > +InitDisplay ( > + IN DISPLAY_CONTEXT **DisplayConfigPPtr > + ); > + > +EFI_STATUS > +ValidateDisplayConfig ( > + IN DISPLAY_CONTEXT *DisplayContextPtr, > + IN DISPLAY_MODE DisplayMode, > + IN DISPLAY_INTERFACE_TYPE *DiOrder > + ); > + > +EFI_STATUS > +SetDisplayConfig ( > + IN OUT DISPLAY_CONTEXT *DisplayContextPtr, > + IN DISPLAY_MODE DisplayMode, > + IN DISPLAY_INTERFACE_TYPE *DiOrder > + ); > + > +EFI_STATUS > +ApplyDisplayConfig ( > + IN OUT DISPLAY_CONTEXT *DisplayContextPtr, > + IN DISPLAY_MODE DisplayMode, > + IN DISPLAY_INTERFACE_TYPE *DiOrder > + ); > + > +EFI_STATUS > +AllocateFrameBuffer ( > + IN OUT SURFACE_INFO *SurfaceInfoPtr > + ); > + > +EFI_STATUS > +ConfigureFrameBuffer ( > + IN DISPLAY_INTERFACE_CONTEXT *DisplayInterfaceContextPtr, > + IN SURFACE_INFO *FrameBufferPtr > + ); > + > +UINT32 > +GetColorDepth ( > + IN PIXEL_FORMAT PixelFormat > + ); > + > +#endif /* _DISPLAY_H_ */ > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c > new file mode 100644 > index 000000000000..7a5fc7e3d6c3 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.c > @@ -0,0 +1,399 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* Copyright 2018 NXP > +* > +* 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 > + > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +#include "Ipu.h" > +#include "Display.h" > +#include "DisplayController.h" > +#include "DisplayInterface.h" > + > +#ifdef DEBUG > +VOID > +DumpBasicDisplayControllerReg ( > + IN VOID *IpuMmioBasePtr > + ) > +{ > + UINT32 Counter; > + UINT32 Index; > + UINT32 RegVal; > + > + DEBUG ((DEBUG_VERBOSE, "%a: ------- DC Register Dump -------\n", __FUNCTION__)); > + > + DEBUG ((DEBUG_VERBOSE, "%a: ## Configuration\n\n", __FUNCTION__)); > + RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_WR_CH_CONF_5_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_WR_CH_CONF_5_OFFSET %x\n", > + __FUNCTION__, RegVal)); > + RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_WR_CH_CONF_1_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_WR_CH_CONF_1_OFFSET %x\n", > + __FUNCTION__, RegVal)); > + RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_DISP_CONF1_0_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_DISP_CONF1_0_OFFSET %x\n", > + __FUNCTION__, RegVal)); > + RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_DISP_CONF1_1_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_DISP_CONF1_1_OFFSET %x\n", > + __FUNCTION__, RegVal)); > + RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_DISP_CONF1_2_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_DISP_CONF1_2_OFFSET %x\n", > + __FUNCTION__, RegVal)); > + RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_DISP_CONF1_3_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_DISP_CONF1_3_OFFSET %x\n", > + __FUNCTION__, RegVal)); > + RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_DISP_CONF2_0_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_DISP_CONF2_0_OFFSET %x\n", > + __FUNCTION__, RegVal)); > + RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_GEN_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_GEN_OFFSET %x\n", > + __FUNCTION__, RegVal)); > + > + DEBUG ((DEBUG_VERBOSE, "%a: ## Bus MAPPING\n\n", __FUNCTION__)); > + { Please move the { to the end of the preceding line. > + for (Counter = 0, Index = 0; Index < 26; Counter += 4, ++Index) { ++ suffix rather than prefix, please. > + RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_MAP_CONF_0_OFFSET + Counter); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_MAP_CONF_%d %x\n", > + __FUNCTION__, Index, RegVal)); > + } > + } > + > + DEBUG ((DEBUG_VERBOSE, "%a: ## Channel MicroCode setup\n\n", __FUNCTION__)); > + // Only print out channel 5 as we only support single mode for now > + RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_RL0_CH_5_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_RL0_CH_5_OFFSET %x\n", > + __FUNCTION__, RegVal)); > + RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_RL1_CH_5_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_RL1_CH_5_OFFSET %x\n", > + __FUNCTION__, RegVal)); > + RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_RL2_CH_5_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_RL2_CH_5_OFFSET %x\n", > + __FUNCTION__, RegVal)); > + RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_RL3_CH_5_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_RL3_CH_5_OFFSET %x\n", > + __FUNCTION__, RegVal)); > + RegVal = IpuRead32 (IpuMmioBasePtr, IPU_DC_RL4_CH_5_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DC_RL4_CH_5_OFFSET %x\n", > + __FUNCTION__, RegVal)); > + > + DEBUG ((DEBUG_VERBOSE, "%a: ## MicroCode\n\n", __FUNCTION__)); > + // There are 256 template, only print out the first 10 > + for (Counter = 0, Index = 0; Index < 10; Counter += 8, ++Index) { > + DEBUG ((DEBUG_VERBOSE, "%a: (%d)\n", __FUNCTION__, Index)); > + RegVal = IpuRead32 ( > + IpuMmioBasePtr, > + IPU_DC_TEMPLATE_REGS_ADDR_OFFSET + Counter); > + DEBUG ((DEBUG_VERBOSE, "%a: - %8x\n", __FUNCTION__, RegVal)); > + RegVal = IpuRead32 ( > + IpuMmioBasePtr, > + IPU_DC_TEMPLATE_REGS_ADDR_OFFSET + Counter + 4); > + DEBUG ((DEBUG_VERBOSE, "%a: %8x -\n", __FUNCTION__, RegVal)); > + } > + > + DEBUG ((DEBUG_VERBOSE, "%a: ---------------------------\n\n", __FUNCTION__)); > +} > +#endif /* DEBUG */ > + > +EFI_STATUS > +WriteWrodCommand ( > + IN VOID *IpuMmioBasePtr, > + IN UINT32 MicroCodeAddr, > + IN UINT32 Data, > + IN UINT32 Mapping, > + IN UINT32 WaveForm, > + IN UINT32 GlueLogic, > + IN UINT32 Sync > + ) > +{ > + UINT32 MicroCodeAddrOffset; > + DISPLAY_CONTROLLER_WROD_COMMAND WrodCommand; > + > + > + MicroCodeAddrOffset = IPU_DC_TEMPLATE_REGS_ADDR_OFFSET + (MicroCodeAddr * 8); > + ZeroMem ((VOID *)&WrodCommand, sizeof (WrodCommand)); > + WrodCommand.STOP = 1; > + WrodCommand.OPCODE = 0x18; > + WrodCommand.DATA = Data; > + WrodCommand.MAPPING = Mapping; > + WrodCommand.WAVEFORM = WaveForm + 1; > + WrodCommand.GLUELOGIC = GlueLogic; > + WrodCommand.SYNC = Sync; > + IpuWrite32 (IpuMmioBasePtr, MicroCodeAddrOffset, WrodCommand.LowWord); > + IpuWrite32 (IpuMmioBasePtr, MicroCodeAddrOffset + 4, WrodCommand.HighWord); > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +SetDisplayControllerChannelState ( > + IN VOID *IpuMmioBasePtr, > + IN PROG_CHAN_TYP ChannelType > + ) > +{ > + IPU_DC_WR_CH_CONF_5_REG WrChConfigReg; > + > + WrChConfigReg.Reg = IpuRead32 (IpuMmioBasePtr, IPU_DC_WR_CH_CONF_5_OFFSET); > + WrChConfigReg.PROG_CHAN_TYP = ChannelType; > + IpuWrite32 (IpuMmioBasePtr, IPU_DC_WR_CH_CONF_5_OFFSET, WrChConfigReg.Reg); > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ConfigureDisplayControllerChannel ( > + IN DISPLAY_INTERFACE_CONTEXT *DisplayInterfaceContextPtr, > + IN DISPLAY_INTERFACE_TYPE DisplayInterface, > + IN UINT32 DisplayIndex, > + IN DISPLAY_TIMING *DisplayTimingPtr > + ) > +{ > + VOID *pIpuMmioBase; > + DC_MAP_CONF_OFFSET_MASK_REG DcConfOffsetMaskReg; > + IPUx_DC_MAP_CONF_MAP_REG DcMapConf0Reg; > + IPU_DC_RL0_CH_5_REG DcRl0Ch5Reg; > + IPU_DC_RL2_CH_5_REG DcRl2Ch5Reg; > + IPU_DC_RL4_CH_5_REG DcRl4Ch5Reg; > + IPUx_DC_DISP_CONF1_REG DisplayConfig1Reg; > + IPUx_IPU_DC_GEN_REG DisplayControllerGenReg; > + UINT32 Mask0; > + UINT32 Mask1; > + UINT32 Mask2; > + UINT32 Offset0; > + UINT32 Offset1; > + UINT32 Offset2; > + EFI_STATUS Status; > + IPU_DC_WR_CH_CONF_5_REG WrChConfigReg; > + > + pIpuMmioBase = DisplayInterfaceContextPtr->IpuMmioBasePtr; > + Status = EFI_SUCCESS; > + > + ZeroMem ((VOID *)&WrChConfigReg, sizeof (WrChConfigReg)); > + WrChConfigReg.PROG_START_TIME = 0; > + WrChConfigReg.FILED_MODE = 0; > + WrChConfigReg.CHAN_MASK_DEFAULT = 0; // only used highest priority > + WrChConfigReg.PROG_CHAN_TYP = 0; // Begin as disable > + WrChConfigReg.PROG_DISP_ID = DisplayInterface; > + WrChConfigReg.PROG_DI_ID = DisplayIndex % 2; > + WrChConfigReg.W_SIZE = 0x02; // 24 Bits > + WrChConfigReg.Reserved1 = 0; > + WrChConfigReg.Reserved2 = 0; > + // Channel 5 is used main primary flow > + IpuWrite32 (pIpuMmioBase, IPU_DC_WR_CH_CONF_5_OFFSET, WrChConfigReg.Reg); > + // Start address of memory always 0 > + IpuWrite32 (pIpuMmioBase, IPU_DC_WR_CH_ADDR_5_OFFSET, 0); > + > + ZeroMem ((VOID *)&WrChConfigReg, sizeof (WrChConfigReg)); > + WrChConfigReg.FILED_MODE = 0; > + WrChConfigReg.CHAN_MASK_DEFAULT = 0; // only used highest priority > + WrChConfigReg.PROG_CHAN_TYP = 4; // Enable > + WrChConfigReg.PROG_DISP_ID = DisplayInterface; > + WrChConfigReg.PROG_DI_ID = DisplayIndex % 2; > + WrChConfigReg.W_SIZE = 0x02; // 1 Bits > + WrChConfigReg.Reserved1 = 0; > + WrChConfigReg.Reserved2 = 0; > + > + // Channel 1 is used as sync/async flow > + IpuWrite32 (pIpuMmioBase, IPU_DC_WR_CH_CONF_1_OFFSET, WrChConfigReg.Reg); > + IpuWrite32 (pIpuMmioBase, IPU_DC_WR_CH_ADDR_1_OFFSET, 0); > + > + DisplayConfig1Reg.DISP_TYP = 0x02; // What is byte_enabled > + DisplayConfig1Reg.ADDR_INCREMENT = 0; // Increase by 1 byte > + DisplayConfig1Reg.ADDR_BE_L_INC = 0; > + DisplayConfig1Reg.MCU_ACC_LB_MASK_3 = 0; > + DisplayConfig1Reg.DISP_RD_VALUE_PTR = 0; > + IpuWrite32 (pIpuMmioBase, IPU_DC_DISP_CONF1_0_OFFSET, DisplayConfig1Reg.Reg); > + > + // Set stride > + IpuWrite32 (pIpuMmioBase, IPU_DC_DISP_CONF2_0_OFFSET, DisplayTimingPtr->VActive); > + > + // Setup general register. Channel 5 is the main channel. > + DisplayControllerGenReg.Sync_1_6 = 2; // Sync flow > + DisplayControllerGenReg.MASK_EN = 0; // Disable masking > + DisplayControllerGenReg.MASK4CHAN_5 = 0; // Ignore as mask is disabled > + DisplayControllerGenReg.SYNC_PRIORITY_5 = 1; // Higher sync priority for channel 5 > + DisplayControllerGenReg.SYNC_PRIORITY_1 = 0; // Lower sync priority > + DisplayControllerGenReg.DC_CH5_TYPE = 0; // Normal mode, sync flow through channel 5 > + DisplayControllerGenReg.DC_BK_EN = 0; // No cursor support > + DisplayControllerGenReg.DC_BKDIV = 0; // No cursor support > + IpuWrite32 (pIpuMmioBase, IPU_DC_GEN_OFFSET, DisplayControllerGenReg.Reg); > + > + // Do not use any user event > + IpuWrite32 (pIpuMmioBase, IPU_DC_UGDE0_0_OFFSET, 0); > + IpuWrite32 (pIpuMmioBase, IPU_DC_UGDE1_0_OFFSET, 0); > + IpuWrite32 (pIpuMmioBase, IPU_DC_UGDE2_0_OFFSET, 0); > + IpuWrite32 (pIpuMmioBase, IPU_DC_UGDE3_0_OFFSET, 0); > + > + DcMapConf0Reg.MAPPING_PNTR_BYTE0_X = 0; > + DcMapConf0Reg.MAPPING_PNTR_BYTE1_X = 1; > + DcMapConf0Reg.MAPPING_PNTR_BYTE2_X = 2; > + DcMapConf0Reg.MAPPING_PNTR_BYTE0_Y = 3; // Unused > + DcMapConf0Reg.MAPPING_PNTR_BYTE1_Y = 4; // Unused > + DcMapConf0Reg.MAPPING_PNTR_BYTE2_Y = 5; // Unused > + IpuWrite32 (pIpuMmioBase, IPU_DC_MAP_CONF_0_OFFSET, DcMapConf0Reg.Reg); > + > + switch (DisplayInterface) { > + // PixelFormat RGB24 > + case HdmiDisplay: > + Mask0 = 0xFF; > + Mask1 = 0xFF; > + Mask2 = 0xFF; > + Offset0 = 7; > + Offset1 = 15; > + Offset2 = 23; > + break; > + // PixelFormat RGB666 > + case Lvds0Display: > + case Lvds1Display: > + Mask0 = 0xFC; > + Mask1 = 0xFC; > + Mask2 = 0xFC; > + Offset0 = 5; > + Offset1 = 11; > + Offset2 = 17; > + break; > + default: > + ASSERT (FALSE); > + Status = EFI_UNSUPPORTED; > + break; > + } > + if (EFI_ERROR (Status)) { > + goto Exit; > + } > + > + DcConfOffsetMaskReg.MD_MASK_X = Mask0; > + DcConfOffsetMaskReg.MD_OFFSET_X = Offset0; // Blue > + DcConfOffsetMaskReg.MD_MASK_Y = Mask1; > + DcConfOffsetMaskReg.MD_OFFSET_Y = Offset1; // Green > + IpuWrite32 (pIpuMmioBase, IPU_DC_MAP_CONF_15_OFFSET, DcConfOffsetMaskReg.Reg); > + > + DcConfOffsetMaskReg.MD_MASK_X = Mask2; > + DcConfOffsetMaskReg.MD_OFFSET_X = Offset2; // Red > + DcConfOffsetMaskReg.MD_MASK_Y = 0x00; > + DcConfOffsetMaskReg.MD_OFFSET_Y = 0; // Unused > + IpuWrite32 (pIpuMmioBase, IPU_DC_MAP_CONF_16_OFFSET, DcConfOffsetMaskReg.Reg); > + > + // Setup microcode > + // New line event point to the first microcode (0) > + ZeroMem ((VOID *)&DcRl0Ch5Reg, sizeof (DcRl0Ch5Reg)); > + DcRl0Ch5Reg.COD_NL_START_CHAN_5 = 0; > + DcRl0Ch5Reg.COD_NL_PRIORITY_CHAN_5 = 3; > + IpuWrite32 (pIpuMmioBase, IPU_DC_RL0_CH_5_OFFSET, DcRl0Ch5Reg.Reg); > + > + // End of line event point to the second microcode (1) > + ZeroMem ((VOID *)&DcRl2Ch5Reg, sizeof (DcRl2Ch5Reg)); > + DcRl2Ch5Reg.COD_EOL_START_CHAN_5 = 1; > + DcRl2Ch5Reg.COD_EOL_PRIORITY_CHAN_5 = 2; > + IpuWrite32 (pIpuMmioBase, IPU_DC_RL2_CH_5_OFFSET, DcRl2Ch5Reg.Reg); > + > + // New data event point to the first microcode (2) > + ZeroMem ((VOID *)&DcRl4Ch5Reg, sizeof (DcRl4Ch5Reg)); > + DcRl4Ch5Reg.COD_NEW_DATA_START_CHAN_5 = 2; > + DcRl4Ch5Reg.COD_NEW_DATA_PRIORITY_CHAN_5 = 1; > + IpuWrite32 (pIpuMmioBase, IPU_DC_RL4_CH_5_OFFSET, DcRl4Ch5Reg.Reg); > + > + // MicroCodeAddr > + // - 0 set for new line event > + // Data > + // - Unsused > + // Map to mapping parameter 0 > + // - In order to point to MAPPING_PNTR_BYTE2_0, MAPPING_PNTR_BYTE1_0, > + // MAPPING_PNTR_BYTE0_0 the user should write 1 to the MAPPING field > + // WaveForm > + // - Points to DI0_DW_GEN_0 or DI1_DW_GEN_0 (Define which waveform > + // register is used, default to first IPUx_DI0_DW_SET0_1) > + // GlueLogic > + // - Once the signal is asserted then it remains asserted (high or low > + // according to the polarity) > + // Sync > + // - Sync with Counter 5 > + WriteWrodCommand ( > + pIpuMmioBase, > + 0, > + 0, > + 1, > + DwGen0, > + 8, > + DI_COUNTER_5_ACTIVE_CLOCK > + ); > + > + // MicroCodeAddr > + // - 1 set for end of line event > + // Data > + // - Unsused > + // Map to mapping parameter 0 > + // - In order to point to MAPPING_PNTR_BYTE2_0, MAPPING_PNTR_BYTE1_0, > + // MAPPING_PNTR_BYTE0_0 the user should write 1 to the MAPPING field > + // WaveForm > + // - Points to DI0_DW_GEN_0 or DI1_DW_GEN_0 (Define which waveform > + // register is used, default to first IPUx_DI0_DW_SET0_1) > + // GlueLogic > + // - Once the signal is negated then it remains negated (high or low > + // according to the polarity) > + // Sync > + // - Sync with Counter 5 > + WriteWrodCommand ( > + pIpuMmioBase, > + 1, > + 0, > + 1, > + DwGen0, > + 4, > + DI_COUNTER_5_ACTIVE_CLOCK > + ); > + > + // MicroCodeAddr > + // - 2 set for new data event > + // Data > + // - Unsused > + // Map to mapping parameter 0 > + // - In order to point to MAPPING_PNTR_BYTE2_0, MAPPING_PNTR_BYTE1_0, > + // MAPPING_PNTR_BYTE0_0 the user should write 1 to the MAPPING field > + // WaveForm > + // - Points to DI0_DW_GEN_0 or DI1_DW_GEN_0 (Define which waveform > + // register is used, default to first IPUx_DI0_DW_SET0_1) > + // GlueLogic > + // - CS mode No impact on the waveform > + // Sync > + // - Sync with channel 5 > + WriteWrodCommand ( > + pIpuMmioBase, > + 2, > + 0, > + 1, > + DwGen0, > + 8, > + DI_COUNTER_5_ACTIVE_CLOCK > + ); > + > + // Turn on channel without anti tearing > + SetDisplayControllerChannelState ( > + DisplayInterfaceContextPtr->IpuMmioBasePtr, > + PROG_CHAN_TYP_NORMAL > + ); > + > +#ifdef DEBUG > + DumpBasicDisplayControllerReg (pIpuMmioBase); > +#endif /* DEBUG */ > + > + Status = EFI_SUCCESS; > + > +Exit: > + return Status; > +} > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h > new file mode 100644 > index 000000000000..46f0fa66d674 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayController.h > @@ -0,0 +1,331 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* > +* 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. > +* > +**/ > + > +#ifndef _DISPLAY_CONTROLLER_H_ > +#define _DISPLAY_CONTROLLER_H_ IMX_ prefix please. > + > +#define IPU_DC_OFFSET 0x00058000 > + > +// DC Registers > +#define IPU_DC_READ_CH_CONF_OFFSET IPU_DC_OFFSET + 0x0000 > +#define IPU_DC_READ_CH_ADDR_OFFSET IPU_DC_OFFSET + 0x0004 > +#define IPU_DC_RL0_CH_0_OFFSET IPU_DC_OFFSET + 0x0008 > +#define IPU_DC_RL1_CH_0_OFFSET IPU_DC_OFFSET + 0x000C > +#define IPU_DC_RL2_CH_0_OFFSET IPU_DC_OFFSET + 0x0010 > +#define IPU_DC_RL3_CH_0_OFFSET IPU_DC_OFFSET + 0x0014 > +#define IPU_DC_RL4_CH_0_OFFSET IPU_DC_OFFSET + 0x0018 > +#define IPU_DC_WR_CH_CONF_1_OFFSET IPU_DC_OFFSET + 0x001C > +#define IPU_DC_WR_CH_ADDR_1_OFFSET IPU_DC_OFFSET + 0x0020 > +#define IPU_DC_RL0_CH_1_OFFSET IPU_DC_OFFSET + 0x0024 > +#define IPU_DC_RL1_CH_1_OFFSET IPU_DC_OFFSET + 0x0028 > +#define IPU_DC_RL2_CH_1_OFFSET IPU_DC_OFFSET + 0x002C > +#define IPU_DC_RL3_CH_1_OFFSET IPU_DC_OFFSET + 0x0030 > +#define IPU_DC_RL4_CH_1_OFFSET IPU_DC_OFFSET + 0x0034 > +#define IPU_DC_WR_CH_CONF_2_OFFSET IPU_DC_OFFSET + 0x0038 > +#define IPU_DC_WR_CH_ADDR_2_OFFSET IPU_DC_OFFSET + 0x003C > +#define IPU_DC_RL0_CH_2_OFFSET IPU_DC_OFFSET + 0x0040 > +#define IPU_DC_RL1_CH_2_OFFSET IPU_DC_OFFSET + 0x0044 > +#define IPU_DC_RL2_CH_2_OFFSET IPU_DC_OFFSET + 0x0048 > +#define IPU_DC_RL3_CH_2_OFFSET IPU_DC_OFFSET + 0x004C > +#define IPU_DC_RL4_CH_2_OFFSET IPU_DC_OFFSET + 0x0050 > +#define IPU_DC_CMD_CH_CONF_3_OFFSET IPU_DC_OFFSET + 0x0054 > +#define IPU_DC_CMD_CH_CONF_4_OFFSET IPU_DC_OFFSET + 0x0058 > +#define IPU_DC_WR_CH_CONF_5_OFFSET IPU_DC_OFFSET + 0x005C > +#define IPU_DC_WR_CH_ADDR_5_OFFSET IPU_DC_OFFSET + 0x0060 > +#define IPU_DC_RL0_CH_5_OFFSET IPU_DC_OFFSET + 0x0064 > +#define IPU_DC_RL1_CH_5_OFFSET IPU_DC_OFFSET + 0x0068 > +#define IPU_DC_RL2_CH_5_OFFSET IPU_DC_OFFSET + 0x006C > +#define IPU_DC_RL3_CH_5_OFFSET IPU_DC_OFFSET + 0x0070 > +#define IPU_DC_RL4_CH_5_OFFSET IPU_DC_OFFSET + 0x0074 > +#define IPU_DC_WR_CH_CONF_6_OFFSET IPU_DC_OFFSET + 0x0078 > +#define IPU_DC_WR_CH_ADDR_6_OFFSET IPU_DC_OFFSET + 0x007C > +#define IPU_DC_RL0_CH_6_OFFSET IPU_DC_OFFSET + 0x0080 > +#define IPU_DC_RL1_CH_6_OFFSET IPU_DC_OFFSET + 0x0084 > +#define IPU_DC_RL2_CH_6_OFFSET IPU_DC_OFFSET + 0x0088 > +#define IPU_DC_RL3_CH_6_OFFSET IPU_DC_OFFSET + 0x008C > +#define IPU_DC_RL4_CH_6_OFFSET IPU_DC_OFFSET + 0x0090 > +#define IPU_DC_WR_CH_CONF1_8_OFFSET IPU_DC_OFFSET + 0x0094 > +#define IPU_DC_WR_CH_CONF2_8_OFFSET IPU_DC_OFFSET + 0x0098 > +#define IPU_DC_RL1_CH_8_OFFSET IPU_DC_OFFSET + 0x009C > +#define IPU_DC_RL2_CH_8_OFFSET IPU_DC_OFFSET + 0x00A0 > +#define IPU_DC_RL3_CH_8_OFFSET IPU_DC_OFFSET + 0x00A4 > +#define IPU_DC_RL4_CH_8_OFFSET IPU_DC_OFFSET + 0x00A8 > +#define IPU_DC_RL5_CH_8_OFFSET IPU_DC_OFFSET + 0x00AC > +#define IPU_DC_RL6_CH_8_OFFSET IPU_DC_OFFSET + 0x00B0 > +#define IPU_DC_WR_CH_CONF1_9_OFFSET IPU_DC_OFFSET + 0x00B4 > +#define IPU_DC_WR_CH_CONF2_9_OFFSET IPU_DC_OFFSET + 0x00B8 > +#define IPU_DC_RL1_CH_9_OFFSET IPU_DC_OFFSET + 0x00BC > +#define IPU_DC_RL2_CH_9_OFFSET IPU_DC_OFFSET + 0x00C0 > +#define IPU_DC_RL3_CH_9_OFFSET IPU_DC_OFFSET + 0x00C4 > +#define IPU_DC_RL4_CH_9_OFFSET IPU_DC_OFFSET + 0x00C8 > +#define IPU_DC_RL5_CH_9_OFFSET IPU_DC_OFFSET + 0x00CC > +#define IPU_DC_RL6_CH_9_OFFSET IPU_DC_OFFSET + 0x00D0 > +#define IPU_DC_GEN_OFFSET IPU_DC_OFFSET + 0x00D4 > +#define IPU_DC_DISP_CONF1_0_OFFSET IPU_DC_OFFSET + 0x00D8 > +#define IPU_DC_DISP_CONF1_1_OFFSET IPU_DC_OFFSET + 0x00DC > +#define IPU_DC_DISP_CONF1_2_OFFSET IPU_DC_OFFSET + 0x00E0 > +#define IPU_DC_DISP_CONF1_3_OFFSET IPU_DC_OFFSET + 0x00E4 > +#define IPU_DC_DISP_CONF2_0_OFFSET IPU_DC_OFFSET + 0x00E8 > +#define IPU_DC_DISP_CONF2_1_OFFSET IPU_DC_OFFSET + 0x00EC > +#define IPU_DC_DISP_CONF2_2_OFFSET IPU_DC_OFFSET + 0x00F0 > +#define IPU_DC_DISP_CONF2_3_OFFSET IPU_DC_OFFSET + 0x00F4 > +#define IPU_DC_DI0_CONF1_OFFSET IPU_DC_OFFSET + 0x00F8 > +#define IPU_DC_DI0_CONF2_OFFSET IPU_DC_OFFSET + 0x00FC > +#define IPU_DC_DI1_CONF1_OFFSET IPU_DC_OFFSET + 0x0100 > +#define IPU_DC_DI1_CONF2_OFFSET IPU_DC_OFFSET + 0x0104 > +#define IPU_DC_MAP_CONF_0_OFFSET IPU_DC_OFFSET + 0x0108 > +#define IPU_DC_MAP_CONF_1_OFFSET IPU_DC_OFFSET + 0x010C > +#define IPU_DC_MAP_CONF_2_OFFSET IPU_DC_OFFSET + 0x0110 > +#define IPU_DC_MAP_CONF_3_OFFSET IPU_DC_OFFSET + 0x0114 > +#define IPU_DC_MAP_CONF_4_OFFSET IPU_DC_OFFSET + 0x0118 > +#define IPU_DC_MAP_CONF_5_OFFSET IPU_DC_OFFSET + 0x011C > +#define IPU_DC_MAP_CONF_6_OFFSET IPU_DC_OFFSET + 0x0120 > +#define IPU_DC_MAP_CONF_7_OFFSET IPU_DC_OFFSET + 0x0124 > +#define IPU_DC_MAP_CONF_8_OFFSET IPU_DC_OFFSET + 0x0128 > +#define IPU_DC_MAP_CONF_9_OFFSET IPU_DC_OFFSET + 0x012C > +#define IPU_DC_MAP_CONF_10_OFFSET IPU_DC_OFFSET + 0x0130 > +#define IPU_DC_MAP_CONF_11_OFFSET IPU_DC_OFFSET + 0x0134 > +#define IPU_DC_MAP_CONF_12_OFFSET IPU_DC_OFFSET + 0x0138 > +#define IPU_DC_MAP_CONF_13_OFFSET IPU_DC_OFFSET + 0x013C > +#define IPU_DC_MAP_CONF_14_OFFSET IPU_DC_OFFSET + 0x0140 > +#define IPU_DC_MAP_CONF_15_OFFSET IPU_DC_OFFSET + 0x0144 > +#define IPU_DC_MAP_CONF_16_OFFSET IPU_DC_OFFSET + 0x0148 > +#define IPU_DC_MAP_CONF_17_OFFSET IPU_DC_OFFSET + 0x014C > +#define IPU_DC_MAP_CONF_18_OFFSET IPU_DC_OFFSET + 0x0150 > +#define IPU_DC_MAP_CONF_19_OFFSET IPU_DC_OFFSET + 0x0154 > +#define IPU_DC_MAP_CONF_20_OFFSET IPU_DC_OFFSET + 0x0158 > +#define IPU_DC_MAP_CONF_21_OFFSET IPU_DC_OFFSET + 0x015C > +#define IPU_DC_MAP_CONF_22_OFFSET IPU_DC_OFFSET + 0x0160 > +#define IPU_DC_MAP_CONF_23_OFFSET IPU_DC_OFFSET + 0x0164 > +#define IPU_DC_MAP_CONF_24_OFFSET IPU_DC_OFFSET + 0x0168 > +#define IPU_DC_MAP_CONF_25_OFFSET IPU_DC_OFFSET + 0x016C > +#define IPU_DC_MAP_CONF_26_OFFSET IPU_DC_OFFSET + 0x0170 > +#define IPU_DC_UGDE0_0_OFFSET IPU_DC_OFFSET + 0x0174 > +#define IPU_DC_UGDE0_1_OFFSET IPU_DC_OFFSET + 0x0178 > +#define IPU_DC_UGDE0_2_OFFSET IPU_DC_OFFSET + 0x017C > +#define IPU_DC_UGDE0_3_OFFSET IPU_DC_OFFSET + 0x0180 > +#define IPU_DC_UGDE1_0_OFFSET IPU_DC_OFFSET + 0x0184 > +#define IPU_DC_UGDE1_1_OFFSET IPU_DC_OFFSET + 0x0188 > +#define IPU_DC_UGDE1_2_OFFSET IPU_DC_OFFSET + 0x018C > +#define IPU_DC_UGDE1_3_OFFSET IPU_DC_OFFSET + 0x0190 > +#define IPU_DC_UGDE2_0_OFFSET IPU_DC_OFFSET + 0x0194 > +#define IPU_DC_UGDE2_1_OFFSET IPU_DC_OFFSET + 0x0198 > +#define IPU_DC_UGDE2_2_OFFSET IPU_DC_OFFSET + 0x019C > +#define IPU_DC_UGDE2_3_OFFSET IPU_DC_OFFSET + 0x01A0 > +#define IPU_DC_UGDE3_0_OFFSET IPU_DC_OFFSET + 0x01A4 > +#define IPU_DC_UGDE3_1_OFFSET IPU_DC_OFFSET + 0x01A8 > +#define IPU_DC_UGDE3_2_OFFSET IPU_DC_OFFSET + 0x01AC > +#define IPU_DC_UGDE3_3_OFFSET IPU_DC_OFFSET + 0x01B0 > +#define IPU_DC_LLA0_OFFSET IPU_DC_OFFSET + 0x01B4 > +#define IPU_DC_LLA1_OFFSET IPU_DC_OFFSET + 0x01B8 > +#define IPU_DC_R_LLA0_OFFSET IPU_DC_OFFSET + 0x01BC > +#define IPU_DC_R_LLA1_OFFSET IPU_DC_OFFSET + 0x01C0 > +#define IPU_DC_WR_CH_ADDR_5_ALT_OFFSET IPU_DC_OFFSET + 0x01C4 > +#define IPU_DC_STAT_OFFSET IPU_DC_OFFSET + 0x01C8 > + > +// Microcode template > +#define IPU_DC_TEMPLATE_REGS_ADDR_OFFSET 0x00180000 > + > +typedef enum { > + DC_CHANNEL_READ = 0, > + DC_CHANNEL_DC_SYNC_ASYNC = 1, > + DC_CHANNEL_DC_ASYNC = 2, > + DC_CHANNEL_DP_MAIN = 5, > + DC_CHANNEL_DP_SECONDARY = 6, > +} DC_CHANNEL; > + > +#pragma pack(push, 1) > + > +// IPU_DC_WR_CH_CONF_1 0x1C > +// IPU_DC_WR_CH_CONF_5 0x5C > +typedef union { > + struct { > + UINT32 W_SIZE : 2; > + UINT32 PROG_DI_ID : 1; > + UINT32 PROG_DISP_ID : 2; > + UINT32 PROG_CHAN_TYP : 3; > + UINT32 CHAN_MASK_DEFAULT : 1; > + UINT32 FILED_MODE : 1; > + UINT32 Reserved1 : 6; > + UINT32 PROG_START_TIME : 11; > + UINT32 Reserved2 : 5; > + }; > + UINT32 Reg; > +} IPU_DC_WR_CH_CONF_1_REG, IPU_DC_WR_CH_CONF_5_REG; > + > +typedef enum { > + PROG_CHAN_TYP_DISABLED, > + PROG_CHAN_TYP_RESERVED1, > + PROG_CHAN_TYP_NORMAL = 4, > + PROG_CHAN_TYP_NORMAL_ANTI_TEARING, > + PROG_CHAN_TYP_RESERVED2, > +} PROG_CHAN_TYP; > + > +// IPU_DC_GEN 0xD4 > +typedef union { > + struct { > + UINT32 Reserved1 : 1; > + UINT32 Sync_1_6 : 2; > + UINT32 Reserved2 : 1; > + UINT32 MASK_EN : 1; > + UINT32 MASK4CHAN_5 : 1; > + UINT32 SYNC_PRIORITY_5 : 1; > + UINT32 SYNC_PRIORITY_1 : 1; > + UINT32 DC_CH5_TYPE : 1; > + UINT32 Reserved3 : 7; > + UINT32 DC_BKDIV : 8; > + UINT32 DC_BK_EN : 1; > + UINT32 Reserved4 : 7; > + }; > + UINT32 Reg; > +} IPUx_IPU_DC_GEN_REG; > + > +// IPU_DC_RL0_CH_5 0x0064 > +typedef union { > + struct { > + UINT32 COD_NF_PRIORITY_CHAN_5 : 4; > + UINT32 Reserved1 : 4; > + UINT32 COD_NF_START_CHAN_5 : 8; > + UINT32 COD_NL_PRIORITY_CHAN_5 : 4; > + UINT32 Reserved2 : 4; > + UINT32 COD_NL_START_CHAN_5 : 24; > + }; > + UINT32 Reg; > +} IPU_DC_RL0_CH_5_REG; > + > +// IPU_DC_RL1_CH_5 0x006C > +typedef union { > + struct { > + UINT32 COD_EOF_PRIORITY_CHAN_5 : 4; > + UINT32 Reserved1 : 4; > + UINT32 COD_EOF_START_CHAN_5 : 8; > + UINT32 COD_NFIELD_PRIORITY_CHAN_5 : 4; > + UINT32 Reserved2 : 4; > + UINT32 COD_NFIELD_START_CHAN_5 : 24; > + }; > + UINT32 Reg; > +} IPU_DC_RL1_CH_5_REG; > + > +// IPU_DC_RL2_CH_5 0x0068 > +typedef union { > + struct { > + UINT32 COD_EOL_PRIORITY_CHAN_5 : 4; > + UINT32 Reserved1 : 4; > + UINT32 COD_EOL_START_CHAN_5 : 8; > + UINT32 COD_EOFIELD_PRIORITY_CHAN_5 : 4; > + UINT32 Reserved2 : 4; > + UINT32 COD_EOFIELD_START_CHAN_5 : 24; > + }; > + UINT32 Reg; > +} IPU_DC_RL2_CH_5_REG; > + > +// IPU_DC_RL3_CH_5 0x0070 > +typedef union { > + struct { > + UINT32 COD_NEW_ADDR_PRIORITY_CHAN_5 : 4; > + UINT32 Reserved1 : 4; > + UINT32 COD_NEW_ADDR_START_CHAN_5 : 8; > + UINT32 COD_NEW_CHAN_PRIORITY_CHAN_5 : 4; > + UINT32 Reserved2 : 4; > + UINT32 COD_NEW_CHAN_START_CHAN_5 : 24; > + }; > + UINT32 Reg; > +} IPU_DC_RL3_CH_5_REG; > + > +// IPU_DC_RL4_CH_5 0x0074 > +typedef union { > + struct { > + UINT32 COD_NEW_DATA_PRIORITY_CHAN_5 : 4; > + UINT32 Reserved1 : 4; > + UINT32 COD_NEW_DATA_START_CHAN_5 : 8; > + UINT32 Reserved2 : 16; > + }; > + UINT32 Reg; > +} IPU_DC_RL4_CH_5_REG; > + > +// DC_DISP_CONF1 0xD8 - 0xE4 > +typedef union { > + struct { > + UINT32 DISP_TYP : 2; > + UINT32 ADDR_INCREMENT : 2; > + UINT32 ADDR_BE_L_INC : 2; > + UINT32 MCU_ACC_LB_MASK_3 : 1; > + UINT32 DISP_RD_VALUE_PTR : 1; > + UINT32 Reserved : 24; > + }; > + UINT32 Reg; > +} IPUx_DC_DISP_CONF1_REG; > + > +// DC_MAP_CONF_MAP_OFFSET 0x0108 - 0x0140 > +typedef union { > + struct { > + UINT32 MAPPING_PNTR_BYTE0_X : 5; > + UINT32 MAPPING_PNTR_BYTE1_X : 5; > + UINT32 MAPPING_PNTR_BYTE2_X : 5; > + UINT32 Reserved1 : 1; > + UINT32 MAPPING_PNTR_BYTE0_Y : 5; > + UINT32 MAPPING_PNTR_BYTE1_Y : 5; > + UINT32 MAPPING_PNTR_BYTE2_Y : 5; > + UINT32 Reserved2 : 1; > + }; > + UINT32 Reg; > +} IPUx_DC_MAP_CONF_MAP_REG; > + > +// DC_MAP_CONF_OFFSET_MASK_OFFSET 0x0144 - 0x0170 > +typedef union { > + struct { > + UINT32 MD_MASK_X : 8; > + UINT32 MD_OFFSET_X : 5; > + UINT32 Reserved1 : 3; > + UINT32 MD_MASK_Y : 8; > + UINT32 MD_OFFSET_Y : 5; > + UINT32 Reserved2 : 3; > + }; > + UINT32 Reg; > +} DC_MAP_CONF_OFFSET_MASK_REG; > + > +typedef union { > + struct { > + UINT32 SYNC : 4; > + UINT32 GLUELOGIC : 7; > + UINT32 WAVEFORM : 4; > + UINT32 MAPPING : 5; > + UINT32 DATA : 16; > + UINT32 OPCODE : 5; > + UINT32 STOP : 1; > + UINT32 Unused : 22; > + }; > + struct { > + UINT32 LowWord; > + UINT32 HighWord; > + }; > +} DISPLAY_CONTROLLER_WROD_COMMAND; > + > +#pragma pack(pop) > + > +EFI_STATUS > +SetDisplayControllerChannelState ( > + IN VOID *IpuMmioBasePtr, > + IN PROG_CHAN_TYP ChannelType > + ); > + > +EFI_STATUS > +ConfigureDisplayControllerChannel ( > + IN DISPLAY_INTERFACE_CONTEXT *DisplayInterfaceContextPtr, > + IN DISPLAY_INTERFACE_TYPE DisplayInterface, > + IN UINT32 DisplayIndex, > + IN DISPLAY_TIMING *DisplayTimingPtr > + ); > + > +#endif /* _DISPLAY_CONTROLLER_H_ */ > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c > new file mode 100644 > index 000000000000..b36d03239652 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.c > @@ -0,0 +1,458 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* > +* 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 > + > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +#include "Ipu.h" > +#include "Display.h" > +#include "DisplayInterface.h" > + > +#ifdef DEBUG > +VOID > +DumpBasicDisplayInterfaceReg ( > + IN VOID *IpuMmioBasePtr, > + IN IPU_DIx_REGS *IpuDiRegsPtr > + ) > +{ > + UINT32 index, setNumber, regVal; > + UINT32 printTotalGen = 8; // Limit printing (max 12) > + > + DEBUG ((DEBUG_VERBOSE, "%a: ------- DI Register Dump -------\n", __FUNCTION__)); > + // Print out generator value for D0 > + DEBUG ((DEBUG_VERBOSE, "%a: ## Wave Gen\n", __FUNCTION__)); > + for (index = 0; index < printTotalGen; ++index) { > + regVal = READ_WAVE_GEN (IpuDiRegsPtr, index); > + DEBUG ((DEBUG_VERBOSE, "%a: DI0_DW_GEN_%d 0x%08x\n", > + __FUNCTION__, index, regVal)); > + } > + // Print out generator value for D0 > + DEBUG ((DEBUG_VERBOSE, "%a: ## Wave Set\n", __FUNCTION__)); > + for (index = 0; index < printTotalGen; ++index) { > + for (setNumber = 0; setNumber < 4; ++setNumber) { > + regVal = READ_WAVE_SET (IpuDiRegsPtr, index, setNumber); > + DEBUG ((DEBUG_VERBOSE, "%a: DI0_DW_SET%d_%d 0x%08x\n", > + __FUNCTION__, setNumber, index, regVal)); > + } > + } > + > + regVal = IpuRead32 (IpuMmioBasePtr, IPU_IPU_PM_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_IPU_PM_OFFSET %x\n", > + __FUNCTION__, regVal)); > + > + regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_BS_CLKGEN0_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_BS_CLKGEN0_OFFSET %x\n", > + __FUNCTION__, regVal)); > + regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_BS_CLKGEN1_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_BS_CLKGEN1_OFFSET %x\n", > + __FUNCTION__, regVal)); > + regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SCR_CONF_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SCR_CONF_OFFSET %x\n", > + __FUNCTION__, regVal)); > + regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN0_1_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN0_1_OFFSET %x\n", > + __FUNCTION__, regVal)); > + regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN1_1_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN1_1_OFFSET %x\n", > + __FUNCTION__, regVal)); > + regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN0_2_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN0_2_OFFSET %x\n", > + __FUNCTION__, regVal)); > + regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN1_2_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN1_2_OFFSET %x\n", > + __FUNCTION__, regVal)); > + regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN0_3_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN0_3_OFFSET %x\n", > + __FUNCTION__, regVal)); > + regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN1_3_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN1_3_OFFSET %x\n", > + __FUNCTION__, regVal)); > + regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN0_4_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN0_4_OFFSET %x\n", > + __FUNCTION__, regVal)); > + regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN1_4_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN1_4_OFFSET %x\n", > + __FUNCTION__, regVal)); > + regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN0_5_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN0_5_OFFSET %x\n", > + __FUNCTION__, regVal)); > + regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SW_GEN1_5_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SW_GEN1_5_OFFSET %x\n", > + __FUNCTION__, regVal)); > + > + for (index = 0; index < 5; ++index) { > + regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_STP_REP_OFFSET + (index * 0x4)); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_STP_%d_REP_OFFSET %x\n", > + __FUNCTION__, index + 1, regVal)); > + } > + > + regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_SYNC_AS_GEN_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_SYNC_AS_GEN_OFFSET %x\n", > + __FUNCTION__, regVal)); > + regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_GENERAL_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_GENERAL_OFFSET %x\n", > + __FUNCTION__, regVal)); > + regVal = DiRead32 (IpuDiRegsPtr, IPU_DIx_POL_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_DIx_POL_OFFSET %x\n", > + __FUNCTION__, regVal)); > + regVal = DiRead32 (IpuDiRegsPtr, IPU_IPU_DISP_GEN_OFFSET); > + DEBUG ((DEBUG_VERBOSE, "%a: IPU_IPU_DISP_GEN_OFFSET %x\n", > + __FUNCTION__, regVal)); > + DEBUG ((DEBUG_VERBOSE, "%a: ------------------------------\n\n", __FUNCTION__)); > +} > +#endif /* DEBUG */ > + > +VOID > +ConfigureSyncWave ( > + IN VOID *IpuMmioBasePtr, > + IN IPU_DIx_REGS *IpuDiRegsPtr, > + IN UINT32 CounterIndex, > + IN UINT32 RunValue, > + IN UINT32 RunResolution, > + IN UINT32 OffsetValue, > + IN UINT32 OffsetResolution, > + IN UINT32 CounterPolarityGenEn, > + IN UINT32 CounterAutoReload, > + IN UINT32 CounterClearSelect, > + IN UINT32 CounterDown, > + IN UINT32 CounterPolarityTriggerSelect, > + IN UINT32 CounterPolarityClearSelect, > + IN UINT32 CounterUp, > + IN UINT32 StepRepeat > + ) > +{ > + IPUx_DIx_SW_GEN0_x_REG DiSwGen0Reg; > + IPUx_DIx_SW_GEN1_x_REG DiSwGen1Reg; > + UINT32 StepIndex; > + IPUx_DIx_STP_REP_REG StepRepeatReg; > + > + ZeroMem ((VOID *)&DiSwGen0Reg, sizeof (DiSwGen0Reg)); > + DiSwGen0Reg.dix_offset_resolution = OffsetResolution; > + DiSwGen0Reg.dix_offset_value = OffsetValue; > + DiSwGen0Reg.dix_run_resolution = RunResolution; > + DiSwGen0Reg.dix_run_value_m1 = RunValue; > + DiWrite32 ( > + IpuDiRegsPtr, > + IPU_DIx_SW_GEN0_1_OFFSET + ((CounterIndex - 1) * 0x04), > + DiSwGen0Reg.Reg > + ); > + > + ZeroMem ((VOID *)&DiSwGen1Reg, sizeof (DiSwGen1Reg)); > + DiSwGen1Reg.dix_cnt_up = CounterUp; > + DiSwGen1Reg.dix_cnt_polarity_clr_sel = CounterPolarityClearSelect; > + DiSwGen1Reg.dix_cnt_polarity_trigger_sel = CounterPolarityTriggerSelect; > + DiSwGen1Reg.dix_cnt_down = CounterDown; > + DiSwGen1Reg.dix_cnt_clr_sel = CounterClearSelect; > + DiSwGen1Reg.dix_cnt_auto_reload = CounterAutoReload; > + DiSwGen1Reg.dix_cnt_polarity_gen_en = CounterPolarityGenEn; > + DiWrite32 ( > + IpuDiRegsPtr, > + IPU_DIx_SW_GEN1_1_OFFSET + ((CounterIndex - 1) * 0x04), > + DiSwGen1Reg.Reg > + ); > + > + StepIndex = (CounterIndex - 1) / 2; > + StepRepeatReg.Reg = IpuRead32 ( > + IpuMmioBasePtr, > + IPU_DI0_STP_REP_OFFSET + (StepIndex * 0x4) > + ); > + > + if (CounterIndex % 2) { > + StepRepeatReg.dix_step_repeat_2i_minus_1 = StepRepeat; > + } else { > + StepRepeatReg.dix_step_repeat_2i = StepRepeat; > + } > + IpuWrite32 ( > + IpuMmioBasePtr, > + IPU_DI0_STP_REP_OFFSET + (StepIndex * 0x4), > + StepRepeatReg.Reg > + ); > +} > + > +EFI_STATUS > +ConfigureDisplayInterface ( > + IN DISPLAY_INTERFACE_CONTEXT *DisplayInterfaceContextPtr, > + IN UINT32 DisplayIndex, > + IN DISPLAY_TIMING *DisplayTimingPtr > + ) > +{ > + IPU_DIx_REGS *pIpuDiRegs; > + VOID *pIpuMmioBase; > + UINT32 BaseDiv; > + UINT32 DispGenReg; > + UINT64 DisplayInterfaceFrequency; > + IPUx_DIx_DW_GEN_REG DixDwGenReg; > + IPUx_DIx_DW_SET_REG DixDwSetReg; > + IPUx_DIx_GENERAL_REG DixGeneralReg; > + IPUx_DIx_POL_REG DixPolReg; > + IPUx_DIx_SYNC_AS_GEN_REG DixSyncAsGenReg; > + UINT32 HorizontalLength; > + EFI_STATUS Status; > + UINT32 VerticalLength; > + > + DisplayInterfaceFrequency = DisplayTimingPtr->PixelClock; > + HorizontalLength = DisplayTimingPtr->HActive + DisplayTimingPtr->HBlank; > + VerticalLength = DisplayTimingPtr->VActive + DisplayTimingPtr->VBlank; > + pIpuMmioBase = DisplayInterfaceContextPtr->IpuMmioBasePtr; > + pIpuDiRegs = DisplayInterfaceContextPtr->IpuDiRegsPtr; > + Status = EFI_SUCCESS; > + > + Status = ImxSetPll5ReferenceRate (DisplayTimingPtr->PixelClock); > + if (Status != EFI_SUCCESS) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to setup PLL5=%r\n", __FUNCTION__, Status)); > + goto Exit; > + } > + > + // Setup base timer (fundamental timer). The base timer should already > + // setup to match the pixel clock frequency. > + // Shift 4 as the bottom 4 bits are fractional > + BaseDiv = (UINT32) ((DisplayInterfaceFrequency << 4) / DisplayTimingPtr->PixelClock); > + DiWrite32 (pIpuDiRegs, IPU_DIx_BS_CLKGEN0_OFFSET, BaseDiv); > + > + // Up is always set to 0. Down is half of the pixel clock period where > + // the first bit is fraction > + BaseDiv >>= 4; > + > + DiWrite32 (pIpuDiRegs, IPU_DIx_BS_CLKGEN1_OFFSET, BaseDiv << 16); > + // Calculate divisor, again this would usually be 1. > + BaseDiv = (UINT32) (DisplayInterfaceFrequency / DisplayTimingPtr->PixelClock); > + > + // Set up wave, there 12 wave quartet, for now default to the first. > + // Each wave quartet has 4 set register > + // Set 0 is just a blank signal where up and down is set to 0 > + ZeroMem ((VOID *)&DixDwSetReg, sizeof (DixDwSetReg)); > + DixDwSetReg.dix_data_cnt_upx_i = 0; > + DixDwSetReg.dix_data_cnt_downx_i = 0; > + WRITE_WAVE_SET ( > + pIpuDiRegs, > + DwGen0, > + DwSet0, > + DixDwSetReg.Reg > + ); > + > + // Set 3 is setup to match pixel clock > + ZeroMem ((VOID *)&DixDwSetReg, sizeof (DixDwSetReg)); > + DixDwSetReg.dix_data_cnt_upx_i = 0; > + DixDwSetReg.dix_data_cnt_downx_i = BaseDiv * 2; > + WRITE_WAVE_SET ( > + pIpuDiRegs, > + DwGen0, > + DwSet3, > + DixDwSetReg.Reg > + ); > + > + // All pins blank signal except pin 15 > + ZeroMem ((VOID *)&DixDwGenReg, sizeof (DixDwGenReg)); > + DixDwGenReg.dix_pt_0_i = DwSet0; > + DixDwGenReg.dix_pt_1_i = DwSet0; > + DixDwGenReg.dix_pt_2_i = DwSet0; > + DixDwGenReg.dix_pt_3_i = DwSet0; > + DixDwGenReg.dix_pt_4_i = DwSet3; > + DixDwGenReg.dix_pt_5_i = DwSet0; > + DixDwGenReg.dix_pt_6_i = DwSet0; > + DixDwGenReg.dix_cst_i = DwSet0; > + // Reuse the base divisor to determine extra IPU cycles. > + DixDwGenReg.dix_componnent_size_i = BaseDiv - 1; > + DixDwGenReg.dix_access_size_i = BaseDiv - 1; > + WRITE_WAVE_GEN (pIpuDiRegs, DwGen0, DixDwGenReg.Reg); > + > + // Spec mention this as number of display rows but display only works > + // properly if this is setup as vertical total > + DiWrite32 (pIpuDiRegs, IPU_DIx_SCR_CONF_OFFSET, VerticalLength - 1); > + > + // Internal HSYNC > + ConfigureSyncWave ( > + pIpuMmioBase, > + pIpuDiRegs, > + DI_COUNTER_1_INTERNAL_HSYNC, // CounterIndex > + HorizontalLength - 1, // Runvalue > + DI_COUNTER_0_DISPLAY_CLOCK + 1, // RunResolution > + 0, // OffsetValue > + 0, // OffsetResolution > + 0, // CounterPolarityGenEn > + 1, // CounterAutoReload > + DI_COUNTER_DISABLED, // CounterClearSelect > + 0, // CountDown > + 0, // CounterPolarityTriggerSelect > + 0, // CounterPolarityClearSelect > + 0, // CounterUp > + 0 // StepRepeat > + ); > + > + // Output HSYNC > + ConfigureSyncWave ( > + pIpuMmioBase, > + pIpuDiRegs, > + DI_COUNTER_2_OUTPUT_HSYNC, // CounterIndex > + HorizontalLength - 1, // Runvalue > + DI_COUNTER_0_DISPLAY_CLOCK + 1, // RunResolution > + 0, // OffsetValue > + DI_COUNTER_0_DISPLAY_CLOCK + 1, // OffsetResolution - Display clock > + 1, // CounterPolarityGenEn > + 1, // CounterAutoReload > + DI_COUNTER_DISABLED, // CounterClearSelect > + DisplayTimingPtr->HSync * 2, // CountDown > + 1, // CounterPolarityTriggerSelect > + 0, // CounterPolarityClearSelect > + 0, // CounterUp > + 0 // StepRepeat > + ); > + > + // Output VSYNC > + ConfigureSyncWave ( > + pIpuMmioBase, > + pIpuDiRegs, > + DI_COUNTER_3_OUTPUT_VSYNC, // CounterIndex > + VerticalLength - 1, // Runvalue > + DI_COUNTER_1_INTERNAL_HSYNC + 1, // RunResolution - Counter 1 > + 0, // OffsetValue > + 0, // OffsetResolution > + 1, // CounterPolarityGenEn > + 1, // CounterAutoReload > + DI_COUNTER_DISABLED, // CounterClearSelect > + DisplayTimingPtr->VSync * 2, // CountDown > + 2, // CounterPolarityTriggerSelect > + 0, // CounterPolarityClearSelect > + 0, // CounterUp > + 0 // StepRepeat > + ); > + > + // Active lines > + ConfigureSyncWave ( > + pIpuMmioBase, > + pIpuDiRegs, > + DI_COUNTER_4_ACTIVE_LINE, // CounterIndex > + 0, // Runvalue > + DI_COUNTER_2_OUTPUT_HSYNC + 1, // RunResolution - Counter 2 > + DisplayTimingPtr->VSync + DisplayTimingPtr->VSyncOffset, // Offset > + DI_COUNTER_2_OUTPUT_HSYNC + 1,// OffsetResolution - Counter 2 > + 0, // CounterPolarityGenEn > + 0, // CounterAutoReload > + DI_COUNTER_3_OUTPUT_VSYNC + 1, // CounterClearSelect - Counter 3 > + 0, // CountDown > + 0, // CounterPolarityTriggerSelect > + 0, // CounterPolarityClearSelect > + 0, // CounterUp > + DisplayTimingPtr->VActive // StepRepeat repeat for total VActive > + ); > + > + // Active clock > + ConfigureSyncWave ( > + pIpuMmioBase, > + pIpuDiRegs, > + DI_COUNTER_5_ACTIVE_CLOCK, // CounterIndex > + 0, // Runvalue > + DI_COUNTER_0_DISPLAY_CLOCK + 1, // RunResolution - Display clock > + DisplayTimingPtr->HSync + DisplayTimingPtr->HSyncOffset, // Offset > + DI_COUNTER_0_DISPLAY_CLOCK + 1, // OffsetResolution - Display clock > + 0, // CounterPolarityGenEn > + 0, // CounterAutoReload > + DI_COUNTER_4_ACTIVE_LINE + 1, // CounterClearSelect - Counter 4 > + 0, // CountDown > + 0, // CounterPolarityTriggerSelect > + 0, // CounterPolarityClearSelect > + 0, // CounterUp > + DisplayTimingPtr->HActive // StepRepeat > + ); > + > + ZeroMem ((VOID *)&DixSyncAsGenReg, sizeof (DixSyncAsGenReg)); > + // VSYNC is setup as counter 3 above, 0 index based > + DixSyncAsGenReg.dix_vsync_sel = 3 - 1; > + // Number of row DI prepares next frame data. > + DixSyncAsGenReg.dix_sync_start = 2; > + DiWrite32 (pIpuDiRegs, IPU_DIx_SYNC_AS_GEN_OFFSET, DixSyncAsGenReg.Reg); > + > + // Setup general register > + ZeroMem ((VOID *)&DixGeneralReg, sizeof (DixGeneralReg)); > + // Counter 1 as display line > + DixGeneralReg.dix_disp_y_sel = DI_COUNTER_1_INTERNAL_HSYNC - 1; > + // Stop at the next edge of the display clock > + DixGeneralReg.DIx_CLOCK_STOP_MODE = 0; > + // The display's clock is stopped after the next VSYNC > + DixGeneralReg.DIx_DISP_CLOCK_INIT = 0; > + // IPP_PIN_2 is coming from counter #2 > + DixGeneralReg.dix_mask_sel = 0; > + // External clock - for not the video PLL > + DixGeneralReg.dix_vsync_ext = 1; > + // External clock - for not the video PLL > + DixGeneralReg.dix_clk_ext = 1; > + // 4 cycle watch dog based on BSP > + DixGeneralReg.DIx_WATCHDOG_MODE = 0; > + // default sync to counter 0 > + DixGeneralReg.dix_sync_count_sel = DI_COUNTER_1_INTERNAL_HSYNC - 1; > + // In the event of error drive the last component > + DixGeneralReg.dix_err_treatment = 0; > + // An internal VSYNC signal asserted 2 lines before the DI's VSYNC > + DixGeneralReg.dix_erm_vsync_sel = 0; > + > + switch (DisplayInterfaceContextPtr->displayInterface) { > + case HdmiDisplay: > + // Zero for HDMI display > + DixGeneralReg.dix_polarity_disp_clk = 0; > + DixGeneralReg.dix_polarity_cs1 = 0; > + DixGeneralReg.dix_polarity_cs0 = 0; > + DixGeneralReg.dix_polarity_i_1 = 0; > + break; > + default: > + Status = EFI_UNSUPPORTED; > + DEBUG ((DEBUG_ERROR, "%a: Unsupported display interface %d\n", > + __FUNCTION__, DisplayInterfaceContextPtr->displayInterface)); > + break; > + } > + if (EFI_ERROR (Status)) { > + goto Exit; > + } > + DiWrite32 (pIpuDiRegs, IPU_DIx_GENERAL_OFFSET, DixGeneralReg.Reg); > + > + ZeroMem ((VOID *)&DixPolReg, sizeof (DixPolReg)); > + // CS0 > + DixPolReg.DIx_CS0_DATA_POLARITY = 1; > + DixPolReg.dix_cs0_polarity = 0x7F; > + // CS1 > + DixPolReg.DIx_CS1_DATA_POLARITY = 1; > + DixPolReg.dix_cs1_polarity = 0x7F; > + // DRDY > + DixPolReg.DIx_DRDY_DATA_POLARITY = 0; > + DixPolReg.dix_drdy_polarity = 0x7F; > + // Wait > + DixPolReg.DIx_WAIT_POLARITY = 0; > + // CS0 byte enable polarity > + DixPolReg.DIx_CS0_BYTE_EN_POLARITY = 0; > + // CS1 byte enable polarity > + DixPolReg.DIx_CS1_BYTE_EN_POLARITY = 0; > + DiWrite32 (pIpuDiRegs, IPU_DIx_POL_OFFSET, DixPolReg.Reg); > + > + DispGenReg = IpuRead32 (pIpuMmioBase, IPU_IPU_DISP_GEN_OFFSET); > + DispGenReg &= ~(0x0F << 18); > + DispGenReg |= (2 << 18); > + IpuWrite32 (pIpuMmioBase, IPU_IPU_DISP_GEN_OFFSET, DispGenReg); > + > +#ifdef DEBUG > + DumpBasicDisplayInterfaceReg (pIpuMmioBase, pIpuDiRegs); > +#endif /* DEBUG */ > + > + Status = EFI_SUCCESS; > + > +Exit: > + return Status; > +} > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h > new file mode 100644 > index 000000000000..786ef1fff5f0 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/DisplayInterface.h > @@ -0,0 +1,195 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* > +* 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. > +* > +**/ > + > +#ifndef _DISPLAY_INTERFACE_H_ > +#define _DISPLAY_INTERFACE_H_ IMX_ prefix please. > + > +#define READ_WAVE_GEN(IPU_BASE, GEN_INDEX) \ > + DiRead32(IPU_BASE, IPU_DIx_DW_GEN_OFFSET + (GEN_INDEX * 0x4)) > + > +#define WRITE_WAVE_GEN(IPU_BASE, GEN_INDEX, VALUE) \ > + DiWrite32(IPU_BASE, IPU_DIx_DW_GEN_OFFSET + (GEN_INDEX * 0x4), VALUE) > + > +#define READ_WAVE_SET(IPU_BASE, GEN_INDEX, SET_NUMBER) \ > + DiRead32(IPU_BASE, IPU_DIx_DW_SET0_OFFSET + (SET_NUMBER * 0x30) + (GEN_INDEX * 0x4)) > + > +#define WRITE_WAVE_SET(IPU_BASE, GEN_INDEX, SET_NUMBER, VALUE) \ > + DiWrite32(IPU_BASE, IPU_DIx_DW_SET0_OFFSET + (SET_NUMBER * 0x30) + (GEN_INDEX * 0x4), VALUE) > + > +#define DI_COUNTER_DISABLED 0 > +#define DI_COUNTER_0_DISPLAY_CLOCK 0 > +#define DI_COUNTER_1_INTERNAL_HSYNC 1 > +#define DI_COUNTER_2_OUTPUT_HSYNC 2 > +#define DI_COUNTER_3_OUTPUT_VSYNC 3 > +#define DI_COUNTER_4_ACTIVE_LINE 4 > +#define DI_COUNTER_5_ACTIVE_CLOCK 5 > + > +typedef enum { > + DwGen0, > + DwGen1, > + DwGen2, > + DwGen3, > + DwGen4, > + DwGen5, > + DwGen6, > + DwGen7, > + DwGen8, > + DwGen9, > + DwGen10, > + DwGen11, > + DwGenMax > +} DW_GEN; > + > +typedef enum { > + DwSet0, > + DwSet1, > + DwSet2, > + DwSet3, > + DwSetMax > +} DW_SET; > + > +#pragma pack(push, 1) > + > +// IPUx_DIx_GENERAL > +typedef union { > + struct { > + UINT32 dix_polarity_i_1 : 8; > + UINT32 dix_polarity_cs0 : 1; > + UINT32 dix_polarity_cs1 : 1; > + UINT32 dix_erm_vsync_sel : 1; > + UINT32 dix_err_treatment : 1; > + UINT32 dix_sync_count_sel : 4; > + UINT32 Reserved : 1; > + UINT32 dix_polarity_disp_clk : 1; > + UINT32 DIx_WATCHDOG_MODE : 2; > + UINT32 dix_clk_ext : 1; > + UINT32 dix_vsync_ext : 1; > + UINT32 dix_mask_sel : 1; > + UINT32 DIx_DISP_CLOCK_INIT : 1; > + UINT32 DIx_CLOCK_STOP_MODE : 4; > + UINT32 dix_disp_y_sel : 3; > + UINT32 dix_pin8_pin15_sel : 1; > + }; > + UINT32 Reg; > +} IPUx_DIx_GENERAL_REG; > + > +// IPUx_DIx_SYNC_AS_GEN > +typedef union { > + struct { > + UINT32 dix_sync_start : 12; > + UINT32 Reserved1 : 1; > + UINT32 dix_vsync_sel : 3; > + UINT32 Reserved2 : 12; > + UINT32 di0_sync_start_en : 1; > + UINT32 Reserved3 : 3; > + }; > + UINT32 Reg; > +} IPUx_DIx_SYNC_AS_GEN_REG; > + > +// IPUx_DIx_DW_SET > +typedef union { > + struct { > + UINT32 dix_data_cnt_upx_i : 9; > + UINT32 Reserved1 : 7; > + UINT32 dix_data_cnt_downx_i : 9; > + UINT32 Reserved2 : 7; > + }; > + UINT32 Reg; > +} IPUx_DIx_DW_SET_REG; > + > +// IPUx_DIx_DW_GEN > +typedef union { > + struct { > + UINT32 dix_pt_0_i : 2; // Pin 11 > + UINT32 dix_pt_1_i : 2; // Pin 12 > + UINT32 dix_pt_2_i : 2; // Pin 13 > + UINT32 dix_pt_3_i : 2; // Pin 14 > + UINT32 dix_pt_4_i : 2; // Pin 15 > + UINT32 dix_pt_5_i : 2; // Pin 16 > + UINT32 dix_pt_6_i : 2; // Pin 17 > + UINT32 dix_cst_i : 2; // Chip Select > + UINT32 dix_componnent_size_i : 8; > + UINT32 dix_access_size_i : 8; > + }; > + UINT32 Reg; > +} IPUx_DIx_DW_GEN_REG; > + > + > +// IPUx_DIx_SW_GEN0_x_REG > +typedef union { > + struct { > + UINT32 dix_offset_resolution : 3; > + UINT32 dix_offset_value : 12; > + UINT32 Reserved1: 1; > + UINT32 dix_run_resolution : 3; > + UINT32 dix_run_value_m1 : 12; > + UINT32 Reserved2 : 1; > + }; > + UINT32 Reg; > +} IPUx_DIx_SW_GEN0_x_REG; > + > +// IPUx_DIx_SW_GEN1_x_REG > +typedef union { > + struct { > + UINT32 dix_cnt_up : 9; > + UINT32 dix_cnt_polarity_clr_sel : 3; > + UINT32 dix_cnt_polarity_trigger_sel : 3; > + UINT32 Reserved1 : 1; > + UINT32 dix_cnt_down: 9; > + UINT32 dix_cnt_clr_sel : 3; > + UINT32 dix_cnt_auto_reload : 1; > + UINT32 dix_cnt_polarity_gen_en : 2; > + UINT32 Reserved2 : 1; > + }; > + UINT32 Reg; > +} IPUx_DIx_SW_GEN1_x_REG; > + > +// IPUx_DIx_STP_REP > +typedef union { > + struct { > + UINT32 dix_step_repeat_2i_minus_1 : 12; > + UINT32 Reserved1 : 4; > + UINT32 dix_step_repeat_2i : 12; > + UINT32 Reserved2 : 4; > + }; > + UINT32 Reg; > +} IPUx_DIx_STP_REP_REG; > + > +// IPUx_DIx_POL > +typedef union { > + struct { > + UINT32 dix_drdy_polarity : 7; > + UINT32 DIx_DRDY_DATA_POLARITY : 1; > + UINT32 dix_cs0_polarity : 7; > + UINT32 DIx_CS0_DATA_POLARITY : 1; > + UINT32 dix_cs1_polarity : 7; > + UINT32 DIx_CS1_DATA_POLARITY : 1; > + UINT32 DIx_CS0_BYTE_EN_POLARITY : 1; > + UINT32 DIx_CS1_BYTE_EN_POLARITY : 1; > + UINT32 DIx_WAIT_POLARITY : 1; > + UINT32 Reserved : 5; > + }; > + UINT32 Reg; > +} IPUx_DIx_POL_REG; > + > +#pragma pack(pop) > + > +EFI_STATUS > +ConfigureDisplayInterface ( > + IN DISPLAY_INTERFACE_CONTEXT *DisplayInterfaceContextPtr, > + IN UINT32 DisplayIndex, > + IN DISPLAY_TIMING *DisplayTimingPtr > + ); > + > +#endif /* _DISPLAY_INTERFACE_H_ */ > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c > new file mode 100644 > index 000000000000..cc6557a58138 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.c > @@ -0,0 +1,96 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* > +* 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 > + > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +#include "Display.h" > +#include "Edid.h" > +#include "Ddc.h" > + > +EFI_STATUS > +ReadEdid ( > + IN DISPLAY_CONTEXT *DisplayContextPtr, > + IN DISPLAY_INTERFACE_TYPE DisplayInterface, > + IN UINT8 *EdidDataPtr, > + OUT UINT32 *EdidDataSizePtr > + ) > +{ > + EFI_STATUS Status; > + > + Status = Imx6DdcRead ( > + DisplayContextPtr, > + DisplayInterface, > + EDID_I2C_ADDRESS, > + 0, > + EDID_MIN_SIZE, > + EdidDataPtr > + ); > + if (Status != EFI_SUCCESS) { > + goto Exit; > + } > + > + Status = ValidateEdidData ( > + EdidDataPtr > + ); > + if (Status != EFI_SUCCESS) { > + DEBUG ((DEBUG_WARN, "%a: Invalid EDID data\n", __FUNCTION__)); > + goto Exit; > + } > + > + DEBUG ((DEBUG_INFO, "%a: EDID initialized\n", __FUNCTION__)); > + > + *EdidDataSizePtr = EDID_MIN_SIZE; > + > +Exit: > + return Status; > +} > + > +EFI_STATUS > +GetEdidPreferredTiming ( > + IN UINT8 *EdidDataPtr, > + IN UINT32 EdidDataSizePtr, > + OUT DISPLAY_TIMING *PreferredTiming > + ) > +{ > + DETAILED_TIMING_DESCRIPTOR *pEdidPreferredTiming; > + EFI_STATUS Status; > + > + if (EdidDataSizePtr < EDID_MIN_SIZE) { > + DEBUG ((DEBUG_WARN, "%a: Insufficient EDID data\n", __FUNCTION__)); > + Status = EFI_INVALID_PARAMETER; > + goto Exit; > + } > + > + pEdidPreferredTiming = (DETAILED_TIMING_DESCRIPTOR *)&EdidDataPtr[EDID_DTD_1_OFFSET]; > + Status = ConvertDTDToDisplayTiming (pEdidPreferredTiming, PreferredTiming); > + if (Status != EFI_SUCCESS) { > + DEBUG ((DEBUG_ERROR, "%a: Conversion to display timing failed\n", > + __FUNCTION__)); > + goto Exit; > + } > + > +Exit: > + > + return Status; > +} > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h > new file mode 100644 > index 000000000000..df714f284deb > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Edid.h > @@ -0,0 +1,33 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* > +* 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. > +* > +**/ > + > +#ifndef _EDID_H_ > +#define _EDID_H_ IMX_ prefix please. > + > +EFI_STATUS > +ReadEdid ( > + IN DISPLAY_CONTEXT *DisplayContextPtr, > + IN DISPLAY_INTERFACE_TYPE DisplayInterface, > + IN UINT8 *EdidDataPtr, > + OUT UINT32 *EdidDataSizePtr > + ); > + > +EFI_STATUS > +GetEdidPreferredTiming ( > + IN UINT8 *EdidDataPtr, > + IN UINT32 EdidDataSizePtr, > + OUT DISPLAY_TIMING *PreferredTiming > + ); > + > +#endif /* _EDID_H_ */ > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c > new file mode 100644 > index 000000000000..2e990a6b14fb > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.c > @@ -0,0 +1,475 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* Copyright 2018 NXP > +* > +* 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 > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +#include "Display.h" > +#include "GopDxe.h" > +#include "Hdmi.h" > +#include "Lvds.h" > + > +#define PIXEL_BYTES 4 > + > +typedef struct { > + VENDOR_DEVICE_PATH Mmc; > + EFI_DEVICE_PATH End; > +} VID_DEVICE_PATH; > + > +DISPLAY_TIMING CONST FullHDTiming = { > + 148500000, // Full 1080p HD PixelClock > + 1920, // HActive > + 280, // HBlank > + 1080, // VActive > + 45, // VBlank > + 44, // HSync > + 5, // VSync > + 88, // HSyncOffset; > + 4, // VSyncOffset; > + 1920, // HImageSize > + 1080, // VImageSize > + 0, // HBorder > + 0, // VBorder > + 30, // EdidFlags > + 0, // Flags > + 1, // PixelRepetition > + 32, // Bpp > + PIXEL_FORMAT_BGRA32, // PixelFormat > +}; > + > +EFI_STATUS > +EFIAPI > +VidGopQueryMode ( > + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, > + IN UINT32 ModeNumber, > + OUT UINTN *SizeOfInfo, > + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info > + ); > + > +EFI_STATUS > +VidGopSetMode ( > + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, > + IN UINT32 ModeNumber > + ); > + > +EFI_STATUS > +VidGopBlt ( > + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, > + IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, > + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, > + IN UINTN SourceX, > + IN UINTN SourceY, > + IN UINTN DestinationX, > + IN UINTN DestinationY, > + IN UINTN Width, > + IN UINTN Height, > + IN UINTN Delta > + ); > + > +STATIC VID_DEVICE_PATH VidDevicePath = { m-prefix for global variables, please. Throughout. (Where they're not for edk2-global visibility and should have g.) > + { > + { > + HARDWARE_DEVICE_PATH, > + HW_VENDOR_DP, > + { > + (UINT8)sizeof (VENDOR_DEVICE_PATH), > + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8), > + } > + }, > + { > + 0xa6b94ebe, > + 0x5ba3, > + 0x44b0, > + { 0x95, 0x92, 0xdc, 0x04, 0x5e, 0xb8, 0xf8, 0x9e } > + } > + }, > + { > + END_DEVICE_PATH_TYPE, > + END_ENTIRE_DEVICE_PATH_SUBTYPE, > + { > + sizeof (EFI_DEVICE_PATH_PROTOCOL), > + 0 > + } > + } > +}; > + > +STATIC EFI_GRAPHICS_OUTPUT_MODE_INFORMATION VidGopModeInfo; > +STATIC EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE VidGopMode; > + > +STATIC EFI_GRAPHICS_OUTPUT_PROTOCOL VidGop = { > + VidGopQueryMode, // QueryMode > + VidGopSetMode, // SetMode > + VidGopBlt, // Blt > + &VidGopMode // Mode > +}; > + > +EFI_EDID_DISCOVERED_PROTOCOL EdidDiscovered = { > + 0, > + NULL > +}; > + > +EFI_EDID_ACTIVE_PROTOCOL EdidActive = { > + 0, > + NULL > +}; > + > +DISPLAY_CONTEXT *DisplayContextPtr; > + > +DISPLAY_INTERFACE_TYPE DisplayDevice; > + > +EFI_STATUS > +GopDxeInitialize ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + DISPLAY_INTERFACE_TYPE DisplayInterfaceOrder[DisplayTypeMax]; > + UINT32 i; > + UINT32 RequestedDisplayMemorySize; > + UINT32 ReservedDisplayMemorySize; > + EFI_STATUS Status; > + > + DEBUG ((DEBUG_INFO, "%a: Enter \n", __FUNCTION__)); > + > + for (i = 0; i < DisplayTypeMax; i++) { > + DisplayInterfaceOrder[i] = NoDisplayType; > + } > + ReservedDisplayMemorySize = FixedPcdGet32 (PcdFrameBufferSize); > + if (FeaturePcdGet (PcdLvdsEnable)) { > + DisplayDevice = Lvds0Display; > + } else { > + DisplayDevice = HdmiDisplay; > + } > + > + Status = InitDisplay (&DisplayContextPtr); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, > + "%a: Fail to init display, Status=%r\n", __FUNCTION__, > + Status)); > + goto Exit; > + } > + > + DEBUG ((DEBUG_INFO, "%a: - Allocate frame buffer\n", __FUNCTION__)); > + // To allocate frame buffer dynamically, there isn`t a built in graphic memory > + // manager for UEFI, so we are allocating frame buffer manually. Currently only > + // support single display, so allocate single(1) frame buffer > + // Allocate frame buffer > + DisplayContextPtr->DisplayConfig.DisplaySurface[0].Width = > + DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming.HActive; > + DisplayContextPtr->DisplayConfig.DisplaySurface[0].Height = > + DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming.VActive; > + DisplayContextPtr->DisplayConfig.DisplaySurface[0].Bpp = > + DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming.Bpp; > + DisplayContextPtr->DisplayConfig.DisplaySurface[0].PixelFormat = > + DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming.PixelFormat; > + > + // iMX6 UEFI reserves display memory for fullHD buffer size. > + // PcdFrameBufferSize=800000h or 8388608 bytes - 1920x1080x4 bytes > + // to prevent larger displays overrun our reserved memory size, > + // cap display resolution to fullHD > + // NOTE: Displays which do not have support for 1920x1080 mode may > + // have poor or missing picture > + RequestedDisplayMemorySize = > + DisplayContextPtr->DisplayConfig.DisplaySurface[0].Width * > + DisplayContextPtr->DisplayConfig.DisplaySurface[0].Height * > + (DisplayContextPtr->DisplayConfig.DisplaySurface[0].Bpp / 8); > + > + DEBUG ((DEBUG_INFO, "%a: Display Memory: Needed=%d, Available=%d\n", > + __FUNCTION__, RequestedDisplayMemorySize, ReservedDisplayMemorySize)); > + > + if (RequestedDisplayMemorySize > ReservedDisplayMemorySize) { > + DEBUG ((DEBUG_INFO, > + "%a: WARNING. Need more video memory than reserved by %d bytes\n", > + __FUNCTION__, RequestedDisplayMemorySize - ReservedDisplayMemorySize)); > + DEBUG ((DEBUG_ERROR, > + "%a: - display resolution too big. Cap to HD 1080p\n", > + __FUNCTION__)); > + DisplayContextPtr->DisplayConfig.DisplaySurface[0].Width = FullHDTiming.HActive; > + DisplayContextPtr->DisplayConfig.DisplaySurface[0].Height = > + FullHDTiming.VActive; > + DisplayContextPtr->DisplayConfig.DisplaySurface[0].Bpp = FullHDTiming.Bpp; > + CopyMem ( > + &DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming, > + &FullHDTiming, > + sizeof (DISPLAY_TIMING) > + ); > + } > + > + DEBUG ((DEBUG_INFO, "%a: - allocating frame buffer... \n", > + __FUNCTION__)); > + Status = AllocateFrameBuffer (&DisplayContextPtr->DisplayConfig.DisplaySurface[0]); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to allocate fb, Status=%r\n", > + __FUNCTION__, Status)); > + goto Exit; > + }; > + > + DEBUG ((DEBUG_INFO, "%a: - Initialize the frame buffer to black\n", > + __FUNCTION__)); > + // Initialize the frame buffer to black > + SetMem32 ( > + (VOID *)DisplayContextPtr->DisplayConfig.DisplaySurface[0].PhyAddr, > + DisplayContextPtr->DisplayConfig.DisplaySurface[0].Width * > + DisplayContextPtr->DisplayConfig.DisplaySurface[0].Height * 4, > + 0xFF000000 > + ); > + > + DEBUG ((DEBUG_INFO, "%a: - set display configuration to single HDMI\n", > + __FUNCTION__)); > + // Set the display configuration to single HDMI/LVDS mode > + DisplayInterfaceOrder[0] = DisplayDevice; > + DisplayContextPtr->DisplayConfig.DisplayTiming[0] = > + DisplayContextPtr->DiContext[DisplayDevice].PreferredTiming; > + > + Status = ApplyDisplayConfig ( > + DisplayContextPtr, > + SINGLE_MODE, > + DisplayInterfaceOrder > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to set display. Exit Status=%r\n", > + __FUNCTION__, Status)); > + goto Exit; > + } > + > + VidGopModeInfo.Version = 0; > + VidGopModeInfo.HorizontalResolution = > + DisplayContextPtr->DisplayConfig.DisplayTiming[0].HActive; > + VidGopModeInfo.VerticalResolution = > + DisplayContextPtr->DisplayConfig.DisplayTiming[0].VActive; > + VidGopModeInfo.PixelFormat = PixelBlueGreenRedReserved8BitPerColor; > + ZeroMem ( > + &VidGopModeInfo.PixelInformation, > + sizeof (VidGopModeInfo.PixelInformation) > + ); > + > + VidGopModeInfo.PixelsPerScanLine = VidGopModeInfo.HorizontalResolution; > + VidGopMode.MaxMode = 1; > + VidGopMode.Mode = 0; > + VidGopMode.Info = &VidGopModeInfo; > + VidGopMode.SizeOfInfo = sizeof (VidGopModeInfo); > + VidGopMode.FrameBufferBase = > + (EFI_PHYSICAL_ADDRESS) DisplayContextPtr->DisplayConfig.DisplaySurface[0].PhyAddr; > + VidGopMode.FrameBufferSize = > + VidGopModeInfo.HorizontalResolution * > + VidGopModeInfo.VerticalResolution * > + (DisplayContextPtr->DisplayConfig.DisplaySurface[0].Bpp / 8); > + DisplayContextPtr->DisplayConfig.OsHandle[0] = (UINT32)&ImageHandle; > + > + Status = gBS->InstallMultipleProtocolInterfaces ( > + &ImageHandle, > + &gEfiGraphicsOutputProtocolGuid, > + &VidGop, > + &gEfiDevicePathProtocolGuid, > + &VidDevicePath, > + NULL > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to install protocol, Status=%x\n", > + __FUNCTION__, Status)); > + goto Exit; > + } > + > +Exit: > + DEBUG ((DEBUG_INFO, "%a: Exit = %Xh\n", > + __FUNCTION__, Status)); > + return Status; > +} > + > +EFI_STATUS > +EFIAPI > +VidGopQueryMode ( > + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, > + IN UINT32 ModeNumber, > + OUT UINTN *SizeOfInfo, > + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info > + ) > +{ > + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *OutputMode; > + EFI_STATUS Status; > + > + if (FeaturePcdGet (PcdLvdsEnable)) { > + DisplayDevice = Lvds0Display; > + } else { > + DisplayDevice = HdmiDisplay; > + } > + > + EdidDiscovered.SizeOfEdid = DisplayContextPtr->DiContext[DisplayDevice].EdidDataSize; > + EdidDiscovered.Edid = DisplayContextPtr->DiContext[DisplayDevice].EdidData; > + EdidActive.SizeOfEdid = DisplayContextPtr->DiContext[DisplayDevice].EdidDataSize; > + EdidActive.Edid = DisplayContextPtr->DiContext[DisplayDevice].EdidData; > + Status = gBS->InstallMultipleProtocolInterfaces ( > + (EFI_HANDLE)DisplayContextPtr->DisplayConfig.OsHandle[0], > + &gEfiEdidDiscoveredProtocolGuid, > + &EdidDiscovered, > + &gEfiEdidActiveProtocolGuid, > + &EdidActive, > + NULL > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to install EDID protocols Status=%r\n", > + __FUNCTION__, Status)); > + } > + > + if (ModeNumber != 0) { > + DEBUG ((DEBUG_ERROR, "%a: Saw request to query mode %d\n", > + __FUNCTION__, ModeNumber)); > + Status = EFI_INVALID_PARAMETER; > + goto Exit; > + } > + > + OutputMode = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) > + AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)); > + if (OutputMode == NULL) { > + Status = EFI_OUT_OF_RESOURCES; > + goto Exit; > + } > + > + OutputMode->Version = 0; > + OutputMode->HorizontalResolution = VidGopModeInfo.HorizontalResolution; > + OutputMode->VerticalResolution = VidGopModeInfo.VerticalResolution; > + OutputMode->PixelFormat = PixelBlueGreenRedReserved8BitPerColor; > + OutputMode->PixelsPerScanLine = VidGopModeInfo.HorizontalResolution; > + *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); > + *Info = OutputMode; > + > + Status = EFI_SUCCESS; > + > +Exit: > + return Status; > +} > + > +EFI_STATUS > +VidGopSetMode ( > + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, > + IN UINT32 ModeNumber > + ) > +{ > + EFI_STATUS Status; > + > + if (ModeNumber != 0) { > + DEBUG ((DEBUG_ERROR, "%a: Saw request to set mode to %d\n", > + __FUNCTION__, ModeNumber)); > + Status = EFI_UNSUPPORTED; > + goto Exit; > + } > + > + Status = EFI_SUCCESS; > + > +Exit: > + return Status; > +} > + > +EFI_STATUS > +VidGopBlt ( > + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, > + IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL > + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, > + IN UINTN SourceX, > + IN UINTN SourceY, > + IN UINTN DestinationX, > + IN UINTN DestinationY, > + IN UINTN Width, > + IN UINTN Height, > + IN UINTN Delta OPTIONAL > + ) > +{ > + UINT32 *FrameBuffer; > + UINT32 BufferOffset; > + UINT32 BufferWidth; > + UINT32 FrameOffset; > + UINT32 FrameWidth; > + UINT32 i; > + > + FrameBuffer = (UINT32 *)((UINTN)VidGopMode.FrameBufferBase); > + FrameWidth = VidGopModeInfo.HorizontalResolution; > + if (Delta == 0) { > + BufferWidth = Width; > + } else { > + BufferWidth = Delta / PIXEL_BYTES; > + } > + > + if (BltOperation == EfiBltVideoFill) { > + FrameOffset = FrameWidth * DestinationY + DestinationX; > + for (i = DestinationY; i < DestinationY + Height; i++) { > + SetMem32 ( > + FrameBuffer + FrameOffset, > + Width * PIXEL_BYTES, > + *(UINT32 *)BltBuffer > + ); > + FrameOffset += FrameWidth; > + } > + } else if (BltOperation == EfiBltVideoToBltBuffer) { > + FrameOffset = FrameWidth * SourceY + SourceX; > + BufferOffset = BufferWidth * DestinationY + DestinationX; > + for (i = SourceY; i < SourceY + Height; i++) { > + CopyMem ( > + BltBuffer + BufferOffset, > + FrameBuffer + FrameOffset, > + Width * PIXEL_BYTES > + ); > + FrameOffset += FrameWidth; > + BufferOffset += BufferWidth; > + } > + } else if (BltOperation == EfiBltBufferToVideo) { > + FrameOffset = FrameWidth * DestinationY + DestinationX; > + BufferOffset = BufferWidth * SourceY + SourceX; > + for (i = SourceY; i < SourceY + Height; i++) { > + CopyMem ( > + FrameBuffer + FrameOffset, > + BltBuffer + BufferOffset, > + Width * PIXEL_BYTES > + ); > + FrameOffset += FrameWidth; > + BufferOffset += BufferWidth; > + } > + } else if (BltOperation == EfiBltVideoToVideo) { > + FrameOffset = FrameWidth * DestinationY + DestinationX; > + BufferOffset = FrameWidth * SourceY + SourceX; > + for (i = SourceY; i < SourceY + Height; i++) { > + CopyMem ( > + FrameBuffer + FrameOffset, > + FrameBuffer + BufferOffset, > + Width * PIXEL_BYTES > + ); > + FrameOffset += FrameWidth; > + BufferOffset += FrameWidth; > + } > + } else { > + DEBUG ((DEBUG_ERROR, "%a: Not implemented %d\n", > + __FUNCTION__, BltOperation)); > + return EFI_INVALID_PARAMETER; > + } > + > + return EFI_SUCCESS; > +} > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h > new file mode 100644 > index 000000000000..b8622283238f > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.h > @@ -0,0 +1,20 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* > +* 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. > +* > +**/ > + > +#ifndef _GOP_DXE_H_ > +#define _GOP_DXE_H_ > + > +#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) > + > +#endif /* _GOP_DXE_H_ */ Use ARRAY_SIZE from Base.h, then this file can be deleted. > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf > new file mode 100644 > index 000000000000..9dbe00ae1ab1 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/GopDxe.inf > @@ -0,0 +1,70 @@ > +#/** @file > +# > +# Copyright (c) 2011, ARM Ltd. All rights reserved.
> +# Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +# > +# 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. > +# > +#**/ > + > +[Defines] > + INF_VERSION = 0x0001001A > + BASE_NAME = GopDxe > + FILE_GUID = E68088EF-D1A4-4336-C1DB-4D3A204730A6 > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = GopDxeInitialize > + > +[Sources.common] > + CPMem.c > + Ddc.c > + Display.c > + DisplayController.c > + DisplayInterface.c > + Edid.c > + GopDxe.c > + Hdmi.c > + IoMux.c > + Lvds.c > + > +[Packages] > + ArmPkg/ArmPkg.dec > + ArmPlatformPkg/ArmPlatformPkg.dec > + EmbeddedPkg/EmbeddedPkg.dec > + MdeModulePkg/MdeModulePkg.dec > + MdePkg/MdePkg.dec > + Silicon/NXP/iMX6Pkg/iMX6Pkg.dec > + > +[LibraryClasses] > + ArmLib > + BaseLib > + BaseMemoryLib > + DebugLib > + iMX6ClkPwrLib > + iMXDisplayLib > + IoLib > + TimerLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + UefiLib > + > +[Protocols] > + gEfiDevicePathProtocolGuid # Produced > + gEfiDevicePathToTextProtocolGuid > + gEfiEdidActiveProtocolGuid # Produced > + gEfiEdidDiscoveredProtocolGuid # Produced > + gEfiGraphicsOutputProtocolGuid # Produced > + > +[Pcd] > + giMX6TokenSpaceGuid.PcdFrameBufferBase > + giMX6TokenSpaceGuid.PcdFrameBufferSize > + giMX6TokenSpaceGuid.PcdLvdsEnable > + > +[Depex] > + gEfiCpuArchProtocolGuid AND gEfiTimerArchProtocolGuid > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c > new file mode 100644 > index 000000000000..fa8fb3ed4aea > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.c > @@ -0,0 +1,761 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* > +* 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 > + > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +#include "Display.h" > +#include "GopDxe.h" > +#include "Hdmi.h" > +#include "Edid.h" > + > +PLL_MPLL_CONFIG PllMpllGenericConfigSetting[] = { Can this be static? m-prefix, please. > + { 13500000, 2, 8, {{3, 0, 3, 3, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, }, > + { 13500000, 2, 10, {{1, 4, 3, 3, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, }, > + { 13500000, 2, 12, {{2, 4, 3, 3, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{0, 0, 0,}}, }, > + { 13500000, 2, 16, {{3, 1, 3, 2, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 0, 0,}}, }, > + { 13500000, 4, 8, {{3, 1, 3, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 0, 0,}}, }, > + { 13500000, 4, 10, {{1, 5, 3, 2, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 0, 0,}}, }, > + { 13500000, 4, 12, {{2, 5, 3, 2, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 0, 0,}}, }, > + { 13500000, 4, 16, {{3, 2, 3, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 0, 0,}}, }, > + { 18000000, 3, 8, {{2, 1, 3, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 0, 0,}}, }, > + { 18000000, 3, 16, {{2, 2, 3, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 0, 0,}}, }, > + { 24175000, 1, 8, {{0, 0, 3, 3, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, }, > + { 24175000, 1, 10, {{1, 0, 3, 3, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, }, > + { 24175000, 1, 12, {{2, 0, 3, 3, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{0, 0, 0,}}, }, > + { 24175000, 1, 16, {{3, 0, 2, 2, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, }, > + { 27000000, 1, 8, {{0, 0, 3, 3, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, }, > + { 27000000, 1, 10, {{1, 0, 3, 3, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, }, > + { 27000000, 1, 12, {{2, 0, 3, 3, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{0, 0, 0,}}, }, > + { 27000000, 1, 16, {{3, 0, 2, 2, 0, 0, 3, 0,}}, {{4, 3, 5, 4, 0,}}, {{1, 0, 0,}}, }, > + { 27000000, 2, 8, {{3, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, }, > + { 27000000, 2, 10, {{1, 1, 3, 2, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 0, 0,}}, }, > + { 27000000, 2, 12, {{2, 1, 3, 2, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 0, 0,}}, }, > + { 27000000, 2, 16, {{3, 1, 2, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 1, 0,}}, }, > + { 27000000, 4, 8, {{3, 1, 2, 1, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 1, 0,}}, }, > + { 27000000, 4, 10, {{1, 2, 3, 1, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 0, 0,}}, }, > + { 27000000, 4, 12, {{2, 2, 3, 1, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 0, 0,}}, }, > + { 27000000, 4, 16, {{3, 2, 2, 0, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 1, 0,}}, }, > + { 36000000, 1, 8, {{0, 0, 3, 3, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{0, 0, 0,}}, }, > + { 36000000, 1, 16, {{3, 0, 2, 2, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, }, > + { 50350000, 1, 8, {{0, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, }, > + { 50350000, 1, 10, {{1, 0, 2, 2, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, }, > + { 50350000, 1, 12, {{2, 0, 2, 2, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, }, > + { 50350000, 1, 16, {{3, 0, 1, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, }, > + { 50350000, 2, 8, {{3, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, }, > + { 50350000, 2, 10, {{1, 1, 2, 1, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 1, 0,}}, }, > + { 50350000, 2, 12, {{2, 1, 2, 1, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 1, 0,}}, }, > + { 50350000, 2, 16, {{3, 1, 1, 0, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 2, 0,}}, }, > + { 54000000, 1, 8, {{0, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, }, > + { 54000000, 1, 10, {{1, 0, 2, 2, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, }, > + { 54000000, 1, 12, {{2, 0, 2, 2, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, }, > + { 54000000, 1, 16, {{3, 0, 1, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, }, > + { 54000000, 2, 8, {{3, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, }, > + { 54000000, 2, 10, {{1, 1, 2, 1, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 1, 0,}}, }, > + { 54000000, 2, 12, {{2, 1, 2, 1, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 1, 0,}}, }, > + { 54000000, 2, 16, {{3, 1, 1, 0, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 2, 0,}}, }, > + { 58400000, 1, 8, {{0, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{1, 1, 0,}}, }, > + { 58400000, 1, 10, {{1, 0, 2, 2, 0, 0, 1, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, }, > + { 58400000, 1, 12, {{2, 0, 2, 2, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, }, > + { 58400000, 1, 16, {{3, 0, 1, 1, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, }, > + { 72000000, 1, 8, {{0, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, }, > + { 72000000, 1, 10, {{1, 0, 2, 2, 0, 0, 1, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, }, > + { 72000000, 1, 12, {{2, 0, 1, 1, 0, 0, 2, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, }, > + { 72000000, 1, 16, {{3, 0, 1, 1, 0, 0, 3, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, }, > + { 74250000, 1, 8, {{0, 0, 2, 2, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{1, 1, 0,}}, }, > + { 74250000, 1, 10, {{1, 0, 1, 1, 0, 0, 1, 0,}}, {{4, 3, 5, 5, 0,}}, {{2, 2, 0,}}, }, > + { 74250000, 1, 12, {{2, 0, 1, 1, 0, 0, 2, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, }, > + { 74250000, 1, 16, {{3, 0, 1, 1, 0, 0, 3, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, }, > + { 108000000, 1, 8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, }, > + { 108000000, 1, 10, {{1, 0, 1, 1, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, }, > + { 108000000, 1, 12, {{2, 0, 1, 1, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, }, > + { 108000000, 1, 16, {{3, 0, 0, 0, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 3, 0,}}, }, > + { 118800000, 1, 8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, }, > + { 118800000, 1, 10, {{1, 0, 1, 1, 0, 0, 1, 0,}}, {{4, 3, 4, 4, 0,}}, {{2, 2, 0,}}, }, > + { 118800000, 1, 12, {{2, 0, 1, 1, 0, 0, 2, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, }, > + { 118800000, 1, 16, {{3, 0, 0, 0, 0, 0, 3, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 3, 0,}}, }, > + { 144000000, 1, 8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, }, > + { 144000000, 1, 10, {{1, 0, 0, 0, 0, 0, 1, 0,}}, {{4, 3, 5, 5, 0,}}, {{3, 3, 0,}}, }, > + { 144000000, 1, 12, {{2, 0, 0, 0, 0, 0, 2, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 3, 0,}}, }, > + { 144000000, 1, 16, {{3, 0, 0, 0, 0, 0, 3, 0,}}, {{4, 3, 3, 3, 0,}}, {{3, 3, 0,}}, }, > + { 148500000, 1, 8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, }, > + { 148500000, 1, 10, {{1, 0, 0, 0, 0, 0, 1, 0,}}, {{4, 3, 5, 5, 0,}}, {{3, 3, 0,}}, }, > + { 148500000, 1, 12, {{2, 0, 0, 0, 0, 0, 2, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 3, 0,}}, }, > + { 148500000, 1, 16, {{3, 0, 0, 0, 0, 0, 3, 0,}}, {{4, 3, 3, 3, 0,}}, {{3, 3, 0,}}, }, > + { 216000000, 1, 8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, }, > + { 216000000, 1, 10, {{1, 0, 0, 0, 0, 0, 1, 0,}}, {{4, 3, 5, 5, 0,}}, {{3, 3, 0,}}, }, > + { 216000000, 1, 12, {{2, 0, 0, 0, 0, 0, 2, 0,}}, {{4, 3, 4, 4, 0,}}, {{3, 3, 0,}}, }, > + // Fallback > + { 65000000, 1, 8, {{0, 0, 1, 1, 0, 0, 0, 0,}}, {{4, 3, 3, 3, 0,}}, {{2, 2, 0,}}, }, > +}; > + > +BOOLEAN > +HdmiPhyPollI2cDone ( > + IN DISPLAY_INTERFACE_CONTEXT *HdmiDisplayContextPtr, > + IN UINT32 Timeout > + ) > +{ > + HDMI_IH_I2CMPHY_STAT0_REG I2cmphyStat0Reg; > + BOOLEAN WaitResult; > + > + WaitResult = FALSE; > + for (; Timeout > 0; Timeout--) { > + I2cmphyStat0Reg.Reg = MmioRead8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + UINTN for addresses, please. Throughout. > + HDMI_IH_I2CMPHY_STAT0 > + ); > + if (I2cmphyStat0Reg.i2cmphydone) { > + WaitResult = TRUE; > + break; > + } > + gBS->Stall (1); > + } > + > +#if DEBUG > + if ((Timeout == 0) || (I2cmphyStat0Reg.i2cmphyerror == 1)) { > + DEBUG ((DEBUG_ERROR, "%a: HDMI I2C failed value %x time out %d\n", > + __FUNCTION__, I2cmphyStat0Reg.Reg, Timeout)); > + } > +#endif > + > + return WaitResult; > +} > + > +BOOLEAN > +HdmiPhyI2cRead ( > + IN DISPLAY_INTERFACE_CONTEXT *HdmiDisplayContextPtr, > + IN UINT8 Addr, > + OUT UINT16 *DataPtr > + ) > +{ > + UINT16 Data0; > + UINT16 Data1; > + HDMI_PHY_I2CM_OPERATION_ADDR_REG I2cmOperationReg; > + HDMI_IH_I2CMPHY_STAT0_REG I2cmphyStat0Reg; > + BOOLEAN ReadStatus; > + > + I2cmphyStat0Reg.i2cmphyerror = 1; > + I2cmphyStat0Reg.i2cmphydone = 1; > + I2cmphyStat0Reg.reserved = 0; > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_IH_I2CMPHY_STAT0, > + I2cmphyStat0Reg.Reg > + ); > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_ADDRESS_ADDR, > + Addr > + ); > + > + I2cmOperationReg.Reg = MmioRead8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + > + HDMI_PHY_I2CM_OPERATION_ADDR > + ); > + I2cmOperationReg.read = 1; > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_OPERATION_ADDR, > + I2cmOperationReg.Reg > + ); > + > + ReadStatus = HdmiPhyPollI2cDone (HdmiDisplayContextPtr, 1000); > + if (!ReadStatus) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to read I2c HDMI Phy\n", __FUNCTION__)); > + goto Exit; > + } > + > + Data0 = MmioRead8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + > + HDMI_PHY_I2CM_DATAI_0_ADDR > + ); > + Data1 = MmioRead8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + > + HDMI_PHY_I2CM_DATAI_1_ADDR > + ); > + *DataPtr = Data0 | (Data1 << 8); > + > +Exit: > + return ReadStatus; > +} > + > +BOOLEAN > +HdmiPhyI2cWrite ( > + IN DISPLAY_INTERFACE_CONTEXT *HdmiDisplayContextPtr, > + IN UINT8 Addr, > + IN UINT16 Data > + ) > +{ > + UINT8 Data0; > + UINT8 Data1; > + HDMI_PHY_I2CM_OPERATION_ADDR_REG I2cmOperationReg; > + HDMI_IH_I2CMPHY_STAT0_REG I2cmphyStat0Reg; > + > + Data0 = (Data & 0x00FF); > + Data1 = (Data >> 8); > + I2cmphyStat0Reg.i2cmphyerror = 1; > + I2cmphyStat0Reg.i2cmphydone = 1; > + I2cmphyStat0Reg.reserved = 1; > + I2cmOperationReg.read = 0; > + I2cmOperationReg.reserved0 = 0; > + I2cmOperationReg.write = 0; > + I2cmOperationReg.reserved1 = 0; > + > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_IH_I2CMPHY_STAT0, > + I2cmphyStat0Reg.Reg > + ); > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_ADDRESS_ADDR, > + Addr > + ); > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_DATAO_0_ADDR, > + Data0 > + ); > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_DATAO_1_ADDR, > + Data1 > + ); > + > + I2cmOperationReg.read = 0; > + I2cmOperationReg.write = 1; > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_I2CM_OPERATION_ADDR, > + I2cmOperationReg.Reg > + ); > + return HdmiPhyPollI2cDone (HdmiDisplayContextPtr, 1000); > +} > + > +BOOLEAN > +GetGenericConfigSetting ( > + IN DISPLAY_TIMING *DisplayTimingPtr, > + OUT PLL_MPLL_CONFIG **ConfigGenericSettingPPtr > + ) > +{ > + UINT32 ColorDepth; > + BOOLEAN FoundConfig; > + UINT32 SettingIndex; > + > + FoundConfig = FALSE; > + ColorDepth = GetColorDepth (DisplayTimingPtr->PixelFormat); > + > + for (SettingIndex = 0; > + SettingIndex < ARRAYSIZE (PllMpllGenericConfigSetting); > + ++SettingIndex) > + { > + if ((DisplayTimingPtr->PixelClock == > + PllMpllGenericConfigSetting[SettingIndex].PixelClock) && > + (DisplayTimingPtr->PixelRepetition == > + PllMpllGenericConfigSetting[SettingIndex].PixelRepetition) && > + (ColorDepth == PllMpllGenericConfigSetting[SettingIndex].ColorDepth)) > + { > + FoundConfig = TRUE; > + *ConfigGenericSettingPPtr = &PllMpllGenericConfigSetting[SettingIndex]; > + break; > + } > + } > + > + // Use the fallback value the last index if no configuration is found > + if (FoundConfig == FALSE) { > + *ConfigGenericSettingPPtr = > + &PllMpllGenericConfigSetting[ARRAYSIZE (PllMpllGenericConfigSetting)]; > + FoundConfig = TRUE; > + } > + > + return FoundConfig; > +} > + > +EFI_STATUS > +InitHdmi ( > + IN DISPLAY_CONTEXT *DisplayContextPtr > + ) > +{ > + DISPLAY_INTERFACE_CONTEXT *pHdmiDisplayContext; > + EFI_STATUS Status; > + > + pHdmiDisplayContext = &DisplayContextPtr->DiContext[HdmiDisplay]; > + Status = EFI_SUCCESS; > + ZeroMem (pHdmiDisplayContext, sizeof (*pHdmiDisplayContext)); > + > + pHdmiDisplayContext->MmioBasePtr = (VOID *)HDMI_BASE; > + if (pHdmiDisplayContext->MmioBasePtr == NULL) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to map HDMI register\n", __FUNCTION__)); > + goto Exit; > + } > + > + // Setup HDMI DDC muxing > + MmioWrite32 ((UINT32)IOMUXC_SW_MUX_CTL_PAD_KEY_COL3, 0x00000012); > + MmioWrite32 ((UINT32)IOMUXC_SW_MUX_CTL_PAD_KEY_ROW3, 0x00000012); > + MmioWrite32 ((UINT32)IOMUXC_HDMI_II2C_CLKIN_SELECT_INPUT, 0x00000001); > + MmioWrite32 ((UINT32)IOMUXC_HDMI_II2C_DATAIN_SELECT_INPUT, 0x00000001); > + SetHdmiPower (pHdmiDisplayContext, TRUE); > + > + // Mask all HDMI PHY interrupt > + MmioWrite8 ( > + (UINT32)pHdmiDisplayContext->MmioBasePtr + HDMI_PHY_MASK0, > + 0xFF > + ); > + > + Status = ReadEdid ( > + DisplayContextPtr, > + HdmiDisplay, > + pHdmiDisplayContext->EdidData, > + &pHdmiDisplayContext->EdidDataSize > + ); > + if (Status != EFI_SUCCESS) { > + DEBUG ((DEBUG_WARN, "%a: Fail to read HDMI EDID data\n", __FUNCTION__)); > + Status = EFI_SUCCESS; > + } > + > + Status = GetPreferredTiming ( > + pHdmiDisplayContext->EdidData, > + pHdmiDisplayContext->EdidDataSize, > + &pHdmiDisplayContext->PreferredTiming > + ); > + if (Status != EFI_SUCCESS) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to retrieve HDMI preferred timing\n", > + __FUNCTION__)); > + goto Exit; > + } > + > + if ((pHdmiDisplayContext->PreferredTiming.HActive == 1920) && > + (pHdmiDisplayContext->PreferredTiming.VActive == 1080)) > + { > + pHdmiDisplayContext->PreferredTiming.HBlank -= 6; > + } > + > +Exit: > + return Status; > +} > + > +EFI_STATUS > +SetHdmiPower ( > + IN DISPLAY_INTERFACE_CONTEXT *HdmiDisplayContextPtr, > + IN BOOLEAN PowerState > + ) > +{ > + HDMI_PHY_CONF0_REG CurrentHdmiPhyConf0Reg; > + > + CurrentHdmiPhyConf0Reg.Reg = MmioRead8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + > + HDMI_PHY_CONF0 > + ); > + if (PowerState) { > + // Setup PHY > + CurrentHdmiPhyConf0Reg.PDZ = 1; > + CurrentHdmiPhyConf0Reg.ENTMDS = 1; > + CurrentHdmiPhyConf0Reg.gen2_pddq = 1; > + CurrentHdmiPhyConf0Reg.gen2_txpwron = 1; > + CurrentHdmiPhyConf0Reg.seldataenpol = 1; > + CurrentHdmiPhyConf0Reg.seldipif = 0; > + } else { > + // Just power down PHY for shutdown > + CurrentHdmiPhyConf0Reg.PDZ = 0; > + } > + > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_CONF0, > + CurrentHdmiPhyConf0Reg.Reg > + ); > + gBS->Stall (3); > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +SetHdmiPhy ( > + IN DISPLAY_INTERFACE_CONTEXT *HdmiDisplayContextPtr, > + IN DISPLAY_TIMING *Timings > + ) > +{ > + PLL_MPLL_CONFIG *pPllMpllConfig; > + HDMI_PHY_CONF0_REG CurrentHdmiPhyConf0Reg; > + HDMI_FC_AUDSCONF_REG FcAudsconfReg; > + HDMI_MC_HEACPHY_RST_REG HeacphyRstReg; > + HDMI_MC_CLKDIS_REG McClkdisReg; > + HDMI_MC_PHYRSTZ_REG PhyRstzReg; > + HDMI_PHY_STAT0_REG PhyStat0Reg; > + BOOLEAN PhyStatus; > + UINT32 RetryCount; > + EFI_STATUS Status; > + > + // Disable Audio > + FcAudsconfReg.Reg = MmioRead8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + > + HDMI_FC_AUDSCONF > + ); > + FcAudsconfReg.aud_packet_layout = 0; > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_FC_AUDSCONF, > + FcAudsconfReg.Reg > + ); > + > + // Minimum PCLK period / frequency (pixel repetition) : 74 ns / 13.5 MHz > + // Minimum PCLK period / frequency (no pixel repetition) : 39.7 ns / 24.175 MHz > + if (Timings->PixelClock < 13500000) { > + DEBUG ((DEBUG_ERROR, "%a: Unsupported pixel clock %d\n", > + __FUNCTION__, Timings->PixelClock)); > + Status = EFI_INVALID_PARAMETER; > + goto Exit; > + } > + > + if (GetGenericConfigSetting (Timings, &pPllMpllConfig) == FALSE) { > + DEBUG ((DEBUG_ERROR, "%a: No compatible generic config found\n", > + __FUNCTION__)); > + Status = EFI_UNSUPPORTED; > + goto Exit; > + } > + > + // Color Space Converter : Not used in UEFI > + McClkdisReg.Reg = MmioRead8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + > + HDMI_MC_CLKDIS > + ); > + // Disable CEC, color converter, audio & pixel repitition > + McClkdisReg.cecclk_disable = 1; > + McClkdisReg.cscclk_disable = 1; > + McClkdisReg.audclk_disable = 1; > + McClkdisReg.prepclk_disable = 1; > + McClkdisReg.hdcpclk_disable = 1; > + McClkdisReg.tmdsclk_disable = 0; > + McClkdisReg.pixelclk_disable = 0; > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_MC_CLKDIS, > + McClkdisReg.Reg > + ); > + > + // Power down the PHY > + // To set the HDMI_PHY in Power-down mode, set the TX_PWRON signal to 1'b0 > + // and the PDDQ signal to 1'b1. To power up the HDMI 3D Tx PHY and place it > + // in Active mode, set TX_PWRON to 1'b1 and PDDQ to 1'b0. Any configuration > + // programmed on the HDMI_PHY must be done in Power-down mode. > + CurrentHdmiPhyConf0Reg.Reg = MmioRead8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + > + HDMI_PHY_CONF0 > + ); > + CurrentHdmiPhyConf0Reg.gen2_txpwron = 0; > + CurrentHdmiPhyConf0Reg.gen2_pddq = 1; > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_CONF0, > + CurrentHdmiPhyConf0Reg.Reg > + ); > + > + // Let's reset the PHY to a well defined state based on spec. > + // The PHY_RESET signal is used to place the digital section of the IP in > + // a well - defined state > + PhyRstzReg.Reg = MmioRead8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + > + HDMI_MC_PHYRSTZ > + ); > + PhyRstzReg.phyrstz = 1; > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_MC_PHYRSTZ, > + PhyRstzReg.Reg > + ); > + PhyRstzReg.phyrstz = 0; > + gBS->Stall (10); > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_MC_PHYRSTZ, > + PhyRstzReg.Reg > + ); > + > + HeacphyRstReg.Reg = MmioRead8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + > + HDMI_MC_HEACPHY_RST > + ); > + HeacphyRstReg.heacphyrst = 1; > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_MC_HEACPHY_RST, > + HeacphyRstReg.Reg > + ); > + > + // Program clock > + // PLL / MPLL Operation > + // The PLL / MPLL can be configured in Coherent mode or NonCoherent mode (default). > + // In Coherent mode, the TMDS clock is the MPLL feedback clock, which is > + // coherent with the MPLL's high-speed output clock, because both clocks are > + // shaped by the MPLL response. > + // In NonCoherent mode, the TMDS clock is the MPLL reference clock, which is > + // not coherent with the MPLL's high-speed output clock. > + PhyStatus = HdmiPhyI2cWrite ( > + HdmiDisplayContextPtr, > + HDMI_PHY_CPCE_CTRL, > + pPllMpllConfig->HdmiPhyCpceCtrl.Reg > + ); > + if (PhyStatus == FALSE) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_CPCE_CTRL %x\n", > + __FUNCTION__, pPllMpllConfig->HdmiPhyCpceCtrl.Reg)); > + Status = EFI_DEVICE_ERROR; > + goto Exit; > + } > + > + PhyStatus = HdmiPhyI2cWrite ( > + HdmiDisplayContextPtr, > + HDMI_PHY_CURRCTRL, > + pPllMpllConfig->HdmiPhyCurrctrl.Reg > + ); > + if (PhyStatus == FALSE) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_CURRCTRL\n", > + __FUNCTION__)); > + Status = EFI_DEVICE_ERROR; > + goto Exit; > + }; > + > + PhyStatus = HdmiPhyI2cWrite ( > + HdmiDisplayContextPtr, > + HDMI_PHY_GMPCTRL, > + pPllMpllConfig->HdmiPhyGmpctrl.Reg > + ); > + if (PhyStatus == FALSE) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_GMPCTRL\n", > + __FUNCTION__)); > + Status = EFI_DEVICE_ERROR; > + goto Exit; > + } > + > + // Maintaining the order of phy register writes > + PhyStatus = HdmiPhyI2cWrite ( > + HdmiDisplayContextPtr, > + HDMI_PHY_PLLPHBYCTRL, > + 0x0000 > + ); > + if (PhyStatus == FALSE) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_PLLPHBYCTRL\n", > + __FUNCTION__)); > + Status = EFI_DEVICE_ERROR; > + goto Exit; > + } > + > + // Coherent mode > + PhyStatus = HdmiPhyI2cWrite ( > + HdmiDisplayContextPtr, > + HDMI_PHY_MSM_CTRL, > + 0x0006 > + ); > + if (PhyStatus == FALSE) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_MSM_CTRL\n", > + __FUNCTION__)); > + Status = EFI_DEVICE_ERROR; > + goto Exit; > + } > + > + // Resistance value 133.33 ohm > + PhyStatus = HdmiPhyI2cWrite ( > + HdmiDisplayContextPtr, > + HDMI_PHY_TXTERM, > + 0x0005 > + ); > + if (PhyStatus == FALSE) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_TXTERM\n", > + __FUNCTION__)); > + Status = EFI_DEVICE_ERROR; > + goto Exit; > + } > + > + // Enable clock symbol > + PhyStatus = HdmiPhyI2cWrite ( > + HdmiDisplayContextPtr, > + HDMI_PHY_CKSYMTXCTRL, > + 0x8009 > + ); > + if (PhyStatus == FALSE) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_CKSYMTXCTRL\n", > + __FUNCTION__)); > + Status = EFI_DEVICE_ERROR; > + goto Exit; > + } > + > + PhyStatus = HdmiPhyI2cWrite ( > + HdmiDisplayContextPtr, > + HDMI_PHY_VLEVCTRL, > + 0x0210 > + ); > + if (PhyStatus == FALSE) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_VLEVCTRL\n", > + __FUNCTION__)); > + Status = EFI_DEVICE_ERROR; > + goto Exit; > + } > + > + // Enable override > + PhyStatus = HdmiPhyI2cWrite ( > + HdmiDisplayContextPtr, > + HDMI_PHY_CKCALCTRL, > + 0x8000 > + ); > + if (PhyStatus == FALSE) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to write to HDMI_PHY_CKCALCTRL\n", > + __FUNCTION__)); > + Status = EFI_DEVICE_ERROR; > + goto Exit; > + } > + > + CurrentHdmiPhyConf0Reg.gen2_txpwron = 1; > + CurrentHdmiPhyConf0Reg.gen2_pddq = 0; > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_PHY_CONF0, > + CurrentHdmiPhyConf0Reg.Reg > + ); > + > + Status = EFI_DEVICE_ERROR; > + for (RetryCount = 5; RetryCount > 0; RetryCount--) { > + PhyStat0Reg.Reg = MmioRead8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + > + HDMI_PHY_STAT0 > + ); > + if (!PhyStat0Reg.TX_PHY_LOCK) { > + Status = EFI_SUCCESS; > + break; > + } > + gBS->Stall (1000); > + } > + > + if (RetryCount == 0) { > + DEBUG ((DEBUG_ERROR, "%a: TX PHY remain unlock\n", __FUNCTION__)); > + } > + > +Exit: > + return Status; > +} > + > +EFI_STATUS > +SetHdmiDisplay ( > + IN DISPLAY_INTERFACE_CONTEXT *HdmiDisplayContextPtr, > + IN DISPLAY_TIMING *Timings > + ) > +{ > + EFI_STATUS Status; > + > + Status = SetHdmiPhy (HdmiDisplayContextPtr, Timings); > + if (Status != EFI_SUCCESS) { > + DEBUG ((DEBUG_ERROR, "%a: SetHdmiPhy failed\n", __FUNCTION__)); > + goto Exit; > + } > + > +Exit: > + return Status; > +} > + > +VOID > +SetDdcSpeed ( > + IN DISPLAY_INTERFACE_CONTEXT *HdmiDisplayContextPtr, > + IN DDC_MODE Mode > + ) > +{ > + MmioWrite8 ((UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_I2CM_DIV, Mode); > +} > + > +EFI_STATUS > +HdmiDdcRead ( > + IN DISPLAY_INTERFACE_CONTEXT *HdmiDisplayContextPtr, > + IN UINT8 SlaveAddress, > + IN UINT8 RegisterAddress, > + IN UINT32 ReadSize, > + IN DDC_MODE DDCMode, > + IN UINT8 *DataReadPtr > + ) > +{ > + UINT8 *pCurrentDataRead; > + UINT32 AddrCount; > + UINT8 I2cmIntStatus; > + UINT32 I2cRetryCount; > + EFI_STATUS Status; > + > + pCurrentDataRead = DataReadPtr; > + Status = EFI_SUCCESS; > + > + // Setup EDID transaction and loop through all byte request > + SetDdcSpeed (HdmiDisplayContextPtr, DDCMode); > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_IH_I2CM_STAT0, > + I2C_MASTER_ERROR | I2C_MASTER_DONE > + ); > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_I2CM_SLAVE, > + SlaveAddress > + ); > + > + for (AddrCount = 0; AddrCount < ReadSize; ++AddrCount) { > + I2cRetryCount = 1000; > + > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_I2CM_ADDRESS, > + (UINT8) ( RegisterAddress + AddrCount) > + ); > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_I2CM_SEGADDR, > + 0x00 > + ); > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_I2CM_OPERATION, > + DDC_READ_OPERATION > + ); > + > + // Poll for completion > + I2cmIntStatus = MmioRead8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + > + HDMI_IH_I2CM_STAT0 > + ); > + for (I2cRetryCount = 1000; I2cRetryCount > 0; I2cRetryCount--) { > + I2cmIntStatus = MmioRead8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + > + HDMI_IH_I2CM_STAT0 > + ); > + if (I2cmIntStatus != 0) { > + break; > + } > + } > + > + if (I2cRetryCount == 0) { > + Status = EFI_DEVICE_ERROR; > + DEBUG ((DEBUG_ERROR, "%a: Timeout waiting for interrupt 0x%02x\n", > + __FUNCTION__, I2cmIntStatus)); > + goto Exit; > + } > + > + if ((I2cmIntStatus & I2C_MASTER_DONE) && > + !(I2cmIntStatus & I2C_MASTER_ERROR)) > + { > + *pCurrentDataRead = MmioRead8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + > + HDMI_I2CM_DATAI > + ); > + pCurrentDataRead++; > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_IH_I2CM_STAT0, > + I2C_MASTER_ERROR | I2C_MASTER_DONE > + ); > + } else { > + Status = EFI_DEVICE_ERROR; > + DEBUG ((DEBUG_ERROR, "%a: Failed to read with DDC 0x%02x\n", > + __FUNCTION__, I2cmIntStatus)); > + goto Exit; > + } > + > + MmioWrite8 ( > + (UINT32)HdmiDisplayContextPtr->MmioBasePtr + HDMI_IH_I2CM_STAT0, > + I2C_MASTER_ERROR | I2C_MASTER_DONE > + ); > + } > + > +Exit: > + return Status; > +} > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h > new file mode 100644 > index 000000000000..e1b7372bc2e9 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Hdmi.h > @@ -0,0 +1,529 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* > +* 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. > +* > +**/ > + > +#ifndef _HDMI_H_ > +#define _HDMI_H_ IMX_ prefix, please. > + > +// HDMI Register Base Address > +#define HDMI_BASE 0x00120000 > + > +// Interrupt Register Offset > +#define HDMI_IH_FC_STAT0 0x0100 > +#define HDMI_IH_FC_STAT1 0x0101 > +#define HDMI_IH_FC_STAT2 0x0102 > +#define HDMI_IH_AS_STAT0 0x0103 > +#define HDMI_IH_PHY_STAT0 0x0104 > +#define HDMI_IH_I2CM_STAT0 0x0105 > +#define HDMI_IH_CEC_STAT0 0x0106 > +#define HDMI_IH_VP_STAT0 0x0107 > +#define HDMI_IH_I2CMPHY_STAT0 0x0108 > +#define HDMI_IH_AHBDMAAUD_STAT0 0x0180 > +#define HDMI_IH_MUTE_FC_STAT1 0x0181 > +#define HDMI_IH_MUTE_FC_STAT2 0x0182 > +#define HDMI_IH_MUTE_AS_STAT0 0x0183 > +#define HDMI_IH_MUTE_PHY_STAT0 0x0184 > +#define HDMI_IH_MUTE_I2CM_STAT0 0x0185 > +#define HDMI_IH_MUTE_CEC_STAT0 0x0186 > +#define HDMI_IH_MUTE_VP_STAT0 0x0187 > +#define HDMI_IH_MUTE_I2CMPHY_STAT0 0x0188 > +#define HDMI_IH_MUTE_AHBDMAAUD_STAT0 0x0189 > +#define HDMI_IH_MUTE 0x01FF > +#define HDMI_FC_INVIDCONF 0x1000 > +#define HDMI_FC_INHACTV0 0x1001 > +#define HDMI_FC_INHACTV1 0x1002 > +#define HDMI_FC_INHBLANK0 0x1003 > +#define HDMI_FC_INHBLANK1 0x1004 > +#define HDMI_FC_INVACTV0 0x1005 > +#define HDMI_FC_INVACTV1 0x1006 > +#define HDMI_FC_INVBLANK 0x1007 > +#define HDMI_FC_HSYNCINDELAY0 0x1008 > +#define HDMI_FC_HSYNCINDELAY1 0x1009 > +#define HDMI_FC_HSYNCINWIDTH0 0x100A > +#define HDMI_FC_HSYNCINWIDTH1 0x100B > +#define HDMI_FC_VSYNCINDELAY 0x100C > +#define HDMI_FC_VSYNCINWIDTH 0x100D > +#define HDMI_FC_INFREQ0 0x100E > +#define HDMI_FC_INFREQ1 0x100F > +#define HDMI_FC_INFREQ2 0x1010 > +#define HDMI_FC_CTRLDUR 0x1011 > +#define HDMI_FC_EXCTRLDUR 0x1012 > +#define HDMI_FC_EXCTRLSPAC 0x1013 > +#define HDMI_FC_CH0PREAM 0x1014 > +#define HDMI_FC_CH1PREAM 0x1015 > +#define HDMI_FC_CH2PREAM 0x1016 > +#define HDMI_FC_AVICONF3 0x1017 > +#define HDMI_FC_GCP 0x1018 > +#define HDMI_FC_AVICONF0 0x1019 > +#define HDMI_FC_AVICONF1 0x101A > +#define HDMI_FC_AVICONF2 0x101B > +#define HDMI_FC_AVIVID 0x101C > +#define HDMI_FC_AVIETB0 0x101D > +#define HDMI_FC_AVIETB1 0x101E > +#define HDMI_FC_AVISBB0 0x101F > +#define HDMI_FC_AVISBB1 0x1020 > +#define HDMI_FC_AVIELB0 0x1021 > +#define HDMI_FC_AVIELB1 0x1022 > +#define HDMI_FC_AVISRB0 0x1023 > +#define HDMI_FC_AVISRB1 0x1024 > +#define HDMI_FC_AUDICONF0 0x1025 > +#define HDMI_FC_AUDICONF1 0x1026 > +#define HDMI_FC_AUDICONF2 0x1027 > +#define HDMI_FC_AUDICONF3 0x1028 > +#define HDMI_FC_VSDIEEEID0 0x1029 > +#define HDMI_FC_VSDSIZE 0x102A > +#define HDMI_FC_VSDIEEEID1 0x1030 > +#define HDMI_FC_VSDIEEEID2 0x1031 > +#define HDMI_FC_VSDPAYLOAD0 0x1032 > +#define HDMI_FC_VSDPAYLOAD1 0x1033 > +#define HDMI_FC_VSDPAYLOAD2 0x1034 > +#define HDMI_FC_VSDPAYLOAD3 0x1035 > +#define HDMI_FC_VSDPAYLOAD4 0x1036 > +#define HDMI_FC_VSDPAYLOAD5 0x1037 > +#define HDMI_FC_VSDPAYLOAD6 0x1038 > +#define HDMI_FC_VSDPAYLOAD7 0x1039 > +#define HDMI_FC_VSDPAYLOAD8 0x103A > +#define HDMI_FC_VSDPAYLOAD9 0x103B > +#define HDMI_FC_VSDPAYLOAD10 0x103C > +#define HDMI_FC_VSDPAYLOAD11 0x103D > +#define HDMI_FC_VSDPAYLOAD12 0x103E > +#define HDMI_FC_VSDPAYLOAD13 0x103F > +#define HDMI_FC_VSDPAYLOAD14 0x1040 > +#define HDMI_FC_VSDPAYLOAD15 0x1041 > +#define HDMI_FC_VSDPAYLOAD16 0x1042 > +#define HDMI_FC_VSDPAYLOAD17 0x1043 > +#define HDMI_FC_VSDPAYLOAD18 0x1044 > +#define HDMI_FC_VSDPAYLOAD19 0x1045 > +#define HDMI_FC_VSDPAYLOAD20 0x1046 > +#define HDMI_FC_VSDPAYLOAD21 0x1047 > +#define HDMI_FC_VSDPAYLOAD22 0x1048 > +#define HDMI_FC_VSDPAYLOAD23 0x1049 > +#define HDMI_FC_SPDVENDORNAME0 0x104A > +#define HDMI_FC_SPDVENDORNAME1 0x104B > +#define HDMI_FC_SPDVENDORNAME2 0x104C > +#define HDMI_FC_SPDVENDORNAME3 0x104D > +#define HDMI_FC_SPDVENDORNAME4 0x104E > +#define HDMI_FC_SPDVENDORNAME5 0x104F > +#define HDMI_FC_SPDVENDORNAME6 0x1050 > +#define HDMI_FC_SPDVENDORNAME7 0x1051 > +#define HDMI_FC_SDPPRODUCTNAME0 0x1052 > +#define HDMI_FC_SDPPRODUCTNAME1 0x1053 > +#define HDMI_FC_SDPPRODUCTNAME2 0x1054 > +#define HDMI_FC_SDPPRODUCTNAME3 0x1055 > +#define HDMI_FC_SDPPRODUCTNAME4 0x1056 > +#define HDMI_FC_SDPPRODUCTNAME5 0x1057 > +#define HDMI_FC_SDPPRODUCTNAME6 0x1058 > +#define HDMI_FC_SDPPRODUCTNAME7 0x1059 > +#define HDMI_FC_SDPPRODUCTNAME8 0x105A > +#define HDMI_FC_SDPPRODUCTNAME9 0x105B > +#define HDMI_FC_SDPPRODUCTNAME10 0x105C > +#define HDMI_FC_SDPPRODUCTNAME11 0x105D > +#define HDMI_FC_SDPPRODUCTNAME12 0x105E > +#define HDMI_FC_SDPPRODUCTNAME13 0x105F > +#define HDMI_FC_SDPPRODUCTNAME14 0x1060 > +#define HDMI_FC_SPDPRODUCTNAME15 0x1061 > +#define HDMI_FC_SPDDEVICEINF 0x1062 > +#define HDMI_FC_AUDSCONF 0x1063 > +#define HDMI_FC_AUDSSTAT 0x1064 > +#define HDMI_FC_AUDSV 0x1065 > +#define HDMI_FC_AUDSU 0x1066 > +#define HDMI_FC_AUDSCHNLS0 0x1067 > +#define HDMI_FC_AUDSCHNLS1 0x1068 > +#define HDMI_FC_AUDSCHNLS2 0x1069 > +#define HDMI_FC_AUDSCHNLS3 0x106A > +#define HDMI_FC_AUDSCHNLS4 0x106B > +#define HDMI_FC_AUDSCHNLS5 0x106C > +#define HDMI_FC_AUDSCHNLS6 0x106D > +#define HDMI_FC_AUDSCHNLS7 0x106E > +#define HDMI_FC_AUDSCHNLS8 0x106F > +#define HDMI_FC_DATACH0FILL 0x1070 > +#define HDMI_FC_DATACH1FILL 0x1071 > +#define HDMI_FC_DATACH2FILL 0x1072 > +#define HDMI_FC_CTRLQHIGH 0x1073 > +#define HDMI_FC_CTRLQLOW 0x1074 > +#define HDMI_FC_ACP0 0x1075 > +#define HDMI_FC_ACP28 0x1076 > +#define HDMI_FC_ACP27 0x1077 > +#define HDMI_FC_ACP26 0x1078 > +#define HDMI_FC_ACP25 0x1079 > +#define HDMI_FC_ACP24 0x107A > +#define HDMI_FC_ACP23 0x107B > +#define HDMI_FC_ACP22 0x107C > +#define HDMI_FC_ACP21 0x107D > +#define HDMI_FC_ACP20 0x107E > +#define HDMI_FC_ACP19 0x107F > +#define HDMI_FC_ACP18 0x1080 > +#define HDMI_FC_ACP17 0x1081 > +#define HDMI_FC_ACP16 0x1082 > +#define HDMI_FC_ACP15 0x1083 > +#define HDMI_FC_ACP14 0x1084 > +#define HDMI_FC_ACP13 0x1085 > +#define HDMI_FC_ACP12 0x1086 > +#define HDMI_FC_ACP11 0x1087 > +#define HDMI_FC_ACP10 0x1088 > +#define HDMI_FC_ACP9 0x1089 > +#define HDMI_FC_ACP8 0x108A > +#define HDMI_FC_ACP7 0x108B > +#define HDMI_FC_ACP6 0x108C > +#define HDMI_FC_ACP5 0x108D > +#define HDMI_FC_ACP4 0x108E > +#define HDMI_FC_ACP3 0x108F > +#define HDMI_FC_ACP2 0x1090 > +#define HDMI_FC_ACP1 0x1091 > +#define HDMI_FC_ISCR1_0 0x1092 > +#define HDMI_FC_ISCR1_16 0x1093 > +#define HDMI_FC_ISCR1_15 0x1094 > +#define HDMI_FC_ISCR1_14 0x1095 > +#define HDMI_FC_ISCR1_13 0x1096 > +#define HDMI_FC_ISCR1_12 0x1097 > +#define HDMI_FC_ISCR1_11 0x1098 > +#define HDMI_FC_ISCR1_10 0x1099 > +#define HDMI_FC_ISCR1_9 0x109A > +#define HDMI_FC_ISCR1_8 0x109B > +#define HDMI_FC_ISCR1_7 0x109C > +#define HDMI_FC_ISCR1_6 0x109D > +#define HDMI_FC_ISCR1_5 0x109E > +#define HDMI_FC_ISCR1_4 0x109F > +#define HDMI_FC_ISCR1_3 0x10A0 > +#define HDMI_FC_ISCR1_2 0x10A1 > +#define HDMI_FC_ISCR1_1 0x10A2 > +#define HDMI_FC_ISCR2_15 0x10A3 > +#define HDMI_FC_ISCR2_14 0x10A4 > +#define HDMI_FC_ISCR2_13 0x10A5 > +#define HDMI_FC_ISCR2_12 0x10A6 > +#define HDMI_FC_ISCR2_11 0x10A7 > +#define HDMI_FC_ISCR2_10 0x10A8 > +#define HDMI_FC_ISCR2_9 0x10A9 > +#define HDMI_FC_ISCR2_8 0x10AA > +#define HDMI_FC_ISCR2_7 0x10AB > +#define HDMI_FC_ISCR2_6 0x10AC > +#define HDMI_FC_ISCR2_5 0x10AD > +#define HDMI_FC_ISCR2_4 0x10AE > +#define HDMI_FC_ISCR2_3 0x10AF > +#define HDMI_FC_ISCR2_2 0x10B0 > +#define HDMI_FC_ISCR2_1 0x10B1 > +#define HDMI_FC_ISCR2_0 0x10B2 > +#define HDMI_FC_DATAUTO0 0x10B3 > +#define HDMI_FC_DATAUTO1 0x10B4 > +#define HDMI_FC_DATAUTO2 0x10B5 > +#define HDMI_FC_DATMAN 0x10B6 > +#define HDMI_FC_DATAUTO3 0x10B7 > +#define HDMI_FC_RDRB0 0x10B8 > +#define HDMI_FC_RDRB1 0x10B9 > +#define HDMI_FC_RDRB2 0x10BA > +#define HDMI_FC_RDRB3 0x10BB > +#define HDMI_FC_RDRB4 0x10BC > +#define HDMI_FC_RDRB5 0x10BD > +#define HDMI_FC_RDRB6 0x10BE > +#define HDMI_FC_RDRB7 0x10BF > +#define HDMI_FC_STAT0 0x10D0 > +#define HDMI_FC_INT0 0x10D1 > +#define HDMI_FC_MASK0 0x10D2 > +#define HDMI_FC_POL0 0x10D3 > +#define HDMI_FC_STAT1 0x10D4 > +#define HDMI_FC_INT1 0x10D5 > +#define HDMI_FC_MASK1 0x10D6 > +#define HDMI_FC_POL1 0x10D7 > +#define HDMI_FC_STAT2 0x10D8 > +#define HDMI_FC_INT2 0x10D9 > +#define HDMI_FC_MASK2 0x10DA > +#define HDMI_FC_POL2 0x10DB > +#define HDMI_FC_PRCONF 0x10E0 > + > +// HDMI PHY Register Offset > +#define HDMI_PHY_CONF0 0x3000 > +#define HDMI_PHY_TST0 0x3001 > +#define HDMI_PHY_TST1 0x3002 > +#define HDMI_PHY_TST2 0x3003 > +#define HDMI_PHY_STAT0 0x3004 > +#define HDMI_PHY_INT0 0x3005 > +#define HDMI_PHY_MASK0 0x3006 > +#define HDMI_PHY_POL0 0x3007 > +#define HDMI_PHY_I2CM_SLAVE_ADDR 0x3020 > +#define HDMI_PHY_I2CM_ADDRESS_ADDR 0x3021 > +#define HDMI_PHY_I2CM_DATAO_1_ADDR 0x3022 > +#define HDMI_PHY_I2CM_DATAO_0_ADDR 0x3023 > +#define HDMI_PHY_I2CM_DATAI_1_ADDR 0x3024 > +#define HDMI_PHY_I2CM_DATAI_0_ADDR 0x3025 > +#define HDMI_PHY_I2CM_OPERATION_ADDR 0x3026 > +#define HDMI_PHY_I2CM_INT_ADDR 0x3027 > +#define HDMI_PHY_I2CM_CTLINT_ADDR 0x3028 > +#define HDMI_PHY_I2CM_DIV_ADDR 0x3029 > +#define HDMI_PHY_I2CM_SOFTRSTZ_ADDR 0x302a > +#define HDMI_PHY_I2CM_SS_SCL_HCNT_1_ADDR 0x302b > +#define HDMI_PHY_I2CM_SS_SCL_HCNT_0_ADDR 0x302c > +#define HDMI_PHY_I2CM_SS_SCL_LCNT_1_ADDR 0x302d > +#define HDMI_PHY_I2CM_SS_SCL_LCNT_0_ADDR 0x302e > +#define HDMI_PHY_I2CM_FS_SCL_HCNT_1_ADDR 0x302f > +#define HDMI_PHY_I2CM_FS_SCL_HCNT_0_ADDR 0x3030 > +#define HDMI_PHY_I2CM_FS_SCL_LCNT_1_ADDR 0x3031 > +#define HDMI_PHY_I2CM_FS_SCL_LCNT_0_ADDR 0x3032 > + > +// Main Controller Registers > +#define HDMI_MC_CLKDIS 0x4001 > +#define HDMI_MC_SWRSTZ 0x4002 > +#define HDMI_MC_OPCTRL 0x4003 > +#define HDMI_MC_FLOWCTRL 0x4004 > +#define HDMI_MC_PHYRSTZ 0x4005 > +#define HDMI_MC_LOCKONCLOCK 0x4006 > +#define HDMI_MC_HEACPHY_RST 0x4007 > + > +// HDMI_PHY absolute address > +#define HDMI_PHY_PWRCTRL 0x00 > +#define HDMI_PHY_SERDIVCTRL 0x01 > +#define HDMI_PHY_SERCKCTRL 0x02 > +#define HDMI_PHY_SERCKKILLCTRL 0x03 > +#define HDMI_PHY_TXRESCTRL 0x04 > +#define HDMI_PHY_CKCALCTRL 0x05 > +#define HDMI_PHY_CPCE_CTRL 0x06 > +#define HDMI_PHY_TXCLKMEASCTRL 0x07 > +#define HDMI_PHY_TXMEASCTRL 0x08 > +#define HDMI_PHY_CKSYMTXCTRL 0x09 > +#define HDMI_PHY_CMPSEQCTRL 0x0A > +#define HDMI_PHY_CMPPWRCTRL 0x0B > +#define HDMI_PHY_CMPMODECTRL 0x0C > +#define HDMI_PHY_MEASCTRL 0x0D > +#define HDMI_PHY_VLEVCTRL 0x0E > +#define HDMI_PHY_D2ACTRL 0x0F > +#define HDMI_PHY_CURRCTRL 0x10 > +#define HDMI_PHY_DRVANACTRL 0x11 > +#define HDMI_PHY_PLLMEASCTRL 0x12 > +#define HDMI_PHY_PLLPHBYCTRL 0x13 > +#define HDMI_PHY_GRP_CTRL 0x14 > +#define HDMI_PHY_GMPCTRL 0x15 > +#define HDMI_PHY_MPLLMEASCTRL 0x16 > +#define HDMI_PHY_MSM_CTRL 0x17 > +#define HDMI_PHY_SCRPB_STATUS 0x18 > +#define HDMI_PHY_TXTERM 0x19 > +#define HDMI_PHY_PTRPT_ENBL 0x1A > +#define HDMI_PHY_PATTERNGEN 0x1B > +#define HDMI_PHY_SDCAP_MODE 0x1C > +#define HDMI_PHY_SCOPEMODE 0x1D > +#define HDMI_PHY_DIGTXMODE 0x1E > +#define HDMI_PHY_STR_STATUS 0x1F > +#define HDMI_PHY_SCOPECNT0 0x20 > +#define HDMI_PHY_SCOPECNT1 0x21 > +#define HDMI_PHY_SCOPECNT2 0x22 > +#define HDMI_PHY_SCOPECNTCLK 0x23 > +#define HDMI_PHY_SCOPESAMPLE 0x24 > +#define HDMI_PHY_SCOPECNTMSB01 0x25 > +#define HDMI_PHY_SCOPECNTMSB2CK 0x26 > + > +// HDMI DDC offset > +#define HDMI_I2CM_SLAVE 0x7E00 > +#define HDMI_I2CM_ADDRESS 0x7E01 > +#define HDMI_I2CM_DATAO 0x7E02 > +#define HDMI_I2CM_DATAI 0x7E03 > +#define HDMI_I2CM_OPERATION 0x7E04 > +#define HDMI_I2CM_INT 0x7E05 > +#define HDMI_I2CM_CTLINT 0x7E06 > +#define HDMI_I2CM_DIV 0x7E07 > +#define HDMI_I2CM_SEGADDR 0x7E08 > +#define HDMI_I2CM_SOFTRSTZ 0x7E09 > +#define HDMI_I2CM_SEGPTR 0x7E0A > +#define HDMI_I2CM_SS_SCL_HCNT_1_ADDR 0x7E0B > +#define HDMI_I2CM_SS_SCL_HCNT_0_ADDR 0x7E0C > +#define HDMI_I2CM_SS_SCL_LCNT_1_ADDR 0x7E0D > +#define HDMI_I2CM_SS_SCL_LCNT_0_ADDR 0x7E0E > +#define HDMI_I2CM_FS_SCL_HCNT_1_ADDR 0x7E0F > +#define HDMI_I2CM_FS_SCL_HCNT_0_ADDR 0x7E10 > +#define HDMI_I2CM_FS_SCL_LCNT_1_ADDR 0x7E11 > +#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR 0x7E12 > + > +// DDC Interrupt status > +#define I2C_MASTER_ERROR 0x01 > +#define I2C_MASTER_DONE 0x02 > + > +// HDMI bit configuration > +typedef enum { > + DDC_READ_OPERATION = 0x01, > + DDC_READ_EXT_OPERATION = 0x02, > + DDC_WRITE_OPERATION = 0x10, > +} DDC_OPERATION; > + > +typedef enum { > + HDMI_DDC_STANDARD_MODE = 0x00, > + HDMI_DDC_FAST_MODE = 0x04, > +} DDC_MODE; > + > +#pragma pack(push, 1) > + > +// HDMI_PHY_CONF0 0x0100 > +typedef union { > + struct { > + UINT8 seldipif : 1; > + UINT8 seldataenpol : 1; > + UINT8 gen2_enhpdrxsense : 1; > + UINT8 gen2_txpwron : 1; > + UINT8 gen2_pddq : 1; > + UINT8 sparectrl : 1; > + UINT8 ENTMDS : 1; > + UINT8 PDZ : 1; > + }; > + UINT8 Reg; > +} HDMI_PHY_CONF0_REG; > + > +// HDMI_IH_I2CMPHY_STAT0 0x0108 > +typedef union { > + struct { > + UINT8 i2cmphyerror : 1; > + UINT8 i2cmphydone : 1; > + UINT8 reserved : 6; > + }; > + UINT8 Reg; > +} HDMI_IH_I2CMPHY_STAT0_REG; > + > +// HDMI_FC_AUDSCONF 0x01063 > +typedef union { > + struct { > + UINT8 aud_packet_layout : 1; > + UINT8 reserved : 4; > + UINT8 aud_packet_sampfit : 4; > + }; > + UINT8 Reg; > +} HDMI_FC_AUDSCONF_REG; > + > +// HDMI_PHY_STAT0 0x3004 > +typedef union { > + struct { > + UINT8 TX_PHY_LOCK : 1; > + UINT8 HPD : 1; > + UINT8 reserved : 2; > + UINT8 RX_SENSE0 : 1; > + UINT8 RX_SENSE1 : 1; > + UINT8 RX_SENSE2 : 1; > + UINT8 RX_SENSE3 : 1; > + }; > + UINT8 Reg; > +} HDMI_PHY_STAT0_REG; > + > +// HDMI_PHY_I2CM_OPERATION_ADDR 0x3026 > +typedef union { > + struct { > + UINT8 read : 1; > + UINT8 reserved0 : 3; > + UINT8 write : 1; > + UINT8 reserved1 : 3; > + }; > + UINT8 Reg; > +} HDMI_PHY_I2CM_OPERATION_ADDR_REG; > + > +// HDMI_MC_CLKDIS 0x4001 > +typedef union { > + struct { > + UINT8 pixelclk_disable : 1; > + UINT8 tmdsclk_disable : 1; > + UINT8 prepclk_disable : 1; > + UINT8 audclk_disable : 1; > + UINT8 cscclk_disable : 1; > + UINT8 cecclk_disable : 1; > + UINT8 hdcpclk_disable : 1; > + UINT8 reserved : 1; > + }; > + UINT8 Reg; > +} HDMI_MC_CLKDIS_REG; > + > +// HDMI_MC_PHYRSTZ 0x4005 > +typedef union { > + struct { > + UINT8 phyrstz : 1; > + UINT8 reserved : 7; > + }; > + UINT8 Reg; > +} HDMI_MC_PHYRSTZ_REG; > + > +// HDMI_MC_HEACPHY_RST 0x4007 > +typedef union { > + struct { > + UINT8 heacphyrst : 1; > + UINT8 reserved : 7; > + }; > + UINT8 Reg; > +} HDMI_MC_HEACPHY_RST_REG; > + > +// HDMI PHY : HDMI_PHY_CPCE_CTRL 0x06 > +typedef union { > + struct { > + UINT16 clr_dpth : 2; > + UINT16 pixel_rep : 3; > + UINT16 pll_n_cntrl : 2; > + UINT16 mpll_n_cntrl : 2; > + UINT16 ck_edgerate : 2; > + UINT16 tx_edgerate : 2; > + UINT16 prep_div : 2; > + UINT16 reserved : 1; > + }; > + UINT16 Reg; > +} HDMI_PHY_CPCE_CTRL_REG; > + > +// HDMI PHY : HDMI_PHY_CURRCTRL 0x10 > +typedef union { > + struct { > + UINT16 pll_int_cntrl : 3; > + UINT16 pll_prop_cntrl : 3; > + UINT16 mpll_int_cntrl : 3; > + UINT16 mpll_prop_cntrl : 3; > + UINT16 reserved : 4; > + }; > + UINT16 Reg; > +} HDMI_PHY_CURRCTRL_REG; > + > +// HDMI PHY : HDMI_PHY_GMPCTRL 0x15 > +typedef union { > + struct { > + UINT16 mpll_gmp_cntrl : 2; > + UINT16 pll_gmp_cntrl : 2; > + UINT16 reserved : 12; > + }; > + UINT16 Reg; > +} HDMI_PHY_GMPCTRL_REG; > + > +#pragma pack(pop) > + > +typedef struct _PLL_MPLL_CONFIG { > + UINT32 PixelClock; > + UINT8 PixelRepetition; > + UINT8 ColorDepth; > + HDMI_PHY_CPCE_CTRL_REG HdmiPhyCpceCtrl; > + HDMI_PHY_CURRCTRL_REG HdmiPhyCurrctrl; > + HDMI_PHY_GMPCTRL_REG HdmiPhyGmpctrl; > +} PLL_MPLL_CONFIG, *PPLL_MPLL_CONFIG; > + > +EFI_STATUS > +InitHdmi ( > + IN DISPLAY_CONTEXT *DisplayContextPtr > + ); > + > +EFI_STATUS > +SetHdmiPower ( > + IN DISPLAY_INTERFACE_CONTEXT *HdmiDisplayContextPtr, > + IN BOOLEAN PowerState > + ); > + > +EFI_STATUS > +SetHdmiDisplay ( > + IN DISPLAY_INTERFACE_CONTEXT *HdmiDisplayContextPtr, > + IN DISPLAY_TIMING *Timings > + ); > + > +EFI_STATUS > +HdmiDdcRead ( > + IN DISPLAY_INTERFACE_CONTEXT *HdmiDisplayContextPtr, > + IN UINT8 SlaveAddress, > + IN UINT8 RegisterAddress, > + IN UINT32 ReadSize, > + IN DDC_MODE DDCMode, > + IN UINT8 *DataReadPtr > + ); > + > +#endif /* _HDMI_H_ */ > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c > new file mode 100644 > index 000000000000..b82fbd2125f5 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.c > @@ -0,0 +1,88 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* Copyright 2018 NXP > +* > +* 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 > + > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +#include "Display.h" > +#include "IoMux.h" > + > +EFI_STATUS > +SetupDisplayMux ( > + IN DISPLAY_CONTEXT *DisplayContextPtr > + ) > +{ > + DISPLAY_INTERFACE_TYPE *pDisplayInterfaceType; > + volatile IMX_IOMUXC_GPR_REGISTERS *pIomuxcGprReg; > + UINT32 DisplayInterfaceIndex; > + DISPLAY_MODE DisplayMode; > + UINT32 Gpr3Reg; > + UINT32 SourceMask; > + UINT32 SourceValue; > + EFI_STATUS Status; > + > + pIomuxcGprReg = DisplayContextPtr->IoMuxMmioBasePtr; > + DisplayMode = DisplayContextPtr->DisplayConfig.DisplayMode; > + pDisplayInterfaceType = DisplayContextPtr->DisplayConfig.DiOrder; > + Status = EFI_SUCCESS; > + > + Gpr3Reg = MmioRead32 ((UINT32)&pIomuxcGprReg->GPR3); > + Gpr3Reg &= ~(HDMI_MUX_CTL_MASK | MIPI_MUX_CTL_MASK | > + LVDS0_MUX_CTL_MASK | LVDS1_MUX_CTL_MASK); > + MmioWrite32 ((UINT32)&pIomuxcGprReg->GPR3, Gpr3Reg); > + > + for (DisplayInterfaceIndex = 0; DisplayInterfaceIndex < (UINT32)DisplayMode; ++DisplayInterfaceIndex) { > + Gpr3Reg = MmioRead32 ((UINT32)&pIomuxcGprReg->GPR3); > + switch (pDisplayInterfaceType[DisplayInterfaceIndex]) { > + case HdmiDisplay: > + SourceMask = HDMI_MUX_CTL_MASK; > + SourceValue = DisplayInterfaceIndex << HDMI_MUX_CTL_OFFSET; > + break; > + case MipiDisplay: > + SourceMask = MIPI_MUX_CTL_MASK; > + SourceValue = DisplayInterfaceIndex << MIPI_MUX_CTL_OFFSET; > + break; > + case Lvds0Display: > + SourceMask = LVDS0_MUX_CTL_MASK; > + SourceValue = DisplayInterfaceIndex << LVDS0_MUX_CTL_OFFSET; > + break; > + case Lvds1Display: > + SourceMask = LVDS1_MUX_CTL_MASK; > + SourceValue = DisplayInterfaceIndex << LVDS1_MUX_CTL_OFFSET; > + break; > + default: > + Status = EFI_UNSUPPORTED; > + break; > + } > + if (EFI_ERROR (Status)) { > + break; > + } > + > + Gpr3Reg &= ~SourceMask; > + Gpr3Reg |= SourceValue; > + MmioWrite32 ((UINT32)&pIomuxcGprReg->GPR3, Gpr3Reg); > + } > + > + return Status; > +} > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h > new file mode 100644 > index 000000000000..4946ab293ae5 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/IoMux.h > @@ -0,0 +1,32 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* > +* 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. > +* > +**/ > + > +#ifndef _IO_MUX_H_ > +#define _IO_MUX_H_ IMX_ prefix, please. > + > +#define HDMI_MUX_CTL_OFFSET 2 > +#define HDMI_MUX_CTL_MASK 0x000C > +#define MIPI_MUX_CTL_OFFSET 4 > +#define MIPI_MUX_CTL_MASK 0x0030 > +#define LVDS0_MUX_CTL_OFFSET 6 > +#define LVDS0_MUX_CTL_MASK 0x00C0 > +#define LVDS1_MUX_CTL_OFFSET 8 > +#define LVDS1_MUX_CTL_MASK 0x0300 > + > +EFI_STATUS > +SetupDisplayMux ( > + IN DISPLAY_CONTEXT *DisplayContextPtr > + ); > + > +#endif /* _IO_MUX_H_ */ > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h > new file mode 100644 > index 000000000000..00d20c881b67 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Ipu.h > @@ -0,0 +1,236 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* > +* 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. > +* > +**/ > + > +#ifndef _IPU_H_ > +#define _IPU_H_ > + > +#define IPU1_BASE 0x02600000 > +#define IPU2_BASE 0x02A00000 > + > +#define IpuRead32(IPU_BASE, OFFSET) \ > + MmioRead32((UINT32)((UINT8 *)IPU_BASE + OFFSET)) > + > +#define IpuWrite32(IPU_BASE, OFFSET, VALUE) \ > + MmioWrite32((UINT32)((UINT8 *)IPU_BASE + OFFSET), VALUE) > + > +#define DiRead32(DI_BASE, OFFSET) \ > + MmioRead32((UINT32)((UINT8 *)DI_BASE + OFFSET)) > + > +#define DiWrite32(DI_BASE, OFFSET, VALUE) \ > + MmioWrite32((UINT32)((UINT8 *)DI_BASE + OFFSET), VALUE) > + > +// IPU Registers > +#define IPU_IPU_CONF_OFFSET 0x00000000 > +#define IPU_SISG_CTRL0_OFFSET 0x00000004 > +#define IPU_SISG_CTRL1_OFFSET 0x00000008 > +#define IPU_SISG_SET_OFFSET 0x0000000C > +#define IPU_SISG_CLR_OFFSET 0x00000024 > +#define IPU_IPU_INT_CTRL_1_OFFSET 0x0000003C > +#define IPU_IPU_INT_CTRL_2_OFFSET 0x00000040 > +#define IPU_IPU_INT_CTRL_3_OFFSET 0x00000044 > +#define IPU_IPU_INT_CTRL_4_OFFSET 0x00000048 > +#define IPU_IPU_INT_CTRL_5_OFFSET 0x0000004C > +#define IPU_IPU_INT_CTRL_6_OFFSET 0x00000050 > +#define IPU_IPU_INT_CTRL_7_OFFSET 0x00000054 > +#define IPU_IPU_INT_CTRL_8_OFFSET 0x00000058 > +#define IPU_IPU_INT_CTRL_9_OFFSET 0x0000005C > +#define IPU_IPU_INT_CTRL_10_OFFSET 0x00000060 > +#define IPU_IPU_INT_CTRL_11_OFFSET 0x00000064 > +#define IPU_IPU_INT_CTRL_12_OFFSET 0x00000068 > +#define IPU_IPU_INT_CTRL_13_OFFSET 0x0000006C > +#define IPU_IPU_INT_CTRL_14_OFFSET 0x00000070 > +#define IPU_IPU_INT_CTRL_15_OFFSET 0x00000074 > +#define IPU_IPU_SDMA_EVENT_1_OFFSET 0x00000078 > +#define IPU_IPU_SDMA_EVENT_2_OFFSET 0x0000007C > +#define IPU_IPU_SDMA_EVENT_3_OFFSET 0x00000080 > +#define IPU_IPU_SDMA_EVENT_4_OFFSET 0x00000084 > +#define IPU_IPU_SDMA_EVENT_7_OFFSET 0x00000088 > +#define IPU_IPU_SDMA_EVENT_8_OFFSET 0x0000008C > +#define IPU_IPU_SDMA_EVENT_11_OFFSET 0x00000090 > +#define IPU_IPU_SDMA_EVENT_12_OFFSET 0x00000094 > +#define IPU_IPU_SDMA_EVENT_13_OFFSET 0x00000098 > +#define IPU_IPU_SDMA_EVENT_14_OFFSET 0x0000009C > +#define IPU_IPU_SRM_PRI1_OFFSET 0x000000A0 > +#define IPU_IPU_SRM_PRI2_OFFSET 0x000000A4 > +#define IPU_IPU_FS_PROC_FLOW1_OFFSET 0x000000A8 > +#define IPU_IPU_FS_PROC_FLOW2_OFFSET 0x000000AC > +#define IPU_IPU_FS_PROC_FLOW3_OFFSET 0x000000B0 > +#define IPU_IPU_FS_DISP_FLOW1_OFFSET 0x000000B4 > +#define IPU_IPU_FS_DISP_FLOW2_OFFSET 0x000000B8 > +#define IPU_IPU_SKIP_OFFSET 0x000000BC > +#define IPU_IPU_DISP_ALT_CONF_OFFSET 0x000000C0 > +#define IPU_IPU_DISP_GEN_OFFSET 0x000000C4 > +#define IPU_IPU_DISP_ALT1_OFFSET 0x000000C8 > +#define IPU_IPU_DISP_ALT2_OFFSET 0x000000CC > +#define IPU_IPU_DISP_ALT3_OFFSET 0x000000D0 > +#define IPU_IPU_DISP_ALT4_OFFSET 0x000000D4 > +#define IPU_IPU_SNOOP_OFFSET 0x000000D8 > +#define IPU_IPU_MEM_RST_OFFSET 0x000000DC > +#define IPU_IPU_PM_OFFSET 0x000000E0 > +#define IPU_IPU_GPR_OFFSET 0x000000E4 > +#define IPU_IPU_INT_STAT_1_OFFSET 0x000000E8 > +#define IPU_IPU_INT_STAT_2_OFFSET 0x000000EC > +#define IPU_IPU_INT_STAT_3_OFFSET 0x000000F0 > +#define IPU_IPU_INT_STAT_4_OFFSET 0x000000F4 > +#define IPU_IPU_INT_STAT_5_OFFSET 0x000000F8 > +#define IPU_IPU_INT_STAT_6_OFFSET 0x000000FC > +#define IPU_IPU_INT_STAT_7_OFFSET 0x00000100 > +#define IPU_IPU_INT_STAT_8_OFFSET 0x00000104 > +#define IPU_IPU_INT_STAT_9_OFFSET 0x00000108 > +#define IPU_IPU_INT_STAT_10_OFFSET 0x0000010C > +#define IPU_IPU_INT_STAT_11_OFFSET 0x00000110 > +#define IPU_IPU_INT_STAT_12_OFFSET 0x00000114 > +#define IPU_IPU_INT_STAT_13_OFFSET 0x00000118 > +#define IPU_IPU_INT_STAT_14_OFFSET 0x0000011C > +#define IPU_IPU_INT_STAT_15_OFFSET 0x00000120 > +#define IPU_IPU_CUR_BUF_0_OFFSET 0x00000124 > +#define IPU_IPU_CUR_BUF_1_OFFSET 0x00000128 > +#define IPU_IPU_ALT_CUR_BUF_0_OFFSET 0x0000012C > +#define IPU_IPU_ALT_CUR_BUF_1_OFFSET 0x00000130 > +#define IPU_IPU_SRM_STAT_OFFSET 0x00000134 > +#define IPU_IPU_PROC_TASKS_STAT_OFFSET 0x00000138 > +#define IPU_IPU_DISP_TASKS_STAT_OFFSET 0x0000013C > +#define IPU_IPU_CH_BUF0_RDY0_OFFSET 0x00000140 > +#define IPU_IPU_CH_BUF0_RDY1_OFFSET 0x00000144 > +#define IPU_IPU_CH_BUF1_RDY0_OFFSET 0x00000148 > +#define IPU_IPU_CH_BUF1_RDY1_OFFSET 0x0000014C > +#define IPU_IPU_CH_DB_MODE_SEL0_OFFSET 0x00000150 > +#define IPU_IPU_CH_DB_MODE_SEL1_OFFSET 0x00000154 > +#define IPU_IPU_ALT_CH_BUF0_RDY0_OFFSET 0x00000158 > +#define IPU_IPU_ALT_CH_BUF0_RDY1_OFFSET 0x0000015C > +#define IPU_IPU_ALT_CH_BUF1_RDY0_OFFSET 0x00000160 > +#define IPU_IPU_ALT_CH_BUF1_RDY1_OFFSET 0x00000164 > +#define IPU_IPU_ALT_CH_DB_MODE_SEL0_OFFSET 0x00000168 > +#define IPU_IPU_ALT_CH_DB_MODE_SEL1_OFFSET 0x0000016C > +#define CSP_IPUV3_CPMEM_REGS_OFFSET 0x00100000 > + > +// IPU DIx Registers > +#define IPU_DIx_GENERAL_OFFSET 0x00000000 > +#define IPU_DIx_BS_CLKGEN0_OFFSET 0x00000004 > +#define IPU_DIx_BS_CLKGEN1_OFFSET 0x00000008 > +#define IPU_DIx_SW_GEN0_1_OFFSET 0x0000000C > +#define IPU_DIx_SW_GEN0_2_OFFSET 0x00000010 > +#define IPU_DIx_SW_GEN0_3_OFFSET 0x00000014 > +#define IPU_DIx_SW_GEN0_4_OFFSET 0x00000018 > +#define IPU_DIx_SW_GEN0_5_OFFSET 0x0000001C > +#define IPU_DIx_SW_GEN0_6_OFFSET 0x00000020 > +#define IPU_DIx_SW_GEN0_7_OFFSET 0x00000024 > +#define IPU_DIx_SW_GEN0_8_OFFSET 0x00000028 > +#define IPU_DIx_SW_GEN0_9_OFFSET 0x0000002C > +#define IPU_DIx_SW_GEN1_1_OFFSET 0x00000030 > +#define IPU_DIx_SW_GEN1_2_OFFSET 0x00000034 > +#define IPU_DIx_SW_GEN1_3_OFFSET 0x00000038 > +#define IPU_DIx_SW_GEN1_4_OFFSET 0x0000003C > +#define IPU_DIx_SW_GEN1_5_OFFSET 0x00000040 > +#define IPU_DIx_SW_GEN1_6_OFFSET 0x00000044 > +#define IPU_DIx_SW_GEN1_7_OFFSET 0x00000048 > +#define IPU_DIx_SW_GEN1_8_OFFSET 0x0000004C > +#define IPU_DIx_SW_GEN1_9_OFFSET 0x00000050 > +#define IPU_DIx_SYNC_AS_GEN_OFFSET 0x00000054 > +#define IPU_DIx_DW_GEN_OFFSET 0x00000058 > +#define IPU_DIx_DW_SET0_OFFSET 0x00000088 > +#define IPU_DIx_DW_SET1_OFFSET 0x000000B8 > +#define IPU_DIx_DW_SET2_OFFSET 0x000000E8 > +#define IPU_DIx_DW_SET3_OFFSET 0x00000118 > +#define IPU_DIx_STP_REP_OFFSET 0x00000148 > +#define IPU_DIx_STP_REP_9_OFFSET 0x00000158 > +#define IPU_DIx_SER_CONF_OFFSET 0x0000015C > +#define IPU_DIx_SSC_OFFSET 0x00000160 > +#define IPU_DIx_POL_OFFSET 0x00000164 > +#define IPU_DIx_AW0_OFFSET 0x00000168 > +#define IPU_DIx_AW1_OFFSET 0x0000016C > +#define IPU_DIx_SCR_CONF_OFFSET 0x00000170 > +#define IPU_DIx_STAT_OFFSET 0x00000174 > + > +// IPU IDMAC Registers > +#define IPU_IDMAC_LOCK_EN_1 0x00008024 > +#define IPU_IDMAC_LOCK_EN_2 0x00008028 > + > +// IPU DisplayInterface0 Registers > +#define IPU_DISPLAY_INTERFACE_0_OFFSET 0x00040000 > +#define IPU_DI0_BS_CLKGEN0_OFFSET 0x00040004 > +#define IPU_DI0_BS_CLKGEN1_OFFSET 0x00040008 > +#define IPU_DI0_SW_GEN0_1_OFFSET 0x0004000C > +#define IPU_DI0_SW_GEN0_2_OFFSET 0x00040010 > +#define IPU_DI0_SW_GEN0_3_OFFSET 0x00040014 > +#define IPU_DI0_SW_GEN0_4_OFFSET 0x00040018 > +#define IPU_DI0_SW_GEN0_5_OFFSET 0x0004001C > +#define IPU_DI0_SW_GEN0_6_OFFSET 0x00040020 > +#define IPU_DI0_SW_GEN0_7_OFFSET 0x00040024 > +#define IPU_DI0_SW_GEN0_8_OFFSET 0x00040028 > +#define IPU_DI0_SW_GEN0_9_OFFSET 0x0004002C > +#define IPU_DI0_SW_GEN1_1_OFFSET 0x00040030 > +#define IPU_DI0_SW_GEN1_2_OFFSET 0x00040034 > +#define IPU_DI0_SW_GEN1_3_OFFSET 0x00040038 > +#define IPU_DI0_SW_GEN1_4_OFFSET 0x0004003C > +#define IPU_DI0_SW_GEN1_5_OFFSET 0x00040040 > +#define IPU_DI0_SW_GEN1_6_OFFSET 0x00040044 > +#define IPU_DI0_SW_GEN1_7_OFFSET 0x00040048 > +#define IPU_DI0_SW_GEN1_8_OFFSET 0x0004004C > +#define IPU_DI0_SW_GEN1_9_OFFSET 0x00040050 > +#define IPU_DI0_SYNC_AS_GEN_OFFSET 0x00040054 > +#define IPU_DI0_DW_GEN_OFFSET 0x00040058 > +#define IPU_DI0_DW_SET0_OFFSET 0x00040088 > +#define IPU_DI0_DW_SET1_OFFSET 0x000400B8 > +#define IPU_DI0_DW_SET2_OFFSET 0x000400E8 > +#define IPU_DI0_DW_SET3_OFFSET 0x00040118 > +#define IPU_DI0_STP_REP_OFFSET 0x00040148 > +#define IPU_DI0_STP_REP_9_OFFSET 0x00040158 > +#define IPU_DI0_SER_CONF_OFFSET 0x0004015C > +#define IPU_DI0_SSC_OFFSET 0x00040160 > +#define IPU_DI0_POL_OFFSET 0x00040164 > +#define IPU_DI0_AW0_OFFSET 0x00040168 > +#define IPU_DI0_AW1_OFFSET 0x0004016C > +#define IPU_DI0_SCR_CONF_OFFSET 0x00040170 > +#define IPU_DI0_STAT_OFFSET 0x00040174 > + > +// IPU DisplayInterface1 Registers > +#define IPU_DISPLAY_INTERFACE_1_OFFSET 0x00048000 > +#define IPU_DI1_BS_CLKGEN0_OFFSET 0x00048004 > +#define IPU_DI1_BS_CLKGEN1_OFFSET 0x00048008 > +#define IPU_DI1_SW_GEN0_1_OFFSET 0x0004800C > +#define IPU_DI1_SW_GEN0_2_OFFSET 0x00048010 > +#define IPU_DI1_SW_GEN0_3_OFFSET 0x00048014 > +#define IPU_DI1_SW_GEN0_4_OFFSET 0x00048018 > +#define IPU_DI1_SW_GEN0_5_OFFSET 0x0004801C > +#define IPU_DI1_SW_GEN0_6_OFFSET 0x00048020 > +#define IPU_DI1_SW_GEN0_7_OFFSET 0x00048024 > +#define IPU_DI1_SW_GEN0_8_OFFSET 0x00048028 > +#define IPU_DI1_SW_GEN0_9_OFFSET 0x0004802C > +#define IPU_DI1_SW_GEN1_1_OFFSET 0x00048030 > +#define IPU_DI1_SW_GEN1_2_OFFSET 0x00048034 > +#define IPU_DI1_SW_GEN1_3_OFFSET 0x00048038 > +#define IPU_DI1_SW_GEN1_4_OFFSET 0x0004803C > +#define IPU_DI1_SW_GEN1_5_OFFSET 0x00048040 > +#define IPU_DI1_SW_GEN1_6_OFFSET 0x00048044 > +#define IPU_DI1_SW_GEN1_7_OFFSET 0x00048048 > +#define IPU_DI1_SW_GEN1_8_OFFSET 0x0004804C > +#define IPU_DI1_SW_GEN1_9_OFFSET 0x00048050 > +#define IPU_DI1_SYNC_AS_GEN_OFFSET 0x00048054 > +#define IPU_DI1_DW_GEN_OFFSET 0x00048058 > +#define IPU_DI1_DW_SET0_OFFSET 0x00048088 > +#define IPU_DI1_DW_SET1_OFFSET 0x000480B8 > +#define IPU_DI1_DW_SET2_OFFSET 0x000480E8 > +#define IPU_DI1_DW_SET3_OFFSET 0x00048118 > +#define IPU_DI1_STP_REP_OFFSET 0x00048148 > +#define IPU_DI1_STP_REP_9_OFFSET 0x00048158 > +#define IPU_DI1_SER_CONF_OFFSET 0x0004815C > +#define IPU_DI1_SSC_OFFSET 0x00048160 > +#define IPU_DI1_POL_OFFSET 0x00048164 > +#define IPU_DI1_AW0_OFFSET 0x00048168 > +#define IPU_DI1_AW1_OFFSET 0x0004816C > +#define IPU_DI1_SCR_CONF_OFFSET 0x00048170 > +#define IPU_DI1_STAT_OFFSET 0x00048174 > + > +#endif /* _IPU_H_ */ > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c > new file mode 100644 > index 000000000000..e6eb3b31bb07 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.c > @@ -0,0 +1,93 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* Copyright 2018 NXP > +* > +* 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 > + > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +#include "Display.h" > +#include "Lvds.h" > +#include "Edid.h" > + > +EFI_STATUS > +InitLvds ( > + IN DISPLAY_CONTEXT *DisplayContextPtr > + ) > +{ > + DISPLAY_INTERFACE_CONTEXT *pLvdsDisplayContext; > + EFI_STATUS Status; > + LDB_CTRL_REG LdbCtrlReg; > + > + Status = EFI_SUCCESS; > + pLvdsDisplayContext = &DisplayContextPtr->DiContext[Lvds0Display]; > + ZeroMem (pLvdsDisplayContext, sizeof (*pLvdsDisplayContext)); > + > + pLvdsDisplayContext->MmioBasePtr = (VOID *)LDB_BASE; > + if (pLvdsDisplayContext->MmioBasePtr == NULL) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to map LDB register\n", __FUNCTION__)); > + goto Exit; > + } > + > + // LVDS CH1 enabled, routed to DisplayInterface0; ipu_di01_vsync_active_low > + LdbCtrlReg.Reg = MmioRead32 ((UINT32)pLvdsDisplayContext->MmioBasePtr + LDB_CTRL); > + LdbCtrlReg.ch0_mode = 1; > + LdbCtrlReg.ch1_mode = 1; > + LdbCtrlReg.di0_vs_polarity = 1; > + LdbCtrlReg.di1_vs_polarity = 1; > + MmioWrite32 ((UINT32)pLvdsDisplayContext->MmioBasePtr + LDB_CTRL, LdbCtrlReg.Reg); > + > + // No EDID available > + pLvdsDisplayContext->EdidDataSize = 0; > + > + Status = GetPreferredTiming ( > + pLvdsDisplayContext->EdidData, > + pLvdsDisplayContext->EdidDataSize, > + &pLvdsDisplayContext->PreferredTiming > + ); > + if (Status != EFI_SUCCESS) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to retrieve LVDS preferred timing\n", > + __FUNCTION__)); > + goto Exit; > + } > + > +Exit: > + return Status; > +} > + > +EFI_STATUS > +SetLvdsPower ( > + IN DISPLAY_INTERFACE_CONTEXT *HdmiDisplayContextPtr, > + IN BOOLEAN PowerState > + ) > +{ > + return EFI_UNSUPPORTED; > +} > + > +EFI_STATUS > +SetLvdsDisplay ( > + IN DISPLAY_INTERFACE_CONTEXT *pLvdsDisplayContext, > + IN DISPLAY_TIMING *Timings > + ) > +{ > + return EFI_UNSUPPORTED; > +} > diff --git a/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h > new file mode 100644 > index 000000000000..b45201fb45fc > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Drivers/GopDxe/Lvds.h > @@ -0,0 +1,67 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* Copyright 2018 NXP > +* > +* 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. > +* > +**/ > + > +#ifndef _LVDS_H_ > +#define _LVDS_H_ IMX_ prefix please. > + > +// LDB Register Base Address > +#define LDB_BASE 0x020E0008 > + > +// LDB Control Register offset > +#define LDB_CTRL 0 > + > +#pragma pack(push, 1) > + > +// LDB_CTRL_REG > +typedef union { > + struct { > + UINT32 ch0_mode : 2; > + UINT32 ch1_mode : 2; > + UINT32 split_mode_en : 1; > + UINT32 data_width_ch0 : 1; > + UINT32 bit_mapping_ch0 : 1; > + UINT32 data_width_ch1 : 1; > + UINT32 bit_mapping_ch1 : 1; > + UINT32 di0_vs_polarity : 1; > + UINT32 di1_vs_polarity : 1; > + UINT32 Reserved11_15 : 5; > + UINT32 lvds_clk_shift : 3; > + UINT32 Reserved19 : 1; > + UINT32 counter_reset_val : 2; > + UINT32 Reserved22_31 : 10; Please rename all struct members to CamelCase. / Leif > + }; > + UINT32 Reg; > +} LDB_CTRL_REG; > + > +#pragma pack(pop) > + > +EFI_STATUS > +InitLvds ( > + IN DISPLAY_CONTEXT *DisplayContextPtr > + ); > + > +EFI_STATUS > +SetLvdsPower ( > + IN DISPLAY_INTERFACE_CONTEXT *HdmiDisplayContextPtr, > + IN BOOLEAN PowerState > + ); > + > +EFI_STATUS > +SetLvdsDisplay ( > + IN DISPLAY_INTERFACE_CONTEXT *LvdsDisplayContextPtr, > + IN DISPLAY_TIMING *Timings > + ); > + > +#endif /* _LVDS_H_ */ > -- > 2.16.2.gvfs.1.33.gf5370f1 >