📄 dispdrvr.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#include <windows.h>
#include <types.h>
#include <drv_glob.h>
#include <string.h>
#include <stdio.h>
#include <tchar.h>
#include "xsc1.h"
#include "xsc1bd.h"
#include "DispDrvr.h"
#include "palette.h"
#include "bcr.h"
#define DEFINE_CURSOR_GLOBALS
#include "cursor.h"
#define NONE (0)
#define LTM04C380K (1) // Sandgate 640x480 active
#define LTM04C387S (2) // Sandgate 640x480 active
#define LQ039Q2DS54 (3) // Sandgate 320x240 active
#define LM8V31 (4) // Lubbock 640x480 passive
#define LM057QCTT03 (5) // Lubbock 320x240 passive
#define TFTQVGA (6) // Lubbock 320x240 active
#define LQ64D341 (7) // Lubbock 220x176 active
#define NL2432DR22_11B (8) // [JiangFQ] NEC NL2432DR22-11B TFT-LCD Module
#define V16C6448AC (9) //prime view 640x480-16bpp,add by hzh
#define LQ035Q7DB02 (10) //sharp 240x320-16bpp,add by hzh
#define LQ10D321 (11) //sharp 640x480-16bpp,add by hzh
#define LTM04C380K_PIXEL_CLOCK_FREQUENCY 25 // MHz
#define LTM04C387S_PIXEL_CLOCK_FREQUENCY 25 // MHz
#define LQ039Q2DS54_PIXEL_CLOCK_FREQUENCY 6 // MHz
#define LM8V31_PIXEL_CLOCK_FREQUENCY 8 // MHz
#define LM057QCTT03_PIXEL_CLOCK_FREQUENCY 6 // MHz
#define TFTQVGA_PIXEL_CLOCK_FREQUENCY 8 // MHz
#define LQ64D341_PIXEL_CLOCK_FREQUENCY 3.85
#define NL2432DR22_11B_PIXEL_CLOCK_FREQUENCY 3 // [JiangFQ] Pixel clock of NEC TFT-LCD
#define V16C6448AC_PIXEL_CLOCK_FREQUENCY 3 //add by hzh
#define LQ035Q7DB02_CLOCK_FREQUENCY 8 //add by hzh
#define LQ10D321_CLOCK_FREQUENCY 3 //add by hzh
#define LIGHT_ON 0x00000080
#define LIGHT_OFF 0x00000080
#define LCD_ON 0x00000100
#define LCD_OFF 0x00000100
#define CLK_PWM0 0x00000001
#define CLK_LCD 0x00010000
#define FRAME_BUFFER_BASE_PHYSICAL FRAME_BUFFER_0_BASE_PHYSICAL
BOOL gDrawCursorFlag = FALSE;
BOOL gInPowerHandler = FALSE;
BOOL bLandscapeDisplay = FALSE;
BOOL bAllowOSFrameBufferUpdates = TRUE;
CRITICAL_SECTION displayMutex;
CRITICAL_SECTION frameDescriptorMutex;
int DispDrvr_cxScreen;
int DispDrvr_cyScreen;
int DispDrvr_cdwStride;
int activeFrameBuffer=0;
unsigned int frameBufferSize = 0;
PBYTE gDibBuffer = NULL; // pointer to first byte of composition buffer
PBYTE gFrameBuffer = NULL; // pointer to first byte of screen memory
PBYTE gBlankFrameBuffer=NULL; // pointer to first byte of screen memory
int gDibBufferWidth;
int gDibBufferHeight;
RECT gCursorRect;
UINT nDisplayType;
void* DispDrvrPhysicalFrameBuffer = NULL;
BOOL gUseDispDrvrPhysicalFrameBuffer = FALSE;
volatile SA2lcdregs *v_pLcdRegs = NULL;
volatile CLKMAN_REGS *v_pClkRegs = NULL;
volatile GPIO_REGS *v_pGPIORegs = NULL;
volatile LCD_FRAME_DESCRIPTOR *frameDescriptorCh0fd1=NULL;
volatile LCD_FRAME_DESCRIPTOR *frameDescriptorCh0fd2=NULL;
volatile LCD_FRAME_DESCRIPTOR *frameDescriptorCh1=NULL;
volatile LCD_FRAME_DESCRIPTOR *frameDescriptorPalette=NULL;
volatile LCD_FRAME_DESCRIPTOR *frameDescriptorTemp=NULL;
volatile LCD_PALETTE *v_pPaletteBuffer=NULL;
#ifdef PLAT_LUBBOCK
volatile BLR_REGS *v_pBoardLevelRegister;
#endif
#ifdef PLAT_SANDGATE
volatile PWM_REGS *v_pPWMRegs = NULL;
#endif
// Instantiate the 8 bit palette
INSTANTIATE_PALETTE
void LCDClearStatusReg();
void LcdSetupGPIOs();
void Cleanup();
void InitLCDController();
void EnableLCDController();
void DisableLCDController();
void InitCursor();
BOOL MapVirtualAddress();
BOOL ReadRegistryData(VOID);
void CopyFrameBuffer(BOOL gDirection);
void ClearFrameBuffer(BOOL color);
void DisplayPageBuffer(int page);
void ScrollBuffer(int direction);
extern void msWait(unsigned msVal);
extern PVOID VirtualAllocCopy(unsigned size,char *str,PVOID pVirtualAddress);
#ifdef OSV_LOCAL_MERLIN
extern BOOL VirtualSetAttributes(LPVOID lpvAddress, DWORD cbSize, DWORD dwNewFlags, DWORD dwMask, LPDWORD lpdwOldFlags);
#endif
//unsigned int GetDescriptorAddress(unsigned int physical_address);
void ConfigureFrameBufferSectionDescriptor(unsigned int descriptor);
#define _OPT_ASM
#ifdef _OPT_ASM
void dirtyRectDump_core_ASM(WORD *pwSrc, WORD *pwDst,int rowLen, DWORD srcWidthB,
DWORD bytesPerRow, DWORD srcMarginWidth, DWORD dstMarginWidth);
void DirtyRectDumpPortraitLoop_C(BYTE *pDstBuf, BYTE *pSrcBuf, DWORD yTop, DWORD yBottom,
DWORD srcWidthB, DWORD bytesPerRow, DWORD bytesPerPixel, DWORD srcMarginWidth, DWORD dstMarginWidth);
void ellipse_core_ASM(WORD srcColor,DWORD margin,DWORD width,WORD* pDstBuf);
void DispDrvrDirtyRectDump2(LPCRECT prc,DWORD color);
void DirtyRectDumpPortraitLoop_C_rectfill(BYTE *pDstBuf, WORD srcColor,DWORD yTop,DWORD yBottom,
DWORD srcWidthB, DWORD bytesPerRow, DWORD bytesPerPixel, DWORD srcMarginWidth, DWORD dstMarginWidth);
void DispDrvrDirtyRectDump_rectfill(LPCRECT prc, DWORD color);
#endif
void DispDrvrSetDibBuffer(void *data)
{
gDibBuffer = data;
ClearFrameBuffer(FALSE);
}
void DispDrvrSetPalette (const PALETTEENTRY source[],unsigned short firstEntry,unsigned short numEntries)
{
int i;
int end = firstEntry + numEntries;
EnterCriticalSection(&frameDescriptorMutex);
// Store the palette entries into palette ram
for(i=firstEntry;i<end;i++)
{
// store 5 bits red, 6 bits green, and 5 bits blue
v_pPaletteBuffer->palette[i] = (
(source[i].peBlue) >> 3 |
((source[i].peGreen & 0xfc) << 3) |
((source[i].peRed & 0xf8) << 8)
);
}
// Reconfigure the second frame descriptor so that when loaded,
// this descriptor loops to itself.
frameDescriptorCh0fd2->FDADR = LCD_FDADR(frameDescriptorCh0fd2->PHYSADDR);
// Reconfigure the palette frame descriptor so that it loads the second frame descriptor
frameDescriptorPalette->FDADR = LCD_FDADR(frameDescriptorCh0fd2->FDADR);
frameDescriptorPalette->FSADR = LCD_FSADR(PALETTE_BUFFER_BASE_PHYSICAL);
frameDescriptorPalette->FIDR = LCD_FIDR(0);
frameDescriptorPalette->LDCMD = LCD_Len(512) | LCD_Pal; // 2^bpp * 2;
frameDescriptorPalette->PHYSADDR = LCD_FDADR(PALETTE_FRAME_DESCRIPTOR_BASE_PHYSICAL);
// Insert the palette descriptor into the descriptor chain to load the palette.
// When this load completes, fd2 is automatically loaded next in the chain.
// fd2 now loops to itself and continues to load frame data.
frameDescriptorCh0fd1->FDADR = LCD_FDADR(PALETTE_FRAME_DESCRIPTOR_BASE_PHYSICAL);
// swap frame descriptor pointers so that this operation is reversed the next time through
frameDescriptorTemp = frameDescriptorCh0fd1;
frameDescriptorCh0fd1 = frameDescriptorCh0fd2;
frameDescriptorCh0fd2 = frameDescriptorTemp;
LeaveCriticalSection(&frameDescriptorMutex);
}
void DispDrvrInitialize (void)
{
// Read display driver configuration from system registry
ReadRegistryData();
// Initializes the subroutine usWait(), which makes a system call
// during its init. Force init now so it can't happen during suspend-
// resume processing, when it would crash the system.
msWait(20);
frameBufferSize = bpp / 8 * DispDrvr_cxScreen * DispDrvr_cyScreen;
// Map registers, the frame buffer, and frame descriptors from Kernel virtual addresse
// into our user mode virtual address space
if (!MapVirtualAddress())
return;
InitializeCriticalSection(&displayMutex);
InitializeCriticalSection(&frameDescriptorMutex);
// Initialize Cursor
InitCursor();
// Initialize the GPIO registers for proper LCD Controller operation
LcdSetupGPIOs();
// Clear the frame buffer
ClearFrameBuffer(TRUE);
// Initialize the LCD Controller and Board Control Register
InitLCDController();
// Clear LCD Controller status register
LCDClearStatusReg();
// Enable the LCD controller
EnableLCDController();
// If required, load the default palette into palette ram
// and feed this to the LCD controller.
if(bpp < 16)
{
DispDrvrSetPalette(_rgbIdentity,0,PALETTE_SIZE);
}
RETAILMSG(0,(TEXT("InitializeDisplayHardware Complete\r\n")));
return;
}
void DisableLCDController()
{
// Copy the active frame buffer into a temporary buffer
// because we are going to write over the active frame buffer
// with a blank all black display. When we restore the display
// when we wake up, we want to be able to copy the original
// frame buffer back in.
CopyFrameBuffer(TRUE);
// Turn the display to black
// and allow a few frames to display
ClearFrameBuffer(FALSE);
msWait(100);
#ifdef PLAT_SANDGATE
// Turn the LCD OFF
set_BCRVal(NOMASK, LCD_OFF, gInPowerHandler);
msWait(300);
// Turn the backlight OFF
set_BCRVal(NOMASK, LIGHT_OFF, gInPowerHandler);
msWait(300);
// Set PWM0 to 0% duty cycle to turn off the backlight.
// Enable graceful shutdown, and prescale count of 1.
v_pPWMRegs->pwcr = 0;
// Set the duty cycle to 100% (0x3FF/0x3FF)
v_pPWMRegs->pwdr = 0x0;
// Set the period value to it's maximum (0x3FF)
v_pPWMRegs->pwpr = 0x0;
#endif
// Initiate power down sequence
switch (nDisplayType)
{
case NL2432DR22_11B:
RETAILMSG(0,(TEXT("DisableLCD:Turn off LCD...\r\n")));
v_pLcdRegs->LCCR0 |= LCD_DIS;
break;
// end
case V16C6448AC: //add by hzh
case LQ035Q7DB02: //add by hzh
case LQ10D321: //add by hzh
default:
RETAILMSG(0,(TEXT("DisableLCD:Turn off LCD...\r\n"))); //add by hzh
// Initiate power down sequence
v_pLcdRegs->LCCR0 |= LCD_DIS;
break;
}
// Initiate power down sequence
//v_pLcdRegs->LCCR0 |= LCD_DIS;
// Wait for LDD bit to get set once the last DMA transfer has completed
while(!(v_pLcdRegs->LCSR & LCD_LDD));
// Clear the sticky LDD bit
v_pLcdRegs->LCSR |= LCD_LDD;
}
void EnableLCDController()
{
v_pLcdRegs->LCCR0 |= LCD_ENB;
}
void InitLCDController()
{
unsigned int CCCR_L = 0;
unsigned int LCLK = 0;
unsigned int PCD = 0;
unsigned int BPP = 0;
v_pLcdRegs->LCCR0 = 0;
v_pLcdRegs->LCCR1 = 0;
v_pLcdRegs->LCCR2 = 0;
v_pLcdRegs->LCCR3 = 0;
#if defined ( PLAT_LUBBOCK )
v_pBoardLevelRegister->misc_wr |= LCD_DISP;
#endif
// Configure the general purpose frame descriptors
// Set the physical address of the frame descriptor
frameDescriptorCh0fd1->FDADR = LCD_FDADR(DMA_CHANNEL_0_FRAME_DESCRIPTOR_BASE_PHYSICAL);
// Set the physical address of the frame buffer
frameDescriptorCh0fd1->FSADR = LCD_FSADR(FRAME_BUFFER_BASE_PHYSICAL);
// Clear the frame ID
frameDescriptorCh0fd1->FIDR = LCD_FIDR(0);
// Set the DMA transfer length to the size of the frame buffer
frameDescriptorCh0fd1->LDCMD = LCD_Len(frameBufferSize);
// Store the physical address of this frame descriptor in the frame descriptor
frameDescriptorCh0fd1->PHYSADDR = frameDescriptorCh0fd1->FDADR;
// frameDescriptorCh0fd2 is used only if a palette load is performed.
// Set the physical address of the frame descriptor
frameDescriptorCh0fd2->FDADR = LCD_FDADR(DMA_CHANNEL_0_ALT_FRAME_DESCRIPTOR_BASE_PHYSICAL);
// Set the physical address of the frame buffer
frameDescriptorCh0fd2->FSADR = LCD_FSADR(FRAME_BUFFER_BASE_PHYSICAL);
// Clear the frame ID
frameDescriptorCh0fd2->FIDR = LCD_FIDR(0);
// Set the DMA transfer length to the size of the frame buffer
frameDescriptorCh0fd2->LDCMD = LCD_Len(frameBufferSize);
// Store the physical address of this frame descriptor in the frame descriptor
frameDescriptorCh0fd2->PHYSADDR = frameDescriptorCh0fd2->FDADR;
// FBR0 is cleared and is not used.
v_pLcdRegs->FBR0 = 0;
// Load the contents of FDADR0 with the physical address of this frame descriptor
v_pLcdRegs->FDADR0 = LCD_FDADR(frameDescriptorCh0fd1->FDADR);
// Determine the LCLK frequency programmed into the CCCR.
// This value will be used to calculate a Pixel Clock Divisor (PCD)
// for a given display type.
CCCR_L = (v_pClkRegs->cccr & 0x0000001F);
if (CCCR_L == 1)
LCLK = 100;
else if (CCCR_L == 2)
LCLK = 118;
else if (CCCR_L == 3)
LCLK = 133;
else if (CCCR_L == 4)
LCLK = 147;
else if (CCCR_L == 5)
LCLK = 166;
else
{
LCLK = 0;
RETAILMSG(0, (TEXT("Bad LCLK setting!")));
}
// Convert the bpp setting into a value that the LCD controller understands.
switch(bpp)
{
case 1:
{
BPP = 0;
break;
}
case 2:
{
BPP = 1;
break;
}
case 4:
{
BPP = 2;
break;
}
case 8:
{
BPP = 3;
break;
}
case 16:
{
BPP = 4;
break;
}
default:
{
BPP = 0;
RETAILMSG(0, (TEXT("Bad BPP setting!")));
break;
}
}
switch(nDisplayType)
{
case NL2432DR22_11B :
{
PCD = (LCLK / (2 * NL2432DR22_11B_PIXEL_CLOCK_FREQUENCY)) - 1;
PCD = 7;
RETAILMSG(0, (TEXT("InitLCDController:NL2432DR22_11B display type, PCD=%d\r\n"), PCD));
// Configure the TMED dithering engine
// Use the magic number described in the Cotulla EAS, 0x00AA5500;
v_pLcdRegs->TRGBR = LCD_TRS(0x00) | LCD_TGS(0x55) | LCD_TBS(0xAA);
// Use the magic number described in the Cotulla EAS, 0x0000754F;
v_pLcdRegs->TCR = LCD_TM2S | LCD_TM1S | LCD_TM2En | LCD_TM1En |
LCD_TVBS(0x04) | LCD_THBS(0x05) | LCD_TSCS(0x03) |
LCD_TED;
v_pLcdRegs->LCCR1 = ( LCD_PPL(0xef) | LCD_HSW(0x0c) |
LCD_ELW(0x15) | LCD_BLW(0x15) );
v_pLcdRegs->LCCR2 = ( LCD_LPP(0x13f) | LCD_VSW(03) |
LCD_EFW(0x06) | LCD_BFW(0x06) );
v_pLcdRegs->LCCR3 = ( LCD_PCD(PCD) | LCD_PCP | LCD_BPP(BPP) | LCD_VSP | LCD_HSP );
v_pLcdRegs->LCCR0 = ( LCD_LDM | LCD_SFM | LCD_IUM |
LCD_EFM | LCD_PAS | LCD_QDM | LCD_BM | LCD_OUM /*| LCD_BLE*/);
}
break;
case V16C6448AC: //add by hzh
{
PCD = 4;
RETAILMSG(1, (TEXT("InitLCDController:V16C6448AC display type, PCD=%d\r\n"), PCD));
// Configure the TMED dithering engine
// Use the magic number described in the Cotulla EAS, 0x00AA5500;
v_pLcdRegs->TRGBR = LCD_TRS(0x00) | LCD_TGS(0x55) | LCD_TBS(0xAA);
// Use the magic number described in the Cotulla EAS, 0x0000754F;
v_pLcdRegs->TCR = LCD_TM2S | LCD_TM1S | LCD_TM2En | LCD_TM1En |
LCD_TVBS(0x04) | LCD_THBS(0x05) | LCD_TSCS(0x03) |
LCD_TED;
v_pLcdRegs->LCCR1 = ( LCD_PPL(639) | LCD_HSW(10) |
LCD_ELW(10) | LCD_BLW(132) );
v_pLcdRegs->LCCR2 = ( LCD_LPP(479) | LCD_VSW(06) |
LCD_EFW(10) | LCD_BFW(10) );
v_pLcdRegs->LCCR3 = ( LCD_PCD(PCD) | LCD_BPP(BPP) | LCD_ACB(255) );
v_pLcdRegs->LCCR0 = ( LCD_LDM | LCD_SFM | LCD_IUM |
LCD_EFM | LCD_PAS | LCD_QDM | LCD_BM | LCD_OUM /*| LCD_BLE*/);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -