dispdrvr.c
来自「PXA255 WINCE 4.2 BSP ,该BSP是商用的。」· C语言 代码 · 共 1,785 行 · 第 1/4 页
C
1,785 行
//
// 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 LQ64D343 (8) // Voipac dimmpc 640x480 active
#define SX14Q001 (9) // Voipac dimmpc 320x240 passive
#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 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(1,(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
v_pGPIORegs->GPSR_y |= GPIO_33; // light off
v_pGPIORegs->GPCR_z |= GPIO_77; // disp off
msWait(30);
// 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; // lcdctrl enable
msWait(30);
v_pGPIORegs->GPCR_y |= GPIO_33; // light on
v_pGPIORegs->GPSR_z |= GPIO_77; // disp on
}
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(1, (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(1, (TEXT("Bad BPP setting!")));
break;
}
}
switch(nDisplayType)
{
#ifdef PLAT_SANDGATE
case LTM04C380K:
{
RETAILMSG(1, (TEXT("Setting display type LTM04C380K")));
PCD = (LCLK / (2 * LTM04C380K_PIXEL_CLOCK_FREQUENCY)) - 1;
// For now, set PCD = 3;
PCD = 3;
// Configure the LCD Controller Control Registers
v_pLcdRegs->LCCR0 = ( LCD_LDM | LCD_SFM | LCD_IUM | LCD_EFM |
LCD_PAS | LCD_QDM | LCD_BM | LCD_OUM );
v_pLcdRegs->LCCR1 = ( LCD_PPL(0x27F) | LCD_HSW(0x01) |
LCD_ELW(0x01) | LCD_BLW(0x9f) );
v_pLcdRegs->LCCR2 = ( LCD_LPP(0x1df) | LCD_VSW(0x2c) |
LCD_EFW(0x00) | LCD_BFW(0x00) );
v_pLcdRegs->LCCR3 = ( LCD_PCD(PCD) | LCD_BPP(BPP) );
// Setup the Board Control Register (BCR)
// This command turns the display on.
set_BCRVal(LCD_ON, NOMASK, gInPowerHandler);
msWait(1000);
// Set PWM0 to 100% duty cycle to turn on the backlight to full brightness.
// When we wish to change the brightness of the backlight, change the duty cycle.
// Enable graceful shutdown, and prescale count of 1.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?