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 + -
显示快捷键?