📄 xllp_lcd.c
字号:
void LCDClearStatusReg(P_XLLP_LCD_T pXllpLCD)
{
volatile LCDRegs *p_LCDRegs;
p_LCDRegs = (LCDRegs *) pXllpLCD->LCDC;
// Clear the status registers by writing 1's to each bit.
p_LCDRegs->LCSR0 = ( LCD_LDD | LCD_SOF0| LCD_BER | LCD_ABC | LCD_IU0 |
LCD_IU1 | LCD_OU | LCD_QD | LCD_EOF0| LCD_BS0 |
LCD_SINT| LCD_RD_ST | LCD_CMD_INTR );
p_LCDRegs->LCSR1 = ( LCD_SOF1| LCD_SOF2| LCD_SOF3| LCD_SOF4| LCD_SOF5 | LCD_SOF6 |
LCD_EOF1| LCD_EOF2| LCD_EOF3| LCD_EOF4| LCD_EOF5 | LCD_EOF6 |
LCD_BS1 | LCD_BS2 | LCD_BS3 | LCD_BS4 | LCD_BS5 | LCD_BS6 |
LCD_IU2 | LCD_IU3 | LCD_IU4 | LCD_IU5 | LCD_IU6 );
}
void LCDSetupGPIOs(P_XLLP_LCD_T pXllpLCD)
{
volatile unsigned int APB_Temp;
volatile XLLP_GPIO_T *p_GPIORegs;
p_GPIORegs = (XLLP_GPIO_T *) pXllpLCD->GPIO;
// XllpLock(XLLP_RESOURCE_GPDR0);
if (pXllpLCD->DisplayType != LS022Q8DD06)
{
p_GPIORegs->GPDR0 = (p_GPIORegs->GPDR0 & ~XLLP_GPIO_BIT_L_VSYNC) | (XLLP_GPIO_BIT_PWM_OUT0 | XLLP_GPIO_BIT_L_CS);
}
// XllpUnlock(XLLP_RESOURCE_GPDR0);
// XllpLock(XLLP_RESOURCE_GPDR1);
p_GPIORegs->GPDR1 |= ( XLLP_GPIO_BIT_L_DD0 | XLLP_GPIO_BIT_L_DD1 | XLLP_GPIO_BIT_L_DD2 | XLLP_GPIO_BIT_L_DD3 | XLLP_GPIO_BIT_L_DD4 | XLLP_GPIO_BIT_L_DD5);
// Set GPIO 38 and 40 as outputs
#if defined XLLP_GPIO_BIT_SSPTXD3 && XLLP_GPIO_BIT_SSPCLK3
if (pXllpLCD->DisplayType == LS022Q8DD06)
{
p_GPIORegs->GPDR1 |= (XLLP_GPIO_BIT_SSPTXD3 | XLLP_GPIO_BIT_SSPCLK3);
}
#endif
// XllpUnlock(XLLP_RESOURCE_GPDR1);
// XllpLock(XLLP_RESOURCE_GPDR2);
if (pXllpLCD->DisplayType != LS022Q8DD06)
{
p_GPIORegs->GPDR2 |= ( XLLP_GPIO_BIT_L_DD6 | XLLP_GPIO_BIT_L_DD7 | XLLP_GPIO_BIT_L_DD8 | XLLP_GPIO_BIT_L_DD9 | XLLP_GPIO_BIT_L_DD10 |
XLLP_GPIO_BIT_L_DD11 | XLLP_GPIO_BIT_L_DD12 | XLLP_GPIO_BIT_L_DD13 | XLLP_GPIO_BIT_L_DD14 | XLLP_GPIO_BIT_L_DD15 |
XLLP_GPIO_BIT_L_FCLK | XLLP_GPIO_BIT_L_LCLK | XLLP_GPIO_BIT_L_PCLK | XLLP_GPIO_BIT_L_BIAS | XLLP_GPIO_BIT_L_DD16 |
XLLP_GPIO_BIT_L_DD17);
} else
{
p_GPIORegs->GPDR2 |= ( XLLP_GPIO_BIT_L_DD6 | XLLP_GPIO_BIT_L_DD7 | XLLP_GPIO_BIT_L_DD8 | XLLP_GPIO_BIT_L_DD9 | XLLP_GPIO_BIT_L_DD10 |
XLLP_GPIO_BIT_L_DD11 | XLLP_GPIO_BIT_L_DD12 | XLLP_GPIO_BIT_L_DD13 | XLLP_GPIO_BIT_L_DD14 | XLLP_GPIO_BIT_L_DD15 |
XLLP_GPIO_BIT_L_FCLK | XLLP_GPIO_BIT_L_LCLK | XLLP_GPIO_BIT_L_PCLK | XLLP_GPIO_BIT_L_BIAS );
#if defined XLLP_GPIO_BIT_SSPRXD3
// Set GPIO 89 as input
p_GPIORegs->GPDR2 &= ~(XLLP_GPIO_BIT_SSPRXD3);
#endif
}
// XllpUnlock(XLLP_RESOURCE_GPDR2);
if (pXllpLCD->DisplayType != LS022Q8DD06)
{
// Program the GAFR0_L to select alternate function 1 for GPIO 14.
// XllpLock(XLLP_RESOURCE_GAFR0_L);
p_GPIORegs->GAFR0_L = (p_GPIORegs->GAFR0_L & ~XLLP_GPIO_AF_BIT_L_VSYNC_MASK) | (XLLP_GPIO_AF_BIT_L_VSYNC);
// XllpUnlock(XLLP_RESOURCE_GAFR0_L);
// Program the GAFR0_U to select alternate function 2 for GPIO 19.
// XllpLock(XLLP_RESOURCE_GAFR0_U);
p_GPIORegs->GAFR0_U = (p_GPIORegs->GAFR0_U & ~XLLP_GPIO_AF_BIT_L_CS_MASK) | (XLLP_GPIO_AF_BIT_L_CS);
// XllpUnlock(XLLP_RESOURCE_GAFR0_U);
}
if (pXllpLCD->DisplayType == LS022Q8DD06)
{
#if defined XLLP_GPIO_AF_BIT_SSPTXD3_MASK && XLLP_GPIO_AF_BIT_SSPCLK3_MASK && XLLP_GPIO_AF_BIT_SSPTXD3 && XLLP_GPIO_AF_BIT_SSPCLK3
// Program the GAFR1_L to select alternate function 1 for GPIO 38, 40.
// XllpLock(XLLP_RESOURCE_GAFR1_L);
p_GPIORegs->GAFR1_L = (p_GPIORegs->GAFR1_L & ~(XLLP_GPIO_AF_BIT_SSPTXD3_MASK | XLLP_GPIO_AF_BIT_SSPCLK3_MASK)) |
(XLLP_GPIO_AF_BIT_SSPTXD3 | XLLP_GPIO_AF_BIT_SSPCLK3);
// XllpUnlock(XLLP_RESOURCE_GAFR1_L);
#endif
}
// Program the GAFR1_U to select alternate function 2 for GPIO 58 through 63.
// XllpLock(XLLP_RESOURCE_GAFR1_U);
p_GPIORegs->GAFR1_U = (p_GPIORegs->GAFR1_U & ~(XLLP_GPIO_AF_BIT_L_DD0_MASK | XLLP_GPIO_AF_BIT_L_DD1_MASK | XLLP_GPIO_AF_BIT_L_DD2_MASK|
XLLP_GPIO_AF_BIT_L_DD3_MASK | XLLP_GPIO_AF_BIT_L_DD4_MASK | XLLP_GPIO_AF_BIT_L_DD5_MASK)) |
(XLLP_GPIO_AF_BIT_L_DD0 | XLLP_GPIO_AF_BIT_L_DD1 | XLLP_GPIO_AF_BIT_L_DD2 |
XLLP_GPIO_AF_BIT_L_DD3 | XLLP_GPIO_AF_BIT_L_DD4 | XLLP_GPIO_AF_BIT_L_DD5 );
// XllpUnlock(XLLP_RESOURCE_GAFR1_U);
// Program the GAFR2_L to select alternate function 2 for GPIO 64 through 77.
// XllpLock(XLLP_RESOURCE_GAFR2_L);
p_GPIORegs->GAFR2_L = (p_GPIORegs->GAFR2_L & ~(XLLP_GPIO_AF_BIT_L_DD6_MASK | XLLP_GPIO_AF_BIT_L_DD7_MASK | XLLP_GPIO_AF_BIT_L_DD8_MASK |
XLLP_GPIO_AF_BIT_L_DD9_MASK | XLLP_GPIO_AF_BIT_L_DD10_MASK | XLLP_GPIO_AF_BIT_L_DD11_MASK |
XLLP_GPIO_AF_BIT_L_DD12_MASK | XLLP_GPIO_AF_BIT_L_DD13_MASK | XLLP_GPIO_AF_BIT_L_DD14_MASK |
XLLP_GPIO_AF_BIT_L_DD15_MASK | XLLP_GPIO_AF_BIT_L_FCLK_RD_MASK | XLLP_GPIO_AF_BIT_L_LCLK_A0_MASK |
XLLP_GPIO_AF_BIT_L_PCLK_WR_MASK | XLLP_GPIO_AF_BIT_L_BIAS_MASK)) |
(XLLP_GPIO_AF_BIT_L_DD6 | XLLP_GPIO_AF_BIT_L_DD7 | XLLP_GPIO_AF_BIT_L_DD8 |
XLLP_GPIO_AF_BIT_L_DD9 | XLLP_GPIO_AF_BIT_L_DD10 | XLLP_GPIO_AF_BIT_L_DD11 |
XLLP_GPIO_AF_BIT_L_DD12 | XLLP_GPIO_AF_BIT_L_DD13 | XLLP_GPIO_AF_BIT_L_DD14 |
XLLP_GPIO_AF_BIT_L_DD15 | XLLP_GPIO_AF_BIT_L_FCLK_RD| XLLP_GPIO_AF_BIT_L_LCLK_A0|
XLLP_GPIO_AF_BIT_L_PCLK_WR | XLLP_GPIO_AF_BIT_L_BIAS );
if (pXllpLCD->DisplayType == LS022Q8DD06)
{
p_GPIORegs->GAFR2_L = (p_GPIORegs->GAFR2_L & ~XLLP_GPIO_AF_BIT_L_BIAS_MASK);
}
// XllpUnlock(XLLP_RESOURCE_GAFR2_L);
if (pXllpLCD->DisplayType != LS022Q8DD06)
{
// Program the GAFR2_U to select alternate function 2 for GPIO 86, 87.
// XllpLock(XLLP_RESOURCE_GAFR2_U);
p_GPIORegs->GAFR2_U = (p_GPIORegs->GAFR2_U & ~(XLLP_GPIO_AF_BIT_L_DD16_MASK | XLLP_GPIO_AF_BIT_L_DD17_MASK)) | (XLLP_GPIO_AF_BIT_L_DD16 | XLLP_GPIO_AF_BIT_L_DD17);
// XllpUnlock(XLLP_RESOURCE_GAFR2_U);
}
if (pXllpLCD->DisplayType == LS022Q8DD06)
{
// XllpLock(XLLP_RESOURCE_GAFR2_U);
#if defined XLLP_GPIO_AF_BIT_SSPRXD3_MASK && XLLP_GPIO_AF_BIT_SSPRXD3
p_GPIORegs->GAFR2_U = (p_GPIORegs->GAFR2_U & ~XLLP_GPIO_AF_BIT_SSPRXD3_MASK) | XLLP_GPIO_AF_BIT_SSPRXD3;
#endif
// XllpUnlock(XLLP_RESOURCE_GAFR2_U);
}
if (pXllpLCD->DisplayType != LS022Q8DD06)
{
// XllpLock(XLLP_RESOURCE_GPSR0);
// Turn on the backlight...
p_GPIORegs->GPSR0 = XLLP_GPIO_BIT_PWM_OUT0;
// XllpUnlock(XLLP_RESOURCE_GPSR0);
}
if (pXllpLCD->DisplayType == LS022Q8DD06)
{
p_GPIORegs->GPCR2 = XLLP_GPIO_BIT_L_BIAS;
}
//
// Ensure GPIO writes that have posted complete
//
APB_Temp = p_GPIORegs->GAFR0_L;
}
void LCDEnableController(P_XLLP_LCD_T pXllpLCD)
{
volatile LCDRegs *p_LCDRegs;
p_LCDRegs = (LCDRegs *) pXllpLCD->LCDC;
p_LCDRegs->LCCR0 |= LCD_ENB;
}
#ifndef NO_NH040609_OVERLAY2_YUVHWFIX
typedef enum
{
WFS_ALL
,WFS_ANY
} WFS_TYPE;
static int WaitForState(volatile unsigned int (*pStatusReg), unsigned int mask, WFS_TYPE wait_type, unsigned int max_ms)
// Wait a max # milliseconds for a register to match a given state (any or all bits)
// Returns number of milliseconds of max_ms remaining (ie. >= 0 = got match, < 0 = no match)
{
int matched = 0;
int sleep_quantum = (max_ms/100); // milliseconds
int sleep_time_left = max_ms;
if (sleep_quantum == 0)
sleep_quantum = 1;
while (1)
{
matched = (wait_type == WFS_ALL) ? ((*pStatusReg & mask) == mask)
: ((*pStatusReg & mask) != 0);
if (matched)
{
if (sleep_time_left < 0)
sleep_time_left = 0;
break;
}
if (sleep_time_left < 0)
break;
SPINSLEEP(sleep_quantum);
sleep_time_left -= sleep_quantum;
}
return(sleep_time_left);
} // WaitForState
#endif /* NH040609_OVERLAY2_YUVHWFIX */
#ifndef NO_NH040609_OVERLAY2_YUVHWFIX
// The enable and disable routines have been changed to implement workaround(s) for
// controller(/hardware) problems (lockup an fade-to-white) described in Tibet sighting 49219
// when enabling and disabling YUV 4:2:0 mode.
// The basic functional changes are...
// 1. When enabling overlay2, set the enable bit (LCD_O2EN) and wait for input FIFO underrun to occur
// BEFORE setting the registers that point to the DMA descriptors for CH2,3&4 (FDADRx).
// 2. When disabling overlay2, after clearing LCD_O2EN wait for DMA branch status (LCD_BSx) to occur
// before restoring the baseframe pixel format.
// DMA branch status is detected by setting branch registers (FBRx) and waiting for LCD_BSx status.
XLLP_STATUS_T XllpLCD_Overlay2_Enable(P_XLLP_LCD_T pXllpLCD, P_XLLP_OVERLAY_T pXllpOverlay)
{
XLLP_STATUS_T status = 0;
volatile LCDRegs *p_LCDRegs;
unsigned int StatMask = 0;
p_LCDRegs = (LCDRegs *) pXllpLCD->LCDC;
if ((p_LCDRegs->OVL2C1) & LCD_O2EN)
{
LOGMSG(1,(TEXT("XllpLCD_Overlay2_Enable: Already enabled\r\n")));
// return(status);
}
// Change baseframe pixel format to reduce memory bus bandwidth
XllpLCDSuspend(pXllpLCD, Suspend_Graceful);
pXllpOverlay->TmpBPP = pXllpLCD->BPP;
if (pXllpOverlay->DegradeBaseFrame)
pXllpLCD->BPP = BPP_1;
pXllpLCD->PixelDataFormat = PDFOR_11;
XllpLCDResume(pXllpLCD);
// Setup frame descriptors
// CH2
pXllpLCD->frameDescriptorCh2_YCbCr_Y->PHYSADDR = LCD_FDADR(pXllpLCD->_DMA_CHANNEL_2_Y_FRAME_DESCRIPTOR_BASE_PHYSICAL); // self
pXllpLCD->frameDescriptorCh2_YCbCr_Y->FDADR = pXllpLCD->frameDescriptorCh2_YCbCr_Y->PHYSADDR; // next = self
pXllpLCD->frameDescriptorCh2_YCbCr_Y->FSADR = LCD_FSADR(pXllpLCD->_OVERLAY2_Y_CHANNEL_BASE_PHYSICAL); // frame buffer
pXllpLCD->frameDescriptorCh2_YCbCr_Y->FIDR = LCD_FIDR(0);
pXllpLCD->frameDescriptorCh2_YCbCr_Y->LDCMD = LCD_Len(pXllpOverlay->ch2_size);
// CH3
pXllpLCD->frameDescriptorCh3_YCbCr_Cb->PHYSADDR = LCD_FDADR(pXllpLCD->_DMA_CHANNEL_3_Cb_FRAME_DESCRIPTOR_BASE_PHYSICAL); // self
pXllpLCD->frameDescriptorCh3_YCbCr_Cb->FDADR = pXllpLCD->frameDescriptorCh3_YCbCr_Cb->PHYSADDR; // next = self
pXllpLCD->frameDescriptorCh3_YCbCr_Cb->FSADR = LCD_FSADR(pXllpLCD->_OVERLAY2_Cb_CHANNEL_BASE_PHYSICAL); // frame buffer
pXllpLCD->frameDescriptorCh3_YCbCr_Cb->FIDR = LCD_FIDR(0);
pXllpLCD->frameDescriptorCh3_YCbCr_Cb->LDCMD = LCD_Len(pXllpOverlay->ch3_size);
// CH4
pXllpLCD->frameDescriptorCh4_YCbCr_Cr->PHYSADDR = LCD_FDADR(pXllpLCD->_DMA_CHANNEL_4_Cr_FRAME_DESCRIPTOR_BASE_PHYSICAL); // self
pXllpLCD->frameDescriptorCh4_YCbCr_Cr->FDADR = pXllpLCD->frameDescriptorCh4_YCbCr_Cr->PHYSADDR; // next = self
pXllpLCD->frameDescriptorCh4_YCbCr_Cr->FSADR = LCD_FSADR(pXllpLCD->_OVERLAY2_Cr_CHANNEL_BASE_PHYSICAL); // frame buffer
pXllpLCD->frameDescriptorCh4_YCbCr_Cr->FIDR = LCD_FIDR(0);
pXllpLCD->frameDescriptorCh4_YCbCr_Cr->LDCMD = LCD_Len(pXllpOverlay->ch4_size);
// Set the physical address of the frame buffer
#if 1
pXllpLCD->frameDescriptorCh2_YCbCr_Y->FSADR = LCD_FSADR(pXllpLCD->_OVERLAY2_Y_CHANNEL_BASE_PHYSICAL);
pXllpLCD->frameDescriptorCh3_YCbCr_Cb->FSADR = LCD_FSADR(pXllpLCD->_OVERLAY2_Y_CHANNEL_BASE_PHYSICAL+pXllpOverlay->ch2_size);
pXllpLCD->frameDescriptorCh4_YCbCr_Cr->FSADR = LCD_FSADR(pXllpLCD->_OVERLAY2_Y_CHANNEL_BASE_PHYSICAL+
pXllpOverlay->ch2_size + pXllpOverlay->ch3_size);
#endif
// FBRx is cleared and is not used.
p_LCDRegs->FBR2 = 0;
p_LCDRegs->FBR3 = 0;
p_LCDRegs->FBR4 = 0;
StatMask = LCD_IU2;
if (pXllpOverlay->Format != FORMAT_RGB)
StatMask |= (LCD_IU3 | LCD_IU4);
p_LCDRegs->LCSR1 = StatMask; // clear
DBGMSG(1, (TEXT("AT XllpLCD_Overlay2_Enable x=%d, y=%d\r\n"), pXllpOverlay->X_Position,pXllpOverlay->Y_Position));
p_LCDRegs->OVL2C2 = (LCD_FOR(pXllpOverlay->Format) | LCD_O2YPOS(pXllpOverlay->Y_Position) | LCD_O2XPOS(pXllpOverlay->X_Position));
//=========================================================
p_LCDRegs->OVL2C1 = (LCD_O2EN | (LCD_BPP2(pXllpOverlay->OverlayBPP) | LCD_LPO2(pXllpOverlay->OverlayHeight-1) | LCD_PPL2(pXllpOverlay->OverlayWidth-1)));
//=========================================================
// Wait for the hardware to signal input FIFOx underrun
// before setting the FDADRx regs (and hence enabling DMA).
// This is a key part of the hardware workaround described in Tibet sighting 49219.
// Note that that IUx doesn't happen the first time after reset or resume.
// The underrun apparently does occur in the controller but the controller doesn't set IUx.
// According HW eng, the 50ms delay introduced by waiting for IUx should be sufficient
// to avoid the hardware problem.
// Note also that this may only needed for YUV modes but also works for RGB modes and
// implementing it for all modes produces less convoluted code.
if (WaitForState(&(p_LCDRegs->LCSR1),StatMask,WFS_ALL,OVERLAY_DELAY_ENABLE) < 0)
DBGMSG(1,(TEXT("XllpLCD_Overlay2_Enable(F=%d): No IUx (LCSR1=x%08x)\r\n"),
pXllpOverlay->Format, p_LCDRegs->LCSR1));
else
DBGMSG(1,(TEXT("XllpLCD_Overlay2_Enable(F=%d): Got IUx (LCSR1=x%08x)\r\n"),
pXllpOverlay->Format, p_LCDRegs->LCSR1));
// Load the FDADRx regs with the physical address of the frame descriptors
// Testing indicates that this is what actually enables DMA transfers.
// If FDADRx isn't set (even if already set to the desired value) the DMA doesn't start.
p_LCDRegs->FDADR2 = LCD_FDADR(pXllpLCD->frameDescriptorCh2_YCbCr_Y->PHYSADDR);
if (pXllpOverlay->Format != FORMAT_RGB)
{
p_LCDRegs->FDADR3 = LCD_FDADR(pXllpLCD->frameDescriptorCh3_YCbCr_Cb->PHYSADDR);
p_LCDRegs->FDADR4 = LCD_FDADR(pXllpLCD->frameDescriptorCh4_YCbCr_Cr->PHYSADDR);
}
p_LCDRegs->LCSR1 = StatMask; // clear
return(status);
} // XllpLCD_Overlay2_Enable
void XllpLCD_Overlay2_Disable(P_XLLP_LCD_T pXllpLCD, P_XLLP_OVERLAY_T pXllpOverlay)
{
volatile LCDRegs *p_LCDRegs;
unsigned int OVL2C1;
unsigned int OVL2C2;
unsigned int OL2Format;
unsigned int StatMask = 0;
p_LCDRegs = (LCDRegs *) pXllpLCD->LCDC;
OVL2C1 = p_LCDRegs->OVL2C1;
if (!(OVL2C1 & LCD_O2EN))
{
LOGMSG(1,(TEXT("XllpLCD_Overlay2_Disable: Not enabled\r\n")));
return;
}
OVL2C2 = p_LCDRegs->OVL2C2;
OL2Format = (OVL2C2 >> 20) & 7;
StatMask = LCD_BS2;
if (OL2Format != FORMAT_RGB)
StatMask |= (LCD_BS3 | LCD_BS4);
p_LCDRegs->LCSR1 = StatMask;
//=========================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -