765 lines
25 KiB
C
765 lines
25 KiB
C
|
/**************************************************************************//**
|
||
|
* @file lcd.c
|
||
|
* @brief N9H30 LCD driver source file
|
||
|
*
|
||
|
* @note
|
||
|
* SPDX-License-Identifier: Apache-2.0
|
||
|
* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved.
|
||
|
*****************************************************************************/
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <math.h>
|
||
|
|
||
|
#include "N9H30.h"
|
||
|
#include "nu_sys.h"
|
||
|
#include "nu_lcd.h"
|
||
|
|
||
|
/** @addtogroup N9H30_Device_Driver N9H30 Device Driver
|
||
|
@{
|
||
|
*/
|
||
|
|
||
|
/** @addtogroup N9H30_LCD_Driver LCD Driver
|
||
|
@{
|
||
|
*/
|
||
|
|
||
|
/** @addtogroup N9H30_LCD_EXPORTED_CONSTANTS LCD Exported Constants
|
||
|
@{
|
||
|
*/
|
||
|
|
||
|
/// @cond HIDDEN_SYMBOLS
|
||
|
|
||
|
/* LCD attributes */
|
||
|
static VPOST_T DEF_E50A2V1 =
|
||
|
{
|
||
|
800, /*!< Panel width */
|
||
|
480, /*!< Panel height */
|
||
|
0, /*!< MPU command line low indicator */
|
||
|
0, /*!< MPU command width */
|
||
|
0, /*!< MPU bus width */
|
||
|
VPOSTB_DATA16or18, /*!< Display bus width */
|
||
|
0, /*!< MPU mode */
|
||
|
VPOSTB_COLORTYPE_64K, /*!< Display colors */
|
||
|
VPOSTB_DEVICE_SYNC_HIGHCOLOR, /*!< Type of display panel */
|
||
|
0x020d03a0, /*!< CRTCSIZE register value */
|
||
|
0x01e00320, /*!< CRTCDEND register value */
|
||
|
0x03250321, /*!< CRTCHR register value */
|
||
|
0x03780348, /*!< CRTCHSYNC register value */
|
||
|
0x01f001ed /*!< CRTCVR register value */
|
||
|
};
|
||
|
|
||
|
static VPOST_T DEF_ILI9341_MPU80 =
|
||
|
{
|
||
|
240, /*!< Panel width */
|
||
|
320, /*!< Panel height */
|
||
|
VPOSTB_CMDLOW, /*!< MPU command line low indicator */
|
||
|
VPOSTB_CM16t18HIGH, /*!< MPU command width */
|
||
|
VPOSTB_CMD8, /*!< MPU bus width */
|
||
|
VPOSTB_DATA16or18, /*!< Display bus width */
|
||
|
VPOSTB_MPU80, /*!< MPU mode */
|
||
|
VPOSTB_COLORTYPE_64K, /*!< Display colors */
|
||
|
VPOSTB_DEVICE_MPU, /*!< Type of display panel */
|
||
|
0x01600100, /*!< CRTCSIZE register value */
|
||
|
0x014000F0, /*!< CRTCDEND register value */
|
||
|
0x00FA00F5, /*!< CRTCHR register value */
|
||
|
0x00FC00FA, /*!< CRTCHSYNC register value */
|
||
|
0x01500145 /*!< CRTCVR register value */
|
||
|
};
|
||
|
|
||
|
static VPOST_T DEF_LSA40AT9001 =
|
||
|
{
|
||
|
800, /*!< Panel width */
|
||
|
600, /*!< Panel height */
|
||
|
0, /*!< MPU command line low indicator */
|
||
|
0, /*!< MPU command width */
|
||
|
0, /*!< MPU bus width */
|
||
|
VPOSTB_DATA16or18, /*!< Display bus width */
|
||
|
0, /*!< MPU mode */
|
||
|
VPOSTB_COLORTYPE_64K, /*!< Display colors */
|
||
|
VPOSTB_DEVICE_SYNC_HIGHCOLOR, /*!< Type of display panel */
|
||
|
0x02800425, /*!< CRTCSIZE register value */
|
||
|
0x02580320, /*!< CRTCDEND register value */
|
||
|
0x032F032A, /*!< CRTCHR register value */
|
||
|
0x0334032A, /*!< CRTCHSYNC register value */
|
||
|
0x026C0262 /*!< CRTCVR register value */
|
||
|
};
|
||
|
|
||
|
|
||
|
static VPOST_T DEF_FW070TFT =
|
||
|
{
|
||
|
800, /*!< Panel width */
|
||
|
480, /*!< Panel height */
|
||
|
0, /*!< MPU command line low indicator */
|
||
|
0, /*!< MPU command width */
|
||
|
0, /*!< MPU bus width */
|
||
|
VPOSTB_DATA16or18, /*!< Display bus width */
|
||
|
0, /*!< MPU mode */
|
||
|
VPOSTB_COLORTYPE_16M, /*!< Display colors */
|
||
|
VPOSTB_DEVICE_SYNC_HIGHCOLOR, /*!< Type of display panel */
|
||
|
0x020d0420, /*!< CRTCSIZE register value */
|
||
|
0x01e00320, /*!< CRTCDEND register value */
|
||
|
0x033e0339, /*!< CRTCHR register value */
|
||
|
0x040c03f8, /*!< CRTCHSYNC register value */
|
||
|
0x020001f6 /*!< CRTCVR register value */
|
||
|
};
|
||
|
|
||
|
/* LCD build-in support list */
|
||
|
static VPOST_T *DisplayDevList[4] = {&DEF_E50A2V1, &DEF_ILI9341_MPU80, &DEF_LSA40AT9001, &DEF_FW070TFT};
|
||
|
static VPOST_T curDisplayDev;
|
||
|
static OSDFORMATEX curOSDDev = {0};
|
||
|
static LCDFORMATEX curVADev = {0};
|
||
|
|
||
|
/// @endcond /* HIDDEN_SYMBOLS */
|
||
|
|
||
|
/*@}*/ /* end of group N9H30_I2C_EXPORTED_CONSTANTS */
|
||
|
|
||
|
/** @addtogroup N9H30_LCD_EXPORTED_FUNCTIONS LCD Exported Functions
|
||
|
@{
|
||
|
*/
|
||
|
/// @cond HIDDEN_SYMBOLS
|
||
|
|
||
|
/* For align 32 */
|
||
|
static uint32_t shift_pointer(uint32_t ptr, uint32_t align)
|
||
|
{
|
||
|
uint32_t alignedPTR;
|
||
|
uint32_t remain;
|
||
|
|
||
|
//printf("pointer position is %x\n",ptr);
|
||
|
if ((ptr % align) != 0)
|
||
|
{
|
||
|
remain = ptr % align;
|
||
|
alignedPTR = ptr + (align - remain);
|
||
|
return alignedPTR;
|
||
|
}
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
/// @endcond /* HIDDEN_SYMBOLS */
|
||
|
|
||
|
/**
|
||
|
* @brief Configure attributes of LCD panel,install interrupt handler and enable LCD engine clock
|
||
|
* @param[in] u32DisplayPanelID is panel id to configure.
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostLCMInit(uint32_t u32DisplayPanelID)
|
||
|
{
|
||
|
// enable lcd engine clock
|
||
|
outpw(REG_CLK_HCLKEN, inpw(REG_CLK_HCLKEN) | (1 << 25));
|
||
|
|
||
|
memset((void *)&curDisplayDev, 0, sizeof(curDisplayDev));
|
||
|
memcpy((void *)&curDisplayDev, DisplayDevList[u32DisplayPanelID], sizeof(curDisplayDev));
|
||
|
|
||
|
outpw(REG_LCM_DEV_CTRL, curDisplayDev.u32CmdLow
|
||
|
| curDisplayDev.u32Cmd16t18
|
||
|
| curDisplayDev.u32CmdBusWidth
|
||
|
| curDisplayDev.u32DataBusWidth
|
||
|
| curDisplayDev.u32MPU_Mode
|
||
|
| curDisplayDev.u32DisplayColors
|
||
|
| curDisplayDev.u32DevType);
|
||
|
|
||
|
outpw(REG_LCM_CRTC_SIZE, curDisplayDev.u32Reg_CRTCSIZE);
|
||
|
outpw(REG_LCM_CRTC_DEND, curDisplayDev.u32Reg_CRTCDEND);
|
||
|
outpw(REG_LCM_CRTC_HR, curDisplayDev.u32Reg_CRTCHR);
|
||
|
outpw(REG_LCM_CRTC_HSYNC, curDisplayDev.u32Reg_CRTCHSYNC);
|
||
|
outpw(REG_LCM_CRTC_VR, curDisplayDev.u32Reg_CRTCVR);
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Query LCM capacity and configuration by ID
|
||
|
* @param[in] u32DisplayPanelID is panel id to configure.
|
||
|
* @return LCM instance
|
||
|
*/
|
||
|
VPOST_T *vpostLCMGetInstance(uint32_t u32DisplayPanelID)
|
||
|
{
|
||
|
if (u32DisplayPanelID > (sizeof(DisplayDevList) / sizeof(VPOST_T *)))
|
||
|
return NULL;
|
||
|
|
||
|
return DisplayDevList[u32DisplayPanelID];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Disable LCD engine
|
||
|
* @param none
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostLCMDeinit(void)
|
||
|
{
|
||
|
// disable lcd engine clock
|
||
|
outpw(REG_CLK_HCLKEN, inpw(REG_CLK_HCLKEN) & ~(1 << 25));
|
||
|
|
||
|
//sysDisableInterrupt(LCD_IRQn);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get the pointer of frame buffer
|
||
|
* @param none
|
||
|
* @return pointer of frame buffer
|
||
|
* @retval NULL fail.
|
||
|
* @note before calling this function, display width, height and source format must be set first.
|
||
|
*/
|
||
|
uint8_t *vpostGetFrameBuffer(void)
|
||
|
{
|
||
|
uint8_t *u8BufPtr;
|
||
|
uint8_t u32BytePerPixel;
|
||
|
|
||
|
if ((curDisplayDev.u32DevWidth == 0) || (curDisplayDev.u32DevHeight == 0))
|
||
|
return NULL;
|
||
|
|
||
|
switch (curVADev.ucVASrcFormat)
|
||
|
{
|
||
|
case VA_SRC_YUV422:
|
||
|
case VA_SRC_YCBCR422:
|
||
|
case VA_SRC_RGB565:
|
||
|
u32BytePerPixel = 2;
|
||
|
break;
|
||
|
|
||
|
case VA_SRC_RGB666:
|
||
|
case VA_SRC_RGB888:
|
||
|
u32BytePerPixel = 4;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
u32BytePerPixel = 2;
|
||
|
}
|
||
|
|
||
|
u8BufPtr = (uint8_t *)malloc((curDisplayDev.u32DevWidth * curDisplayDev.u32DevHeight * u32BytePerPixel) + 32);
|
||
|
if (u8BufPtr == NULL)
|
||
|
return NULL;
|
||
|
u8BufPtr = (uint8_t *)shift_pointer((uint32_t)u8BufPtr, 32);
|
||
|
|
||
|
outpw(REG_LCM_VA_BADDR0, (uint32_t)((uint32_t)u8BufPtr | 0x80000000));
|
||
|
outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~(1 << 30) & ~VPOSTB_DB_EN);
|
||
|
|
||
|
return (uint8_t *)((uint32_t)u8BufPtr | 0x80000000);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief Get the pointer of frame buffer
|
||
|
* @param[in] u32Cnt is the frame buffer count to allocate. Min value is 1.
|
||
|
* @return pointer of frame buffer
|
||
|
* @retval NULL fail.
|
||
|
* @note before calling this function, display width, height and source format must be set first.
|
||
|
*/
|
||
|
uint8_t *vpostGetMultiFrameBuffer(uint32_t u32Cnt)
|
||
|
{
|
||
|
uint8_t *u8BufPtr;
|
||
|
uint8_t u32BytePerPixel;
|
||
|
|
||
|
if ((curDisplayDev.u32DevWidth == 0) || (curDisplayDev.u32DevHeight == 0) || (u32Cnt == 0))
|
||
|
return NULL;
|
||
|
|
||
|
switch (curVADev.ucVASrcFormat)
|
||
|
{
|
||
|
case VA_SRC_YUV422:
|
||
|
case VA_SRC_YCBCR422:
|
||
|
case VA_SRC_RGB565:
|
||
|
u32BytePerPixel = 2;
|
||
|
break;
|
||
|
|
||
|
case VA_SRC_RGB666:
|
||
|
case VA_SRC_RGB888:
|
||
|
u32BytePerPixel = 4;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
u32BytePerPixel = 2;
|
||
|
}
|
||
|
|
||
|
u8BufPtr = (uint8_t *)malloc((curDisplayDev.u32DevWidth * curDisplayDev.u32DevHeight * u32BytePerPixel) * u32Cnt + 32);
|
||
|
if (u8BufPtr == NULL)
|
||
|
return NULL;
|
||
|
u8BufPtr = (uint8_t *)shift_pointer((uint32_t)u8BufPtr, 32);
|
||
|
|
||
|
outpw(REG_LCM_VA_BADDR0, (uint32_t)((uint32_t)u8BufPtr | 0x80000000));
|
||
|
outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~(1 << 30) & ~VPOSTB_DB_EN);
|
||
|
|
||
|
return (uint8_t *)((uint32_t)u8BufPtr | 0x80000000);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Set active display window
|
||
|
* @param[in] u16StartY is y start position
|
||
|
* @param[in] u16EndY is y end position
|
||
|
* @param[in] u8BGColorR is background R color
|
||
|
* @param[in] u8BGColorG is background G color
|
||
|
* @param[in] u8BGColorB is background B color
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostSetActiveWindow(uint16_t u16StartY, uint16_t u16EndY, uint8_t u8BGColorR, uint8_t u8BGColorG, uint8_t u8BGColorB)
|
||
|
{
|
||
|
outpw(REG_LCM_VA_WIN, (u16StartY << 16) | u16EndY);
|
||
|
outpw(REG_LCM_VA_STUFF, (u8BGColorR << 16) | (u8BGColorG << 8) | u8BGColorB);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Configure LCD display mode
|
||
|
* @param[in] u8DisplayMode is display mode, value could be
|
||
|
* - \ref VPOST_DISPLAY_SINGLE
|
||
|
* - \ref VPOST_DISPLAY_CONTINUOUS
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostSetDisplayMode(uint8_t u8DisplayMode)
|
||
|
{
|
||
|
if (u8DisplayMode == 0)
|
||
|
outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(1 << 7)); //clear setting
|
||
|
else
|
||
|
outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | (u8DisplayMode) << 7);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Configure display attributes of video interface,
|
||
|
* @param[in] u32VASrcType is display type, value could be
|
||
|
* - \ref VA_SRC_YUV422
|
||
|
* - \ref VA_SRC_YCBCR422
|
||
|
* - \ref VA_SRC_RGB888
|
||
|
* - \ref VA_SRC_RGB666
|
||
|
* - \ref VA_SRC_RGB565
|
||
|
* - \ref VA_SRC_RGB444_LOW
|
||
|
* - \ref VA_SRC_RGB444_HIGH
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostSetVASrc(uint32_t u32VASrcType)
|
||
|
{
|
||
|
uint32_t u32BytePerPixel, VA_FF, VA_Sride;
|
||
|
|
||
|
curVADev.ucVASrcFormat = u32VASrcType;
|
||
|
|
||
|
outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(7 << 8));
|
||
|
if (u32VASrcType != 0)
|
||
|
outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | u32VASrcType);
|
||
|
else
|
||
|
outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(7 << 8));
|
||
|
|
||
|
if ((u32VASrcType == VA_SRC_RGB888) || (u32VASrcType == VA_SRC_RGB666))
|
||
|
outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~0x7ff07ff | (curDisplayDev.u32DevWidth << 16) | curDisplayDev.u32DevWidth);
|
||
|
else
|
||
|
outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~0x7ff07ff | ((curDisplayDev.u32DevWidth / 2) << 16) | (curDisplayDev.u32DevWidth / 2));
|
||
|
|
||
|
switch (u32VASrcType)
|
||
|
{
|
||
|
case VA_SRC_YUV422:
|
||
|
case VA_SRC_YCBCR422:
|
||
|
case VA_SRC_RGB565:
|
||
|
u32BytePerPixel = 2;
|
||
|
break;
|
||
|
|
||
|
case VA_SRC_RGB666:
|
||
|
case VA_SRC_RGB888:
|
||
|
u32BytePerPixel = 4;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
u32BytePerPixel = 2;
|
||
|
}
|
||
|
|
||
|
/* set video stream frame buffer control */
|
||
|
VA_FF = curDisplayDev.u32DevWidth * u32BytePerPixel / 4;
|
||
|
VA_Sride = curDisplayDev.u32DevWidth * u32BytePerPixel / 4;
|
||
|
outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~0x7ff07ff | (VA_FF << 16) | VA_Sride);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Start to display
|
||
|
* @param none
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostVAStartTrigger(void)
|
||
|
{
|
||
|
if ((inpw(REG_LCM_DCCS) & VPOSTB_SINGLE) == VPOSTB_SINGLE)
|
||
|
while ((inpw(REG_LCM_DCCS) & VPOSTB_VA_EN) == VPOSTB_VA_EN); //wait VA_EN low
|
||
|
outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | VPOSTB_DISP_OUT_EN); //display_out-enable
|
||
|
outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | VPOSTB_VA_EN); //va-enable
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Stop to display
|
||
|
* @param none
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostVAStopTrigger(void)
|
||
|
{
|
||
|
outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(VPOSTB_DISP_OUT_EN | VPOSTB_VA_EN)); //OSD disable
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Configure LCD scaling attribute
|
||
|
* @param[in] u8HIntegral is horizontal integral
|
||
|
* @param[in] u16HDecimal is horizontal decimal
|
||
|
* @param[in] u8VIntegral is vertical integral
|
||
|
* @param[in] u16VDecimal is vertical decimal
|
||
|
* @param[in] u32Mode is scale mode, value could be
|
||
|
* - \ref VA_SCALE_INTERPOLATION
|
||
|
* - \ref VA_SCALE_DUPLICATION
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostVAScalingCtrl(uint8_t u8HIntegral, uint16_t u16HDecimal, uint8_t u8VIntegral, uint16_t u16VDecimal, uint32_t u32Mode)
|
||
|
{
|
||
|
outpw(REG_LCM_VA_SCALE, ((((uint32_t)u8VIntegral << 10) + ((uint32_t)ceil((double)1024 / 10)*u16VDecimal)) << 16)
|
||
|
| (((uint32_t)u8HIntegral << 10) + ((uint32_t)ceil((double)1024 / 10)*u16HDecimal)) | u32Mode);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Set OSD color key
|
||
|
* @param[in] u8CKeyColorR is color key R color
|
||
|
* @param[in] u8CKeyColorG is color key G color
|
||
|
* @param[in] u8CKeyColorB is color key B color
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostOSDSetColKey(uint8_t u8CKeyColorR, uint8_t u8CKeyColorG, uint8_t u8CKeyColorB)
|
||
|
{
|
||
|
outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) & ~(VPOSTB_BLI_ON | VPOSTB_CKEY_ON)); //blinking disable, color-key disable
|
||
|
outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | VPOSTB_CKEY_ON);//color-key enable
|
||
|
outpw(REG_LCM_OSD_CKEY, ((uint32_t)(u8CKeyColorR << 16) | (uint32_t)(u8CKeyColorG << 8) | u8CKeyColorB));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Set OSD color mask, OSD data only will be displayed if the mask bit is set as 1.
|
||
|
* @param[in] u8MaskColorR is color key R color
|
||
|
* @param[in] u8MaskColorG is color key G color
|
||
|
* @param[in] u8MaskColorB is color key B color
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostOSDSetColMask(uint8_t u8MaskColorR, uint8_t u8MaskColorG, uint8_t u8MaskColorB)
|
||
|
{
|
||
|
outpw(REG_LCM_OSD_CMASK, ((u8MaskColorR << 16) | (u8MaskColorG << 8) | u8MaskColorB));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Set OSD blinking function
|
||
|
* @param[in] u8OSDBlinkVcnt is blinking cycle time, unit is VSync
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostOSDSetBlinking(uint8_t u8OSDBlinkVcnt)
|
||
|
{
|
||
|
outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) & ~(VPOSTB_BLI_ON | VPOSTB_CKEY_ON)); //blinking disable, color-key disable
|
||
|
outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | VPOSTB_BLI_ON);
|
||
|
outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | ((uint32_t)(u8OSDBlinkVcnt) << 16));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Disable OSD blinking function
|
||
|
* @param none
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostOSDDisableBlinking(void)
|
||
|
{
|
||
|
outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) & ~ VPOSTB_BLI_ON);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Configure display attributes of OSD
|
||
|
* @param[in] u32OSDSrcType is display type, value could be
|
||
|
* - \ref OSD_SRC_YUV422
|
||
|
* - \ref OSD_SRC_YCBCR422
|
||
|
* - \ref OSD_SRC_RGB888
|
||
|
* - \ref OSD_SRC_RGB666
|
||
|
* - \ref OSD_SRC_RGB565
|
||
|
* - \ref OSD_SRC_RGB444_LOW
|
||
|
* - \ref OSD_SRC_RGB444_HIGH
|
||
|
* - \ref OSD_SRC_RGB332
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostSetOSDSrc(uint32_t u32OSDSrcType)
|
||
|
{
|
||
|
uint32_t u32BytePerPixel, VA_FF, VA_Sride;
|
||
|
|
||
|
outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(7 << 12) | u32OSDSrcType);
|
||
|
curOSDDev.ucOSDSrcFormat = u32OSDSrcType;
|
||
|
|
||
|
switch (u32OSDSrcType)
|
||
|
{
|
||
|
case OSD_SRC_YUV422:
|
||
|
case OSD_SRC_YCBCR422:
|
||
|
case OSD_SRC_RGB565:
|
||
|
u32BytePerPixel = 2;
|
||
|
break;
|
||
|
|
||
|
case OSD_SRC_RGB666:
|
||
|
case OSD_SRC_RGB888:
|
||
|
u32BytePerPixel = 4;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
u32BytePerPixel = 2;
|
||
|
}
|
||
|
|
||
|
/* set video stream frame buffer control */
|
||
|
VA_FF = curOSDDev.nOSDWidth * u32BytePerPixel / 4;
|
||
|
VA_Sride = curOSDDev.nOSDWidth * u32BytePerPixel / 4;
|
||
|
outpw(REG_LCM_OSD_FBCTRL, inpw(REG_LCM_OSD_FBCTRL) & ~0x7ff07ff | (VA_FF << 16) | VA_Sride);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get the pointer of OSD frame buffer
|
||
|
* @param none
|
||
|
* @return pointer of OSD frame buffer
|
||
|
* @retval NULL fail.
|
||
|
* @note Must call \ref vpostOSDSetWindow and \ref vpostSetOSDSrc before calling this function
|
||
|
*/
|
||
|
uint8_t *vpostGetOSDBuffer(void)
|
||
|
{
|
||
|
uint32_t u32BytePerPixel;
|
||
|
uint8_t *u8BufPtr;
|
||
|
|
||
|
if ((curOSDDev.nOSDWidth == 0) || (curOSDDev.nOSDHeight == 0))
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
switch (curOSDDev.ucOSDSrcFormat)
|
||
|
{
|
||
|
case OSD_SRC_YUV422:
|
||
|
case OSD_SRC_YCBCR422:
|
||
|
case OSD_SRC_RGB565:
|
||
|
u32BytePerPixel = 2;
|
||
|
break;
|
||
|
|
||
|
case OSD_SRC_RGB666:
|
||
|
case OSD_SRC_RGB888:
|
||
|
u32BytePerPixel = 4;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
u32BytePerPixel = 2;
|
||
|
}
|
||
|
|
||
|
u8BufPtr = (uint8_t *)malloc((curOSDDev.nOSDWidth * curOSDDev.nOSDHeight * u32BytePerPixel) + 32);
|
||
|
if (u8BufPtr == NULL)
|
||
|
return NULL;
|
||
|
u8BufPtr = (uint8_t *)shift_pointer((uint32_t)u8BufPtr, 32);
|
||
|
|
||
|
outpw(REG_LCM_OSD_BADDR, (uint32_t)((uint32_t)u8BufPtr | 0x80000000));
|
||
|
|
||
|
return (uint8_t *)((uint32_t)u8BufPtr | 0x80000000);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Enable OSD function
|
||
|
* @param none
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostOSDEnable(void)
|
||
|
{
|
||
|
outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | VPOSTB_OSD_EN); //OSD enable
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Disable OSD function
|
||
|
* @param none
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostOSDDisable(void)
|
||
|
{
|
||
|
outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~VPOSTB_OSD_EN); //OSD disable
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Configure OSD scaling attribute
|
||
|
* @param[in] u8HIntegral is horizontal integral
|
||
|
* @param[in] u16HDecimal is horizontal decimal
|
||
|
* @param[in] u8VScall is scale mode, value could be
|
||
|
* - \ref VPOSTB_OSD_VUP_1X
|
||
|
* - \ref VPOSTB_OSD_VUP_2X
|
||
|
* - \ref VPOSTB_OSD_VUP_4X
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostOSDScalingCtrl(uint8_t u8HIntegral, uint16_t u16HDecimal, uint8_t u8VScall)
|
||
|
{
|
||
|
outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & 0xfff0ffff); //clear OSD scaling setting
|
||
|
if (u8VScall != 0)
|
||
|
outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | (u8VScall << 16));
|
||
|
outpw(REG_LCM_OSD_SCALE, ((uint32_t)u8HIntegral << 10) | ((uint32_t)ceil((double)1024 / 10 * u16HDecimal)) << 6);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Set OSD display window, including start position, width and height.
|
||
|
* @param[in] u32XStart is X start position
|
||
|
* @param[in] u32YStart is Y start position
|
||
|
* @param[in] u32Width is OSD display width
|
||
|
* @param[in] u32Height is OSD display height
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostOSDSetWindow(uint32_t u32XStart, uint32_t u32YStart, uint32_t u32Width, uint32_t u32Height)
|
||
|
{
|
||
|
outpw(REG_LCM_OSD_WINS, ((u32YStart + 1) << 16) | (u32XStart + 1));
|
||
|
outpw(REG_LCM_OSD_WINE, ((u32YStart + u32Height) << 16) | (u32XStart + u32Width));
|
||
|
|
||
|
curOSDDev.nOSDWidth = u32Width;
|
||
|
curOSDDev.nOSDHeight = u32Height;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Initialize hardware cursor function
|
||
|
* @param[in] u32CursorBMPBuff is pointer of hardware cursor image
|
||
|
* @param[in] ucMode is hardware cursor mode, value could be
|
||
|
* - \ref HC_MODE0
|
||
|
* - \ref HC_MODE1
|
||
|
* - \ref HC_MODE2
|
||
|
* - \ref HC_MODE3
|
||
|
* - \ref HC_MODE4
|
||
|
* - \ref HC_MODE5
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostHCInit(uint32_t *u32CursorBMPBuff, VA_HCMODE_E ucMode)
|
||
|
{
|
||
|
int bpp = 2;
|
||
|
int BlockWidth = 32;
|
||
|
int bpw = 32;
|
||
|
|
||
|
outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x003f3f00 | (0x00 << 8) | (0x00 << 16)); //set TIP
|
||
|
if (ucMode == HC_MODE0)
|
||
|
{
|
||
|
bpp = 2;
|
||
|
BlockWidth = 32;
|
||
|
outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7); //set mode 0 32X32X2bpp 4 color
|
||
|
|
||
|
}
|
||
|
else if (ucMode == HC_MODE1)
|
||
|
{
|
||
|
bpp = 2;
|
||
|
BlockWidth = 32;
|
||
|
outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x1); //set mode 1 32X32X2bpp 3 color and 1 transparent
|
||
|
}
|
||
|
else if (ucMode == HC_MODE2)
|
||
|
{
|
||
|
bpp = 2;
|
||
|
BlockWidth = 64;
|
||
|
outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x2); //set mode 2 64X64X2bpp 4 color
|
||
|
}
|
||
|
else if (ucMode == HC_MODE3)
|
||
|
{
|
||
|
bpp = 2;
|
||
|
BlockWidth = 64;
|
||
|
outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x3); //set mode 3 64X64X2bpp 3 color and 1 transparent
|
||
|
}
|
||
|
else if (ucMode == HC_MODE4)
|
||
|
{
|
||
|
bpp = 1;
|
||
|
BlockWidth = 128;
|
||
|
outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x4); //set mode 4 128X128X1bpp 2 color
|
||
|
}
|
||
|
else if (ucMode == HC_MODE5)
|
||
|
{
|
||
|
bpp = 1;
|
||
|
BlockWidth = 128;
|
||
|
outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x5); //set mode 5 128X128X1bpp 1 color and 1 transparent
|
||
|
}
|
||
|
|
||
|
outpw(REG_LCM_HC_WBCTRL, ((bpp * BlockWidth / bpw) << 16) | (bpp * BlockWidth / bpw));
|
||
|
outpw(REG_LCM_HC_BADDR, (uint32_t)u32CursorBMPBuff);
|
||
|
outpw(REG_LCM_HC_COLOR0, 0x00ff0000); // RED color
|
||
|
outpw(REG_LCM_HC_COLOR1, 0x0000ff00); // GREEN color
|
||
|
outpw(REG_LCM_HC_COLOR2, 0x000000ff); // BLUE color
|
||
|
outpw(REG_LCM_HC_COLOR3, 0x00ffff00); // YELLOW color
|
||
|
outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | VPOSTB_HC_EN);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Set the position of hardware cursor
|
||
|
* @param[in] u32CursorX is X position
|
||
|
* @param[in] u32CursorY is Y position
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostHCPosCtrl(uint32_t u32CursorX, uint32_t u32CursorY)
|
||
|
{
|
||
|
outpw(REG_LCM_HC_POS, (u32CursorY << 16) | u32CursorX); //set Cursor position
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Set OSD overlay condition
|
||
|
* @param[in] u8OSDDisplayMatch is display method when mask bit is matched, value could be
|
||
|
* - \ref DISPLAY_VIDEO
|
||
|
* - \ref DISPLAY_OSD
|
||
|
* - \ref DISPLAY_SYNTHESIZED
|
||
|
* @param[in] u8OSDDisplayUnMatch is display method when mask bit is unmatched
|
||
|
* - \ref DISPLAY_VIDEO
|
||
|
* - \ref DISPLAY_OSD
|
||
|
* - \ref DISPLAY_SYNTHESIZED
|
||
|
* @param[in] u8OSDSynW is synthesis video weighting, based on match condition
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostOSDSetOverlay(uint8_t u8OSDDisplayMatch, uint8_t u8OSDDisplayUnMatch, uint8_t u8OSDSynW)
|
||
|
{
|
||
|
/* clear OCR0 and OCR1 */
|
||
|
outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) & 0xfffffff0);
|
||
|
|
||
|
/* match condition */
|
||
|
if (u8OSDDisplayMatch != 0)
|
||
|
{
|
||
|
outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | (u8OSDDisplayMatch << 2));
|
||
|
}
|
||
|
|
||
|
/* unmatch condition */
|
||
|
if (u8OSDDisplayUnMatch != 0)
|
||
|
{
|
||
|
outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | (u8OSDDisplayUnMatch));
|
||
|
}
|
||
|
|
||
|
/* synthesized weight */
|
||
|
if (u8OSDDisplayMatch == DISPLAY_SYNTHESIZED || u8OSDDisplayUnMatch == DISPLAY_SYNTHESIZED)
|
||
|
{
|
||
|
outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | (u8OSDSynW << 4));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Write MPU command
|
||
|
* @param[in] uscmd MPU command code
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostMPUWriteAddr(uint16_t uscmd)
|
||
|
{
|
||
|
outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) & ~(1 << 30)); //RS=0
|
||
|
outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) & ~(1 << 29)); //w
|
||
|
|
||
|
outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) | (1 << 5))); //CMD ON
|
||
|
outpw(REG_LCM_MPU_CMD, (inpw(REG_LCM_MPU_CMD) & 0xffff0000 | uscmd));
|
||
|
while (inpw(REG_LCM_MPU_CMD) & (1UL << 31));
|
||
|
outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) & ~(1 << 5))); //CMD OFF
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Write MPU data
|
||
|
* @param[in] usdata MPU data
|
||
|
* @return none
|
||
|
*/
|
||
|
void vpostMPUWriteData(uint16_t usdata)
|
||
|
{
|
||
|
outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) | (1 << 30)); //RS=1
|
||
|
outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) & ~(1 << 29)); //w
|
||
|
outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) | (1 << 5))); //CMD ON
|
||
|
outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) & 0xffff0000 | usdata);
|
||
|
while (inpw(REG_LCM_MPU_CMD) & (1UL << 31));
|
||
|
outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) & ~(1 << 5))); //CMD OFF
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Read MPU data
|
||
|
* @param none
|
||
|
* @return MPU data
|
||
|
*/
|
||
|
uint32_t vpostMPUReadData(void)
|
||
|
{
|
||
|
uint32_t udata;
|
||
|
|
||
|
outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) | (1 << 30)); //RS=1
|
||
|
outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) | (1 << 5))); //CMD ON
|
||
|
outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) | (1 << 29)); //r
|
||
|
while (inpw(REG_LCM_MPU_CMD) & (1UL << 31));
|
||
|
udata = inpw(REG_LCM_MPU_CMD) & 0xffff;
|
||
|
outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) & ~(1 << 5))); //CMD OFF
|
||
|
|
||
|
return udata;
|
||
|
}
|
||
|
|
||
|
/*@}*/ /* end of group N9H30_LCD_EXPORTED_FUNCTIONS */
|
||
|
|
||
|
/*@}*/ /* end of group N9H30_LCD_Driver */
|
||
|
|
||
|
/*@}*/ /* end of group N9H30_Device_Driver */
|
||
|
|
||
|
/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/
|
||
|
|